|
|
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.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.7 root 42: #include "video.h"
43:
1.1.1.8 root 44: /* Cycles to run for in non-hog mode */
45: #define NONHOG_CYCLES (64*4)
1.1 root 46:
1.1.1.8 root 47: /* BLiTTER registers, incs are signed, others unsigned */
48: #define REG_HT_RAM 0xff8a00 /* - 0xff8a1e */
1.1 root 49:
1.1.1.4 root 50: #define REG_SRC_X_INC 0xff8a20
51: #define REG_SRC_Y_INC 0xff8a22
52: #define REG_SRC_ADDR 0xff8a24
53:
54: #define REG_END_MASK1 0xff8a28
55: #define REG_END_MASK2 0xff8a2a
56: #define REG_END_MASK3 0xff8a2c
57:
58: #define REG_DST_X_INC 0xff8a2e
59: #define REG_DST_Y_INC 0xff8a30
60: #define REG_DST_ADDR 0xff8a32
61:
1.1.1.7 root 62: #define REG_X_COUNT 0xff8a36
63: #define REG_Y_COUNT 0xff8a38
1.1.1.4 root 64:
65: #define REG_BLIT_HOP 0xff8a3a /* halftone blit operation byte */
66: #define REG_BLIT_LOP 0xff8a3b /* logical blit operation byte */
1.1.1.7 root 67: #define REG_CONTROL 0xff8a3c
1.1.1.8 root 68: #define REG_SKEW 0xff8a3d
1.1.1.4 root 69:
1.1.1.8 root 70: /* Blitter registers */
71: typedef struct
72: {
73: Uint32 src_addr;
74: Uint32 dst_addr;
75: Uint32 words;
76: Uint32 lines;
77: short src_x_incr;
78: short src_y_incr;
79: short dst_x_incr;
80: short dst_y_incr;
81: Uint16 end_mask_1;
82: Uint16 end_mask_2;
83: Uint16 end_mask_3;
84: Uint8 hop;
85: Uint8 lop;
86: Uint8 ctrl;
87: Uint8 skew;
88: } BLITTERREGS;
89:
90: /* Blitter vars */
91: typedef struct
92: {
1.1.1.9 ! root 93: int pass_cycles;
! 94: int op_cycles;
1.1.1.8 root 95: Uint32 buffer;
96: Uint32 src_words_reset;
97: Uint32 dst_words_reset;
98: Uint32 src_words;
99: Uint8 hog;
100: Uint8 smudge;
101: Uint8 line;
102: Uint8 fxsr;
103: Uint8 nfsr;
104: Uint8 skew;
105: } BLITTERVARS;
106:
107: /* Blitter state */
108: typedef struct
109: {
110: Uint16 src_word;
111: Uint16 dst_word;
112: Uint16 end_mask;
113: Uint8 have_src;
114: Uint8 have_dst;
115: Uint8 fxsr;
116: Uint8 nfsr;
117: } BLITTERSTATE;
118:
1.1.1.9 ! root 119: /* Blitter logical op func */
! 120: typedef Uint16 (*BLITTER_OP_FUNC)(void);
! 121:
1.1.1.8 root 122: static BLITTERREGS BlitterRegs;
123: static BLITTERVARS BlitterVars;
124: static BLITTERSTATE BlitterState;
125: static Uint16 BlitterHalftone[16];
1.1.1.3 root 126:
1.1.1.9 ! root 127: static BLITTER_OP_FUNC Blitter_ComputeHOP;
! 128: static BLITTER_OP_FUNC Blitter_ComputeLOP;
! 129:
1.1.1.8 root 130: /*-----------------------------------------------------------------------*/
131: /**
132: * Count blitter cycles
133: */
1.1.1.3 root 134:
1.1.1.8 root 135: static void Blitter_AddCycles(int cycles)
1.1.1.4 root 136: {
1.1.1.8 root 137: int all_cycles = cycles + nWaitStateCycles;
1.1.1.4 root 138:
1.1.1.9 ! root 139: BlitterVars.op_cycles += all_cycles;
1.1.1.4 root 140:
1.1.1.9 ! root 141: nCyclesMainCounter += all_cycles >> nCpuFreqShift;
1.1.1.8 root 142: nWaitStateCycles = 0;
1.1.1.9 ! root 143: }
! 144:
! 145: static void Blitter_FlushCycles(void)
! 146: {
! 147: int op_cycles = INT_CONVERT_TO_INTERNAL(BlitterVars.op_cycles, INT_CPU_CYCLE);
! 148:
! 149: BlitterVars.pass_cycles += BlitterVars.op_cycles;
! 150: BlitterVars.op_cycles = 0;
1.1.1.8 root 151:
1.1.1.9 ! root 152: PendingInterruptCount -= op_cycles;
1.1.1.8 root 153: while (PendingInterruptCount <= 0 && PendingInterruptFunction)
154: CALL_VAR(PendingInterruptFunction);
1.1 root 155: }
156:
1.1.1.8 root 157: /*-----------------------------------------------------------------------*/
158: /**
159: * Read & Write operations
160: */
161: static Uint16 Blitter_ReadWord(Uint32 addr)
1.1.1.7 root 162: {
1.1.1.8 root 163: Uint16 value;
1.1 root 164:
1.1.1.8 root 165: if (addr < 0x00ff8000)
166: value = STMemory_ReadWord(addr);
167: else
1.1.1.9 ! root 168: value = (Uint16)(IoMem_wget(addr));
1.1.1.7 root 169:
1.1.1.8 root 170: Blitter_AddCycles(4);
1.1.1.7 root 171:
1.1.1.8 root 172: return value;
173: }
174:
175: static void Blitter_WriteWord(Uint32 addr, Uint16 value)
176: {
177: if (addr < 0x00ff8000)
178: STMemory_WriteWord(addr, value);
179: else
180: IoMem_wput(addr, (Uint32)(value));
1.1.1.7 root 181:
1.1.1.8 root 182: Blitter_AddCycles(4);
1.1.1.7 root 183: }
184:
1.1.1.8 root 185: /*-----------------------------------------------------------------------*/
1.1.1.7 root 186: /**
1.1.1.8 root 187: * Blitter emulation - level 1
1.1.1.7 root 188: */
1.1.1.8 root 189:
190: static void Blitter_BeginLine(void)
1.1.1.7 root 191: {
1.1.1.8 root 192: BlitterVars.src_words = BlitterVars.src_words_reset;
193: }
1.1.1.7 root 194:
1.1.1.8 root 195: static void Blitter_SetState(Uint8 fxsr, Uint8 nfsr, Uint16 end_mask)
196: {
197: BlitterState.end_mask = end_mask;
198: BlitterState.have_src = false;
199: BlitterState.have_dst = false;
200: BlitterState.fxsr = fxsr;
201: BlitterState.nfsr = nfsr;
202: }
203:
204: static void Blitter_SourceShift(void)
205: {
206: if (BlitterRegs.src_x_incr < 0)
207: BlitterVars.buffer >>= 16;
208: else
209: BlitterVars.buffer <<= 16;
210: }
211:
212: static void Blitter_SourceFetch(void)
213: {
214: Uint32 src_word = (Uint32)Blitter_ReadWord(BlitterRegs.src_addr);
215:
216: if (BlitterRegs.src_x_incr < 0)
217: BlitterVars.buffer |= src_word << 16;
218: else
219: BlitterVars.buffer |= src_word;
220:
221: if (BlitterVars.src_words == 1)
1.1.1.7 root 222: {
1.1.1.8 root 223: BlitterRegs.src_addr += BlitterRegs.src_y_incr;
224: }
225: else
226: {
227: --BlitterVars.src_words;
228: BlitterRegs.src_addr += BlitterRegs.src_x_incr;
1.1.1.7 root 229: }
230: }
231:
1.1.1.8 root 232: static Uint16 Blitter_SourceRead(void)
233: {
234: if (!BlitterState.have_src)
235: {
236: if (BlitterState.fxsr)
237: {
238: Blitter_SourceShift();
239: Blitter_SourceFetch();
240: }
1.1.1.7 root 241:
1.1.1.8 root 242: Blitter_SourceShift();
1.1.1.7 root 243:
1.1.1.8 root 244: if (!BlitterState.nfsr)
245: {
246: Blitter_SourceFetch();
247: }
1.1.1.7 root 248:
1.1.1.8 root 249: BlitterState.src_word = (Uint16)(BlitterVars.buffer >> BlitterVars.skew);
250: BlitterState.have_src = true;
1.1.1.7 root 251: }
1.1 root 252:
1.1.1.8 root 253: return BlitterState.src_word;
254: }
1.1 root 255:
1.1.1.8 root 256: static Uint16 Blitter_GetHalftoneWord(void)
257: {
258: if (BlitterVars.smudge)
259: return BlitterHalftone[Blitter_SourceRead() & 15];
260: else
261: return BlitterHalftone[BlitterVars.line];
262: }
1.1.1.4 root 263:
1.1.1.9 ! root 264: /* HOP */
! 265:
! 266: static Uint16 Blitter_HOP_0(void)
1.1 root 267: {
1.1.1.9 ! root 268: return 0xFFFF;
! 269: }
1.1.1.7 root 270:
1.1.1.9 ! root 271: static Uint16 Blitter_HOP_1(void)
! 272: {
! 273: return Blitter_GetHalftoneWord();
! 274: }
! 275:
! 276: static Uint16 Blitter_HOP_2(void)
! 277: {
! 278: return Blitter_SourceRead();
! 279: }
1.1.1.8 root 280:
1.1.1.9 ! root 281: static Uint16 Blitter_HOP_3(void)
! 282: {
! 283: return Blitter_SourceRead() & Blitter_GetHalftoneWord();
1.1.1.8 root 284: }
285:
1.1.1.9 ! root 286: static BLITTER_OP_FUNC Blitter_HOP_Table [4] =
! 287: {
! 288: Blitter_HOP_0,
! 289: Blitter_HOP_1,
! 290: Blitter_HOP_2,
! 291: Blitter_HOP_3
! 292: };
! 293:
! 294: static void Blitter_Select_HOP(void)
! 295: {
! 296: Blitter_ComputeHOP = Blitter_HOP_Table[BlitterRegs.hop];
! 297: }
! 298:
! 299: /* end HOP */
! 300:
1.1.1.8 root 301: static Uint16 Blitter_DestRead(void)
302: {
303: if (!BlitterState.have_dst)
304: {
305: BlitterState.dst_word = Blitter_ReadWord(BlitterRegs.dst_addr);
306: BlitterState.have_dst = true;
307: }
308:
309: return BlitterState.dst_word;
310: }
311:
1.1.1.9 ! root 312: /* LOP */
! 313:
! 314: static Uint16 Blitter_LOP_0(void)
! 315: {
! 316: return 0;
! 317: }
! 318:
! 319: static Uint16 Blitter_LOP_1(void)
1.1.1.8 root 320: {
1.1.1.9 ! root 321: return Blitter_ComputeHOP() & Blitter_DestRead();
! 322: }
1.1.1.8 root 323:
1.1.1.9 ! root 324: static Uint16 Blitter_LOP_2(void)
! 325: {
! 326: return Blitter_ComputeHOP() & ~Blitter_DestRead();
! 327: }
! 328:
! 329: static Uint16 Blitter_LOP_3(void)
! 330: {
! 331: return Blitter_ComputeHOP();
! 332: }
! 333:
! 334: static Uint16 Blitter_LOP_4(void)
! 335: {
! 336: return ~Blitter_ComputeHOP() & Blitter_DestRead();
! 337: }
! 338:
! 339: static Uint16 Blitter_LOP_5(void)
! 340: {
! 341: return Blitter_DestRead();
! 342: }
! 343:
! 344: static Uint16 Blitter_LOP_6(void)
! 345: {
! 346: return Blitter_ComputeHOP() ^ Blitter_DestRead();
! 347: }
! 348:
! 349: static Uint16 Blitter_LOP_7(void)
! 350: {
! 351: return Blitter_ComputeHOP() | Blitter_DestRead();
! 352: }
! 353:
! 354: static Uint16 Blitter_LOP_8(void)
! 355: {
! 356: return ~Blitter_ComputeHOP() & ~Blitter_DestRead();
! 357: }
! 358:
! 359: static Uint16 Blitter_LOP_9(void)
! 360: {
! 361: return ~Blitter_ComputeHOP() ^ Blitter_DestRead();
! 362: }
! 363:
! 364: static Uint16 Blitter_LOP_A(void)
! 365: {
! 366: return ~Blitter_DestRead();
! 367: }
1.1.1.8 root 368:
1.1.1.9 ! root 369: static Uint16 Blitter_LOP_B(void)
! 370: {
! 371: return Blitter_ComputeHOP() | ~Blitter_DestRead();
1.1.1.8 root 372: }
373:
1.1.1.9 ! root 374: static Uint16 Blitter_LOP_C(void)
! 375: {
! 376: return ~Blitter_ComputeHOP();
! 377: }
! 378:
! 379: static Uint16 Blitter_LOP_D(void)
! 380: {
! 381: return ~Blitter_ComputeHOP() | Blitter_DestRead();
! 382: }
! 383:
! 384: static Uint16 Blitter_LOP_E(void)
! 385: {
! 386: return ~Blitter_ComputeHOP() | ~Blitter_DestRead();
! 387: }
! 388:
! 389: static Uint16 Blitter_LOP_F(void)
! 390: {
! 391: return 0xFFFF;
! 392: }
! 393:
! 394: static BLITTER_OP_FUNC Blitter_LOP_Table [16] =
! 395: {
! 396: Blitter_LOP_0,
! 397: Blitter_LOP_1,
! 398: Blitter_LOP_2,
! 399: Blitter_LOP_3,
! 400: Blitter_LOP_4,
! 401: Blitter_LOP_5,
! 402: Blitter_LOP_6,
! 403: Blitter_LOP_7,
! 404: Blitter_LOP_8,
! 405: Blitter_LOP_9,
! 406: Blitter_LOP_A,
! 407: Blitter_LOP_B,
! 408: Blitter_LOP_C,
! 409: Blitter_LOP_D,
! 410: Blitter_LOP_E,
! 411: Blitter_LOP_F
! 412: };
! 413:
! 414: static void Blitter_Select_LOP(void)
! 415: {
! 416: Blitter_ComputeLOP = Blitter_LOP_Table[BlitterRegs.lop];
! 417: }
! 418:
! 419: /* end LOP */
! 420:
1.1.1.8 root 421: static Uint16 Blitter_ComputeMask(void)
422: {
423: return (Blitter_ComputeLOP() & BlitterState.end_mask) |
424: (Blitter_DestRead() & ~BlitterState.end_mask);
425: }
426:
427: static void Blitter_ProcessWord(void)
428: {
429: /* when NFSR, a read-modify-write is always performed */
430: Uint16 dst_data = ((BlitterState.nfsr || BlitterState.end_mask != 0xFFFF)
431: ? Blitter_ComputeMask()
432: : Blitter_ComputeLOP());
433:
434: Blitter_WriteWord(BlitterRegs.dst_addr, dst_data);
1.1 root 435:
1.1.1.8 root 436: if (BlitterRegs.words == 1)
1.1.1.7 root 437: {
1.1.1.8 root 438: BlitterRegs.dst_addr += BlitterRegs.dst_y_incr;
1.1.1.7 root 439: }
1.1.1.8 root 440: else
1.1.1.7 root 441: {
1.1.1.8 root 442: --BlitterRegs.words;
443: BlitterRegs.dst_addr += BlitterRegs.dst_x_incr;
1.1.1.7 root 444: }
1.1.1.8 root 445: }
446:
447: static void Blitter_EndLine(void)
448: {
449: --BlitterRegs.lines;
450: BlitterRegs.words = BlitterVars.dst_words_reset;
1.1.1.7 root 451:
1.1.1.8 root 452: if (BlitterRegs.dst_y_incr >= 0)
453: BlitterVars.line = (BlitterVars.line+1) & 15;
1.1.1.7 root 454: else
1.1.1.8 root 455: BlitterVars.line = (BlitterVars.line-1) & 15;
456: }
457:
458: /*-----------------------------------------------------------------------*/
459: /**
460: * Blitter emulation - level 2
461: */
462:
463: static void Blitter_SingleWord(void)
464: {
465: Blitter_BeginLine();
466: Blitter_SetState(BlitterVars.fxsr, BlitterVars.nfsr, BlitterRegs.end_mask_1);
467: Blitter_ProcessWord();
468: Blitter_EndLine();
469: }
470:
471: static void Blitter_FirstWord(void)
472: {
473: Blitter_BeginLine();
474: Blitter_SetState(BlitterVars.fxsr, 0, BlitterRegs.end_mask_1);
475: Blitter_ProcessWord();
476: }
477:
478: static void Blitter_MiddleWord(void)
479: {
480: Blitter_SetState(0, 0, BlitterRegs.end_mask_2);
481: Blitter_ProcessWord();
482: }
1.1.1.7 root 483:
1.1.1.8 root 484: static void Blitter_LastWord(void)
485: {
486: Blitter_SetState(0, BlitterVars.nfsr, BlitterRegs.end_mask_3);
487: Blitter_ProcessWord();
488: Blitter_EndLine();
1.1.1.7 root 489: }
1.1 root 490:
1.1.1.8 root 491: static void Blitter_Step(void)
492: {
493: if (BlitterVars.dst_words_reset == 1)
494: {
495: Blitter_SingleWord();
496: }
497: else if (BlitterRegs.words == BlitterVars.dst_words_reset)
498: {
499: Blitter_FirstWord();
500: }
501: else if (BlitterRegs.words == 1)
502: {
503: Blitter_LastWord();
504: }
505: else
506: {
507: Blitter_MiddleWord();
508: }
509: }
1.1 root 510:
1.1.1.3 root 511: /*-----------------------------------------------------------------------*/
1.1.1.5 root 512: /**
1.1.1.7 root 513: * Let's do the blit.
514: * Note that in non-HOG mode, the blitter only runs for 64 bus cycles (2 MHz!)
515: * before giving the bus back to the CPU. Due to this mode, this function must
516: * be able to abort and resume the blitting at any time.
1.1.1.5 root 517: */
1.1.1.8 root 518: static void Blitter_Start(void)
1.1.1.4 root 519: {
1.1.1.9 ! root 520: /* select HOP & LOP funcs */
! 521: Blitter_Select_HOP();
! 522: Blitter_Select_LOP();
! 523:
1.1.1.8 root 524: /* setup vars */
1.1.1.9 ! root 525: BlitterVars.pass_cycles = 0;
! 526: BlitterVars.op_cycles = 0;
1.1.1.8 root 527: BlitterVars.src_words_reset = BlitterVars.dst_words_reset +
528: BlitterVars.fxsr - BlitterVars.nfsr;
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 */
557: MFP_InputOnChannel(MFP_GPU_DONE_BIT, MFP_IERB, &MFP_IPRB);
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.9 ! root 562: Int_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 */
925: Int_RemovePendingInterrupt(INTERRUPT_BLITTER);
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 */
938: Int_AddRelativeInterrupt((CurrentInstrCycles+nWaitStateCycles)>>nCpuFreqShift,
1.1.1.8 root 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: {
963: Int_AcknowledgeInterrupt();
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.