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

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

unix.superglobalmegacorp.com

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