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