Annotation of hatari/src/blitter.c, revision 1.1.1.13

1.1.1.2   root        1: /*
1.1.1.3   root        2:  * Hatari - blitter.c
1.1.1.2   root        3:  *
1.1.1.12  root        4:  * This file is distributed under the GNU General Public License, version 2
                      5:  * or at your option any later version. Read the file gpl.txt for details.
1.1.1.2   root        6:  *
1.1.1.7   root        7:  * Blitter emulation. The 'Blitter' chip is found in the Mega-ST, STE/Mega-STE
                      8:  * and Falcon. It provides a very fast BitBlit function in hardware.
1.1       root        9:  *
1.1.1.7   root       10:  * This file has originally been taken from STonX, but it has been completely
                     11:  * modified for better maintainability and higher compatibility.
1.1.1.8   root       12:  *
                     13:  * NOTES:
                     14:  * ----------------------------------------------------------------------------
                     15:  * Strange end mask condition ((~(0xffff>>skew)) > end_mask_1)
                     16:  *
                     17:  * """Similarly the  NFSR (aka  post-flush) bit, when set, will prevent the last
                     18:  * source read of the  line. This read  may not  be necessary  with certain
                     19:  * combinations of end masks and skews."""
                     20:  *     - doesn't mean the blitter will skip source read by itself, just a hint
                     21:  *       for developers as far as i understand it.
                     22:  * ----------------------------------------------------------------------------
                     23:  * Does smudge mode change the line register ?
                     24:  * ----------------------------------------------------------------------------
1.1       root       25:  */
1.1.1.9   root       26: 
1.1.1.8   root       27: const char Blitter_fileid[] = "Hatari blitter.c : " __DATE__ " " __TIME__;
1.1       root       28: 
                     29: #include <SDL_types.h>
                     30: #include <stdio.h>
                     31: #include <stdlib.h>
                     32: 
1.1.1.2   root       33: #include "main.h"
1.1       root       34: #include "blitter.h"
1.1.1.7   root       35: #include "configuration.h"
                     36: #include "dmaSnd.h"
1.1.1.3   root       37: #include "ioMem.h"
                     38: #include "m68000.h"
1.1.1.7   root       39: #include "mfp.h"
1.1.1.2   root       40: #include "memorySnapShot.h"
1.1       root       41: #include "stMemory.h"
1.1.1.11  root       42: #include "screen.h"
1.1.1.7   root       43: #include "video.h"
                     44: 
1.1.1.8   root       45: /* Cycles to run for in non-hog mode */
                     46: #define NONHOG_CYCLES  (64*4)
1.1       root       47: 
1.1.1.8   root       48: /* BLiTTER registers, incs are signed, others unsigned */
                     49: #define REG_HT_RAM             0xff8a00        /* - 0xff8a1e */
1.1       root       50: 
1.1.1.4   root       51: #define REG_SRC_X_INC  0xff8a20
                     52: #define REG_SRC_Y_INC  0xff8a22
                     53: #define REG_SRC_ADDR   0xff8a24
                     54: 
                     55: #define REG_END_MASK1  0xff8a28
                     56: #define REG_END_MASK2  0xff8a2a
                     57: #define REG_END_MASK3  0xff8a2c
                     58: 
                     59: #define REG_DST_X_INC  0xff8a2e
                     60: #define REG_DST_Y_INC  0xff8a30
                     61: #define REG_DST_ADDR   0xff8a32
                     62: 
1.1.1.7   root       63: #define REG_X_COUNT    0xff8a36
                     64: #define REG_Y_COUNT    0xff8a38
1.1.1.4   root       65: 
                     66: #define REG_BLIT_HOP   0xff8a3a        /* halftone blit operation byte */
                     67: #define REG_BLIT_LOP   0xff8a3b        /* logical blit operation byte */
1.1.1.7   root       68: #define REG_CONTROL    0xff8a3c
1.1.1.8   root       69: #define REG_SKEW               0xff8a3d
1.1.1.4   root       70: 
1.1.1.8   root       71: /* Blitter registers */
                     72: typedef struct
                     73: {
                     74:        Uint32  src_addr;
                     75:        Uint32  dst_addr;
                     76:        Uint32  words;
                     77:        Uint32  lines;
                     78:        short   src_x_incr;
                     79:        short   src_y_incr;
                     80:        short   dst_x_incr;
                     81:        short   dst_y_incr;
                     82:        Uint16  end_mask_1;
                     83:        Uint16  end_mask_2;
                     84:        Uint16  end_mask_3;
                     85:        Uint8   hop;
                     86:        Uint8   lop;
                     87:        Uint8   ctrl;
                     88:        Uint8   skew;
                     89: } BLITTERREGS;
                     90: 
                     91: /* Blitter vars */
                     92: typedef struct
                     93: {
1.1.1.9   root       94:        int             pass_cycles;
                     95:        int             op_cycles;
1.1.1.8   root       96:        Uint32  buffer;
                     97:        Uint32  src_words_reset;
                     98:        Uint32  dst_words_reset;
                     99:        Uint32  src_words;
                    100:        Uint8   hog;
                    101:        Uint8   smudge;
                    102:        Uint8   line;
                    103:        Uint8   fxsr;
                    104:        Uint8   nfsr;
                    105:        Uint8   skew;
                    106: } BLITTERVARS;
                    107: 
                    108: /* Blitter state */
                    109: typedef struct
                    110: {
                    111:        Uint16  src_word;
                    112:        Uint16  dst_word;
                    113:        Uint16  end_mask;
                    114:        Uint8   have_src;
                    115:        Uint8   have_dst;
                    116:        Uint8   fxsr;
                    117:        Uint8   nfsr;
                    118: } BLITTERSTATE;
                    119: 
1.1.1.9   root      120: /* Blitter logical op func */
                    121: typedef Uint16 (*BLITTER_OP_FUNC)(void);
                    122: 
1.1.1.8   root      123: static BLITTERREGS     BlitterRegs;
                    124: static BLITTERVARS     BlitterVars;
                    125: static BLITTERSTATE    BlitterState;
                    126: static Uint16          BlitterHalftone[16];
1.1.1.3   root      127: 
1.1.1.9   root      128: static BLITTER_OP_FUNC Blitter_ComputeHOP;
                    129: static BLITTER_OP_FUNC Blitter_ComputeLOP;
                    130: 
1.1.1.8   root      131: /*-----------------------------------------------------------------------*/
                    132: /**
                    133:  * Count blitter cycles
                    134:  */
1.1.1.3   root      135: 
1.1.1.8   root      136: static void Blitter_AddCycles(int cycles)
1.1.1.4   root      137: {
1.1.1.8   root      138:        int all_cycles = cycles + nWaitStateCycles;
1.1.1.4   root      139: 
1.1.1.9   root      140:        BlitterVars.op_cycles += all_cycles;
1.1.1.4   root      141: 
1.1.1.9   root      142:        nCyclesMainCounter += all_cycles >> nCpuFreqShift;
1.1.1.8   root      143:        nWaitStateCycles = 0;
1.1.1.9   root      144: }
                    145: 
                    146: static void Blitter_FlushCycles(void)
                    147: {
                    148:        int op_cycles = INT_CONVERT_TO_INTERNAL(BlitterVars.op_cycles, INT_CPU_CYCLE);
                    149: 
                    150:        BlitterVars.pass_cycles += BlitterVars.op_cycles;
                    151:        BlitterVars.op_cycles = 0;
1.1.1.8   root      152: 
1.1.1.9   root      153:        PendingInterruptCount -= op_cycles;
1.1.1.8   root      154:        while (PendingInterruptCount <= 0 && PendingInterruptFunction)
                    155:                CALL_VAR(PendingInterruptFunction);
1.1       root      156: }
                    157: 
1.1.1.8   root      158: /*-----------------------------------------------------------------------*/
                    159: /**
                    160:  * Read & Write operations
                    161:  */
                    162: static Uint16 Blitter_ReadWord(Uint32 addr)
1.1.1.7   root      163: {
1.1.1.8   root      164:        Uint16 value;
1.1       root      165: 
1.1.1.8   root      166:        if (addr < 0x00ff8000)
                    167:                value = STMemory_ReadWord(addr);
                    168:        else
1.1.1.9   root      169:                value = (Uint16)(IoMem_wget(addr));
1.1.1.7   root      170: 
1.1.1.8   root      171:        Blitter_AddCycles(4);
1.1.1.7   root      172: 
1.1.1.8   root      173:        return value;
                    174: }
                    175: 
                    176: static void Blitter_WriteWord(Uint32 addr, Uint16 value)
                    177: {
                    178:        if (addr < 0x00ff8000)
                    179:                STMemory_WriteWord(addr, value);
                    180:        else
                    181:                IoMem_wput(addr, (Uint32)(value));
1.1.1.7   root      182: 
1.1.1.8   root      183:        Blitter_AddCycles(4);
1.1.1.7   root      184: }
                    185: 
1.1.1.8   root      186: /*-----------------------------------------------------------------------*/
1.1.1.7   root      187: /**
1.1.1.8   root      188:  * Blitter emulation - level 1
1.1.1.7   root      189:  */
1.1.1.8   root      190: 
                    191: static void Blitter_BeginLine(void)
1.1.1.7   root      192: {
1.1.1.8   root      193:        BlitterVars.src_words = BlitterVars.src_words_reset;
                    194: }
1.1.1.7   root      195: 
1.1.1.8   root      196: static void Blitter_SetState(Uint8 fxsr, Uint8 nfsr, Uint16 end_mask)
                    197: {
                    198:        BlitterState.end_mask = end_mask;
                    199:        BlitterState.have_src = false;
                    200:        BlitterState.have_dst = false;
                    201:        BlitterState.fxsr = fxsr;
                    202:        BlitterState.nfsr = nfsr;
                    203: }
                    204: 
                    205: static void Blitter_SourceShift(void)
                    206: {
                    207:        if (BlitterRegs.src_x_incr < 0)
                    208:                BlitterVars.buffer >>= 16;
                    209:        else
                    210:                BlitterVars.buffer <<= 16;
                    211: }
                    212: 
                    213: static void Blitter_SourceFetch(void)
                    214: {
                    215:        Uint32 src_word = (Uint32)Blitter_ReadWord(BlitterRegs.src_addr);
                    216: 
                    217:        if (BlitterRegs.src_x_incr < 0)
                    218:                BlitterVars.buffer |= src_word << 16;
                    219:        else
                    220:                BlitterVars.buffer |= src_word;
                    221: 
                    222:        if (BlitterVars.src_words == 1)
1.1.1.7   root      223:        {
1.1.1.8   root      224:                BlitterRegs.src_addr += BlitterRegs.src_y_incr;
                    225:        }
                    226:        else
                    227:        {
                    228:                --BlitterVars.src_words;
                    229:                BlitterRegs.src_addr += BlitterRegs.src_x_incr;
1.1.1.7   root      230:        }
                    231: }
                    232: 
1.1.1.8   root      233: static Uint16 Blitter_SourceRead(void)
                    234: {
                    235:        if (!BlitterState.have_src)
                    236:        {
                    237:                if (BlitterState.fxsr)
                    238:                {
                    239:                        Blitter_SourceShift();
                    240:                        Blitter_SourceFetch();
                    241:                }
1.1.1.7   root      242: 
1.1.1.8   root      243:                Blitter_SourceShift();
1.1.1.7   root      244: 
1.1.1.8   root      245:                if (!BlitterState.nfsr)
                    246:                {
                    247:                        Blitter_SourceFetch();
                    248:                }
1.1.1.7   root      249: 
1.1.1.8   root      250:                BlitterState.src_word = (Uint16)(BlitterVars.buffer >> BlitterVars.skew);
                    251:                BlitterState.have_src = true;
1.1.1.7   root      252:        }
1.1       root      253: 
1.1.1.8   root      254:        return BlitterState.src_word;
                    255: }
1.1       root      256: 
1.1.1.8   root      257: static Uint16 Blitter_GetHalftoneWord(void)
                    258: {
                    259:        if (BlitterVars.smudge)
                    260:                return BlitterHalftone[Blitter_SourceRead() & 15];
                    261:        else
                    262:                return BlitterHalftone[BlitterVars.line];
                    263: }
1.1.1.4   root      264: 
1.1.1.9   root      265: /* HOP */
                    266: 
                    267: static Uint16 Blitter_HOP_0(void)
1.1       root      268: {
1.1.1.9   root      269:        return 0xFFFF;
                    270: }
1.1.1.7   root      271: 
1.1.1.9   root      272: static Uint16 Blitter_HOP_1(void)
                    273: {
                    274:        return Blitter_GetHalftoneWord();
                    275: }
                    276: 
                    277: static Uint16 Blitter_HOP_2(void)
                    278: {
                    279:        return Blitter_SourceRead();
                    280: }
1.1.1.8   root      281: 
1.1.1.9   root      282: static Uint16 Blitter_HOP_3(void)
                    283: {
                    284:        return Blitter_SourceRead() & Blitter_GetHalftoneWord();
1.1.1.8   root      285: }
                    286: 
1.1.1.9   root      287: static BLITTER_OP_FUNC Blitter_HOP_Table [4] =
                    288: {
                    289:        Blitter_HOP_0,
                    290:        Blitter_HOP_1,
                    291:        Blitter_HOP_2,
                    292:        Blitter_HOP_3
                    293: };
                    294: 
                    295: static void Blitter_Select_HOP(void)
                    296: {
                    297:        Blitter_ComputeHOP = Blitter_HOP_Table[BlitterRegs.hop];
                    298: }
                    299: 
                    300: /* end HOP */
                    301: 
1.1.1.8   root      302: static Uint16 Blitter_DestRead(void)
                    303: {
                    304:        if (!BlitterState.have_dst)
                    305:        {
                    306:                BlitterState.dst_word = Blitter_ReadWord(BlitterRegs.dst_addr);
                    307:                BlitterState.have_dst = true;
                    308:        }
                    309: 
                    310:        return BlitterState.dst_word;
                    311: }
                    312: 
1.1.1.9   root      313: /* LOP */
                    314: 
                    315: static Uint16 Blitter_LOP_0(void)
                    316: {
                    317:        return 0;
                    318: }
                    319: 
                    320: static Uint16 Blitter_LOP_1(void)
1.1.1.8   root      321: {
1.1.1.9   root      322:        return Blitter_ComputeHOP() & Blitter_DestRead();
                    323: }
1.1.1.8   root      324: 
1.1.1.9   root      325: static Uint16 Blitter_LOP_2(void)
                    326: {
                    327:        return Blitter_ComputeHOP() & ~Blitter_DestRead();
                    328: }
                    329: 
                    330: static Uint16 Blitter_LOP_3(void)
                    331: {
                    332:        return Blitter_ComputeHOP();
                    333: }
                    334: 
                    335: static Uint16 Blitter_LOP_4(void)
                    336: {
                    337:        return ~Blitter_ComputeHOP() & Blitter_DestRead();
                    338: }
                    339: 
                    340: static Uint16 Blitter_LOP_5(void)
                    341: {
                    342:        return Blitter_DestRead();
                    343: }
                    344: 
                    345: static Uint16 Blitter_LOP_6(void)
                    346: {
                    347:        return Blitter_ComputeHOP() ^ Blitter_DestRead();
                    348: }
                    349: 
                    350: static Uint16 Blitter_LOP_7(void)
                    351: {
                    352:        return Blitter_ComputeHOP() | Blitter_DestRead();
                    353: }
                    354: 
                    355: static Uint16 Blitter_LOP_8(void)
                    356: {
                    357:        return ~Blitter_ComputeHOP() & ~Blitter_DestRead();
                    358: }
                    359: 
                    360: static Uint16 Blitter_LOP_9(void)
                    361: {
                    362:        return ~Blitter_ComputeHOP() ^ Blitter_DestRead();
                    363: }
                    364: 
                    365: static Uint16 Blitter_LOP_A(void)
                    366: {
                    367:        return ~Blitter_DestRead();
                    368: }
1.1.1.8   root      369: 
1.1.1.9   root      370: static Uint16 Blitter_LOP_B(void)
                    371: {
                    372:        return Blitter_ComputeHOP() | ~Blitter_DestRead();
1.1.1.8   root      373: }
                    374: 
1.1.1.9   root      375: static Uint16 Blitter_LOP_C(void)
                    376: {
                    377:        return ~Blitter_ComputeHOP();
                    378: }
                    379: 
                    380: static Uint16 Blitter_LOP_D(void)
                    381: {
                    382:        return ~Blitter_ComputeHOP() | Blitter_DestRead();
                    383: }
                    384: 
                    385: static Uint16 Blitter_LOP_E(void)
                    386: {
                    387:        return ~Blitter_ComputeHOP() | ~Blitter_DestRead();
                    388: }
                    389: 
                    390: static Uint16 Blitter_LOP_F(void)
                    391: {
                    392:        return 0xFFFF;
                    393: }
                    394: 
                    395: static BLITTER_OP_FUNC Blitter_LOP_Table [16] =
                    396: {
                    397:        Blitter_LOP_0,
                    398:        Blitter_LOP_1,
                    399:        Blitter_LOP_2,
                    400:        Blitter_LOP_3,
                    401:        Blitter_LOP_4,
                    402:        Blitter_LOP_5,
                    403:        Blitter_LOP_6,
                    404:        Blitter_LOP_7,
                    405:        Blitter_LOP_8,
                    406:        Blitter_LOP_9,
                    407:        Blitter_LOP_A,
                    408:        Blitter_LOP_B,
                    409:        Blitter_LOP_C,
                    410:        Blitter_LOP_D,
                    411:        Blitter_LOP_E,
                    412:        Blitter_LOP_F
                    413: };
                    414: 
                    415: static void Blitter_Select_LOP(void)
                    416: {
                    417:        Blitter_ComputeLOP = Blitter_LOP_Table[BlitterRegs.lop];
                    418: }
                    419: 
                    420: /* end LOP */
                    421: 
1.1.1.8   root      422: static Uint16 Blitter_ComputeMask(void)
                    423: {
                    424:        return (Blitter_ComputeLOP() & BlitterState.end_mask) |
                    425:                        (Blitter_DestRead() & ~BlitterState.end_mask);
                    426: }
                    427: 
                    428: static void Blitter_ProcessWord(void)
                    429: {
                    430:        /* when NFSR, a read-modify-write is always performed */
                    431:        Uint16 dst_data = ((BlitterState.nfsr || BlitterState.end_mask != 0xFFFF)
                    432:                                                        ? Blitter_ComputeMask()
                    433:                                                        : Blitter_ComputeLOP());
                    434: 
                    435:        Blitter_WriteWord(BlitterRegs.dst_addr, dst_data);
1.1       root      436: 
1.1.1.8   root      437:        if (BlitterRegs.words == 1)
1.1.1.7   root      438:        {
1.1.1.8   root      439:                BlitterRegs.dst_addr += BlitterRegs.dst_y_incr;
1.1.1.7   root      440:        }
1.1.1.8   root      441:        else
1.1.1.7   root      442:        {
1.1.1.8   root      443:                --BlitterRegs.words;
                    444:                BlitterRegs.dst_addr += BlitterRegs.dst_x_incr;
1.1.1.7   root      445:        }
1.1.1.8   root      446: }
                    447: 
                    448: static void Blitter_EndLine(void)
                    449: {
                    450:        --BlitterRegs.lines;
                    451:        BlitterRegs.words = BlitterVars.dst_words_reset;
1.1.1.7   root      452: 
1.1.1.8   root      453:        if (BlitterRegs.dst_y_incr >= 0)
                    454:                BlitterVars.line = (BlitterVars.line+1) & 15;
1.1.1.7   root      455:        else
1.1.1.8   root      456:                BlitterVars.line = (BlitterVars.line-1) & 15;
                    457: }
                    458: 
                    459: /*-----------------------------------------------------------------------*/
                    460: /**
                    461:  * Blitter emulation - level 2
                    462:  */
                    463: 
                    464: static void Blitter_SingleWord(void)
                    465: {
                    466:        Blitter_BeginLine();
                    467:        Blitter_SetState(BlitterVars.fxsr, BlitterVars.nfsr, BlitterRegs.end_mask_1);
                    468:        Blitter_ProcessWord();
                    469:        Blitter_EndLine();
                    470: }
                    471: 
                    472: static void Blitter_FirstWord(void)
                    473: {
                    474:        Blitter_BeginLine();
                    475:        Blitter_SetState(BlitterVars.fxsr, 0, BlitterRegs.end_mask_1);
                    476:        Blitter_ProcessWord();
                    477: }
                    478: 
                    479: static void Blitter_MiddleWord(void)
                    480: {
                    481:        Blitter_SetState(0, 0, BlitterRegs.end_mask_2);
                    482:        Blitter_ProcessWord();
                    483: }
1.1.1.7   root      484: 
1.1.1.8   root      485: static void Blitter_LastWord(void)
                    486: {
                    487:        Blitter_SetState(0, BlitterVars.nfsr, BlitterRegs.end_mask_3);
                    488:        Blitter_ProcessWord();
                    489:        Blitter_EndLine();
1.1.1.7   root      490: }
1.1       root      491: 
1.1.1.8   root      492: static void Blitter_Step(void)
                    493: {
                    494:        if (BlitterVars.dst_words_reset == 1)
                    495:        {
                    496:                Blitter_SingleWord();
                    497:        }
                    498:        else if (BlitterRegs.words == BlitterVars.dst_words_reset)
                    499:        {
                    500:                Blitter_FirstWord();
                    501:        }
                    502:        else if (BlitterRegs.words == 1)
                    503:        {
                    504:                Blitter_LastWord();
                    505:        }
                    506:        else
                    507:        {
                    508:                Blitter_MiddleWord();
                    509:        }
                    510: }
1.1       root      511: 
1.1.1.3   root      512: /*-----------------------------------------------------------------------*/
1.1.1.5   root      513: /**
1.1.1.7   root      514:  * Let's do the blit.
                    515:  * Note that in non-HOG mode, the blitter only runs for 64 bus cycles (2 MHz!)
                    516:  * before giving the bus back to the CPU. Due to this mode, this function must
                    517:  * be able to abort and resume the blitting at any time.
1.1.1.5   root      518:  */
1.1.1.8   root      519: static void Blitter_Start(void)
1.1.1.4   root      520: {
1.1.1.9   root      521:        /* select HOP & LOP funcs */
                    522:        Blitter_Select_HOP();
                    523:        Blitter_Select_LOP();
                    524: 
1.1.1.8   root      525:        /* setup vars */
1.1.1.9   root      526:        BlitterVars.pass_cycles = 0;
                    527:        BlitterVars.op_cycles = 0;
1.1.1.12  root      528:        BlitterVars.src_words_reset = BlitterVars.dst_words_reset + BlitterVars.fxsr - BlitterVars.nfsr;
1.1.1.8   root      529: 
                    530:        /* bus arbitration */
                    531:        BusMode = BUS_MODE_BLITTER;             /* bus is now owned by the blitter */
                    532:        Blitter_AddCycles(4);
1.1.1.9   root      533:        Blitter_FlushCycles();
1.1.1.7   root      534: 
                    535:        /* Now we enter the main blitting loop */
                    536:        do
                    537:        {
1.1.1.8   root      538:                Blitter_Step();
1.1.1.9   root      539:                Blitter_FlushCycles();
1.1.1.8   root      540:        }
                    541:        while (BlitterRegs.lines > 0
1.1.1.9   root      542:               && (BlitterVars.hog || BlitterVars.pass_cycles < NONHOG_CYCLES));
1.1.1.7   root      543: 
1.1.1.8   root      544:        /* bus arbitration */
                    545:        Blitter_AddCycles(4);
1.1.1.9   root      546:        Blitter_FlushCycles();
1.1.1.8   root      547:        BusMode = BUS_MODE_CPU;                 /* bus is now owned by the cpu again */
1.1.1.7   root      548: 
1.1.1.8   root      549:        BlitterRegs.ctrl = (BlitterRegs.ctrl & 0xF0) | BlitterVars.line;
1.1.1.7   root      550: 
1.1.1.8   root      551:        if (BlitterRegs.lines == 0)
                    552:        {
                    553:                /* We're done, clear busy bit */
                    554:                BlitterRegs.ctrl &= ~0x80;
1.1.1.7   root      555: 
1.1.1.8   root      556:                /* Blitter done interrupt */
1.1.1.12  root      557:                MFP_InputOnChannel ( MFP_INT_GPU_DONE , 0 );
1.1.1.7   root      558:        }
1.1.1.8   root      559:        else
1.1.1.7   root      560:        {
1.1.1.8   root      561:                /* Continue blitting later */
1.1.1.10  root      562:                CycInt_AddRelativeInterrupt(NONHOG_CYCLES, INT_CPU_CYCLE, INTERRUPT_BLITTER);
1.1.1.7   root      563:        }
                    564: }
                    565: 
1.1.1.8   root      566: /*-----------------------------------------------------------------------*/
                    567: /**
                    568:  * Read blitter halftone ram.
                    569:  */
                    570: static void Blitter_Halftone_ReadWord(int index)
                    571: {
                    572:        IoMem_WriteWord(REG_HT_RAM + index + index, BlitterHalftone[index]);
                    573: }
                    574: 
                    575: void Blitter_Halftone00_ReadWord(void) { Blitter_Halftone_ReadWord(0); }
                    576: void Blitter_Halftone01_ReadWord(void) { Blitter_Halftone_ReadWord(1); }
                    577: void Blitter_Halftone02_ReadWord(void) { Blitter_Halftone_ReadWord(2); }
                    578: void Blitter_Halftone03_ReadWord(void) { Blitter_Halftone_ReadWord(3); }
                    579: void Blitter_Halftone04_ReadWord(void) { Blitter_Halftone_ReadWord(4); }
                    580: void Blitter_Halftone05_ReadWord(void) { Blitter_Halftone_ReadWord(5); }
                    581: void Blitter_Halftone06_ReadWord(void) { Blitter_Halftone_ReadWord(6); }
                    582: void Blitter_Halftone07_ReadWord(void) { Blitter_Halftone_ReadWord(7); }
                    583: void Blitter_Halftone08_ReadWord(void) { Blitter_Halftone_ReadWord(8); }
                    584: void Blitter_Halftone09_ReadWord(void) { Blitter_Halftone_ReadWord(9); }
                    585: void Blitter_Halftone10_ReadWord(void) { Blitter_Halftone_ReadWord(10); }
                    586: void Blitter_Halftone11_ReadWord(void) { Blitter_Halftone_ReadWord(11); }
                    587: void Blitter_Halftone12_ReadWord(void) { Blitter_Halftone_ReadWord(12); }
                    588: void Blitter_Halftone13_ReadWord(void) { Blitter_Halftone_ReadWord(13); }
                    589: void Blitter_Halftone14_ReadWord(void) { Blitter_Halftone_ReadWord(14); }
                    590: void Blitter_Halftone15_ReadWord(void) { Blitter_Halftone_ReadWord(15); }
                    591: 
                    592: /*-----------------------------------------------------------------------*/
                    593: /**
                    594:  * Read blitter source x increment (0xff8a20).
                    595:  */
                    596: void Blitter_SourceXInc_ReadWord(void)
                    597: {
                    598:        IoMem_WriteWord(REG_SRC_X_INC, (Uint16)(BlitterRegs.src_x_incr));
                    599: }
                    600: 
                    601: /*-----------------------------------------------------------------------*/
                    602: /**
                    603:  * Read blitter source y increment (0xff8a22).
                    604:  */
                    605: void Blitter_SourceYInc_ReadWord(void)
                    606: {
                    607:        IoMem_WriteWord(REG_SRC_Y_INC, (Uint16)(BlitterRegs.src_y_incr));
                    608: }
1.1.1.7   root      609: 
                    610: /*-----------------------------------------------------------------------*/
                    611: /**
                    612:  * Read blitter source address (0xff8a24).
                    613:  */
                    614: void Blitter_SourceAddr_ReadLong(void)
                    615: {
1.1.1.8   root      616:        IoMem_WriteLong(REG_SRC_ADDR, BlitterRegs.src_addr);
1.1.1.4   root      617: }
                    618: 
                    619: /*-----------------------------------------------------------------------*/
1.1.1.5   root      620: /**
                    621:  * Read blitter endmask 1.
                    622:  */
1.1.1.3   root      623: void Blitter_Endmask1_ReadWord(void)
1.1       root      624: {
1.1.1.8   root      625:        IoMem_WriteWord(REG_END_MASK1, BlitterRegs.end_mask_1);
1.1       root      626: }
                    627: 
1.1.1.3   root      628: /*-----------------------------------------------------------------------*/
1.1.1.5   root      629: /**
                    630:  * Read blitter endmask 2.
                    631:  */
1.1.1.3   root      632: void Blitter_Endmask2_ReadWord(void)
1.1       root      633: {
1.1.1.8   root      634:        IoMem_WriteWord(REG_END_MASK2, BlitterRegs.end_mask_2);
1.1       root      635: }
                    636: 
1.1.1.3   root      637: /*-----------------------------------------------------------------------*/
1.1.1.5   root      638: /**
                    639:  * Read blitter endmask 3.
                    640:  */
1.1.1.3   root      641: void Blitter_Endmask3_ReadWord(void)
1.1       root      642: {
1.1.1.8   root      643:        IoMem_WriteWord(REG_END_MASK3, BlitterRegs.end_mask_3);
                    644: }
                    645: 
                    646: /*-----------------------------------------------------------------------*/
                    647: /**
                    648:  * Read blitter destination x increment (0xff8a2E).
                    649:  */
                    650: void Blitter_DestXInc_ReadWord(void)
                    651: {
                    652:        IoMem_WriteWord(REG_DST_X_INC, (Uint16)(BlitterRegs.dst_x_incr));
                    653: }
                    654: 
                    655: /*-----------------------------------------------------------------------*/
                    656: /**
                    657:  * Read blitter destination y increment (0xff8a30).
                    658:  */
                    659: void Blitter_DestYInc_ReadWord(void)
                    660: {
                    661:        IoMem_WriteWord(REG_DST_Y_INC, (Uint16)(BlitterRegs.dst_y_incr));
1.1       root      662: }
                    663: 
1.1.1.3   root      664: /*-----------------------------------------------------------------------*/
1.1.1.5   root      665: /**
                    666:  * Read blitter destination address.
                    667:  */
1.1.1.3   root      668: void Blitter_DestAddr_ReadLong(void)
1.1       root      669: {
1.1.1.8   root      670:        IoMem_WriteLong(REG_DST_ADDR, BlitterRegs.dst_addr);
1.1       root      671: }
                    672: 
1.1.1.3   root      673: /*-----------------------------------------------------------------------*/
1.1.1.5   root      674: /**
                    675:  * Read blitter words-per-line register.
                    676:  */
1.1.1.3   root      677: void Blitter_WordsPerLine_ReadWord(void)
1.1       root      678: {
1.1.1.8   root      679:        IoMem_WriteWord(REG_X_COUNT, (Uint16)(BlitterRegs.words & 0xFFFF));
1.1       root      680: }
                    681: 
1.1.1.3   root      682: /*-----------------------------------------------------------------------*/
1.1.1.5   root      683: /**
                    684:  * Read blitter lines-per-bitblock register.
                    685:  */
1.1.1.3   root      686: void Blitter_LinesPerBitblock_ReadWord(void)
1.1       root      687: {
1.1.1.8   root      688:        IoMem_WriteWord(REG_Y_COUNT, (Uint16)(BlitterRegs.lines & 0xFFFF));
1.1       root      689: }
                    690: 
1.1.1.3   root      691: /*-----------------------------------------------------------------------*/
1.1.1.5   root      692: /**
                    693:  * Read blitter halftone operation register.
                    694:  */
1.1.1.3   root      695: void Blitter_HalftoneOp_ReadByte(void)
1.1       root      696: {
1.1.1.8   root      697:        IoMem_WriteByte(REG_BLIT_HOP, BlitterRegs.hop);
1.1       root      698: }
                    699: 
1.1.1.3   root      700: /*-----------------------------------------------------------------------*/
1.1.1.5   root      701: /**
                    702:  * Read blitter logical operation register.
                    703:  */
1.1.1.3   root      704: void Blitter_LogOp_ReadByte(void)
1.1       root      705: {
1.1.1.8   root      706:        IoMem_WriteByte(REG_BLIT_LOP, BlitterRegs.lop);
1.1       root      707: }
                    708: 
1.1.1.3   root      709: /*-----------------------------------------------------------------------*/
1.1.1.5   root      710: /**
                    711:  * Read blitter control register.
                    712:  */
1.1.1.4   root      713: void Blitter_Control_ReadByte(void)
1.1       root      714: {
1.1.1.7   root      715:        /* busy, hog/blit, smudge, n/a, 4bits for line number */
1.1.1.8   root      716:        IoMem_WriteByte(REG_CONTROL, BlitterRegs.ctrl);
1.1       root      717: }
                    718: 
1.1.1.3   root      719: /*-----------------------------------------------------------------------*/
1.1.1.5   root      720: /**
                    721:  * Read blitter skew register.
                    722:  */
1.1.1.3   root      723: void Blitter_Skew_ReadByte(void)
1.1       root      724: {
1.1.1.8   root      725:        IoMem_WriteByte(REG_SKEW, BlitterRegs.skew);
                    726: }
                    727: 
                    728: 
                    729: /*-----------------------------------------------------------------------*/
                    730: /**
                    731:  * Write to blitter halftone ram.
                    732:  */
                    733: static void Blitter_Halftone_WriteWord(int index)
                    734: {
                    735:        BlitterHalftone[index] = IoMem_ReadWord(REG_HT_RAM + index + index);
                    736: }
                    737: 
                    738: void Blitter_Halftone00_WriteWord(void) { Blitter_Halftone_WriteWord(0); }
                    739: void Blitter_Halftone01_WriteWord(void) { Blitter_Halftone_WriteWord(1); }
                    740: void Blitter_Halftone02_WriteWord(void) { Blitter_Halftone_WriteWord(2); }
                    741: void Blitter_Halftone03_WriteWord(void) { Blitter_Halftone_WriteWord(3); }
                    742: void Blitter_Halftone04_WriteWord(void) { Blitter_Halftone_WriteWord(4); }
                    743: void Blitter_Halftone05_WriteWord(void) { Blitter_Halftone_WriteWord(5); }
                    744: void Blitter_Halftone06_WriteWord(void) { Blitter_Halftone_WriteWord(6); }
                    745: void Blitter_Halftone07_WriteWord(void) { Blitter_Halftone_WriteWord(7); }
                    746: void Blitter_Halftone08_WriteWord(void) { Blitter_Halftone_WriteWord(8); }
                    747: void Blitter_Halftone09_WriteWord(void) { Blitter_Halftone_WriteWord(9); }
                    748: void Blitter_Halftone10_WriteWord(void) { Blitter_Halftone_WriteWord(10); }
                    749: void Blitter_Halftone11_WriteWord(void) { Blitter_Halftone_WriteWord(11); }
                    750: void Blitter_Halftone12_WriteWord(void) { Blitter_Halftone_WriteWord(12); }
                    751: void Blitter_Halftone13_WriteWord(void) { Blitter_Halftone_WriteWord(13); }
                    752: void Blitter_Halftone14_WriteWord(void) { Blitter_Halftone_WriteWord(14); }
                    753: void Blitter_Halftone15_WriteWord(void) { Blitter_Halftone_WriteWord(15); }
                    754: 
                    755: /*-----------------------------------------------------------------------*/
                    756: /**
                    757:  * Write to blitter source x increment.
                    758:  */
                    759: void Blitter_SourceXInc_WriteWord(void)
                    760: {
                    761:        BlitterRegs.src_x_incr = (short)(IoMem_ReadWord(REG_SRC_X_INC) & 0xFFFE);
1.1       root      762: }
                    763: 
1.1.1.8   root      764: /*-----------------------------------------------------------------------*/
                    765: /**
                    766:  * Write to blitter source y increment.
                    767:  */
                    768: void Blitter_SourceYInc_WriteWord(void)
                    769: {
                    770:        BlitterRegs.src_y_incr = (short)(IoMem_ReadWord(REG_SRC_Y_INC) & 0xFFFE);
                    771: }
1.1       root      772: 
1.1.1.3   root      773: /*-----------------------------------------------------------------------*/
1.1.1.5   root      774: /**
1.1.1.7   root      775:  * Write to blitter source address register (0xff8a24).
                    776:  */
                    777: void Blitter_SourceAddr_WriteLong(void)
                    778: {
1.1.1.8   root      779:        BlitterRegs.src_addr = IoMem_ReadLong(REG_SRC_ADDR) & 0xFFFFFE;
1.1.1.7   root      780: }
                    781: 
                    782: /*-----------------------------------------------------------------------*/
                    783: /**
1.1.1.5   root      784:  * Write to blitter endmask 1.
                    785:  */
1.1.1.3   root      786: void Blitter_Endmask1_WriteWord(void)
1.1       root      787: {
1.1.1.8   root      788:        BlitterRegs.end_mask_1 = IoMem_ReadWord(REG_END_MASK1);
1.1       root      789: }
                    790: 
1.1.1.3   root      791: /*-----------------------------------------------------------------------*/
1.1.1.5   root      792: /**
                    793:  * Write to blitter endmask 2.
                    794:  */
1.1.1.3   root      795: void Blitter_Endmask2_WriteWord(void)
1.1       root      796: {
1.1.1.8   root      797:        BlitterRegs.end_mask_2 = IoMem_ReadWord(REG_END_MASK2);
1.1       root      798: }
                    799: 
1.1.1.3   root      800: /*-----------------------------------------------------------------------*/
1.1.1.5   root      801: /**
                    802:  * Write to blitter endmask 3.
                    803:  */
1.1.1.3   root      804: void Blitter_Endmask3_WriteWord(void)
1.1       root      805: {
1.1.1.8   root      806:        BlitterRegs.end_mask_3 = IoMem_ReadWord(REG_END_MASK3);
                    807: }
                    808: 
                    809: /*-----------------------------------------------------------------------*/
                    810: /**
                    811:  * Write to blitter destination x increment.
                    812:  */
                    813: void Blitter_DestXInc_WriteWord(void)
                    814: {
                    815:        BlitterRegs.dst_x_incr = (short)(IoMem_ReadWord(REG_DST_X_INC) & 0xFFFE);
                    816: }
                    817: 
                    818: /*-----------------------------------------------------------------------*/
                    819: /**
                    820:  * Write to blitter source y increment.
                    821:  */
                    822: void Blitter_DestYInc_WriteWord(void)
                    823: {
                    824:        BlitterRegs.dst_y_incr = (short)(IoMem_ReadWord(REG_DST_Y_INC) & 0xFFFE);
1.1       root      825: }
                    826: 
1.1.1.3   root      827: /*-----------------------------------------------------------------------*/
1.1.1.5   root      828: /**
                    829:  * Write to blitter destination address register.
                    830:  */
1.1.1.3   root      831: void Blitter_DestAddr_WriteLong(void)
                    832: {
1.1.1.8   root      833:        BlitterRegs.dst_addr = IoMem_ReadLong(REG_DST_ADDR) & 0xFFFFFE;
1.1       root      834: }
                    835: 
1.1.1.3   root      836: /*-----------------------------------------------------------------------*/
1.1.1.5   root      837: /**
                    838:  * Write to blitter words-per-line register.
                    839:  */
1.1.1.3   root      840: void Blitter_WordsPerLine_WriteWord(void)
1.1       root      841: {
1.1.1.8   root      842:        Uint32 words = (Uint32)IoMem_ReadWord(REG_X_COUNT);
                    843: 
                    844:        if (words == 0)
                    845:                words = 65536;
                    846: 
                    847:        BlitterRegs.words = words;
                    848:        BlitterVars.dst_words_reset = words;
1.1       root      849: }
                    850: 
1.1.1.3   root      851: /*-----------------------------------------------------------------------*/
1.1.1.5   root      852: /**
1.1.1.8   root      853:  * Write to blitter lines-per-bitblock register.
1.1.1.5   root      854:  */
1.1.1.3   root      855: void Blitter_LinesPerBitblock_WriteWord(void)
1.1       root      856: {
1.1.1.8   root      857:        Uint32 lines = (Uint32)IoMem_ReadWord(REG_Y_COUNT);
                    858: 
                    859:        if (lines == 0)
                    860:                lines = 65536;
                    861: 
                    862:        BlitterRegs.lines = lines;
1.1       root      863: }
                    864: 
1.1.1.3   root      865: /*-----------------------------------------------------------------------*/
1.1.1.5   root      866: /**
                    867:  * Write to blitter halftone operation register.
                    868:  */
1.1.1.3   root      869: void Blitter_HalftoneOp_WriteByte(void)
1.1       root      870: {
1.1.1.4   root      871:        /* h/ware reg masks out the top 6 bits! */
1.1.1.8   root      872:        BlitterRegs.hop = IoMem_ReadByte(REG_BLIT_HOP) & 3;
1.1       root      873: }
                    874: 
1.1.1.3   root      875: /*-----------------------------------------------------------------------*/
1.1.1.5   root      876: /**
                    877:  * Write to blitter logical operation register.
                    878:  */
1.1.1.3   root      879: void Blitter_LogOp_WriteByte(void)
1.1.1.7   root      880: {
1.1.1.4   root      881:        /* h/ware reg masks out the top 4 bits! */
1.1.1.8   root      882:        BlitterRegs.lop = IoMem_ReadByte(REG_BLIT_LOP) & 0xF;
1.1       root      883: }
                    884: 
1.1.1.3   root      885: /*-----------------------------------------------------------------------*/
1.1.1.5   root      886: /**
                    887:  * Write to blitter control register.
                    888:  */
1.1.1.4   root      889: void Blitter_Control_WriteByte(void)
                    890: {
                    891:        /* Control register bits:
                    892:         * 0x80: busy bit
                    893:         * - Turn on Blitter activity and stay "1" until copy finished
                    894:         * 0x40: Blit-mode bit
                    895:         * - 0: Blit mode, CPU and Blitter get 64 clockcycles in turns
                    896:         * - 1: HOG Mode, Blitter reserves and hogs the bus for as long
                    897:         *      as the copy takes, CPU and DMA get no Bus access
                    898:         * 0x20: Smudge mode
                    899:         * - Which line of the halftone pattern to start with is
                    900:         *   read from the first source word when the copy starts
                    901:         * 0x10: not used
                    902:         * 0x0f
                    903:         *
                    904:         * The lowest 4 bits contain the Halftone pattern line number
                    905:         */
1.1.1.7   root      906: 
1.1.1.9   root      907:        if (LOG_TRACE_LEVEL(TRACE_BLITTER))
1.1.1.3   root      908:        {
1.1.1.9   root      909:                int FrameCycles, HblCounterVideo, LineCycles;
                    910: 
                    911:                Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    912: 
                    913:                LOG_TRACE_PRINT("blitter write ctrl=%x video_cyc=%d %d@%d pc=%x instr_cyc=%d\n" ,
1.1.1.7   root      914:                                IoMem_ReadByte(REG_CONTROL) ,
1.1.1.9   root      915:                                FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles );
1.1.1.7   root      916:        }
1.1.1.3   root      917: 
1.1.1.8   root      918:        BlitterRegs.ctrl = IoMem_ReadByte(REG_CONTROL) & 0xEF;
                    919: 
                    920:        BlitterVars.hog = BlitterRegs.ctrl & 0x40;
                    921:        BlitterVars.smudge = BlitterRegs.ctrl & 0x20;
                    922:        BlitterVars.line = BlitterRegs.ctrl & 0xF;
1.1.1.7   root      923: 
                    924:        /* Remove old pending update interrupt */
1.1.1.10  root      925:        CycInt_RemovePendingInterrupt(INTERRUPT_BLITTER);
1.1.1.7   root      926: 
                    927:        /* Busy bit set? */
1.1.1.8   root      928:        if (BlitterRegs.ctrl & 0x80)
1.1.1.7   root      929:        {
1.1.1.8   root      930:                if (BlitterRegs.lines == 0)
1.1.1.7   root      931:                {
                    932:                        /* We're done, clear busy bit */
1.1.1.8   root      933:                        BlitterRegs.ctrl &= ~0x80;
1.1.1.7   root      934:                }
                    935:                else
                    936:                {
                    937:                        /* Start blitting after some CPU cycles */
1.1.1.10  root      938:                        CycInt_AddRelativeInterrupt((CurrentInstrCycles+nWaitStateCycles)>>nCpuFreqShift,
                    939:                                                         INT_CPU_CYCLE, INTERRUPT_BLITTER);
1.1.1.7   root      940:                }
1.1.1.3   root      941:        }
1.1       root      942: }
                    943: 
1.1.1.3   root      944: /*-----------------------------------------------------------------------*/
1.1.1.5   root      945: /**
                    946:  * Write to blitter skew register.
                    947:  */
1.1.1.3   root      948: void Blitter_Skew_WriteByte(void)
                    949: {
1.1.1.8   root      950:        BlitterRegs.skew = IoMem_ReadByte(REG_SKEW);
                    951:        BlitterVars.fxsr = (BlitterRegs.skew & 0x80)?1:0;
                    952:        BlitterVars.nfsr = (BlitterRegs.skew & 0x40)?1:0;
                    953:        BlitterVars.skew = BlitterRegs.skew & 0xF;
1.1       root      954: }
1.1.1.2   root      955: 
                    956: 
                    957: /*-----------------------------------------------------------------------*/
1.1.1.5   root      958: /**
1.1.1.7   root      959:  * Handler which continues blitting after 64 bus cycles.
                    960:  */
                    961: void Blitter_InterruptHandler(void)
                    962: {
1.1.1.10  root      963:        CycInt_AcknowledgeInterrupt();
1.1.1.7   root      964: 
1.1.1.8   root      965:        if (BlitterRegs.ctrl & 0x80)
1.1.1.7   root      966:        {
1.1.1.8   root      967:                Blitter_Start();
1.1.1.7   root      968:        }
1.1.1.8   root      969: }
1.1.1.7   root      970: 
1.1.1.8   root      971: /*-----------------------------------------------------------------------*/
                    972: /**
                    973:  * Save/Restore snapshot of Blitter variables.
                    974:  */
                    975: void Blitter_MemorySnapShot_Capture(bool bSave)
                    976: {
                    977:        /* Save/Restore details */
                    978:        MemorySnapShot_Store(&BlitterRegs, sizeof(BlitterRegs));
                    979:        MemorySnapShot_Store(&BlitterVars, sizeof(BlitterVars));
                    980:        MemorySnapShot_Store(&BlitterHalftone, sizeof(BlitterHalftone));
1.1.1.2   root      981: }
1.1.1.12  root      982: 
                    983: /*-----------------------------------------------------------------------*/
                    984: /**
                    985:  * Show Blitter register values.
                    986:  */
                    987: void Blitter_Info(Uint32 dummy)
                    988: {
                    989:        BLITTERREGS *regs = &BlitterRegs;
                    990:        FILE *fp = stderr;
                    991: 
                    992:        fprintf(fp, "src addr:  0x%06x\n", regs->src_addr);
                    993:        fprintf(fp, "dst addr:  0x%06x\n", regs->dst_addr);
                    994:        fprintf(fp, "words:     %u\n", regs->words);
                    995:        fprintf(fp, "lines:     %u\n", regs->lines);
                    996:        fprintf(fp, "src X-inc: %hd\n", regs->src_x_incr);
                    997:        fprintf(fp, "src Y-inc: %hd\n", regs->src_y_incr);
                    998:        fprintf(fp, "dst X-inc: %hd\n", regs->dst_x_incr);
                    999:        fprintf(fp, "dst Y-inc: %hd\n", regs->dst_y_incr);
                   1000:        fprintf(fp, "end mask1: 0x%04x\n", regs->end_mask_1);
                   1001:        fprintf(fp, "end mask2: 0x%04x\n", regs->end_mask_2);
                   1002:        fprintf(fp, "end mask3: 0x%04x\n", regs->end_mask_3);
                   1003:        fprintf(fp, "HOP:       0x%02x\n", regs->hop);
                   1004:        fprintf(fp, "LOP:       0x%02x\n", regs->lop);
                   1005:        fprintf(fp, "control:   0x%02x\n", regs->ctrl);
                   1006:        fprintf(fp, "skew:      0x%02x\n", regs->skew);
1.1.1.13! root     1007:        fprintf(fp, "Note: internally changed register values aren't visible to breakpoints\nor in memdump output until emulated code reads or writes them!\n");
1.1.1.12  root     1008: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.