|
|
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.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.8 root 528: BlitterVars.src_words_reset = BlitterVars.dst_words_reset +
529: BlitterVars.fxsr - BlitterVars.nfsr;
530:
531: /* bus arbitration */
532: BusMode = BUS_MODE_BLITTER; /* bus is now owned by the blitter */
533: Blitter_AddCycles(4);
1.1.1.9 root 534: Blitter_FlushCycles();
1.1.1.7 root 535:
536: /* Now we enter the main blitting loop */
537: do
538: {
1.1.1.8 root 539: Blitter_Step();
1.1.1.9 root 540: Blitter_FlushCycles();
1.1.1.8 root 541: }
542: while (BlitterRegs.lines > 0
1.1.1.9 root 543: && (BlitterVars.hog || BlitterVars.pass_cycles < NONHOG_CYCLES));
1.1.1.7 root 544:
1.1.1.8 root 545: /* bus arbitration */
546: Blitter_AddCycles(4);
1.1.1.9 root 547: Blitter_FlushCycles();
1.1.1.8 root 548: BusMode = BUS_MODE_CPU; /* bus is now owned by the cpu again */
1.1.1.7 root 549:
1.1.1.8 root 550: BlitterRegs.ctrl = (BlitterRegs.ctrl & 0xF0) | BlitterVars.line;
1.1.1.7 root 551:
1.1.1.8 root 552: if (BlitterRegs.lines == 0)
553: {
554: /* We're done, clear busy bit */
555: BlitterRegs.ctrl &= ~0x80;
1.1.1.7 root 556:
1.1.1.8 root 557: /* Blitter done interrupt */
558: MFP_InputOnChannel(MFP_GPU_DONE_BIT, MFP_IERB, &MFP_IPRB);
1.1.1.7 root 559: }
1.1.1.8 root 560: else
1.1.1.7 root 561: {
1.1.1.8 root 562: /* Continue blitting later */
1.1.1.10 root 563: CycInt_AddRelativeInterrupt(NONHOG_CYCLES, INT_CPU_CYCLE, INTERRUPT_BLITTER);
1.1.1.7 root 564: }
565: }
566:
1.1.1.8 root 567: /*-----------------------------------------------------------------------*/
568: /**
569: * Read blitter halftone ram.
570: */
571: static void Blitter_Halftone_ReadWord(int index)
572: {
573: IoMem_WriteWord(REG_HT_RAM + index + index, BlitterHalftone[index]);
574: }
575:
576: void Blitter_Halftone00_ReadWord(void) { Blitter_Halftone_ReadWord(0); }
577: void Blitter_Halftone01_ReadWord(void) { Blitter_Halftone_ReadWord(1); }
578: void Blitter_Halftone02_ReadWord(void) { Blitter_Halftone_ReadWord(2); }
579: void Blitter_Halftone03_ReadWord(void) { Blitter_Halftone_ReadWord(3); }
580: void Blitter_Halftone04_ReadWord(void) { Blitter_Halftone_ReadWord(4); }
581: void Blitter_Halftone05_ReadWord(void) { Blitter_Halftone_ReadWord(5); }
582: void Blitter_Halftone06_ReadWord(void) { Blitter_Halftone_ReadWord(6); }
583: void Blitter_Halftone07_ReadWord(void) { Blitter_Halftone_ReadWord(7); }
584: void Blitter_Halftone08_ReadWord(void) { Blitter_Halftone_ReadWord(8); }
585: void Blitter_Halftone09_ReadWord(void) { Blitter_Halftone_ReadWord(9); }
586: void Blitter_Halftone10_ReadWord(void) { Blitter_Halftone_ReadWord(10); }
587: void Blitter_Halftone11_ReadWord(void) { Blitter_Halftone_ReadWord(11); }
588: void Blitter_Halftone12_ReadWord(void) { Blitter_Halftone_ReadWord(12); }
589: void Blitter_Halftone13_ReadWord(void) { Blitter_Halftone_ReadWord(13); }
590: void Blitter_Halftone14_ReadWord(void) { Blitter_Halftone_ReadWord(14); }
591: void Blitter_Halftone15_ReadWord(void) { Blitter_Halftone_ReadWord(15); }
592:
593: /*-----------------------------------------------------------------------*/
594: /**
595: * Read blitter source x increment (0xff8a20).
596: */
597: void Blitter_SourceXInc_ReadWord(void)
598: {
599: IoMem_WriteWord(REG_SRC_X_INC, (Uint16)(BlitterRegs.src_x_incr));
600: }
601:
602: /*-----------------------------------------------------------------------*/
603: /**
604: * Read blitter source y increment (0xff8a22).
605: */
606: void Blitter_SourceYInc_ReadWord(void)
607: {
608: IoMem_WriteWord(REG_SRC_Y_INC, (Uint16)(BlitterRegs.src_y_incr));
609: }
1.1.1.7 root 610:
611: /*-----------------------------------------------------------------------*/
612: /**
613: * Read blitter source address (0xff8a24).
614: */
615: void Blitter_SourceAddr_ReadLong(void)
616: {
1.1.1.8 root 617: IoMem_WriteLong(REG_SRC_ADDR, BlitterRegs.src_addr);
1.1.1.4 root 618: }
619:
620: /*-----------------------------------------------------------------------*/
1.1.1.5 root 621: /**
622: * Read blitter endmask 1.
623: */
1.1.1.3 root 624: void Blitter_Endmask1_ReadWord(void)
1.1 root 625: {
1.1.1.8 root 626: IoMem_WriteWord(REG_END_MASK1, BlitterRegs.end_mask_1);
1.1 root 627: }
628:
1.1.1.3 root 629: /*-----------------------------------------------------------------------*/
1.1.1.5 root 630: /**
631: * Read blitter endmask 2.
632: */
1.1.1.3 root 633: void Blitter_Endmask2_ReadWord(void)
1.1 root 634: {
1.1.1.8 root 635: IoMem_WriteWord(REG_END_MASK2, BlitterRegs.end_mask_2);
1.1 root 636: }
637:
1.1.1.3 root 638: /*-----------------------------------------------------------------------*/
1.1.1.5 root 639: /**
640: * Read blitter endmask 3.
641: */
1.1.1.3 root 642: void Blitter_Endmask3_ReadWord(void)
1.1 root 643: {
1.1.1.8 root 644: IoMem_WriteWord(REG_END_MASK3, BlitterRegs.end_mask_3);
645: }
646:
647: /*-----------------------------------------------------------------------*/
648: /**
649: * Read blitter destination x increment (0xff8a2E).
650: */
651: void Blitter_DestXInc_ReadWord(void)
652: {
653: IoMem_WriteWord(REG_DST_X_INC, (Uint16)(BlitterRegs.dst_x_incr));
654: }
655:
656: /*-----------------------------------------------------------------------*/
657: /**
658: * Read blitter destination y increment (0xff8a30).
659: */
660: void Blitter_DestYInc_ReadWord(void)
661: {
662: IoMem_WriteWord(REG_DST_Y_INC, (Uint16)(BlitterRegs.dst_y_incr));
1.1 root 663: }
664:
1.1.1.3 root 665: /*-----------------------------------------------------------------------*/
1.1.1.5 root 666: /**
667: * Read blitter destination address.
668: */
1.1.1.3 root 669: void Blitter_DestAddr_ReadLong(void)
1.1 root 670: {
1.1.1.8 root 671: IoMem_WriteLong(REG_DST_ADDR, BlitterRegs.dst_addr);
1.1 root 672: }
673:
1.1.1.3 root 674: /*-----------------------------------------------------------------------*/
1.1.1.5 root 675: /**
676: * Read blitter words-per-line register.
677: */
1.1.1.3 root 678: void Blitter_WordsPerLine_ReadWord(void)
1.1 root 679: {
1.1.1.8 root 680: IoMem_WriteWord(REG_X_COUNT, (Uint16)(BlitterRegs.words & 0xFFFF));
1.1 root 681: }
682:
1.1.1.3 root 683: /*-----------------------------------------------------------------------*/
1.1.1.5 root 684: /**
685: * Read blitter lines-per-bitblock register.
686: */
1.1.1.3 root 687: void Blitter_LinesPerBitblock_ReadWord(void)
1.1 root 688: {
1.1.1.8 root 689: IoMem_WriteWord(REG_Y_COUNT, (Uint16)(BlitterRegs.lines & 0xFFFF));
1.1 root 690: }
691:
1.1.1.3 root 692: /*-----------------------------------------------------------------------*/
1.1.1.5 root 693: /**
694: * Read blitter halftone operation register.
695: */
1.1.1.3 root 696: void Blitter_HalftoneOp_ReadByte(void)
1.1 root 697: {
1.1.1.8 root 698: IoMem_WriteByte(REG_BLIT_HOP, BlitterRegs.hop);
1.1 root 699: }
700:
1.1.1.3 root 701: /*-----------------------------------------------------------------------*/
1.1.1.5 root 702: /**
703: * Read blitter logical operation register.
704: */
1.1.1.3 root 705: void Blitter_LogOp_ReadByte(void)
1.1 root 706: {
1.1.1.8 root 707: IoMem_WriteByte(REG_BLIT_LOP, BlitterRegs.lop);
1.1 root 708: }
709:
1.1.1.3 root 710: /*-----------------------------------------------------------------------*/
1.1.1.5 root 711: /**
712: * Read blitter control register.
713: */
1.1.1.4 root 714: void Blitter_Control_ReadByte(void)
1.1 root 715: {
1.1.1.7 root 716: /* busy, hog/blit, smudge, n/a, 4bits for line number */
1.1.1.8 root 717: IoMem_WriteByte(REG_CONTROL, BlitterRegs.ctrl);
1.1 root 718: }
719:
1.1.1.3 root 720: /*-----------------------------------------------------------------------*/
1.1.1.5 root 721: /**
722: * Read blitter skew register.
723: */
1.1.1.3 root 724: void Blitter_Skew_ReadByte(void)
1.1 root 725: {
1.1.1.8 root 726: IoMem_WriteByte(REG_SKEW, BlitterRegs.skew);
727: }
728:
729:
730: /*-----------------------------------------------------------------------*/
731: /**
732: * Write to blitter halftone ram.
733: */
734: static void Blitter_Halftone_WriteWord(int index)
735: {
736: BlitterHalftone[index] = IoMem_ReadWord(REG_HT_RAM + index + index);
737: }
738:
739: void Blitter_Halftone00_WriteWord(void) { Blitter_Halftone_WriteWord(0); }
740: void Blitter_Halftone01_WriteWord(void) { Blitter_Halftone_WriteWord(1); }
741: void Blitter_Halftone02_WriteWord(void) { Blitter_Halftone_WriteWord(2); }
742: void Blitter_Halftone03_WriteWord(void) { Blitter_Halftone_WriteWord(3); }
743: void Blitter_Halftone04_WriteWord(void) { Blitter_Halftone_WriteWord(4); }
744: void Blitter_Halftone05_WriteWord(void) { Blitter_Halftone_WriteWord(5); }
745: void Blitter_Halftone06_WriteWord(void) { Blitter_Halftone_WriteWord(6); }
746: void Blitter_Halftone07_WriteWord(void) { Blitter_Halftone_WriteWord(7); }
747: void Blitter_Halftone08_WriteWord(void) { Blitter_Halftone_WriteWord(8); }
748: void Blitter_Halftone09_WriteWord(void) { Blitter_Halftone_WriteWord(9); }
749: void Blitter_Halftone10_WriteWord(void) { Blitter_Halftone_WriteWord(10); }
750: void Blitter_Halftone11_WriteWord(void) { Blitter_Halftone_WriteWord(11); }
751: void Blitter_Halftone12_WriteWord(void) { Blitter_Halftone_WriteWord(12); }
752: void Blitter_Halftone13_WriteWord(void) { Blitter_Halftone_WriteWord(13); }
753: void Blitter_Halftone14_WriteWord(void) { Blitter_Halftone_WriteWord(14); }
754: void Blitter_Halftone15_WriteWord(void) { Blitter_Halftone_WriteWord(15); }
755:
756: /*-----------------------------------------------------------------------*/
757: /**
758: * Write to blitter source x increment.
759: */
760: void Blitter_SourceXInc_WriteWord(void)
761: {
762: BlitterRegs.src_x_incr = (short)(IoMem_ReadWord(REG_SRC_X_INC) & 0xFFFE);
1.1 root 763: }
764:
1.1.1.8 root 765: /*-----------------------------------------------------------------------*/
766: /**
767: * Write to blitter source y increment.
768: */
769: void Blitter_SourceYInc_WriteWord(void)
770: {
771: BlitterRegs.src_y_incr = (short)(IoMem_ReadWord(REG_SRC_Y_INC) & 0xFFFE);
772: }
1.1 root 773:
1.1.1.3 root 774: /*-----------------------------------------------------------------------*/
1.1.1.5 root 775: /**
1.1.1.7 root 776: * Write to blitter source address register (0xff8a24).
777: */
778: void Blitter_SourceAddr_WriteLong(void)
779: {
1.1.1.8 root 780: BlitterRegs.src_addr = IoMem_ReadLong(REG_SRC_ADDR) & 0xFFFFFE;
1.1.1.7 root 781: }
782:
783: /*-----------------------------------------------------------------------*/
784: /**
1.1.1.5 root 785: * Write to blitter endmask 1.
786: */
1.1.1.3 root 787: void Blitter_Endmask1_WriteWord(void)
1.1 root 788: {
1.1.1.8 root 789: BlitterRegs.end_mask_1 = IoMem_ReadWord(REG_END_MASK1);
1.1 root 790: }
791:
1.1.1.3 root 792: /*-----------------------------------------------------------------------*/
1.1.1.5 root 793: /**
794: * Write to blitter endmask 2.
795: */
1.1.1.3 root 796: void Blitter_Endmask2_WriteWord(void)
1.1 root 797: {
1.1.1.8 root 798: BlitterRegs.end_mask_2 = IoMem_ReadWord(REG_END_MASK2);
1.1 root 799: }
800:
1.1.1.3 root 801: /*-----------------------------------------------------------------------*/
1.1.1.5 root 802: /**
803: * Write to blitter endmask 3.
804: */
1.1.1.3 root 805: void Blitter_Endmask3_WriteWord(void)
1.1 root 806: {
1.1.1.8 root 807: BlitterRegs.end_mask_3 = IoMem_ReadWord(REG_END_MASK3);
808: }
809:
810: /*-----------------------------------------------------------------------*/
811: /**
812: * Write to blitter destination x increment.
813: */
814: void Blitter_DestXInc_WriteWord(void)
815: {
816: BlitterRegs.dst_x_incr = (short)(IoMem_ReadWord(REG_DST_X_INC) & 0xFFFE);
817: }
818:
819: /*-----------------------------------------------------------------------*/
820: /**
821: * Write to blitter source y increment.
822: */
823: void Blitter_DestYInc_WriteWord(void)
824: {
825: BlitterRegs.dst_y_incr = (short)(IoMem_ReadWord(REG_DST_Y_INC) & 0xFFFE);
1.1 root 826: }
827:
1.1.1.3 root 828: /*-----------------------------------------------------------------------*/
1.1.1.5 root 829: /**
830: * Write to blitter destination address register.
831: */
1.1.1.3 root 832: void Blitter_DestAddr_WriteLong(void)
833: {
1.1.1.8 root 834: BlitterRegs.dst_addr = IoMem_ReadLong(REG_DST_ADDR) & 0xFFFFFE;
1.1 root 835: }
836:
1.1.1.3 root 837: /*-----------------------------------------------------------------------*/
1.1.1.5 root 838: /**
839: * Write to blitter words-per-line register.
840: */
1.1.1.3 root 841: void Blitter_WordsPerLine_WriteWord(void)
1.1 root 842: {
1.1.1.8 root 843: Uint32 words = (Uint32)IoMem_ReadWord(REG_X_COUNT);
844:
845: if (words == 0)
846: words = 65536;
847:
848: BlitterRegs.words = words;
849: BlitterVars.dst_words_reset = words;
1.1 root 850: }
851:
1.1.1.3 root 852: /*-----------------------------------------------------------------------*/
1.1.1.5 root 853: /**
1.1.1.8 root 854: * Write to blitter lines-per-bitblock register.
1.1.1.5 root 855: */
1.1.1.3 root 856: void Blitter_LinesPerBitblock_WriteWord(void)
1.1 root 857: {
1.1.1.8 root 858: Uint32 lines = (Uint32)IoMem_ReadWord(REG_Y_COUNT);
859:
860: if (lines == 0)
861: lines = 65536;
862:
863: BlitterRegs.lines = lines;
1.1 root 864: }
865:
1.1.1.3 root 866: /*-----------------------------------------------------------------------*/
1.1.1.5 root 867: /**
868: * Write to blitter halftone operation register.
869: */
1.1.1.3 root 870: void Blitter_HalftoneOp_WriteByte(void)
1.1 root 871: {
1.1.1.4 root 872: /* h/ware reg masks out the top 6 bits! */
1.1.1.8 root 873: BlitterRegs.hop = IoMem_ReadByte(REG_BLIT_HOP) & 3;
1.1 root 874: }
875:
1.1.1.3 root 876: /*-----------------------------------------------------------------------*/
1.1.1.5 root 877: /**
878: * Write to blitter logical operation register.
879: */
1.1.1.3 root 880: void Blitter_LogOp_WriteByte(void)
1.1.1.7 root 881: {
1.1.1.4 root 882: /* h/ware reg masks out the top 4 bits! */
1.1.1.8 root 883: BlitterRegs.lop = IoMem_ReadByte(REG_BLIT_LOP) & 0xF;
1.1 root 884: }
885:
1.1.1.3 root 886: /*-----------------------------------------------------------------------*/
1.1.1.5 root 887: /**
888: * Write to blitter control register.
889: */
1.1.1.4 root 890: void Blitter_Control_WriteByte(void)
891: {
892: /* Control register bits:
893: * 0x80: busy bit
894: * - Turn on Blitter activity and stay "1" until copy finished
895: * 0x40: Blit-mode bit
896: * - 0: Blit mode, CPU and Blitter get 64 clockcycles in turns
897: * - 1: HOG Mode, Blitter reserves and hogs the bus for as long
898: * as the copy takes, CPU and DMA get no Bus access
899: * 0x20: Smudge mode
900: * - Which line of the halftone pattern to start with is
901: * read from the first source word when the copy starts
902: * 0x10: not used
903: * 0x0f
904: *
905: * The lowest 4 bits contain the Halftone pattern line number
906: */
1.1.1.7 root 907:
1.1.1.9 root 908: if (LOG_TRACE_LEVEL(TRACE_BLITTER))
1.1.1.3 root 909: {
1.1.1.9 root 910: int FrameCycles, HblCounterVideo, LineCycles;
911:
912: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
913:
914: LOG_TRACE_PRINT("blitter write ctrl=%x video_cyc=%d %d@%d pc=%x instr_cyc=%d\n" ,
1.1.1.7 root 915: IoMem_ReadByte(REG_CONTROL) ,
1.1.1.9 root 916: FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles );
1.1.1.7 root 917: }
1.1.1.3 root 918:
1.1.1.8 root 919: BlitterRegs.ctrl = IoMem_ReadByte(REG_CONTROL) & 0xEF;
920:
921: BlitterVars.hog = BlitterRegs.ctrl & 0x40;
922: BlitterVars.smudge = BlitterRegs.ctrl & 0x20;
923: BlitterVars.line = BlitterRegs.ctrl & 0xF;
1.1.1.7 root 924:
925: /* Remove old pending update interrupt */
1.1.1.10 root 926: CycInt_RemovePendingInterrupt(INTERRUPT_BLITTER);
1.1.1.7 root 927:
928: /* Busy bit set? */
1.1.1.8 root 929: if (BlitterRegs.ctrl & 0x80)
1.1.1.7 root 930: {
1.1.1.8 root 931: if (BlitterRegs.lines == 0)
1.1.1.7 root 932: {
933: /* We're done, clear busy bit */
1.1.1.8 root 934: BlitterRegs.ctrl &= ~0x80;
1.1.1.7 root 935: }
936: else
937: {
938: /* Start blitting after some CPU cycles */
1.1.1.10 root 939: CycInt_AddRelativeInterrupt((CurrentInstrCycles+nWaitStateCycles)>>nCpuFreqShift,
940: INT_CPU_CYCLE, INTERRUPT_BLITTER);
1.1.1.7 root 941: }
1.1.1.3 root 942: }
1.1 root 943: }
944:
1.1.1.3 root 945: /*-----------------------------------------------------------------------*/
1.1.1.5 root 946: /**
947: * Write to blitter skew register.
948: */
1.1.1.3 root 949: void Blitter_Skew_WriteByte(void)
950: {
1.1.1.8 root 951: BlitterRegs.skew = IoMem_ReadByte(REG_SKEW);
952: BlitterVars.fxsr = (BlitterRegs.skew & 0x80)?1:0;
953: BlitterVars.nfsr = (BlitterRegs.skew & 0x40)?1:0;
954: BlitterVars.skew = BlitterRegs.skew & 0xF;
1.1 root 955: }
1.1.1.2 root 956:
957:
958: /*-----------------------------------------------------------------------*/
1.1.1.5 root 959: /**
1.1.1.7 root 960: * Handler which continues blitting after 64 bus cycles.
961: */
962: void Blitter_InterruptHandler(void)
963: {
1.1.1.10 root 964: CycInt_AcknowledgeInterrupt();
1.1.1.7 root 965:
1.1.1.8 root 966: if (BlitterRegs.ctrl & 0x80)
1.1.1.7 root 967: {
1.1.1.8 root 968: Blitter_Start();
1.1.1.7 root 969: }
1.1.1.8 root 970: }
1.1.1.7 root 971:
1.1.1.8 root 972: /*-----------------------------------------------------------------------*/
973: /**
974: * Save/Restore snapshot of Blitter variables.
975: */
976: void Blitter_MemorySnapShot_Capture(bool bSave)
977: {
978: /* Save/Restore details */
979: MemorySnapShot_Store(&BlitterRegs, sizeof(BlitterRegs));
980: MemorySnapShot_Store(&BlitterVars, sizeof(BlitterVars));
981: MemorySnapShot_Store(&BlitterHalftone, sizeof(BlitterHalftone));
1.1.1.2 root 982: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.