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

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       root       12:  */
1.1.1.7 ! root       13: const char Blitter_rcsid[] = "Hatari $Id: blitter.c,v 1.35 2008/11/15 10:00:06 thothy Exp $";
1.1       root       14: 
                     15: #include <SDL_types.h>
                     16: #include <stdio.h>
                     17: #include <stdlib.h>
                     18: 
1.1.1.2   root       19: #include "main.h"
1.1       root       20: #include "blitter.h"
1.1.1.7 ! root       21: #include "configuration.h"
        !            22: #include "dmaSnd.h"
1.1.1.3   root       23: #include "ioMem.h"
                     24: #include "m68000.h"
1.1.1.7 ! root       25: #include "mfp.h"
1.1.1.2   root       26: #include "memorySnapShot.h"
1.1       root       27: #include "stMemory.h"
1.1.1.7 ! root       28: #include "video.h"
        !            29: 
1.1       root       30: 
1.1.1.4   root       31: #define DEBUG 0
1.1       root       32: 
1.1.1.7 ! root       33: #define NONHOG_CYCLES (64*4)    /* Cycles to run for in non-hog mode */
        !            34: 
        !            35: 
1.1.1.4   root       36: /* BLiTTER registers, counts and incs are signed, others unsigned */
                     37: #define REG_HT_RAM     0xff8a00        /* - 0xff8a1e */
1.1       root       38: 
1.1.1.4   root       39: #define REG_SRC_X_INC  0xff8a20
                     40: #define REG_SRC_Y_INC  0xff8a22
                     41: #define REG_SRC_ADDR   0xff8a24
                     42: 
                     43: #define REG_END_MASK1  0xff8a28
                     44: #define REG_END_MASK2  0xff8a2a
                     45: #define REG_END_MASK3  0xff8a2c
                     46: 
                     47: #define REG_DST_X_INC  0xff8a2e
                     48: #define REG_DST_Y_INC  0xff8a30
                     49: #define REG_DST_ADDR   0xff8a32
                     50: 
1.1.1.7 ! root       51: #define REG_X_COUNT    0xff8a36
        !            52: #define REG_Y_COUNT    0xff8a38
1.1.1.4   root       53: 
                     54: #define REG_BLIT_HOP   0xff8a3a        /* halftone blit operation byte */
                     55: #define REG_BLIT_LOP   0xff8a3b        /* logical blit operation byte */
1.1.1.7 ! root       56: #define REG_CONTROL    0xff8a3c
1.1.1.4   root       57: #define REG_SKEW       0xff8a3d
                     58: 
1.1.1.7 ! root       59: #define SRC_READ_NOPS  0x1
        !            60: #define DST_READ_NOPS  0x2
        !            61: #define DST_WRITE_NOPS 0x4
        !            62: #define DST_ALL_NOPS   0x6
        !            63: #define ALL_NOPS       0x7
1.1.1.4   root       64: 
                     65: static Uint16 halftone_ram[16];
                     66: static Uint16 end_mask_1, end_mask_2, end_mask_3;
1.1.1.7 ! root       67: static Uint16 x_count, x_count_max, y_count;
1.1.1.4   root       68: static Uint8 hop, op, blit_control, skewreg;
1.1.1.7 ! root       69: static Uint8 NFSR, FXSR;
        !            70: static Uint32 dest_addr, source_addr;
        !            71: static int halftone_curroffset;
        !            72: static Uint32 source_buffer;
        !            73: static int nCurrentCycles;
        !            74: 
        !            75: 
        !            76: /*
        !            77:  * Blitter timings - read write method.
        !            78:  * To perform an operation on a single word, the blitter might need to:
        !            79:  * - Read source memory
        !            80:  * - Read destination memory
        !            81:  * - Write destination memory
        !            82:  * Each of this actions takes one nop
        !            83:  */
        !            84: 
        !            85: /* source reading nop for each ops */
        !            86: static int blit_src_read[16][4] =
        !            87: {
        !            88:        /* All ones | Halftone | Source | Source AND Halftone */
        !            89:        {     0,          0,        0,        0 }, // All zeros
        !            90:        {     0,          0,        1,        1 }, // Source AND destination
        !            91:        {     0,          0,        1,        1 }, // Source AND NOT destination
        !            92:        {     0,          0,        1,        1 }, // Source
        !            93:        {     0,          0,        1,        1 }, // NOT source AND destination
        !            94:        {     0,          0,        0,        0 }, // Destination
        !            95:        {     0,          0,        1,        1 }, // Source XOR destination
        !            96:        {     0,          0,        1,        1 }, // Source OR destination
        !            97:        {     0,          0,        1,        1 }, // NOT source AND NOT destination
        !            98:        {     0,          0,        1,        1 }, // NOT source XOR destination
        !            99:        {     0,          0,        0,        0 }, // NOT destination
        !           100:        {     0,          0,        1,        1 }, // Source OR NOT destination
        !           101:        {     0,          0,        1,        1 }, // NOT source
        !           102:        {     0,          0,        1,        1 }, // NOT source OR destination
        !           103:        {     0,          0,        1,        1 }, // NOT source OR NOT destination
        !           104:        {     0,          0,        0,        0 }  // All ones
        !           105: };
1.1       root      106: 
1.1.1.7 ! root      107: /* source reading nop for each smudge ops */
        !           108: static int blit_src_read_smudge[16][4] =
        !           109: {
        !           110:        /* All ones | Halftone | Source | Source AND Halftone */
        !           111:        {     0,          0,        0,        0 }, // All zeros
        !           112:        {     1,          1,        1,        1 }, // Source AND destination
        !           113:        {     1,          1,        1,        1 }, // Source AND NOT destination
        !           114:        {     1,          1,        1,        1 }, // Source
        !           115:        {     1,          1,        1,        1 }, // NOT source AND destination
        !           116:        {     0,          0,        0,        0 }, // Destination
        !           117:        {     1,          1,        1,        1 }, // Source XOR destination
        !           118:        {     1,          1,        1,        1 }, // Source OR destination
        !           119:        {     1,          1,        1,        1 }, // NOT source AND NOT destination
        !           120:        {     1,          1,        1,        1 }, // NOT source XOR destination
        !           121:        {     0,          0,        0,        0 }, // NOT destination
        !           122:        {     1,          1,        1,        1 }, // Source OR NOT destination
        !           123:        {     1,          1,        1,        1 }, // NOT source
        !           124:        {     1,          1,        1,        1 }, // NOT source OR destination
        !           125:        {     1,          1,        1,        1 }, // NOT source OR NOT destination
        !           126:        {     0,          0,        0,        0 }  // All ones
        !           127: };
        !           128: 
        !           129: /* destination reading nop for each ops */
        !           130: static int blit_dst_read[16][4] =
        !           131: {
        !           132:        /* All ones | Halftone | Source | Source AND Halftone */
        !           133:        {     0,          0,        0,        0 }, // All zeros
        !           134:        {     1,          1,        1,        1 }, // Source AND destination
        !           135:        {     1,          1,        1,        1 }, // Source AND NOT destination
        !           136:        {     0,          0,        0,        0 }, // Source
        !           137:        {     1,          1,        1,        1 }, // NOT source AND destination
        !           138:        {     1,          1,        1,        1 }, // Destination
        !           139:        {     1,          1,        1,        1 }, // Source XOR destination
        !           140:        {     1,          1,        1,        1 }, // Source OR destination
        !           141:        {     1,          1,        1,        1 }, // NOT source AND NOT destination
        !           142:        {     1,          1,        1,        1 }, // NOT source XOR destination
        !           143:        {     1,          1,        1,        1 }, // NOT destination
        !           144:        {     1,          1,        1,        1 }, // Source OR NOT destination
        !           145:        {     0,          0,        0,        0 }, // NOT source
        !           146:        {     1,          1,        1,        1 }, // NOT source OR destination
        !           147:        {     1,          1,        1,        1 }, // NOT source OR NOT destination
        !           148:        {     0,          0,        0,        0 }  // All ones
        !           149: };
1.1       root      150: 
1.1.1.4   root      151: #if DEBUG
1.1.1.7 ! root      152: static void show_params(void)
1.1       root      153: {
1.1.1.4   root      154:        fprintf(stderr, "Source Address:%X\n", source_addr);
1.1.1.7 ! root      155:        fprintf(stderr, "  Dest Address:%X\n", dest_addr);
1.1.1.4   root      156:        fprintf(stderr, "       X count:%X\n", x_count);
                    157:        fprintf(stderr, "       Y count:%X\n", y_count);
1.1.1.7 ! root      158:        fprintf(stderr, "  Source X inc:%X\n", IoMem_ReadWord(REG_SRC_X_INC));
        !           159:        fprintf(stderr, "    Dest X inc:%X\n", IoMem_ReadWord(REG_DST_X_INC));
        !           160:        fprintf(stderr, "  Source Y inc:%X\n", IoMem_ReadWord(REG_SRC_Y_INC));
        !           161:        fprintf(stderr, "    Dest Y inc:%X\n", IoMem_ReadWord(REG_DST_Y_INC));
1.1.1.4   root      162:        fprintf(stderr, "HOP:%2X    OP:%X\n", hop, op);
                    163:        fprintf(stderr, "   source SKEW:%X\n", skewreg);
                    164:        fprintf(stderr, "     endmask 1:%X\n", end_mask_1);
                    165:        fprintf(stderr, "     endmask 2:%X\n", end_mask_2);
                    166:        fprintf(stderr, "     endmask 3:%X\n", end_mask_3);
                    167:        fprintf(stderr, "  blit control:%X\n", blit_control);
                    168:        if (NFSR) fprintf(stderr, "NFSR is Set!\n");
                    169:        if (FXSR) fprintf(stderr, "FXSR is Set!\n");
                    170: }
                    171: 
                    172: static void show_halftones(void)
                    173: {
                    174:        int i, j;
                    175:        fprintf(stderr, "Halftone registers:\n");
1.1.1.7 ! root      176:        for (i = 0; i < 2; i++)
        !           177:        {
        !           178:                for (j = 0; j < 8; j++)
        !           179:                {
1.1.1.4   root      180:                        fprintf(stderr,"%4X, ", halftone_ram[i*8+j]);
                    181:                }
                    182:                fprintf(stderr, "\n");
                    183:        }
                    184: }
                    185: #endif
1.1.1.3   root      186: 
                    187: 
1.1.1.4   root      188: /* called only before halftone operations, for HOP modes 01 and 11 */
1.1.1.7 ! root      189: static void load_halftone_ram(void)
1.1.1.4   root      190: {
1.1.1.7 ! root      191:        halftone_ram[0]  = IoMem_ReadWord(REG_HT_RAM);
        !           192:        halftone_ram[1]  = IoMem_ReadWord(REG_HT_RAM+2);
        !           193:        halftone_ram[2]  = IoMem_ReadWord(REG_HT_RAM+4);
        !           194:        halftone_ram[3]  = IoMem_ReadWord(REG_HT_RAM+6);
        !           195:        halftone_ram[4]  = IoMem_ReadWord(REG_HT_RAM+8);
        !           196:        halftone_ram[5]  = IoMem_ReadWord(REG_HT_RAM+10);
        !           197:        halftone_ram[6]  = IoMem_ReadWord(REG_HT_RAM+12);
        !           198:        halftone_ram[7]  = IoMem_ReadWord(REG_HT_RAM+14);
        !           199:        halftone_ram[8]  = IoMem_ReadWord(REG_HT_RAM+16);
        !           200:        halftone_ram[9]  = IoMem_ReadWord(REG_HT_RAM+18);
        !           201:        halftone_ram[10] = IoMem_ReadWord(REG_HT_RAM+20);
        !           202:        halftone_ram[11] = IoMem_ReadWord(REG_HT_RAM+22);
        !           203:        halftone_ram[12] = IoMem_ReadWord(REG_HT_RAM+24);
        !           204:        halftone_ram[13] = IoMem_ReadWord(REG_HT_RAM+26);
        !           205:        halftone_ram[14] = IoMem_ReadWord(REG_HT_RAM+28);
        !           206:        halftone_ram[15] = IoMem_ReadWord(REG_HT_RAM+30);
1.1.1.4   root      207: 
1.1.1.7 ! root      208:        if (!(blit_control & 0x20))
        !           209:        {
1.1.1.4   root      210:                /* No smudge mode: Get halftone offset from control register */
                    211:                halftone_curroffset = blit_control & 15;
                    212:        }
                    213: 
                    214: #if DEBUG
1.1.1.7 ! root      215:        show_params();
1.1.1.4   root      216:        show_halftones();
                    217: #endif
1.1       root      218: }
                    219: 
1.1.1.7 ! root      220: static int Blitter_GetNops(int flag, Uint16 mask)
        !           221: {
        !           222:        int nops = 0;
1.1       root      223: 
1.1.1.7 ! root      224:        if (flag & SRC_READ_NOPS)
        !           225:        {
        !           226:                /* nop for reading source */
        !           227:                nops += ((blit_control & 0x20)
        !           228:                                        ? blit_src_read_smudge[op][hop]
        !           229:                                        : blit_src_read[op][hop]);
        !           230:        }
        !           231: 
        !           232:        if (flag & DST_READ_NOPS)
        !           233:        {
        !           234:                /* nop for reading destination
        !           235:                 * note that when mask != 0xFFFF a read is always performed
        !           236:                 * in order to compute the final word */
        !           237:                nops += (((mask != 0xFFFF) ? 1 : blit_dst_read[op][hop]));
        !           238:        }
        !           239: 
        !           240:        if (flag & DST_WRITE_NOPS)
        !           241:        {
        !           242:                /* nop for writing destination */
        !           243:                nops += 1;
        !           244:        }
        !           245: 
        !           246:        return nops;
        !           247: }
        !           248: 
        !           249: /**
        !           250:  * Count blitter cycles
        !           251:  */
        !           252: static void Blitter_AddCycles(int cycles)
        !           253: {
        !           254:        PendingInterruptCount -= INT_CONVERT_TO_INTERNAL(cycles, INT_CPU_CYCLE);
        !           255:        nCyclesMainCounter += cycles;
        !           256:        nCurrentCycles += cycles;
        !           257: 
        !           258:        /* We've got to update pending int functions regularly to make sure
        !           259:         * that other effects are not delayed too much. (Needed for "Obsession",
        !           260:         * "Braindamage", and Doughnut screen in "Just Musix 2") */
        !           261:        if (PendingInterruptCount <= 0 && PendingInterruptFunction)
        !           262:        {
        !           263:            CALL_VAR(PendingInterruptFunction);
        !           264:        }
        !           265: }
        !           266: 
        !           267: 
        !           268: #define do_source_shift() \
        !           269:        if (((short)IoMem_ReadWord(REG_SRC_X_INC)) < 0) \
        !           270:                source_buffer >>= 16; \
1.1.1.6   root      271:        else \
1.1.1.7 ! root      272:                source_buffer <<= 16
        !           273: 
        !           274: 
        !           275: #define get_source_data() \
        !           276:        if (hop >= 2) \
1.1.1.6   root      277:        { \
1.1.1.7 ! root      278:                if (((short)IoMem_ReadWord(REG_SRC_X_INC)) < 0) \
        !           279:                        source_buffer |= ((Uint32) STMemory_ReadWord(source_addr) << 16); \
        !           280:                else \
        !           281:                        source_buffer |= ((Uint32) STMemory_ReadWord(source_addr));  \
        !           282:        }
1.1       root      283: 
                    284: 
1.1.1.4   root      285: /* In smudge mode, the halftone offset is determined by the lowest 4 bits of
                    286:  * the first source word, after it has been skewed */
                    287: #define HALFTONE_OFFSET  ((blit_control & 0x20) ? \
                    288:        ((STMemory_ReadWord(source_addr) >> skew) & 15) : halftone_curroffset)
                    289: 
                    290: 
1.1.1.7 ! root      291: static inline void put_dst_data(Uint8 skew, Uint16 end_mask)
1.1       root      292: {
1.1.1.7 ! root      293:        Uint16 dst_data, opd_data;
        !           294: 
        !           295:        dst_data = STMemory_ReadWord(dest_addr);
1.1       root      296: 
1.1.1.7 ! root      297:        switch (hop)
        !           298:        {
        !           299:         default:
        !           300:         case 0: opd_data = 0xffff; break;
        !           301:         case 1: opd_data = halftone_ram[HALFTONE_OFFSET]; break;
        !           302:         case 2: opd_data = (source_buffer >> skew); break;
        !           303:         case 3: opd_data = (source_buffer >> skew)
        !           304:                            & halftone_ram[HALFTONE_OFFSET];  break;
        !           305:        }
        !           306: 
        !           307:        switch (op)
        !           308:        {
        !           309:         default:
        !           310:         case  0: opd_data = 0; break;
        !           311:         case  1: opd_data = opd_data & dst_data; break;
        !           312:         case  2: opd_data = opd_data & ~dst_data; break;
        !           313:         case  3: opd_data = opd_data; break;
        !           314:         case  4: opd_data = ~opd_data & dst_data; break;
        !           315:         case  5: opd_data = dst_data; break;
        !           316:         case  6: opd_data = opd_data ^ dst_data; break;
        !           317:         case  7: opd_data = opd_data | dst_data; break;
        !           318:         case  8: opd_data = ~opd_data & ~dst_data; break;
        !           319:         case  9: opd_data = ~opd_data ^ dst_data; break;
        !           320:         case 10: opd_data = ~dst_data; break;
        !           321:         case 11: opd_data = opd_data | ~dst_data; break;
        !           322:         case 12: opd_data = ~opd_data; break;
        !           323:         case 13: opd_data = ~opd_data | dst_data; break;
        !           324:         case 14: opd_data = ~opd_data | ~dst_data; break;
        !           325:         case 15: opd_data = 0xffff; break;
        !           326:        }
        !           327: 
        !           328:        opd_data = (dst_data & ~end_mask) | (opd_data & end_mask);
        !           329:        if (dest_addr < 0x00ff8000)
        !           330:                STMemory_WriteWord(dest_addr, opd_data);
        !           331:        else
        !           332:                IoMem_wput(dest_addr, opd_data);
        !           333: 
        !           334:        --x_count;
        !           335: }
1.1       root      336: 
                    337: 
1.1.1.3   root      338: /*-----------------------------------------------------------------------*/
1.1.1.5   root      339: /**
1.1.1.7 ! root      340:  * Let's do the blit.
        !           341:  * Note that in non-HOG mode, the blitter only runs for 64 bus cycles (2 MHz!)
        !           342:  * before giving the bus back to the CPU. Due to this mode, this function must
        !           343:  * be able to abort and resume the blitting at any time.
1.1.1.5   root      344:  */
1.1.1.4   root      345: static void Do_Blit(void)
                    346: {
1.1.1.7 ! root      347:        Uint8 skew = skewreg & 15;
        !           348:        int source_x_inc, source_y_inc;
        !           349:        int dest_x_inc, dest_y_inc;
        !           350:        int halftone_direction;
        !           351:        int cyc_per_nop;
        !           352: 
        !           353:        /*if(address_space_24)*/
        !           354:        { source_addr &= 0x0fffffe; dest_addr &= 0x0fffffe; }
        !           355: 
        !           356:        if (op == 0 || op == 15)
        !           357:        {
        !           358:                /* Do not increment source address for OP 0 and 15  */
        !           359:                /* (needed for Grotesque demo by Omega for example) */
        !           360:                source_x_inc = 0;
        !           361:                source_y_inc = 0;
        !           362:        }
        !           363:        else
        !           364:        {
        !           365:                source_x_inc = (short) IoMem_ReadWord(REG_SRC_X_INC);
        !           366:                source_y_inc = (short) IoMem_ReadWord(REG_SRC_Y_INC);
        !           367:        }
        !           368:        dest_x_inc   = (short) IoMem_ReadWord(REG_DST_X_INC);
        !           369:        dest_y_inc   = (short) IoMem_ReadWord(REG_DST_Y_INC);
        !           370: 
        !           371:        /* Set up halftone ram */
        !           372:        if (hop & 1)
        !           373:                load_halftone_ram();
        !           374: 
        !           375:        if (dest_y_inc >= 0)
        !           376:                halftone_direction = 1;
        !           377:        else
        !           378:                halftone_direction = -1;
        !           379: 
        !           380:        /* Set up variables for cycle counting */
        !           381:        nCurrentCycles = 0;
        !           382: 
        !           383:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
        !           384:                cyc_per_nop = 2;  // 16 MHz Blitter on Falcon
1.1.1.4   root      385:        else
1.1.1.7 ! root      386:                cyc_per_nop = 4;  // 8 MHz Blitter on ST/STE
        !           387: 
        !           388:        /* Now we enter the main blitting loop */
        !           389:        do
        !           390:        {
        !           391:                /* First word of a line */
        !           392:                if (x_count == x_count_max)
        !           393:                {
        !           394:                        if (FXSR)
        !           395:                        {
        !           396:                                do_source_shift();
        !           397:                                get_source_data();
        !           398:                                source_addr += source_x_inc;
        !           399:                                Blitter_AddCycles(Blitter_GetNops(SRC_READ_NOPS,0) * cyc_per_nop);
        !           400:                        }
        !           401: 
        !           402:                        do_source_shift();
        !           403:                        get_source_data();
        !           404:                        put_dst_data(skew, end_mask_1);
        !           405:                        Blitter_AddCycles(Blitter_GetNops(ALL_NOPS,end_mask_1) * cyc_per_nop);
        !           406:                }
        !           407: 
        !           408:                /* Middle words of a line */
        !           409:                while (x_count > 1
        !           410:                       && ((blit_control & 0x40) || nCurrentCycles < NONHOG_CYCLES))
        !           411:                {
        !           412:                        source_addr += source_x_inc;
        !           413:                        dest_addr += dest_x_inc;
        !           414:                        do_source_shift();
        !           415:                        get_source_data();
        !           416:                        put_dst_data(skew, end_mask_2);
        !           417:                        Blitter_AddCycles(Blitter_GetNops(ALL_NOPS,end_mask_2) * cyc_per_nop);
        !           418:                }
        !           419: 
        !           420:                /* Last word of a line */
        !           421:                if (x_count == 1
        !           422:                    && ((blit_control & 0x40) || nCurrentCycles < NONHOG_CYCLES))
        !           423:                {
        !           424:                        dest_addr += dest_x_inc;
        !           425:                        do_source_shift();
        !           426:                        if ( (!NFSR) || ((~(0xffff>>skew)) > end_mask_3) )
        !           427:                        {
        !           428:                                source_addr += source_x_inc;
        !           429:                                get_source_data();
        !           430:                                put_dst_data(skew, end_mask_3);
        !           431:                                Blitter_AddCycles(Blitter_GetNops(ALL_NOPS,end_mask_3) * cyc_per_nop);
        !           432:                        }
        !           433:                        else
        !           434:                        {
        !           435:                                put_dst_data(skew, end_mask_3);
        !           436:                                Blitter_AddCycles(Blitter_GetNops(DST_ALL_NOPS,end_mask_3) * cyc_per_nop);
        !           437:                        }
        !           438:                }
        !           439: 
        !           440:                /* Line done? */
        !           441:                if (x_count == 0)
        !           442:                {
        !           443:                        --y_count;
        !           444:                        x_count = x_count_max;
        !           445: 
        !           446:                        source_addr += source_y_inc;
        !           447:                        dest_addr += dest_y_inc;
        !           448: 
        !           449:                        /* Do halftone increment */
        !           450:                        if (hop & 1)
        !           451:                                halftone_curroffset = (halftone_curroffset+halftone_direction) & 15;
        !           452:                }
        !           453:        }
        !           454:        while (y_count > 0
        !           455:               && ((blit_control & 0x40) || nCurrentCycles < NONHOG_CYCLES));
        !           456: 
        !           457:        if (!(blit_control & 0x20))
        !           458:        {
        !           459:                /* Not smudge mode: put halftone offset back into control register */
        !           460:                blit_control = (blit_control & 0xf0) | halftone_curroffset;
        !           461:        }
        !           462: }
        !           463: 
        !           464: 
        !           465: /*-----------------------------------------------------------------------*/
        !           466: /**
        !           467:  * Read blitter source address (0xff8a24).
        !           468:  */
        !           469: void Blitter_SourceAddr_ReadLong(void)
        !           470: {
        !           471:        IoMem_WriteLong(REG_SRC_ADDR, source_addr);
1.1.1.4   root      472: }
                    473: 
                    474: /*-----------------------------------------------------------------------*/
1.1.1.5   root      475: /**
                    476:  * Read blitter endmask 1.
                    477:  */
1.1.1.3   root      478: void Blitter_Endmask1_ReadWord(void)
1.1       root      479: {
1.1.1.4   root      480:        IoMem_WriteWord(REG_END_MASK1, end_mask_1);
1.1       root      481: }
                    482: 
1.1.1.3   root      483: /*-----------------------------------------------------------------------*/
1.1.1.5   root      484: /**
                    485:  * Read blitter endmask 2.
                    486:  */
1.1.1.3   root      487: void Blitter_Endmask2_ReadWord(void)
1.1       root      488: {
1.1.1.4   root      489:        IoMem_WriteWord(REG_END_MASK2, end_mask_2);
1.1       root      490: }
                    491: 
1.1.1.3   root      492: /*-----------------------------------------------------------------------*/
1.1.1.5   root      493: /**
                    494:  * Read blitter endmask 3.
                    495:  */
1.1.1.3   root      496: void Blitter_Endmask3_ReadWord(void)
1.1       root      497: {
1.1.1.4   root      498:        IoMem_WriteWord(REG_END_MASK3, end_mask_3);
1.1       root      499: }
                    500: 
1.1.1.3   root      501: /*-----------------------------------------------------------------------*/
1.1.1.5   root      502: /**
                    503:  * Read blitter destination address.
                    504:  */
1.1.1.3   root      505: void Blitter_DestAddr_ReadLong(void)
1.1       root      506: {
1.1.1.7 ! root      507:        IoMem_WriteLong(REG_DST_ADDR, dest_addr);
1.1       root      508: }
                    509: 
1.1.1.3   root      510: /*-----------------------------------------------------------------------*/
1.1.1.5   root      511: /**
                    512:  * Read blitter words-per-line register.
                    513:  */
1.1.1.3   root      514: void Blitter_WordsPerLine_ReadWord(void)
1.1       root      515: {
1.1.1.4   root      516:        IoMem_WriteWord(REG_X_COUNT, x_count);
1.1       root      517: }
                    518: 
1.1.1.3   root      519: /*-----------------------------------------------------------------------*/
1.1.1.5   root      520: /**
                    521:  * Read blitter lines-per-bitblock register.
                    522:  */
1.1.1.3   root      523: void Blitter_LinesPerBitblock_ReadWord(void)
1.1       root      524: {
1.1.1.4   root      525:        IoMem_WriteWord(REG_Y_COUNT, y_count);
1.1       root      526: }
                    527: 
1.1.1.3   root      528: /*-----------------------------------------------------------------------*/
1.1.1.5   root      529: /**
                    530:  * Read blitter halftone operation register.
                    531:  */
1.1.1.3   root      532: void Blitter_HalftoneOp_ReadByte(void)
1.1       root      533: {
1.1.1.4   root      534:        IoMem_WriteByte(REG_BLIT_HOP, hop);
1.1       root      535: }
                    536: 
1.1.1.3   root      537: /*-----------------------------------------------------------------------*/
1.1.1.5   root      538: /**
                    539:  * Read blitter logical operation register.
                    540:  */
1.1.1.3   root      541: void Blitter_LogOp_ReadByte(void)
1.1       root      542: {
1.1.1.4   root      543:        IoMem_WriteByte(REG_BLIT_LOP, op);
1.1       root      544: }
                    545: 
1.1.1.3   root      546: /*-----------------------------------------------------------------------*/
1.1.1.5   root      547: /**
                    548:  * Read blitter control register.
                    549:  */
1.1.1.4   root      550: void Blitter_Control_ReadByte(void)
1.1       root      551: {
1.1.1.7 ! root      552:        /* busy, hog/blit, smudge, n/a, 4bits for line number */
        !           553:        IoMem_WriteByte(REG_CONTROL, blit_control);
1.1       root      554: }
                    555: 
1.1.1.3   root      556: /*-----------------------------------------------------------------------*/
1.1.1.5   root      557: /**
                    558:  * Read blitter skew register.
                    559:  */
1.1.1.3   root      560: void Blitter_Skew_ReadByte(void)
1.1       root      561: {
1.1.1.4   root      562:        IoMem_WriteByte(REG_SKEW, skewreg);
1.1       root      563: }
                    564: 
                    565: 
1.1.1.3   root      566: /*-----------------------------------------------------------------------*/
1.1.1.5   root      567: /**
1.1.1.7 ! root      568:  * Write to blitter source address register (0xff8a24).
        !           569:  */
        !           570: void Blitter_SourceAddr_WriteLong(void)
        !           571: {
        !           572:        source_addr = IoMem_ReadLong(REG_SRC_ADDR) & 0x0fffffe;
        !           573: }
        !           574: 
        !           575: /*-----------------------------------------------------------------------*/
        !           576: /**
1.1.1.5   root      577:  * Write to blitter endmask 1.
                    578:  */
1.1.1.3   root      579: void Blitter_Endmask1_WriteWord(void)
1.1       root      580: {
1.1.1.4   root      581:        end_mask_1 = IoMem_ReadWord(REG_END_MASK1);
1.1       root      582: }
                    583: 
1.1.1.3   root      584: /*-----------------------------------------------------------------------*/
1.1.1.5   root      585: /**
                    586:  * Write to blitter endmask 2.
                    587:  */
1.1.1.3   root      588: void Blitter_Endmask2_WriteWord(void)
1.1       root      589: {
1.1.1.4   root      590:        end_mask_2 = IoMem_ReadWord(REG_END_MASK2);
1.1       root      591: }
                    592: 
1.1.1.3   root      593: /*-----------------------------------------------------------------------*/
1.1.1.5   root      594: /**
                    595:  * Write to blitter endmask 3.
                    596:  */
1.1.1.3   root      597: void Blitter_Endmask3_WriteWord(void)
1.1       root      598: {
1.1.1.4   root      599:        end_mask_3 = IoMem_ReadWord(REG_END_MASK3);
1.1       root      600: }
                    601: 
1.1.1.3   root      602: /*-----------------------------------------------------------------------*/
1.1.1.5   root      603: /**
                    604:  * Write to blitter destination address register.
                    605:  */
1.1.1.3   root      606: void Blitter_DestAddr_WriteLong(void)
                    607: {
1.1.1.7 ! root      608:        dest_addr = IoMem_ReadLong(REG_DST_ADDR) & 0x0fffffe;
1.1       root      609: }
                    610: 
1.1.1.3   root      611: /*-----------------------------------------------------------------------*/
1.1.1.5   root      612: /**
                    613:  * Write to blitter words-per-line register.
                    614:  */
1.1.1.3   root      615: void Blitter_WordsPerLine_WriteWord(void)
1.1       root      616: {
1.1.1.7 ! root      617:        x_count = x_count_max = IoMem_ReadWord(REG_X_COUNT);
1.1       root      618: }
                    619: 
1.1.1.3   root      620: /*-----------------------------------------------------------------------*/
1.1.1.5   root      621: /**
                    622:  * Write to blitter words-per-bitblock register.
                    623:  */
1.1.1.3   root      624: void Blitter_LinesPerBitblock_WriteWord(void)
1.1       root      625: {
1.1.1.4   root      626:        y_count = IoMem_ReadWord(REG_Y_COUNT);
1.1       root      627: }
                    628: 
1.1.1.3   root      629: /*-----------------------------------------------------------------------*/
1.1.1.5   root      630: /**
                    631:  * Write to blitter halftone operation register.
                    632:  */
1.1.1.3   root      633: void Blitter_HalftoneOp_WriteByte(void)
1.1       root      634: {
1.1.1.4   root      635:        /* h/ware reg masks out the top 6 bits! */
                    636:        hop = IoMem_ReadByte(REG_BLIT_HOP) & 3;
1.1       root      637: }
                    638: 
1.1.1.3   root      639: /*-----------------------------------------------------------------------*/
1.1.1.5   root      640: /**
                    641:  * Write to blitter logical operation register.
                    642:  */
1.1.1.3   root      643: void Blitter_LogOp_WriteByte(void)
1.1.1.7 ! root      644: {
1.1.1.4   root      645:        /* h/ware reg masks out the top 4 bits! */
                    646:        op = IoMem_ReadByte(REG_BLIT_LOP) & 15;
1.1       root      647: }
                    648: 
1.1.1.3   root      649: /*-----------------------------------------------------------------------*/
1.1.1.5   root      650: /**
                    651:  * Write to blitter control register.
                    652:  */
1.1.1.4   root      653: void Blitter_Control_WriteByte(void)
                    654: {
                    655:        /* Control register bits:
                    656:         * 0x80: busy bit
                    657:         * - Turn on Blitter activity and stay "1" until copy finished
                    658:         * 0x40: Blit-mode bit
                    659:         * - 0: Blit mode, CPU and Blitter get 64 clockcycles in turns
                    660:         * - 1: HOG Mode, Blitter reserves and hogs the bus for as long
                    661:         *      as the copy takes, CPU and DMA get no Bus access
                    662:         * 0x20: Smudge mode
                    663:         * - Which line of the halftone pattern to start with is
                    664:         *   read from the first source word when the copy starts
                    665:         * 0x10: not used
                    666:         * 0x0f
                    667:         *
                    668:         * The lowest 4 bits contain the Halftone pattern line number
                    669:         */
1.1.1.7 ! root      670: 
        !           671:        if ( HATARI_TRACE_LEVEL ( HATARI_TRACE_BLITTER ) )
1.1.1.3   root      672:        {
1.1.1.7 ! root      673:                int nFrameCycles = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
        !           674:                int nLineCycles = nFrameCycles % nCyclesPerLine;
        !           675:                HATARI_TRACE_PRINT ( "blitter write ctrl=%x video_cyc=%d %d@%d pc=%x instr_cyc=%d\n" ,
        !           676:                                IoMem_ReadByte(REG_CONTROL) ,
        !           677:                                nFrameCycles, nLineCycles, nHBL, M68000_GetPC(), CurrentInstrCycles );
        !           678:        }
1.1.1.3   root      679: 
1.1.1.7 ! root      680:        blit_control = IoMem_ReadByte(REG_CONTROL) & 0xef;
        !           681: 
        !           682:        /* Remove old pending update interrupt */
        !           683:        Int_RemovePendingInterrupt(INTERRUPT_BLITTER);
        !           684: 
        !           685:        /* Busy bit set? */
        !           686:        if (blit_control & 0x80)
        !           687:        {
        !           688:                if (y_count == 0)
        !           689:                {
        !           690:                        /* We're done, clear busy bit */
        !           691:                        blit_control &= ~0x80;
        !           692:                }
        !           693:                else
        !           694:                {
        !           695:                        /* Start blitting after some CPU cycles */
        !           696:                        Int_AddRelativeInterrupt((CurrentInstrCycles+nWaitStateCycles)>>nCpuFreqShift,
        !           697:                                                 INT_CPU_CYCLE, INTERRUPT_BLITTER);
        !           698:                }
1.1.1.3   root      699:        }
1.1       root      700: }
                    701: 
1.1.1.3   root      702: /*-----------------------------------------------------------------------*/
1.1.1.5   root      703: /**
                    704:  * Write to blitter skew register.
                    705:  */
1.1.1.3   root      706: void Blitter_Skew_WriteByte(void)
                    707: {
1.1.1.4   root      708:        Uint8 v = IoMem_ReadByte(REG_SKEW);
1.1.1.3   root      709:        NFSR = (v & 0x40) != 0;
                    710:        FXSR = (v & 0x80) != 0;
1.1.1.4   root      711:        skewreg = v & 0xcf;        /* h/ware reg mask %11001111 !*/
1.1       root      712: }
1.1.1.2   root      713: 
                    714: 
                    715: /*-----------------------------------------------------------------------*/
1.1.1.5   root      716: /**
                    717:  * Save/Restore snapshot of Blitter variables.
                    718:  */
1.1.1.7 ! root      719: void Blitter_MemorySnapShot_Capture(bool bSave)
1.1.1.2   root      720: {
1.1.1.3   root      721:        /* Save/Restore details */
                    722:        MemorySnapShot_Store(halftone_ram, sizeof(halftone_ram));
1.1.1.7 ! root      723:        MemorySnapShot_Store(&source_addr, sizeof(source_addr));
1.1.1.3   root      724:        MemorySnapShot_Store(&end_mask_1, sizeof(end_mask_1));
                    725:        MemorySnapShot_Store(&end_mask_2, sizeof(end_mask_2));
                    726:        MemorySnapShot_Store(&end_mask_3, sizeof(end_mask_3));
                    727:        MemorySnapShot_Store(&NFSR, sizeof(NFSR));
                    728:        MemorySnapShot_Store(&FXSR, sizeof(FXSR));
1.1.1.7 ! root      729:        MemorySnapShot_Store(&x_count, sizeof(x_count));
        !           730:        MemorySnapShot_Store(&x_count_max, sizeof(x_count_max));
        !           731:        MemorySnapShot_Store(&y_count, sizeof(y_count));
1.1.1.3   root      732:        MemorySnapShot_Store(&hop, sizeof(hop));
                    733:        MemorySnapShot_Store(&op, sizeof(op));
1.1.1.4   root      734:        MemorySnapShot_Store(&blit_control, sizeof(blit_control));
1.1.1.3   root      735:        MemorySnapShot_Store(&skewreg, sizeof(skewreg));
1.1.1.7 ! root      736:        MemorySnapShot_Store(&dest_addr, sizeof(dest_addr));
1.1.1.3   root      737:        MemorySnapShot_Store(&halftone_curroffset, sizeof(halftone_curroffset));
1.1.1.7 ! root      738:        MemorySnapShot_Store(&source_buffer, sizeof(source_buffer));
        !           739: }
        !           740: 
        !           741: 
        !           742: /**
        !           743:  * Handler which continues blitting after 64 bus cycles.
        !           744:  */
        !           745: void Blitter_InterruptHandler(void)
        !           746: {
        !           747:        Int_AcknowledgeInterrupt();
        !           748: 
        !           749:        if((y_count !=0) && (blit_control & 0x80))
        !           750:        {
        !           751:                Do_Blit();
        !           752:        }
        !           753: 
        !           754:        if (y_count == 0)
        !           755:        {
        !           756:                /* We're done, clear busy bit */
        !           757:                blit_control &= ~0x80;
        !           758: 
        !           759:                /* Blitter done interrupt */
        !           760:                MFP_InputOnChannel(MFP_GPU_DONE_BIT, MFP_IERB, &MFP_IPRB);
        !           761:        }
        !           762:        else
        !           763:        {
        !           764:                /* Continue blitting later */
        !           765:                Int_AddRelativeInterrupt(NONHOG_CYCLES+8, INT_CPU_CYCLE, INTERRUPT_BLITTER);
        !           766:        }
1.1.1.2   root      767: }

unix.superglobalmegacorp.com

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