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