|
|
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);
1.1.1.13! root 1007: fprintf(fp, "Note: internally changed register values aren't visible to breakpoints\nor in memdump output until emulated code reads or writes them!\n");
1.1.1.12 root 1008: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.