|
|
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.14! root 71:
! 72: #define BLITTER_READ_WORD_BUS_ERR 0x0000 /* This value is returned when the blitter try to read a word */
! 73: /* in a region that would cause a bus error */
! 74: /* [NP] FIXME : for now we return a constant, but it should depend on the bus activity */
! 75:
1.1.1.8 root 76: /* Blitter registers */
77: typedef struct
78: {
79: Uint32 src_addr;
80: Uint32 dst_addr;
81: Uint32 words;
82: Uint32 lines;
83: short src_x_incr;
84: short src_y_incr;
85: short dst_x_incr;
86: short dst_y_incr;
87: Uint16 end_mask_1;
88: Uint16 end_mask_2;
89: Uint16 end_mask_3;
90: Uint8 hop;
91: Uint8 lop;
92: Uint8 ctrl;
93: Uint8 skew;
94: } BLITTERREGS;
95:
96: /* Blitter vars */
97: typedef struct
98: {
1.1.1.9 root 99: int pass_cycles;
100: int op_cycles;
1.1.1.8 root 101: Uint32 buffer;
102: Uint32 src_words_reset;
103: Uint32 dst_words_reset;
104: Uint32 src_words;
105: Uint8 hog;
106: Uint8 smudge;
107: Uint8 line;
108: Uint8 fxsr;
109: Uint8 nfsr;
110: Uint8 skew;
111: } BLITTERVARS;
112:
113: /* Blitter state */
114: typedef struct
115: {
116: Uint16 src_word;
117: Uint16 dst_word;
118: Uint16 end_mask;
119: Uint8 have_src;
120: Uint8 have_dst;
121: Uint8 fxsr;
122: Uint8 nfsr;
123: } BLITTERSTATE;
124:
1.1.1.9 root 125: /* Blitter logical op func */
126: typedef Uint16 (*BLITTER_OP_FUNC)(void);
127:
1.1.1.8 root 128: static BLITTERREGS BlitterRegs;
129: static BLITTERVARS BlitterVars;
130: static BLITTERSTATE BlitterState;
131: static Uint16 BlitterHalftone[16];
1.1.1.3 root 132:
1.1.1.9 root 133: static BLITTER_OP_FUNC Blitter_ComputeHOP;
134: static BLITTER_OP_FUNC Blitter_ComputeLOP;
135:
1.1.1.8 root 136: /*-----------------------------------------------------------------------*/
137: /**
138: * Count blitter cycles
139: */
1.1.1.3 root 140:
1.1.1.8 root 141: static void Blitter_AddCycles(int cycles)
1.1.1.4 root 142: {
1.1.1.8 root 143: int all_cycles = cycles + nWaitStateCycles;
1.1.1.4 root 144:
1.1.1.9 root 145: BlitterVars.op_cycles += all_cycles;
1.1.1.4 root 146:
1.1.1.9 root 147: nCyclesMainCounter += all_cycles >> nCpuFreqShift;
1.1.1.14! root 148: CyclesGlobalClockCounter += all_cycles >> nCpuFreqShift;
1.1.1.8 root 149: nWaitStateCycles = 0;
1.1.1.9 root 150: }
151:
152: static void Blitter_FlushCycles(void)
153: {
154: int op_cycles = INT_CONVERT_TO_INTERNAL(BlitterVars.op_cycles, INT_CPU_CYCLE);
155:
156: BlitterVars.pass_cycles += BlitterVars.op_cycles;
157: BlitterVars.op_cycles = 0;
1.1.1.8 root 158:
1.1.1.9 root 159: PendingInterruptCount -= op_cycles;
1.1.1.8 root 160: while (PendingInterruptCount <= 0 && PendingInterruptFunction)
161: CALL_VAR(PendingInterruptFunction);
1.1 root 162: }
163:
1.1.1.14! root 164:
! 165: /*-----------------------------------------------------------------------*/
! 166: /**
! 167: * Handle bus arbitration when switching between CPU and Blitter
! 168: * When a write is made to FF8A3C to start the blitter, it will take a few cycles
! 169: * before doing the bus arbitration. During this time the CPU will be able to
! 170: * partially execute the next instruction in parallel to the blitter
! 171: * (until an access to the BUS is needed by the CPU).
! 172: *
! 173: * NOTE [NP] : this is mostly handled with hardcoded cases for now, as it
! 174: * requires cycle exact emulation to exactly know when bus is accessed
! 175: * by the CPU to prefetch the next word.
! 176: * More tests are needed on a real STE to have a proper model of this.
! 177: *
! 178: * Based on several examples, possible sequence when starting the blitter seems to be :
! 179: * - t+0 : write to FF8A3C
! 180: * - t+0 : CPU can still run during 4 cycles and access bus
! 181: * - t+4 : bus arbitration takes 4 cycles (no access for cpu and blitter during this time)
! 182: * - t+8 : blitter owns the bus and starts tranferring data
! 183: *
! 184: * When blitter stops owning the bus in favor of the cpu, this seems to always take 4 cycles
! 185: */
! 186: static void Blitter_BusArbitration ( int RequestBusMode )
! 187: {
! 188: int cycles;
! 189:
! 190: if ( RequestBusMode == BUS_MODE_BLITTER ) /* Bus is requested by the blitter */
! 191: {
! 192: //fprintf ( stderr , "blitter start pc %x %x\n" , M68000_GetPC() , M68000_InstrPC );
! 193: cycles = 4; /* Default case : take 4 cycles when going from cpu to blitter */
! 194:
! 195: /* Different timing for some specific cases */
! 196:
! 197: /* 'Relapse - Graphix Sound 2' by Cybernetics (overscan plasma using blitter) */
! 198: /* $e764 : move.b d5,(a4) + dbra d1,$fff2 : 4 cycles of the dbra can be executed while blitter starts */
! 199: if ( STMemory_ReadLong ( M68000_InstrPC ) == 0x188551c9 ) /* PC = E764 */
! 200: cycles = 4-4; /* 4 cycles less than default case */
! 201: }
! 202:
! 203: else /* Bus is requested by the cpu */
! 204: {
! 205: cycles = 4; /* Always 4 cycles ? */
! 206: }
! 207:
! 208: /* Add arbitration cycles and update BusMode */
! 209: if ( cycles > 0 )
! 210: {
! 211: Blitter_AddCycles(cycles);
! 212: Blitter_FlushCycles();
! 213: }
! 214: BusMode = RequestBusMode;
! 215: }
! 216:
! 217:
1.1.1.8 root 218: /*-----------------------------------------------------------------------*/
219: /**
220: * Read & Write operations
221: */
222: static Uint16 Blitter_ReadWord(Uint32 addr)
1.1.1.7 root 223: {
1.1.1.8 root 224: Uint16 value;
1.1 root 225:
1.1.1.14! root 226: /* When reading from a bus error region, just return a constant */
! 227: if ( STMemory_CheckRegionBusError ( addr ) )
! 228: value = BLITTER_READ_WORD_BUS_ERR;
1.1.1.8 root 229: else
1.1.1.14! root 230: value = (Uint16)get_word ( addr );
! 231: //fprintf ( stderr , "read %x %x %x\n" , addr , value , STMemory_CheckRegionBusError(addr) );
1.1.1.7 root 232:
1.1.1.8 root 233: Blitter_AddCycles(4);
1.1.1.7 root 234:
1.1.1.8 root 235: return value;
236: }
237:
238: static void Blitter_WriteWord(Uint32 addr, Uint16 value)
239: {
1.1.1.14! root 240: /* Call put_word only if the address doesn't point to a bus error region */
! 241: if ( STMemory_CheckRegionBusError ( addr ) == false )
! 242: put_word ( addr , (Uint32)(value) );
! 243: //fprintf ( stderr , "write %x %x %x\n" , addr , value , STMemory_CheckRegionBusError(addr) );
1.1.1.7 root 244:
1.1.1.8 root 245: Blitter_AddCycles(4);
1.1.1.7 root 246: }
247:
1.1.1.8 root 248: /*-----------------------------------------------------------------------*/
1.1.1.7 root 249: /**
1.1.1.8 root 250: * Blitter emulation - level 1
1.1.1.7 root 251: */
1.1.1.8 root 252:
253: static void Blitter_BeginLine(void)
1.1.1.7 root 254: {
1.1.1.8 root 255: BlitterVars.src_words = BlitterVars.src_words_reset;
256: }
1.1.1.7 root 257:
1.1.1.8 root 258: static void Blitter_SetState(Uint8 fxsr, Uint8 nfsr, Uint16 end_mask)
259: {
260: BlitterState.end_mask = end_mask;
261: BlitterState.have_src = false;
262: BlitterState.have_dst = false;
263: BlitterState.fxsr = fxsr;
264: BlitterState.nfsr = nfsr;
265: }
266:
267: static void Blitter_SourceShift(void)
268: {
269: if (BlitterRegs.src_x_incr < 0)
270: BlitterVars.buffer >>= 16;
271: else
272: BlitterVars.buffer <<= 16;
273: }
274:
275: static void Blitter_SourceFetch(void)
276: {
277: Uint32 src_word = (Uint32)Blitter_ReadWord(BlitterRegs.src_addr);
278:
279: if (BlitterRegs.src_x_incr < 0)
280: BlitterVars.buffer |= src_word << 16;
281: else
282: BlitterVars.buffer |= src_word;
283:
284: if (BlitterVars.src_words == 1)
1.1.1.7 root 285: {
1.1.1.8 root 286: BlitterRegs.src_addr += BlitterRegs.src_y_incr;
287: }
288: else
289: {
290: --BlitterVars.src_words;
291: BlitterRegs.src_addr += BlitterRegs.src_x_incr;
1.1.1.7 root 292: }
293: }
294:
1.1.1.8 root 295: static Uint16 Blitter_SourceRead(void)
296: {
297: if (!BlitterState.have_src)
298: {
299: if (BlitterState.fxsr)
300: {
301: Blitter_SourceShift();
302: Blitter_SourceFetch();
303: }
1.1.1.7 root 304:
1.1.1.8 root 305: Blitter_SourceShift();
1.1.1.7 root 306:
1.1.1.8 root 307: if (!BlitterState.nfsr)
308: {
309: Blitter_SourceFetch();
310: }
1.1.1.7 root 311:
1.1.1.8 root 312: BlitterState.src_word = (Uint16)(BlitterVars.buffer >> BlitterVars.skew);
313: BlitterState.have_src = true;
1.1.1.7 root 314: }
1.1 root 315:
1.1.1.8 root 316: return BlitterState.src_word;
317: }
1.1 root 318:
1.1.1.8 root 319: static Uint16 Blitter_GetHalftoneWord(void)
320: {
321: if (BlitterVars.smudge)
322: return BlitterHalftone[Blitter_SourceRead() & 15];
323: else
324: return BlitterHalftone[BlitterVars.line];
325: }
1.1.1.4 root 326:
1.1.1.9 root 327: /* HOP */
328:
329: static Uint16 Blitter_HOP_0(void)
1.1 root 330: {
1.1.1.9 root 331: return 0xFFFF;
332: }
1.1.1.7 root 333:
1.1.1.9 root 334: static Uint16 Blitter_HOP_1(void)
335: {
336: return Blitter_GetHalftoneWord();
337: }
338:
339: static Uint16 Blitter_HOP_2(void)
340: {
341: return Blitter_SourceRead();
342: }
1.1.1.8 root 343:
1.1.1.9 root 344: static Uint16 Blitter_HOP_3(void)
345: {
346: return Blitter_SourceRead() & Blitter_GetHalftoneWord();
1.1.1.8 root 347: }
348:
1.1.1.9 root 349: static BLITTER_OP_FUNC Blitter_HOP_Table [4] =
350: {
351: Blitter_HOP_0,
352: Blitter_HOP_1,
353: Blitter_HOP_2,
354: Blitter_HOP_3
355: };
356:
357: static void Blitter_Select_HOP(void)
358: {
359: Blitter_ComputeHOP = Blitter_HOP_Table[BlitterRegs.hop];
360: }
361:
362: /* end HOP */
363:
1.1.1.8 root 364: static Uint16 Blitter_DestRead(void)
365: {
366: if (!BlitterState.have_dst)
367: {
368: BlitterState.dst_word = Blitter_ReadWord(BlitterRegs.dst_addr);
369: BlitterState.have_dst = true;
370: }
371:
372: return BlitterState.dst_word;
373: }
374:
1.1.1.9 root 375: /* LOP */
376:
377: static Uint16 Blitter_LOP_0(void)
378: {
379: return 0;
380: }
381:
382: static Uint16 Blitter_LOP_1(void)
1.1.1.8 root 383: {
1.1.1.9 root 384: return Blitter_ComputeHOP() & Blitter_DestRead();
385: }
1.1.1.8 root 386:
1.1.1.9 root 387: static Uint16 Blitter_LOP_2(void)
388: {
389: return Blitter_ComputeHOP() & ~Blitter_DestRead();
390: }
391:
392: static Uint16 Blitter_LOP_3(void)
393: {
394: return Blitter_ComputeHOP();
395: }
396:
397: static Uint16 Blitter_LOP_4(void)
398: {
399: return ~Blitter_ComputeHOP() & Blitter_DestRead();
400: }
401:
402: static Uint16 Blitter_LOP_5(void)
403: {
404: return Blitter_DestRead();
405: }
406:
407: static Uint16 Blitter_LOP_6(void)
408: {
409: return Blitter_ComputeHOP() ^ Blitter_DestRead();
410: }
411:
412: static Uint16 Blitter_LOP_7(void)
413: {
414: return Blitter_ComputeHOP() | Blitter_DestRead();
415: }
416:
417: static Uint16 Blitter_LOP_8(void)
418: {
419: return ~Blitter_ComputeHOP() & ~Blitter_DestRead();
420: }
421:
422: static Uint16 Blitter_LOP_9(void)
423: {
424: return ~Blitter_ComputeHOP() ^ Blitter_DestRead();
425: }
426:
427: static Uint16 Blitter_LOP_A(void)
428: {
429: return ~Blitter_DestRead();
430: }
1.1.1.8 root 431:
1.1.1.9 root 432: static Uint16 Blitter_LOP_B(void)
433: {
434: return Blitter_ComputeHOP() | ~Blitter_DestRead();
1.1.1.8 root 435: }
436:
1.1.1.9 root 437: static Uint16 Blitter_LOP_C(void)
438: {
439: return ~Blitter_ComputeHOP();
440: }
441:
442: static Uint16 Blitter_LOP_D(void)
443: {
444: return ~Blitter_ComputeHOP() | Blitter_DestRead();
445: }
446:
447: static Uint16 Blitter_LOP_E(void)
448: {
449: return ~Blitter_ComputeHOP() | ~Blitter_DestRead();
450: }
451:
452: static Uint16 Blitter_LOP_F(void)
453: {
454: return 0xFFFF;
455: }
456:
457: static BLITTER_OP_FUNC Blitter_LOP_Table [16] =
458: {
459: Blitter_LOP_0,
460: Blitter_LOP_1,
461: Blitter_LOP_2,
462: Blitter_LOP_3,
463: Blitter_LOP_4,
464: Blitter_LOP_5,
465: Blitter_LOP_6,
466: Blitter_LOP_7,
467: Blitter_LOP_8,
468: Blitter_LOP_9,
469: Blitter_LOP_A,
470: Blitter_LOP_B,
471: Blitter_LOP_C,
472: Blitter_LOP_D,
473: Blitter_LOP_E,
474: Blitter_LOP_F
475: };
476:
477: static void Blitter_Select_LOP(void)
478: {
479: Blitter_ComputeLOP = Blitter_LOP_Table[BlitterRegs.lop];
480: }
481:
482: /* end LOP */
483:
1.1.1.8 root 484: static Uint16 Blitter_ComputeMask(void)
485: {
486: return (Blitter_ComputeLOP() & BlitterState.end_mask) |
487: (Blitter_DestRead() & ~BlitterState.end_mask);
488: }
489:
490: static void Blitter_ProcessWord(void)
491: {
492: /* when NFSR, a read-modify-write is always performed */
493: Uint16 dst_data = ((BlitterState.nfsr || BlitterState.end_mask != 0xFFFF)
494: ? Blitter_ComputeMask()
495: : Blitter_ComputeLOP());
496:
497: Blitter_WriteWord(BlitterRegs.dst_addr, dst_data);
1.1 root 498:
1.1.1.8 root 499: if (BlitterRegs.words == 1)
1.1.1.7 root 500: {
1.1.1.8 root 501: BlitterRegs.dst_addr += BlitterRegs.dst_y_incr;
1.1.1.7 root 502: }
1.1.1.8 root 503: else
1.1.1.7 root 504: {
1.1.1.8 root 505: --BlitterRegs.words;
506: BlitterRegs.dst_addr += BlitterRegs.dst_x_incr;
1.1.1.7 root 507: }
1.1.1.8 root 508: }
509:
510: static void Blitter_EndLine(void)
511: {
512: --BlitterRegs.lines;
513: BlitterRegs.words = BlitterVars.dst_words_reset;
1.1.1.7 root 514:
1.1.1.8 root 515: if (BlitterRegs.dst_y_incr >= 0)
516: BlitterVars.line = (BlitterVars.line+1) & 15;
1.1.1.7 root 517: else
1.1.1.8 root 518: BlitterVars.line = (BlitterVars.line-1) & 15;
519: }
520:
521: /*-----------------------------------------------------------------------*/
522: /**
523: * Blitter emulation - level 2
524: */
525:
526: static void Blitter_SingleWord(void)
527: {
528: Blitter_BeginLine();
529: Blitter_SetState(BlitterVars.fxsr, BlitterVars.nfsr, BlitterRegs.end_mask_1);
530: Blitter_ProcessWord();
531: Blitter_EndLine();
532: }
533:
534: static void Blitter_FirstWord(void)
535: {
536: Blitter_BeginLine();
537: Blitter_SetState(BlitterVars.fxsr, 0, BlitterRegs.end_mask_1);
538: Blitter_ProcessWord();
539: }
540:
541: static void Blitter_MiddleWord(void)
542: {
543: Blitter_SetState(0, 0, BlitterRegs.end_mask_2);
544: Blitter_ProcessWord();
545: }
1.1.1.7 root 546:
1.1.1.8 root 547: static void Blitter_LastWord(void)
548: {
549: Blitter_SetState(0, BlitterVars.nfsr, BlitterRegs.end_mask_3);
550: Blitter_ProcessWord();
551: Blitter_EndLine();
1.1.1.7 root 552: }
1.1 root 553:
1.1.1.8 root 554: static void Blitter_Step(void)
555: {
556: if (BlitterVars.dst_words_reset == 1)
557: {
558: Blitter_SingleWord();
559: }
560: else if (BlitterRegs.words == BlitterVars.dst_words_reset)
561: {
562: Blitter_FirstWord();
563: }
564: else if (BlitterRegs.words == 1)
565: {
566: Blitter_LastWord();
567: }
568: else
569: {
570: Blitter_MiddleWord();
571: }
572: }
1.1 root 573:
1.1.1.3 root 574: /*-----------------------------------------------------------------------*/
1.1.1.5 root 575: /**
1.1.1.7 root 576: * Let's do the blit.
577: * Note that in non-HOG mode, the blitter only runs for 64 bus cycles (2 MHz!)
578: * before giving the bus back to the CPU. Due to this mode, this function must
579: * be able to abort and resume the blitting at any time.
1.1.1.5 root 580: */
1.1.1.8 root 581: static void Blitter_Start(void)
1.1.1.4 root 582: {
1.1.1.9 root 583: /* select HOP & LOP funcs */
584: Blitter_Select_HOP();
585: Blitter_Select_LOP();
586:
1.1.1.8 root 587: /* setup vars */
1.1.1.9 root 588: BlitterVars.pass_cycles = 0;
589: BlitterVars.op_cycles = 0;
1.1.1.12 root 590: BlitterVars.src_words_reset = BlitterVars.dst_words_reset + BlitterVars.fxsr - BlitterVars.nfsr;
1.1.1.8 root 591:
592: /* bus arbitration */
1.1.1.14! root 593: Blitter_BusArbitration ( BUS_MODE_BLITTER );
! 594:
! 595: /* Busy=1, set line to high/1 and clear interrupt */
! 596: MFP_GPIP_Set_Line_Input ( MFP_GPIP_LINE_GPU_DONE , MFP_GPIP_STATE_HIGH );
1.1.1.7 root 597:
598: /* Now we enter the main blitting loop */
599: do
600: {
1.1.1.8 root 601: Blitter_Step();
1.1.1.9 root 602: Blitter_FlushCycles();
1.1.1.8 root 603: }
604: while (BlitterRegs.lines > 0
1.1.1.9 root 605: && (BlitterVars.hog || BlitterVars.pass_cycles < NONHOG_CYCLES));
1.1.1.7 root 606:
1.1.1.8 root 607: /* bus arbitration */
1.1.1.14! root 608: Blitter_BusArbitration ( BUS_MODE_CPU );
1.1.1.7 root 609:
1.1.1.8 root 610: BlitterRegs.ctrl = (BlitterRegs.ctrl & 0xF0) | BlitterVars.line;
1.1.1.7 root 611:
1.1.1.8 root 612: if (BlitterRegs.lines == 0)
613: {
1.1.1.14! root 614: /* We're done, clear busy and hog bits */
! 615: BlitterRegs.ctrl &= ~(0x80|0x40);
1.1.1.7 root 616:
1.1.1.14! root 617: /* Busy=0, set line to low/0 and request interrupt */
! 618: MFP_GPIP_Set_Line_Input ( MFP_GPIP_LINE_GPU_DONE , MFP_GPIP_STATE_LOW );
1.1.1.7 root 619: }
1.1.1.8 root 620: else
1.1.1.7 root 621: {
1.1.1.8 root 622: /* Continue blitting later */
1.1.1.10 root 623: CycInt_AddRelativeInterrupt(NONHOG_CYCLES, INT_CPU_CYCLE, INTERRUPT_BLITTER);
1.1.1.7 root 624: }
625: }
626:
1.1.1.8 root 627: /*-----------------------------------------------------------------------*/
628: /**
629: * Read blitter halftone ram.
630: */
631: static void Blitter_Halftone_ReadWord(int index)
632: {
633: IoMem_WriteWord(REG_HT_RAM + index + index, BlitterHalftone[index]);
634: }
635:
636: void Blitter_Halftone00_ReadWord(void) { Blitter_Halftone_ReadWord(0); }
637: void Blitter_Halftone01_ReadWord(void) { Blitter_Halftone_ReadWord(1); }
638: void Blitter_Halftone02_ReadWord(void) { Blitter_Halftone_ReadWord(2); }
639: void Blitter_Halftone03_ReadWord(void) { Blitter_Halftone_ReadWord(3); }
640: void Blitter_Halftone04_ReadWord(void) { Blitter_Halftone_ReadWord(4); }
641: void Blitter_Halftone05_ReadWord(void) { Blitter_Halftone_ReadWord(5); }
642: void Blitter_Halftone06_ReadWord(void) { Blitter_Halftone_ReadWord(6); }
643: void Blitter_Halftone07_ReadWord(void) { Blitter_Halftone_ReadWord(7); }
644: void Blitter_Halftone08_ReadWord(void) { Blitter_Halftone_ReadWord(8); }
645: void Blitter_Halftone09_ReadWord(void) { Blitter_Halftone_ReadWord(9); }
646: void Blitter_Halftone10_ReadWord(void) { Blitter_Halftone_ReadWord(10); }
647: void Blitter_Halftone11_ReadWord(void) { Blitter_Halftone_ReadWord(11); }
648: void Blitter_Halftone12_ReadWord(void) { Blitter_Halftone_ReadWord(12); }
649: void Blitter_Halftone13_ReadWord(void) { Blitter_Halftone_ReadWord(13); }
650: void Blitter_Halftone14_ReadWord(void) { Blitter_Halftone_ReadWord(14); }
651: void Blitter_Halftone15_ReadWord(void) { Blitter_Halftone_ReadWord(15); }
652:
653: /*-----------------------------------------------------------------------*/
654: /**
655: * Read blitter source x increment (0xff8a20).
656: */
657: void Blitter_SourceXInc_ReadWord(void)
658: {
659: IoMem_WriteWord(REG_SRC_X_INC, (Uint16)(BlitterRegs.src_x_incr));
660: }
661:
662: /*-----------------------------------------------------------------------*/
663: /**
664: * Read blitter source y increment (0xff8a22).
665: */
666: void Blitter_SourceYInc_ReadWord(void)
667: {
668: IoMem_WriteWord(REG_SRC_Y_INC, (Uint16)(BlitterRegs.src_y_incr));
669: }
1.1.1.7 root 670:
671: /*-----------------------------------------------------------------------*/
672: /**
673: * Read blitter source address (0xff8a24).
674: */
675: void Blitter_SourceAddr_ReadLong(void)
676: {
1.1.1.8 root 677: IoMem_WriteLong(REG_SRC_ADDR, BlitterRegs.src_addr);
1.1.1.4 root 678: }
679:
680: /*-----------------------------------------------------------------------*/
1.1.1.5 root 681: /**
682: * Read blitter endmask 1.
683: */
1.1.1.3 root 684: void Blitter_Endmask1_ReadWord(void)
1.1 root 685: {
1.1.1.8 root 686: IoMem_WriteWord(REG_END_MASK1, BlitterRegs.end_mask_1);
1.1 root 687: }
688:
1.1.1.3 root 689: /*-----------------------------------------------------------------------*/
1.1.1.5 root 690: /**
691: * Read blitter endmask 2.
692: */
1.1.1.3 root 693: void Blitter_Endmask2_ReadWord(void)
1.1 root 694: {
1.1.1.8 root 695: IoMem_WriteWord(REG_END_MASK2, BlitterRegs.end_mask_2);
1.1 root 696: }
697:
1.1.1.3 root 698: /*-----------------------------------------------------------------------*/
1.1.1.5 root 699: /**
700: * Read blitter endmask 3.
701: */
1.1.1.3 root 702: void Blitter_Endmask3_ReadWord(void)
1.1 root 703: {
1.1.1.8 root 704: IoMem_WriteWord(REG_END_MASK3, BlitterRegs.end_mask_3);
705: }
706:
707: /*-----------------------------------------------------------------------*/
708: /**
709: * Read blitter destination x increment (0xff8a2E).
710: */
711: void Blitter_DestXInc_ReadWord(void)
712: {
713: IoMem_WriteWord(REG_DST_X_INC, (Uint16)(BlitterRegs.dst_x_incr));
714: }
715:
716: /*-----------------------------------------------------------------------*/
717: /**
718: * Read blitter destination y increment (0xff8a30).
719: */
720: void Blitter_DestYInc_ReadWord(void)
721: {
722: IoMem_WriteWord(REG_DST_Y_INC, (Uint16)(BlitterRegs.dst_y_incr));
1.1 root 723: }
724:
1.1.1.3 root 725: /*-----------------------------------------------------------------------*/
1.1.1.5 root 726: /**
727: * Read blitter destination address.
728: */
1.1.1.3 root 729: void Blitter_DestAddr_ReadLong(void)
1.1 root 730: {
1.1.1.8 root 731: IoMem_WriteLong(REG_DST_ADDR, BlitterRegs.dst_addr);
1.1 root 732: }
733:
1.1.1.3 root 734: /*-----------------------------------------------------------------------*/
1.1.1.5 root 735: /**
736: * Read blitter words-per-line register.
737: */
1.1.1.3 root 738: void Blitter_WordsPerLine_ReadWord(void)
1.1 root 739: {
1.1.1.8 root 740: IoMem_WriteWord(REG_X_COUNT, (Uint16)(BlitterRegs.words & 0xFFFF));
1.1 root 741: }
742:
1.1.1.3 root 743: /*-----------------------------------------------------------------------*/
1.1.1.5 root 744: /**
745: * Read blitter lines-per-bitblock register.
746: */
1.1.1.3 root 747: void Blitter_LinesPerBitblock_ReadWord(void)
1.1 root 748: {
1.1.1.8 root 749: IoMem_WriteWord(REG_Y_COUNT, (Uint16)(BlitterRegs.lines & 0xFFFF));
1.1 root 750: }
751:
1.1.1.3 root 752: /*-----------------------------------------------------------------------*/
1.1.1.5 root 753: /**
754: * Read blitter halftone operation register.
755: */
1.1.1.3 root 756: void Blitter_HalftoneOp_ReadByte(void)
1.1 root 757: {
1.1.1.8 root 758: IoMem_WriteByte(REG_BLIT_HOP, BlitterRegs.hop);
1.1 root 759: }
760:
1.1.1.3 root 761: /*-----------------------------------------------------------------------*/
1.1.1.5 root 762: /**
763: * Read blitter logical operation register.
764: */
1.1.1.3 root 765: void Blitter_LogOp_ReadByte(void)
1.1 root 766: {
1.1.1.8 root 767: IoMem_WriteByte(REG_BLIT_LOP, BlitterRegs.lop);
1.1 root 768: }
769:
1.1.1.3 root 770: /*-----------------------------------------------------------------------*/
1.1.1.5 root 771: /**
772: * Read blitter control register.
773: */
1.1.1.4 root 774: void Blitter_Control_ReadByte(void)
1.1 root 775: {
1.1.1.7 root 776: /* busy, hog/blit, smudge, n/a, 4bits for line number */
1.1.1.8 root 777: IoMem_WriteByte(REG_CONTROL, BlitterRegs.ctrl);
1.1 root 778: }
779:
1.1.1.3 root 780: /*-----------------------------------------------------------------------*/
1.1.1.5 root 781: /**
782: * Read blitter skew register.
783: */
1.1.1.3 root 784: void Blitter_Skew_ReadByte(void)
1.1 root 785: {
1.1.1.8 root 786: IoMem_WriteByte(REG_SKEW, BlitterRegs.skew);
787: }
788:
789:
790: /*-----------------------------------------------------------------------*/
791: /**
792: * Write to blitter halftone ram.
793: */
794: static void Blitter_Halftone_WriteWord(int index)
795: {
796: BlitterHalftone[index] = IoMem_ReadWord(REG_HT_RAM + index + index);
797: }
798:
799: void Blitter_Halftone00_WriteWord(void) { Blitter_Halftone_WriteWord(0); }
800: void Blitter_Halftone01_WriteWord(void) { Blitter_Halftone_WriteWord(1); }
801: void Blitter_Halftone02_WriteWord(void) { Blitter_Halftone_WriteWord(2); }
802: void Blitter_Halftone03_WriteWord(void) { Blitter_Halftone_WriteWord(3); }
803: void Blitter_Halftone04_WriteWord(void) { Blitter_Halftone_WriteWord(4); }
804: void Blitter_Halftone05_WriteWord(void) { Blitter_Halftone_WriteWord(5); }
805: void Blitter_Halftone06_WriteWord(void) { Blitter_Halftone_WriteWord(6); }
806: void Blitter_Halftone07_WriteWord(void) { Blitter_Halftone_WriteWord(7); }
807: void Blitter_Halftone08_WriteWord(void) { Blitter_Halftone_WriteWord(8); }
808: void Blitter_Halftone09_WriteWord(void) { Blitter_Halftone_WriteWord(9); }
809: void Blitter_Halftone10_WriteWord(void) { Blitter_Halftone_WriteWord(10); }
810: void Blitter_Halftone11_WriteWord(void) { Blitter_Halftone_WriteWord(11); }
811: void Blitter_Halftone12_WriteWord(void) { Blitter_Halftone_WriteWord(12); }
812: void Blitter_Halftone13_WriteWord(void) { Blitter_Halftone_WriteWord(13); }
813: void Blitter_Halftone14_WriteWord(void) { Blitter_Halftone_WriteWord(14); }
814: void Blitter_Halftone15_WriteWord(void) { Blitter_Halftone_WriteWord(15); }
815:
816: /*-----------------------------------------------------------------------*/
817: /**
818: * Write to blitter source x increment.
819: */
820: void Blitter_SourceXInc_WriteWord(void)
821: {
822: BlitterRegs.src_x_incr = (short)(IoMem_ReadWord(REG_SRC_X_INC) & 0xFFFE);
1.1 root 823: }
824:
1.1.1.8 root 825: /*-----------------------------------------------------------------------*/
826: /**
827: * Write to blitter source y increment.
828: */
829: void Blitter_SourceYInc_WriteWord(void)
830: {
831: BlitterRegs.src_y_incr = (short)(IoMem_ReadWord(REG_SRC_Y_INC) & 0xFFFE);
832: }
1.1 root 833:
1.1.1.3 root 834: /*-----------------------------------------------------------------------*/
1.1.1.5 root 835: /**
1.1.1.7 root 836: * Write to blitter source address register (0xff8a24).
837: */
838: void Blitter_SourceAddr_WriteLong(void)
839: {
1.1.1.14! root 840: if ( ConfigureParams.System.bAddressSpace24 == true )
! 841: BlitterRegs.src_addr = IoMem_ReadLong(REG_SRC_ADDR) & 0x00FFFFFE; /* Normal STF/STE */
! 842: else
! 843: BlitterRegs.src_addr = IoMem_ReadLong(REG_SRC_ADDR) & 0xFFFFFFFE; /* Falcon with extra TT RAM */
1.1.1.7 root 844: }
845:
846: /*-----------------------------------------------------------------------*/
847: /**
1.1.1.5 root 848: * Write to blitter endmask 1.
849: */
1.1.1.3 root 850: void Blitter_Endmask1_WriteWord(void)
1.1 root 851: {
1.1.1.8 root 852: BlitterRegs.end_mask_1 = IoMem_ReadWord(REG_END_MASK1);
1.1 root 853: }
854:
1.1.1.3 root 855: /*-----------------------------------------------------------------------*/
1.1.1.5 root 856: /**
857: * Write to blitter endmask 2.
858: */
1.1.1.3 root 859: void Blitter_Endmask2_WriteWord(void)
1.1 root 860: {
1.1.1.8 root 861: BlitterRegs.end_mask_2 = IoMem_ReadWord(REG_END_MASK2);
1.1 root 862: }
863:
1.1.1.3 root 864: /*-----------------------------------------------------------------------*/
1.1.1.5 root 865: /**
866: * Write to blitter endmask 3.
867: */
1.1.1.3 root 868: void Blitter_Endmask3_WriteWord(void)
1.1 root 869: {
1.1.1.8 root 870: BlitterRegs.end_mask_3 = IoMem_ReadWord(REG_END_MASK3);
871: }
872:
873: /*-----------------------------------------------------------------------*/
874: /**
875: * Write to blitter destination x increment.
876: */
877: void Blitter_DestXInc_WriteWord(void)
878: {
879: BlitterRegs.dst_x_incr = (short)(IoMem_ReadWord(REG_DST_X_INC) & 0xFFFE);
880: }
881:
882: /*-----------------------------------------------------------------------*/
883: /**
884: * Write to blitter source y increment.
885: */
886: void Blitter_DestYInc_WriteWord(void)
887: {
888: BlitterRegs.dst_y_incr = (short)(IoMem_ReadWord(REG_DST_Y_INC) & 0xFFFE);
1.1 root 889: }
890:
1.1.1.3 root 891: /*-----------------------------------------------------------------------*/
1.1.1.5 root 892: /**
893: * Write to blitter destination address register.
894: */
1.1.1.3 root 895: void Blitter_DestAddr_WriteLong(void)
896: {
1.1.1.14! root 897: if ( ConfigureParams.System.bAddressSpace24 == true )
! 898: BlitterRegs.dst_addr = IoMem_ReadLong(REG_DST_ADDR) & 0x00FFFFFE; /* Normal STF/STE */
! 899: else
! 900: BlitterRegs.dst_addr = IoMem_ReadLong(REG_DST_ADDR) & 0xFFFFFFFE; /* Falcon with extra TT RAM */
1.1 root 901: }
902:
1.1.1.3 root 903: /*-----------------------------------------------------------------------*/
1.1.1.5 root 904: /**
905: * Write to blitter words-per-line register.
906: */
1.1.1.3 root 907: void Blitter_WordsPerLine_WriteWord(void)
1.1 root 908: {
1.1.1.8 root 909: Uint32 words = (Uint32)IoMem_ReadWord(REG_X_COUNT);
910:
911: if (words == 0)
912: words = 65536;
913:
914: BlitterRegs.words = words;
915: BlitterVars.dst_words_reset = words;
1.1 root 916: }
917:
1.1.1.3 root 918: /*-----------------------------------------------------------------------*/
1.1.1.5 root 919: /**
1.1.1.8 root 920: * Write to blitter lines-per-bitblock register.
1.1.1.5 root 921: */
1.1.1.3 root 922: void Blitter_LinesPerBitblock_WriteWord(void)
1.1 root 923: {
1.1.1.8 root 924: Uint32 lines = (Uint32)IoMem_ReadWord(REG_Y_COUNT);
925:
926: if (lines == 0)
927: lines = 65536;
928:
929: BlitterRegs.lines = lines;
1.1 root 930: }
931:
1.1.1.3 root 932: /*-----------------------------------------------------------------------*/
1.1.1.5 root 933: /**
934: * Write to blitter halftone operation register.
935: */
1.1.1.3 root 936: void Blitter_HalftoneOp_WriteByte(void)
1.1 root 937: {
1.1.1.4 root 938: /* h/ware reg masks out the top 6 bits! */
1.1.1.8 root 939: BlitterRegs.hop = IoMem_ReadByte(REG_BLIT_HOP) & 3;
1.1 root 940: }
941:
1.1.1.3 root 942: /*-----------------------------------------------------------------------*/
1.1.1.5 root 943: /**
944: * Write to blitter logical operation register.
945: */
1.1.1.3 root 946: void Blitter_LogOp_WriteByte(void)
1.1.1.7 root 947: {
1.1.1.4 root 948: /* h/ware reg masks out the top 4 bits! */
1.1.1.8 root 949: BlitterRegs.lop = IoMem_ReadByte(REG_BLIT_LOP) & 0xF;
1.1 root 950: }
951:
1.1.1.3 root 952: /*-----------------------------------------------------------------------*/
1.1.1.5 root 953: /**
954: * Write to blitter control register.
955: */
1.1.1.4 root 956: void Blitter_Control_WriteByte(void)
957: {
958: /* Control register bits:
959: * 0x80: busy bit
960: * - Turn on Blitter activity and stay "1" until copy finished
961: * 0x40: Blit-mode bit
962: * - 0: Blit mode, CPU and Blitter get 64 clockcycles in turns
963: * - 1: HOG Mode, Blitter reserves and hogs the bus for as long
964: * as the copy takes, CPU and DMA get no Bus access
965: * 0x20: Smudge mode
966: * - Which line of the halftone pattern to start with is
967: * read from the first source word when the copy starts
968: * 0x10: not used
969: * 0x0f
970: *
971: * The lowest 4 bits contain the Halftone pattern line number
972: */
1.1.1.7 root 973:
1.1.1.9 root 974: if (LOG_TRACE_LEVEL(TRACE_BLITTER))
1.1.1.3 root 975: {
1.1.1.9 root 976: int FrameCycles, HblCounterVideo, LineCycles;
977:
978: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
979:
980: LOG_TRACE_PRINT("blitter write ctrl=%x video_cyc=%d %d@%d pc=%x instr_cyc=%d\n" ,
1.1.1.7 root 981: IoMem_ReadByte(REG_CONTROL) ,
1.1.1.9 root 982: FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles );
1.1.1.7 root 983: }
1.1.1.3 root 984:
1.1.1.8 root 985: BlitterRegs.ctrl = IoMem_ReadByte(REG_CONTROL) & 0xEF;
986:
987: BlitterVars.hog = BlitterRegs.ctrl & 0x40;
988: BlitterVars.smudge = BlitterRegs.ctrl & 0x20;
989: BlitterVars.line = BlitterRegs.ctrl & 0xF;
1.1.1.7 root 990:
991: /* Remove old pending update interrupt */
1.1.1.10 root 992: CycInt_RemovePendingInterrupt(INTERRUPT_BLITTER);
1.1.1.7 root 993:
994: /* Busy bit set? */
1.1.1.8 root 995: if (BlitterRegs.ctrl & 0x80)
1.1.1.7 root 996: {
1.1.1.8 root 997: if (BlitterRegs.lines == 0)
1.1.1.7 root 998: {
1.1.1.14! root 999: /* We're done, clear busy and hog bits */
! 1000: BlitterRegs.ctrl &= ~(0x80|0x40);
1.1.1.7 root 1001: }
1002: else
1003: {
1004: /* Start blitting after some CPU cycles */
1.1.1.10 root 1005: CycInt_AddRelativeInterrupt((CurrentInstrCycles+nWaitStateCycles)>>nCpuFreqShift,
1006: INT_CPU_CYCLE, INTERRUPT_BLITTER);
1.1.1.7 root 1007: }
1.1.1.3 root 1008: }
1.1 root 1009: }
1010:
1.1.1.3 root 1011: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1012: /**
1013: * Write to blitter skew register.
1014: */
1.1.1.3 root 1015: void Blitter_Skew_WriteByte(void)
1016: {
1.1.1.8 root 1017: BlitterRegs.skew = IoMem_ReadByte(REG_SKEW);
1018: BlitterVars.fxsr = (BlitterRegs.skew & 0x80)?1:0;
1019: BlitterVars.nfsr = (BlitterRegs.skew & 0x40)?1:0;
1020: BlitterVars.skew = BlitterRegs.skew & 0xF;
1.1 root 1021: }
1.1.1.2 root 1022:
1023:
1024: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1025: /**
1.1.1.7 root 1026: * Handler which continues blitting after 64 bus cycles.
1027: */
1028: void Blitter_InterruptHandler(void)
1029: {
1.1.1.10 root 1030: CycInt_AcknowledgeInterrupt();
1.1.1.7 root 1031:
1.1.1.8 root 1032: if (BlitterRegs.ctrl & 0x80)
1.1.1.7 root 1033: {
1.1.1.8 root 1034: Blitter_Start();
1.1.1.7 root 1035: }
1.1.1.8 root 1036: }
1.1.1.7 root 1037:
1.1.1.8 root 1038: /*-----------------------------------------------------------------------*/
1039: /**
1040: * Save/Restore snapshot of Blitter variables.
1041: */
1042: void Blitter_MemorySnapShot_Capture(bool bSave)
1043: {
1044: /* Save/Restore details */
1045: MemorySnapShot_Store(&BlitterRegs, sizeof(BlitterRegs));
1046: MemorySnapShot_Store(&BlitterVars, sizeof(BlitterVars));
1047: MemorySnapShot_Store(&BlitterHalftone, sizeof(BlitterHalftone));
1.1.1.2 root 1048: }
1.1.1.12 root 1049:
1050: /*-----------------------------------------------------------------------*/
1051: /**
1052: * Show Blitter register values.
1053: */
1.1.1.14! root 1054: void Blitter_Info(FILE *fp, Uint32 dummy)
1.1.1.12 root 1055: {
1056: BLITTERREGS *regs = &BlitterRegs;
1057:
1058: fprintf(fp, "src addr: 0x%06x\n", regs->src_addr);
1059: fprintf(fp, "dst addr: 0x%06x\n", regs->dst_addr);
1060: fprintf(fp, "words: %u\n", regs->words);
1061: fprintf(fp, "lines: %u\n", regs->lines);
1062: fprintf(fp, "src X-inc: %hd\n", regs->src_x_incr);
1063: fprintf(fp, "src Y-inc: %hd\n", regs->src_y_incr);
1064: fprintf(fp, "dst X-inc: %hd\n", regs->dst_x_incr);
1065: fprintf(fp, "dst Y-inc: %hd\n", regs->dst_y_incr);
1066: fprintf(fp, "end mask1: 0x%04x\n", regs->end_mask_1);
1067: fprintf(fp, "end mask2: 0x%04x\n", regs->end_mask_2);
1068: fprintf(fp, "end mask3: 0x%04x\n", regs->end_mask_3);
1069: fprintf(fp, "HOP: 0x%02x\n", regs->hop);
1070: fprintf(fp, "LOP: 0x%02x\n", regs->lop);
1071: fprintf(fp, "control: 0x%02x\n", regs->ctrl);
1072: fprintf(fp, "skew: 0x%02x\n", regs->skew);
1.1.1.13 root 1073: 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 1074: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.