|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.