|
|
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.16 root 27:
28:
29: /*
30:
31: NOTES [NP] : As of August 2017, the blitter code was partly rewritten to allow cycle exact bus accesses
32: between the blitter and the CPU, allowing to have CPU instruction running in parallel to the blitter
33: when the CPU doesn't need to access the bus.
34:
35: The internal work of the blitter regarding bus accesses was deduced from studying many cases
36: on a real STE, including several demos using the blitter with overscan, some tests programs on
37: www.atari-forum.com (from Cyprian Konador), as well as my own tests on an STE.
38:
39: Depending on the CPU instruction used to start the blitter, we can see that the next instruction
40: can be partially or totally executed during the blit, or that it will be executed only after the blit is done.
41:
42: To understand the reason for this parallel execution, we must know the sequence used by the blitter
43: until it gets the bus and start transferring data.
44:
45: Based on several examples, possible sequence when starting the blitter seems to be :
46: - t+0 : write to FF8A3C is complete or blitter "restarts" itself in non-hog mode
47: - t+0 : CPU can still run during 4 cycles and access bus
48: - t+4 : bus arbitration takes 4 cycles (no access for CPU and blitter during this time)
49: - t+8 : blitter owns the bus and starts transferring data
50:
51: In case of MegaSTE, the arbitration to grant the bus to the blitter takes 8 cycles instead of 4.
52: But when bus is granted back to the CPU, it takes 4 cycles on both STE and MegaSTE.
53:
54: We can see there's a 4 cycles latency between when the busy bit is set and when the blitter asks
55: for a bus grant. It's during these 4 cycles that part of the next CPU instruction can be run, if the
56: current instruction that started the blitter doesn't need the bus anymore.
57:
58: For example :
59: - move.b d0,(a0) + nop : MOVE.B will do a write then a read to prefetch the next instruction
60: -> NOP will run after the blit
61: - bset #7,(a0) + nop : BSET will read first then finish with a write
62: -> NOP will run before the blit
63: - bset #7,(a0) + mulu dx,dy : BSET will read first then finish with a write. Then mulu will prefetch before the blit starts
64: -> MULU will run in parallel to the blitter
65: - bset #7,(a0) + divu dx,dy : BSET will read first then finish with a write. Then divu will run internal cycles and finish with a prefetch
66: -> all the cycles from the DIVU will run in parallel to the blitter until we reach the DIVU's prefetch
67:
68: So, by interleaving CPU instructions with some blitter transfers, it is possible to run part of those instructions
69: in parallel to the blitter, thus saving CPU cycles on some costly instructions (div,mul,...)
70:
71: - Number of bus shared between CPU and blitter : as described in Atari developers documentation,
72: when HOG mode is disabled the blitter will run during 64 bus accesses (read or write), then it
73: will give the bus to the CPU for 64 bus accesses too. But in some cases (see below), a possible
74: bug in the blitter will make it use the bus during only 63 accesses instead of 64.
75:
76: - As verified on a real STE, when the blitter owns the bus in non-hog mode, it will give back the bus to the CPU
77: exactly after the 64th (or 63th) bus access, not just after writing the result of the current word transfer.
78: For the emulation, this means the blitter's state must be preserved to be able to resume after any bus read
79: made by the blitter (blitter's operations can have between 0 and 2 reads and 1 write).
80:
81: - Blitter doing only 63 bus accesses instead of 64 in non-hog mode : my guess is that in non-hog mode the blitter
82: will always count bus accesses as soon as busy bit is set, even when it has not started to transfer its own data.
83: So, if the CPU does a bus access during the 4 cycles latency between t+0 and t+4 above, then this CPU bus access
84: will be counted by the blitter as a blitter bus access, thus effectively losing one bus access and doing
85: only 63 bus accesses after that (before granting the bus to the CPU for the next 64 bus accesses).
86:
87:
88: Some examples of demos requiring cycle exact blitter mode to correctly work :
89: - 'Relapse - Graphix Sound 2' by Cybernetics (overscan plasma using blitter)
90: This demo uses a self-calibration routine to adapt blitter code to the MegaSTE.
91: $e764 : move.b d5,(a4) + dbra d1,$fff2 : 4 cycles of the dbra can be executed while blitter starts
92:
93:
94: From an emulation point of view, the code needed for cycle exact blitter mode requires to intercept
95: bus accesses before and after they occur, as well as intercepting "do_cycle" before and after too.
96:
97: Parallel execution of the CPU is obtained by skipping as many CPU cycles as the blitter ran,
98: or by skipping CPU cycles until the next CPU bus access (at which point the CPU would stall).
99:
1.1.1.17! root 100: When HOG mode is disabled, the CPU can also stop the blitter in case it needs more than 64 bus accesses
! 101: (for example to handle some timing-sensitive interrupts). When CPU owns the bus, writing '0' to bit 7 of the control
! 102: register will stop the blitter, writing '1' will resume the blitter from where it was before being stopped.
! 103: Note that writing '0' will not end the current blitter transfer, reading 'busy' bit 7 will still return '1'.
! 104: It's only when 'y count' reaches '0' that transfer will be complete and busy bit will be cleared.
! 105:
1.1.1.16 root 106: */
107:
108: /*
109:
110: TODO : as measured on STE (as well as on Falcon), the blitter produces strange results when
111: each line is only 1 word (xcount=1) and when nfsr/fxsr are set at the same time : in some cases
112: an extra word will be read, depending also on whether src X increment is >0 or <0.
113: This was discussed in may 2017 in Hatari mailing list and a model still need to be found to cover all cases.
114:
115: */
116:
117:
118:
1.1.1.8 root 119: const char Blitter_fileid[] = "Hatari blitter.c : " __DATE__ " " __TIME__;
1.1 root 120:
121: #include <SDL_types.h>
122: #include <stdio.h>
123: #include <stdlib.h>
124:
1.1.1.2 root 125: #include "main.h"
1.1 root 126: #include "blitter.h"
1.1.1.7 root 127: #include "configuration.h"
128: #include "dmaSnd.h"
1.1.1.3 root 129: #include "ioMem.h"
130: #include "m68000.h"
1.1.1.7 root 131: #include "mfp.h"
1.1.1.2 root 132: #include "memorySnapShot.h"
1.1 root 133: #include "stMemory.h"
1.1.1.11 root 134: #include "screen.h"
1.1.1.7 root 135: #include "video.h"
1.1.1.16 root 136: #include "hatari-glue.h"
1.1.1.17! root 137: #include "falcon/dsp.h"
1.1.1.7 root 138:
1.1 root 139:
1.1.1.8 root 140: /* BLiTTER registers, incs are signed, others unsigned */
1.1.1.16 root 141: #define REG_HT_RAM 0xff8a00 /* - 0xff8a1e */
1.1 root 142:
1.1.1.4 root 143: #define REG_SRC_X_INC 0xff8a20
144: #define REG_SRC_Y_INC 0xff8a22
145: #define REG_SRC_ADDR 0xff8a24
146:
147: #define REG_END_MASK1 0xff8a28
148: #define REG_END_MASK2 0xff8a2a
149: #define REG_END_MASK3 0xff8a2c
150:
151: #define REG_DST_X_INC 0xff8a2e
152: #define REG_DST_Y_INC 0xff8a30
153: #define REG_DST_ADDR 0xff8a32
154:
1.1.1.7 root 155: #define REG_X_COUNT 0xff8a36
156: #define REG_Y_COUNT 0xff8a38
1.1.1.4 root 157:
1.1.1.16 root 158: #define REG_BLIT_HOP 0xff8a3a /* halftone blit operation byte */
159: #define REG_BLIT_LOP 0xff8a3b /* logical blit operation byte */
1.1.1.7 root 160: #define REG_CONTROL 0xff8a3c
1.1.1.16 root 161: #define REG_SKEW 0xff8a3d
1.1.1.4 root 162:
1.1.1.14 root 163:
164: #define BLITTER_READ_WORD_BUS_ERR 0x0000 /* This value is returned when the blitter try to read a word */
165: /* in a region that would cause a bus error */
166: /* [NP] FIXME : for now we return a constant, but it should depend on the bus activity */
167:
1.1.1.8 root 168: /* Blitter registers */
169: typedef struct
170: {
171: Uint32 src_addr;
172: Uint32 dst_addr;
173: Uint32 words;
174: Uint32 lines;
175: short src_x_incr;
176: short src_y_incr;
177: short dst_x_incr;
178: short dst_y_incr;
179: Uint16 end_mask_1;
180: Uint16 end_mask_2;
181: Uint16 end_mask_3;
182: Uint8 hop;
183: Uint8 lop;
184: Uint8 ctrl;
185: Uint8 skew;
186: } BLITTERREGS;
187:
188: /* Blitter vars */
189: typedef struct
190: {
1.1.1.16 root 191: Uint32 pass_cycles;
192: Uint32 op_cycles;
193: Uint32 total_cycles;
1.1.1.8 root 194: Uint32 buffer;
195: Uint32 src_words_reset;
196: Uint32 dst_words_reset;
197: Uint32 src_words;
198: Uint8 hog;
199: Uint8 smudge;
200: Uint8 line;
201: Uint8 fxsr;
202: Uint8 nfsr;
203: Uint8 skew;
204: } BLITTERVARS;
205:
206: /* Blitter state */
207: typedef struct
208: {
209: Uint16 src_word;
210: Uint16 dst_word;
211: Uint16 end_mask;
212: Uint8 have_src;
213: Uint8 have_dst;
214: Uint8 fxsr;
215: Uint8 nfsr;
1.1.1.16 root 216:
217: Uint16 CountBusBlitter; /* To count bus accesses made by the blitter */
218: Uint16 CountBusCpu; /* To count bus accesses made by the CPU */
219: Uint8 ContinueLater; /* 0=false / 1=true */
1.1.1.8 root 220: } BLITTERSTATE;
221:
1.1.1.16 root 222:
1.1.1.9 root 223: /* Blitter logical op func */
224: typedef Uint16 (*BLITTER_OP_FUNC)(void);
225:
1.1.1.8 root 226: static BLITTERREGS BlitterRegs;
227: static BLITTERVARS BlitterVars;
228: static BLITTERSTATE BlitterState;
229: static Uint16 BlitterHalftone[16];
1.1.1.3 root 230:
1.1.1.16 root 231: static BLITTER_OP_FUNC Blitter_ComputeHOP;
232: static BLITTER_OP_FUNC Blitter_ComputeLOP;
233:
234:
235:
236: /* To handle CPU/blitter bus sharing in non-hog mode (require cycle exact mode for CPU emulation) */
1.1.1.17! root 237: #define BLITTER_PHASE_STOP 0 /* blitter is completely stopped */
1.1.1.16 root 238: #define BLITTER_PHASE_PRE_START 1
239: #define BLITTER_PHASE_START 2
1.1.1.17! root 240: #define BLITTER_PHASE_RUN_TRANSFER 4 /* blitter owns the bus and transfer data */
! 241: #define BLITTER_PHASE_COUNT_CPU_BUS 8 /* cpu owns the bus during 64 accesses */
1.1.1.16 root 242: #define BLITTER_PHASE_IGNORE_LAST_CPU_CYCLES 16
1.1.1.17! root 243: #define BLITTER_PHASE_PAUSE 32 /* cpu owns the bus (COUNT_CPU_BUS) and stops the blitter */
1.1.1.16 root 244:
245: Uint16 BlitterPhase = BLITTER_PHASE_STOP; /* Internal state of the blitter */
246:
247: static Uint16 Blitter_CyclesBeforeStart; /* Number of cycles after setting busy bit before calling Blitter_Start */
248: /* (during this time, the CPU can still run and access the bus) */
249:
250: static Uint8 Blitter_HOG_CPU_FromBusAccess; /* 0 or 1 (false/true) */
251: static Uint8 Blitter_HOG_CPU_BlitterStartDuringBusAccess; /* 0 or 1 (false/true) */
252: static Uint16 Blitter_HOG_CPU_BusCountError; /* 0 or 1 (false/true) */
253: static Uint16 Blitter_HOG_CPU_IgnoreMaxCpuCycles; /* Max number of blitter cycles during which the CPU might run in parallel */
254: /* (unless the CPU is stalled earlier by a bus access) */
255:
256:
257: /* Number of bus accesses allocated to blitter and CPU in non-hog mode */
258: #define BLITTER_NONHOG_BUS_BLITTER 64 /* Can also be 63, see Blitter_HOG_CPU_BusCountError */
259: #define BLITTER_NONHOG_BUS_CPU 64
260:
261: #define BLITTER_CYCLES_PER_BUS_READ 4 /* The blitter takes 4 cycles to read 1 memory word on STE */
262: #define BLITTER_CYCLES_PER_BUS_WRITE 4 /* The blitter takes 4 cycles to write 1 memory word on STE */
263:
264:
265: /* Return 'true' if CE mode can be enabled for blitter (ie when using 68000 CE mode) */
266: #define BLITTER_RUN_CE ( ( currprefs.cpu_cycle_exact ) && ( currprefs.cpu_level == 0 ) )
267:
268:
269: /* Used to compute the blitter's usage during each VBL (for statusbar) */
270: static int BlitterStatsRate;
271:
272:
1.1.1.9 root 273:
1.1.1.8 root 274: /*-----------------------------------------------------------------------*/
275: /**
1.1.1.16 root 276: * Compute some stats for the blitter's usage during a period (eg one VBL)
277: * Used to determine a percent per VBL and show a led in the statusbar
1.1.1.8 root 278: */
1.1.1.16 root 279: void Blitter_StatsUpdateRate ( int period_cycles )
280: {
281: int percent;
282:
283: if ( period_cycles == 0 )
284: percent = 0;
285: else
286: percent = ceil ( 100.0 * BlitterVars.total_cycles / period_cycles );
287:
288: //fprintf ( stderr , "blitter %d %%\n" , percent );
289: BlitterVars.total_cycles = 0;
290: BlitterStatsRate = percent;
291: }
292:
293:
294: int Blitter_StatsGetRate ( void )
295: {
296: return BlitterStatsRate;
297: }
298:
1.1.1.3 root 299:
1.1.1.16 root 300:
301: /*-----------------------------------------------------------------------*/
302: /**
303: * Count blitter cycles (this assumes blitter and CPU runs at the same freq)
304: */
1.1.1.8 root 305: static void Blitter_AddCycles(int cycles)
1.1.1.4 root 306: {
1.1.1.15 root 307: int all_cycles = cycles + WaitStateCycles;
1.1.1.4 root 308:
1.1.1.9 root 309: BlitterVars.op_cycles += all_cycles;
1.1.1.16 root 310: BlitterVars.total_cycles += all_cycles;
311: //fprintf ( stderr , "blitter add_cyc cyc=%d total=%d cur_cyc=%lu\n" , all_cycles , BlitterVars.op_cycles , currcycle/cpucycleunit );
312: //fprintf ( stderr , "blitter src %x dst %x ycount %d\n" , BlitterRegs.src_addr , BlitterRegs.dst_addr , BlitterRegs.lines );
1.1.1.4 root 313:
1.1.1.15 root 314: nCyclesMainCounter += all_cycles;
315: CyclesGlobalClockCounter += all_cycles;
316: WaitStateCycles = 0;
1.1.1.9 root 317: }
318:
319: static void Blitter_FlushCycles(void)
320: {
321: int op_cycles = INT_CONVERT_TO_INTERNAL(BlitterVars.op_cycles, INT_CPU_CYCLE);
1.1.1.16 root 322:
323: //fprintf ( stderr , "blitter flush_cyc cyc=%d pass=%d %d cur_cyc=%lu\n" , BlitterVars.op_cycles , BlitterVars.pass_cycles , nCyclesMainCounter , currcycle/cpucycleunit );
1.1.1.9 root 324:
1.1.1.16 root 325: #if ENABLE_WINUAE_CPU
326: if ( BLITTER_RUN_CE ) /* In CE mode, flush cycles already counted in the current cpu instruction */
327: {
328: M68000_AddCycles_CE ( currcycle * 2 / CYCLE_UNIT );
329: currcycle = 0;
330: }
331: #endif
332:
1.1.1.9 root 333: PendingInterruptCount -= op_cycles;
1.1.1.8 root 334: while (PendingInterruptCount <= 0 && PendingInterruptFunction)
335: CALL_VAR(PendingInterruptFunction);
1.1.1.17! root 336:
! 337: #if ENABLE_WINUAE_CPU
! 338: /* Run DSP while blitter owns the bus */
! 339: if (bDspEnabled) {
! 340: DSP_Run(2 * BlitterVars.op_cycles);
! 341: }
! 342: #endif
! 343:
! 344: BlitterVars.pass_cycles += BlitterVars.op_cycles;
! 345: BlitterVars.op_cycles = 0;
1.1 root 346: }
347:
1.1.1.14 root 348:
349: /*-----------------------------------------------------------------------*/
350: /**
351: * Handle bus arbitration when switching between CPU and Blitter
352: * When a write is made to FF8A3C to start the blitter, it will take a few cycles
353: * before doing the bus arbitration. During this time the CPU will be able to
354: * partially execute the next instruction in parallel to the blitter
355: * (until an access to the BUS is needed by the CPU).
356: *
357: * Based on several examples, possible sequence when starting the blitter seems to be :
358: * - t+0 : write to FF8A3C
359: * - t+0 : CPU can still run during 4 cycles and access bus
360: * - t+4 : bus arbitration takes 4 cycles (no access for cpu and blitter during this time)
1.1.1.16 root 361: * - t+8 : blitter owns the bus and starts transferring data
1.1.1.15 root 362: * (in case of MegaSTE bus arbitration takes 8 cycles instead of 4)
1.1.1.14 root 363: *
364: * When blitter stops owning the bus in favor of the cpu, this seems to always take 4 cycles
365: */
366: static void Blitter_BusArbitration ( int RequestBusMode )
367: {
368: int cycles;
369:
370: if ( RequestBusMode == BUS_MODE_BLITTER ) /* Bus is requested by the blitter */
371: {
1.1.1.16 root 372: cycles = 4; /* Default case : take 4 cycles when going from cpu to blitter */
1.1.1.15 root 373: if ( ConfigureParams.System.nMachineType == MACHINE_MEGA_STE )
374: cycles = 8; /* MegaSTE blitter needs 4 extra cycles when requesting the bus */
1.1.1.16 root 375: // fprintf ( stderr , "blitter bus start pc %x %x cyc=%d cur_cyc=%lu\n" , M68000_GetPC() , M68000_InstrPC , cycles , currcycle/cpucycleunit );
1.1.1.14 root 376: }
377:
378: else /* Bus is requested by the cpu */
379: {
1.1.1.15 root 380: cycles = 4; /* Always 4 cycles (even for MegaSTE) */
1.1.1.16 root 381: // fprintf ( stderr , "blitter bus end pc %x %x cyc=%d\n" , M68000_GetPC() , M68000_InstrPC , cycles );
1.1.1.14 root 382: }
383:
384: /* Add arbitration cycles and update BusMode */
1.1.1.16 root 385: Blitter_AddCycles ( cycles );
386: Blitter_FlushCycles();
387:
1.1.1.14 root 388: BusMode = RequestBusMode;
389: }
390:
391:
1.1.1.16 root 392:
1.1.1.8 root 393: /*-----------------------------------------------------------------------*/
394: /**
1.1.1.16 root 395: * Low level memory accesses to read / write a word
396: * For each word access we increment the blitter's bus accesses counter.
1.1.1.8 root 397: */
398: static Uint16 Blitter_ReadWord(Uint32 addr)
1.1.1.7 root 399: {
1.1.1.8 root 400: Uint16 value;
1.1 root 401:
1.1.1.14 root 402: /* When reading from a bus error region, just return a constant */
403: if ( STMemory_CheckRegionBusError ( addr ) )
404: value = BLITTER_READ_WORD_BUS_ERR;
1.1.1.8 root 405: else
1.1.1.14 root 406: value = (Uint16)get_word ( addr );
407: //fprintf ( stderr , "read %x %x %x\n" , addr , value , STMemory_CheckRegionBusError(addr) );
1.1.1.7 root 408:
1.1.1.16 root 409: BlitterState.CountBusBlitter++;
410: Blitter_AddCycles ( BLITTER_CYCLES_PER_BUS_READ );
411: Blitter_FlushCycles();
1.1.1.7 root 412:
1.1.1.8 root 413: return value;
414: }
415:
416: static void Blitter_WriteWord(Uint32 addr, Uint16 value)
417: {
1.1.1.14 root 418: /* Call put_word only if the address doesn't point to a bus error region */
1.1.1.15 root 419: /* (also see SysMem_wput for addr < 0x8) */
1.1.1.14 root 420: if ( STMemory_CheckRegionBusError ( addr ) == false )
421: put_word ( addr , (Uint32)(value) );
422: //fprintf ( stderr , "write %x %x %x\n" , addr , value , STMemory_CheckRegionBusError(addr) );
1.1.1.7 root 423:
1.1.1.16 root 424: BlitterState.CountBusBlitter++;
425: Blitter_AddCycles ( BLITTER_CYCLES_PER_BUS_WRITE );
426: Blitter_FlushCycles();
1.1.1.7 root 427: }
428:
1.1.1.16 root 429:
430:
1.1.1.8 root 431: /*-----------------------------------------------------------------------*/
1.1.1.7 root 432: /**
1.1.1.16 root 433: * Used to determine how long the blitter can keep the bus in non-hog mode
434: * Return true if the blitter can continue its operations and return false
435: * if the blitter must suspend its work and give back the bus to the CPU
1.1.1.7 root 436: */
1.1.1.16 root 437: static bool Blitter_ContinueNonHog ( void )
1.1.1.7 root 438: {
1.1.1.16 root 439: if ( BlitterState.CountBusBlitter < BLITTER_NONHOG_BUS_BLITTER )
440: return true;
441: else
442: return false;
1.1.1.8 root 443: }
1.1.1.7 root 444:
1.1.1.16 root 445:
446: /* Macro to check if blitter can continue and do a 'return' if not */
447: #define BLITTER_RETURN_IF_MAX_BUS_REACHED if ( !BlitterVars.hog && !Blitter_ContinueNonHog() ) return 0;
448:
449: /* Macro to suspend this transfer for now and keep src/dst to continue later */
450: #define BLITTER_CONTINUE_LATER_IF_MAX_BUS_REACHED if ( !BlitterVars.hog && !Blitter_ContinueNonHog() ) \
451: { \
452: /* fprintf ( stderr , "blitter suspended before write word have_src=%d have_dst=%d\n" , BlitterState.have_src ,BlitterState.have_dst ); */ \
453: BlitterState.ContinueLater = 1; return; \
454: }
455:
456:
457:
458: /*-----------------------------------------------------------------------*/
459: /**
460: * Blitter emulation - level 1
461: */
1.1.1.8 root 462:
463: static void Blitter_SourceShift(void)
464: {
465: if (BlitterRegs.src_x_incr < 0)
466: BlitterVars.buffer >>= 16;
467: else
468: BlitterVars.buffer <<= 16;
469: }
470:
471: static void Blitter_SourceFetch(void)
472: {
473: Uint32 src_word = (Uint32)Blitter_ReadWord(BlitterRegs.src_addr);
474:
475: if (BlitterRegs.src_x_incr < 0)
476: BlitterVars.buffer |= src_word << 16;
477: else
478: BlitterVars.buffer |= src_word;
479:
480: if (BlitterVars.src_words == 1)
1.1.1.7 root 481: {
1.1.1.8 root 482: BlitterRegs.src_addr += BlitterRegs.src_y_incr;
483: }
484: else
485: {
486: --BlitterVars.src_words;
487: BlitterRegs.src_addr += BlitterRegs.src_x_incr;
1.1.1.7 root 488: }
489: }
490:
1.1.1.8 root 491: static Uint16 Blitter_SourceRead(void)
492: {
493: if (!BlitterState.have_src)
494: {
495: if (BlitterState.fxsr)
496: {
497: Blitter_SourceShift();
498: Blitter_SourceFetch();
499: }
1.1.1.7 root 500:
1.1.1.8 root 501: Blitter_SourceShift();
1.1.1.7 root 502:
1.1.1.8 root 503: if (!BlitterState.nfsr)
504: {
505: Blitter_SourceFetch();
506: }
1.1.1.7 root 507:
1.1.1.8 root 508: BlitterState.src_word = (Uint16)(BlitterVars.buffer >> BlitterVars.skew);
509: BlitterState.have_src = true;
1.1.1.7 root 510: }
1.1 root 511:
1.1.1.8 root 512: return BlitterState.src_word;
513: }
1.1 root 514:
1.1.1.16 root 515: static Uint16 Blitter_DestRead(void)
516: {
517: if (!BlitterState.have_dst)
518: {
519: BlitterState.dst_word = Blitter_ReadWord(BlitterRegs.dst_addr);
520: BlitterState.have_dst = true;
521: }
522:
523: return BlitterState.dst_word;
524: }
525:
1.1.1.8 root 526: static Uint16 Blitter_GetHalftoneWord(void)
527: {
528: if (BlitterVars.smudge)
529: return BlitterHalftone[Blitter_SourceRead() & 15];
530: else
531: return BlitterHalftone[BlitterVars.line];
532: }
1.1.1.4 root 533:
1.1.1.9 root 534: /* HOP */
535:
536: static Uint16 Blitter_HOP_0(void)
1.1 root 537: {
1.1.1.9 root 538: return 0xFFFF;
539: }
1.1.1.7 root 540:
1.1.1.9 root 541: static Uint16 Blitter_HOP_1(void)
542: {
543: return Blitter_GetHalftoneWord();
544: }
545:
546: static Uint16 Blitter_HOP_2(void)
547: {
548: return Blitter_SourceRead();
549: }
1.1.1.8 root 550:
1.1.1.9 root 551: static Uint16 Blitter_HOP_3(void)
552: {
1.1.1.16 root 553: Uint16 src;
554:
555: src = Blitter_SourceRead();
556: BLITTER_RETURN_IF_MAX_BUS_REACHED;
557: return src & Blitter_GetHalftoneWord();
1.1.1.8 root 558: }
559:
1.1.1.9 root 560: static BLITTER_OP_FUNC Blitter_HOP_Table [4] =
561: {
562: Blitter_HOP_0,
563: Blitter_HOP_1,
564: Blitter_HOP_2,
565: Blitter_HOP_3
566: };
567:
568: static void Blitter_Select_HOP(void)
569: {
570: Blitter_ComputeHOP = Blitter_HOP_Table[BlitterRegs.hop];
571: }
572:
573: /* end HOP */
574:
575: /* LOP */
576:
577: static Uint16 Blitter_LOP_0(void)
578: {
579: return 0;
580: }
581:
582: static Uint16 Blitter_LOP_1(void)
1.1.1.8 root 583: {
1.1.1.16 root 584: Uint16 hop;
585:
586: hop = Blitter_ComputeHOP();
587: BLITTER_RETURN_IF_MAX_BUS_REACHED;
588: return hop & Blitter_DestRead();
1.1.1.9 root 589: }
1.1.1.8 root 590:
1.1.1.9 root 591: static Uint16 Blitter_LOP_2(void)
592: {
1.1.1.16 root 593: Uint16 hop;
594:
595: hop = Blitter_ComputeHOP();
596: BLITTER_RETURN_IF_MAX_BUS_REACHED;
597: return hop & ~Blitter_DestRead();
1.1.1.9 root 598: }
599:
600: static Uint16 Blitter_LOP_3(void)
601: {
602: return Blitter_ComputeHOP();
603: }
604:
605: static Uint16 Blitter_LOP_4(void)
606: {
1.1.1.16 root 607: Uint16 hop;
608:
609: hop = Blitter_ComputeHOP();
610: BLITTER_RETURN_IF_MAX_BUS_REACHED;
611: return ~hop & Blitter_DestRead();
1.1.1.9 root 612: }
613:
614: static Uint16 Blitter_LOP_5(void)
615: {
616: return Blitter_DestRead();
617: }
618:
619: static Uint16 Blitter_LOP_6(void)
620: {
1.1.1.16 root 621: Uint16 hop;
622:
623: hop = Blitter_ComputeHOP();
624: BLITTER_RETURN_IF_MAX_BUS_REACHED;
625: return hop ^ Blitter_DestRead();
1.1.1.9 root 626: }
627:
628: static Uint16 Blitter_LOP_7(void)
629: {
1.1.1.16 root 630: Uint16 hop;
631:
632: hop = Blitter_ComputeHOP();
633: BLITTER_RETURN_IF_MAX_BUS_REACHED;
634: return hop | Blitter_DestRead();
1.1.1.9 root 635: }
636:
637: static Uint16 Blitter_LOP_8(void)
638: {
1.1.1.16 root 639: Uint16 hop;
640:
641: hop = Blitter_ComputeHOP();
642: BLITTER_RETURN_IF_MAX_BUS_REACHED;
643: return ~hop & ~Blitter_DestRead();
1.1.1.9 root 644: }
645:
646: static Uint16 Blitter_LOP_9(void)
647: {
1.1.1.16 root 648: Uint16 hop;
649:
650: hop = Blitter_ComputeHOP();
651: BLITTER_RETURN_IF_MAX_BUS_REACHED;
652: return ~hop ^ Blitter_DestRead();
1.1.1.9 root 653: }
654:
655: static Uint16 Blitter_LOP_A(void)
656: {
657: return ~Blitter_DestRead();
658: }
1.1.1.8 root 659:
1.1.1.9 root 660: static Uint16 Blitter_LOP_B(void)
661: {
1.1.1.16 root 662: Uint16 hop;
663:
664: hop = Blitter_ComputeHOP();
665: BLITTER_RETURN_IF_MAX_BUS_REACHED;
666: return hop | ~Blitter_DestRead();
1.1.1.8 root 667: }
668:
1.1.1.9 root 669: static Uint16 Blitter_LOP_C(void)
670: {
671: return ~Blitter_ComputeHOP();
672: }
673:
674: static Uint16 Blitter_LOP_D(void)
675: {
1.1.1.16 root 676: Uint16 hop;
677:
678: hop = Blitter_ComputeHOP();
679: BLITTER_RETURN_IF_MAX_BUS_REACHED;
680: return ~hop | Blitter_DestRead();
1.1.1.9 root 681: }
682:
683: static Uint16 Blitter_LOP_E(void)
684: {
1.1.1.16 root 685: Uint16 hop;
686:
687: hop = Blitter_ComputeHOP();
688: BLITTER_RETURN_IF_MAX_BUS_REACHED;
689: return ~hop | ~Blitter_DestRead();
1.1.1.9 root 690: }
691:
692: static Uint16 Blitter_LOP_F(void)
693: {
694: return 0xFFFF;
695: }
696:
697: static BLITTER_OP_FUNC Blitter_LOP_Table [16] =
698: {
699: Blitter_LOP_0,
700: Blitter_LOP_1,
701: Blitter_LOP_2,
702: Blitter_LOP_3,
703: Blitter_LOP_4,
704: Blitter_LOP_5,
705: Blitter_LOP_6,
706: Blitter_LOP_7,
707: Blitter_LOP_8,
708: Blitter_LOP_9,
709: Blitter_LOP_A,
710: Blitter_LOP_B,
711: Blitter_LOP_C,
712: Blitter_LOP_D,
713: Blitter_LOP_E,
714: Blitter_LOP_F
715: };
716:
717: static void Blitter_Select_LOP(void)
718: {
719: Blitter_ComputeLOP = Blitter_LOP_Table[BlitterRegs.lop];
720: }
721:
722: /* end LOP */
723:
1.1.1.16 root 724:
725: /*-----------------------------------------------------------------------*/
726: /*
727: * If BlitterState.ContinueLater==1, it means we're resuming from a previous
728: * Blitter_ProcessWord() call that did not complete because we reached
729: * maximum number of bus accesses. In that case, we continue from the latest
730: * state, keeping the values we already have for src_word and dst_word.
731: */
732:
733: static void Blitter_BeginLine(void)
734: {
735: if ( BlitterState.ContinueLater ) /* Resuming, don't start a new line */
736: return;
737:
738: BlitterVars.src_words = BlitterVars.src_words_reset;
739: }
740:
741: static void Blitter_SetState(Uint8 fxsr, Uint8 nfsr, Uint16 end_mask)
742: {
743: BlitterState.fxsr = fxsr;
744: BlitterState.nfsr = nfsr;
745: BlitterState.end_mask = end_mask;
746:
747: if ( BlitterState.ContinueLater )
748: BlitterState.ContinueLater = 0; /* Resuming, keep previous values of have_src / have_dst */
1.1.1.17! root 749: }
! 750:
! 751: static void Blitter_FlushWordSrcDest(void)
! 752: {
! 753: BlitterState.have_src = false;
! 754: BlitterState.have_dst = false;
1.1.1.16 root 755: }
756:
757: static Uint16 Blitter_ComputeMask(Uint16 lop)
1.1.1.8 root 758: {
1.1.1.16 root 759: return (lop & BlitterState.end_mask) | (Blitter_DestRead() & ~BlitterState.end_mask);
1.1.1.8 root 760: }
761:
762: static void Blitter_ProcessWord(void)
763: {
1.1.1.16 root 764: Uint16 lop;
765: Uint16 dst_data;
766:
767: lop = Blitter_ComputeLOP();
768: BLITTER_CONTINUE_LATER_IF_MAX_BUS_REACHED;
769:
770: /* When NFSR or mask is not all '1', a read-modify-write is always performed */
771: if ( BlitterState.nfsr || ( BlitterState.end_mask != 0xFFFF ) )
772: {
773: dst_data = Blitter_ComputeMask( lop );
774: BLITTER_CONTINUE_LATER_IF_MAX_BUS_REACHED;
775: }
776: else
777: {
778: dst_data = lop;
779: }
1.1.1.8 root 780:
781: Blitter_WriteWord(BlitterRegs.dst_addr, dst_data);
1.1 root 782:
1.1.1.8 root 783: if (BlitterRegs.words == 1)
1.1.1.7 root 784: {
1.1.1.8 root 785: BlitterRegs.dst_addr += BlitterRegs.dst_y_incr;
1.1.1.7 root 786: }
1.1.1.8 root 787: else
1.1.1.7 root 788: {
1.1.1.8 root 789: --BlitterRegs.words;
790: BlitterRegs.dst_addr += BlitterRegs.dst_x_incr;
1.1.1.7 root 791: }
1.1.1.17! root 792:
! 793: /* ProcessWord is complete, reset internal content of src/dst words */
! 794: Blitter_FlushWordSrcDest ();
1.1.1.8 root 795: }
796:
797: static void Blitter_EndLine(void)
798: {
1.1.1.16 root 799: if ( BlitterState.ContinueLater ) /* We will continue later, don't end this line for now */
800: return;
801:
1.1.1.8 root 802: --BlitterRegs.lines;
803: BlitterRegs.words = BlitterVars.dst_words_reset;
1.1.1.7 root 804:
1.1.1.8 root 805: if (BlitterRegs.dst_y_incr >= 0)
806: BlitterVars.line = (BlitterVars.line+1) & 15;
1.1.1.7 root 807: else
1.1.1.8 root 808: BlitterVars.line = (BlitterVars.line-1) & 15;
809: }
810:
811: /*-----------------------------------------------------------------------*/
812: /**
813: * Blitter emulation - level 2
814: */
815:
816: static void Blitter_SingleWord(void)
817: {
818: Blitter_BeginLine();
819: Blitter_SetState(BlitterVars.fxsr, BlitterVars.nfsr, BlitterRegs.end_mask_1);
820: Blitter_ProcessWord();
821: Blitter_EndLine();
822: }
823:
824: static void Blitter_FirstWord(void)
825: {
826: Blitter_BeginLine();
827: Blitter_SetState(BlitterVars.fxsr, 0, BlitterRegs.end_mask_1);
828: Blitter_ProcessWord();
829: }
830:
831: static void Blitter_MiddleWord(void)
832: {
833: Blitter_SetState(0, 0, BlitterRegs.end_mask_2);
834: Blitter_ProcessWord();
835: }
1.1.1.7 root 836:
1.1.1.8 root 837: static void Blitter_LastWord(void)
838: {
839: Blitter_SetState(0, BlitterVars.nfsr, BlitterRegs.end_mask_3);
840: Blitter_ProcessWord();
841: Blitter_EndLine();
1.1.1.7 root 842: }
1.1 root 843:
1.1.1.8 root 844: static void Blitter_Step(void)
845: {
846: if (BlitterVars.dst_words_reset == 1)
847: {
848: Blitter_SingleWord();
849: }
850: else if (BlitterRegs.words == BlitterVars.dst_words_reset)
851: {
852: Blitter_FirstWord();
853: }
854: else if (BlitterRegs.words == 1)
855: {
856: Blitter_LastWord();
857: }
858: else
859: {
860: Blitter_MiddleWord();
861: }
862: }
1.1 root 863:
1.1.1.3 root 864: /*-----------------------------------------------------------------------*/
1.1.1.5 root 865: /**
1.1.1.7 root 866: * Let's do the blit.
1.1.1.16 root 867: * Note that in non-HOG mode, the blitter only runs for 64 bus cycles
1.1.1.7 root 868: * before giving the bus back to the CPU. Due to this mode, this function must
869: * be able to abort and resume the blitting at any time.
1.1.1.16 root 870: * - In cycle exact mode, the blitter will have 64 bus accesses and the cpu 64 bus accesses
871: * - In non cycle exact mode, the blitter will have 64 bus accesses and the cpu
872: * will run during 64*4 = 256 cpu cycles
1.1.1.5 root 873: */
1.1.1.8 root 874: static void Blitter_Start(void)
1.1.1.4 root 875: {
1.1.1.16 root 876: int FrameCycles, HblCounterVideo, LineCycles;
877: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
878:
879: //fprintf ( stderr , "blitter start %d video_cyc=%d %d@%d\n" , nCyclesMainCounter , FrameCycles , LineCycles, HblCounterVideo );
880:
881: /* Select HOP & LOP funcs */
1.1.1.9 root 882: Blitter_Select_HOP();
883: Blitter_Select_LOP();
884:
1.1.1.16 root 885: /* Setup vars */
1.1.1.9 root 886: BlitterVars.pass_cycles = 0;
887: BlitterVars.op_cycles = 0;
1.1.1.12 root 888: BlitterVars.src_words_reset = BlitterVars.dst_words_reset + BlitterVars.fxsr - BlitterVars.nfsr;
1.1.1.16 root 889: BlitterState.CountBusBlitter = 0;
890: if ( Blitter_HOG_CPU_BusCountError )
891: BlitterState.CountBusBlitter++; /* Bug in the blitter : count 1 CPU access as a blitter access */
1.1.1.8 root 892:
1.1.1.16 root 893: /* Bus arbitration */
1.1.1.14 root 894: Blitter_BusArbitration ( BUS_MODE_BLITTER );
1.1.1.16 root 895: BlitterPhase = BLITTER_PHASE_RUN_TRANSFER;
1.1.1.14 root 896:
897: /* Busy=1, set line to high/1 and clear interrupt */
898: MFP_GPIP_Set_Line_Input ( MFP_GPIP_LINE_GPU_DONE , MFP_GPIP_STATE_HIGH );
1.1.1.7 root 899:
900: /* Now we enter the main blitting loop */
901: do
902: {
1.1.1.8 root 903: Blitter_Step();
904: }
1.1.1.16 root 905: while ( BlitterRegs.lines > 0
906: && ( BlitterVars.hog || Blitter_ContinueNonHog() ) );
1.1.1.7 root 907:
1.1.1.16 root 908: /* Bus arbitration */
1.1.1.14 root 909: Blitter_BusArbitration ( BUS_MODE_CPU );
1.1.1.7 root 910:
1.1.1.8 root 911: BlitterRegs.ctrl = (BlitterRegs.ctrl & 0xF0) | BlitterVars.line;
1.1.1.7 root 912:
1.1.1.8 root 913: if (BlitterRegs.lines == 0)
914: {
1.1.1.16 root 915: /* Blit complete, clear busy and hog bits */
1.1.1.14 root 916: BlitterRegs.ctrl &= ~(0x80|0x40);
1.1.1.7 root 917:
1.1.1.14 root 918: /* Busy=0, set line to low/0 and request interrupt */
919: MFP_GPIP_Set_Line_Input ( MFP_GPIP_LINE_GPU_DONE , MFP_GPIP_STATE_LOW );
1.1.1.16 root 920:
921: BlitterPhase = BLITTER_PHASE_STOP;
922:
923: if ( BLITTER_RUN_CE )
924: {
925: /* In CE mode, we check if a CPU instruction could have ran in parallel to the blitter */
926: BlitterPhase |= BLITTER_PHASE_IGNORE_LAST_CPU_CYCLES;
927: Blitter_HOG_CPU_IgnoreMaxCpuCycles = BlitterVars.pass_cycles;
928: }
1.1.1.7 root 929: }
1.1.1.8 root 930: else
1.1.1.7 root 931: {
1.1.1.16 root 932: /* Blit not complete yet in non-hog mode, give back the bus to the CPU */
933: BlitterPhase = BLITTER_PHASE_COUNT_CPU_BUS;
934:
935: if ( BLITTER_RUN_CE )
936: {
937: /* Continue blitting after 64 bus accesses in 68000 CE mode + check for parallel CPU instruction */
938: BlitterPhase |= BLITTER_PHASE_IGNORE_LAST_CPU_CYCLES;
939: Blitter_HOG_CPU_IgnoreMaxCpuCycles = BlitterVars.pass_cycles;
940: BlitterState.CountBusCpu = 0; /* Reset CPU bus counter */
941: }
942: else
943: {
944: /* In non-cycle exact 68000 mode, we run the CPU for 64*4=256 cpu cycles, */
945: /* which gives a good approximation */
946: CycInt_AddRelativeInterrupt ( BLITTER_NONHOG_BUS_CPU*4, INT_CPU_CYCLE, INTERRUPT_BLITTER );
947: }
1.1.1.7 root 948: }
949: }
950:
1.1.1.16 root 951:
952: /*-----------------------------------------------------------------------*/
953: /**
954: * This is called when no more CPU cycles should be ignored in case an
955: * instruction was running in parallel to the blitter
956: */
957: static void Blitter_Stop_IgnoreLastCpuCycles(void)
958: {
959: BlitterPhase &= ~BLITTER_PHASE_IGNORE_LAST_CPU_CYCLES; /* No more CPU in parallel, stop ignoring next CPU cycles */
960:
961: /* If blitter is completely OFF now, disable the cpu specific part */
962: if ( BlitterPhase == BLITTER_PHASE_STOP )
963: M68000_SetBlitter_CE ( false );
964: }
965:
966:
1.1.1.8 root 967: /*-----------------------------------------------------------------------*/
968: /**
969: * Read blitter halftone ram.
970: */
971: static void Blitter_Halftone_ReadWord(int index)
972: {
973: IoMem_WriteWord(REG_HT_RAM + index + index, BlitterHalftone[index]);
974: }
975:
976: void Blitter_Halftone00_ReadWord(void) { Blitter_Halftone_ReadWord(0); }
977: void Blitter_Halftone01_ReadWord(void) { Blitter_Halftone_ReadWord(1); }
978: void Blitter_Halftone02_ReadWord(void) { Blitter_Halftone_ReadWord(2); }
979: void Blitter_Halftone03_ReadWord(void) { Blitter_Halftone_ReadWord(3); }
980: void Blitter_Halftone04_ReadWord(void) { Blitter_Halftone_ReadWord(4); }
981: void Blitter_Halftone05_ReadWord(void) { Blitter_Halftone_ReadWord(5); }
982: void Blitter_Halftone06_ReadWord(void) { Blitter_Halftone_ReadWord(6); }
983: void Blitter_Halftone07_ReadWord(void) { Blitter_Halftone_ReadWord(7); }
984: void Blitter_Halftone08_ReadWord(void) { Blitter_Halftone_ReadWord(8); }
985: void Blitter_Halftone09_ReadWord(void) { Blitter_Halftone_ReadWord(9); }
986: void Blitter_Halftone10_ReadWord(void) { Blitter_Halftone_ReadWord(10); }
987: void Blitter_Halftone11_ReadWord(void) { Blitter_Halftone_ReadWord(11); }
988: void Blitter_Halftone12_ReadWord(void) { Blitter_Halftone_ReadWord(12); }
989: void Blitter_Halftone13_ReadWord(void) { Blitter_Halftone_ReadWord(13); }
990: void Blitter_Halftone14_ReadWord(void) { Blitter_Halftone_ReadWord(14); }
991: void Blitter_Halftone15_ReadWord(void) { Blitter_Halftone_ReadWord(15); }
992:
993: /*-----------------------------------------------------------------------*/
994: /**
995: * Read blitter source x increment (0xff8a20).
996: */
997: void Blitter_SourceXInc_ReadWord(void)
998: {
999: IoMem_WriteWord(REG_SRC_X_INC, (Uint16)(BlitterRegs.src_x_incr));
1000: }
1001:
1002: /*-----------------------------------------------------------------------*/
1003: /**
1004: * Read blitter source y increment (0xff8a22).
1005: */
1006: void Blitter_SourceYInc_ReadWord(void)
1007: {
1008: IoMem_WriteWord(REG_SRC_Y_INC, (Uint16)(BlitterRegs.src_y_incr));
1009: }
1.1.1.7 root 1010:
1011: /*-----------------------------------------------------------------------*/
1012: /**
1013: * Read blitter source address (0xff8a24).
1014: */
1015: void Blitter_SourceAddr_ReadLong(void)
1016: {
1.1.1.8 root 1017: IoMem_WriteLong(REG_SRC_ADDR, BlitterRegs.src_addr);
1.1.1.4 root 1018: }
1019:
1020: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1021: /**
1022: * Read blitter endmask 1.
1023: */
1.1.1.3 root 1024: void Blitter_Endmask1_ReadWord(void)
1.1 root 1025: {
1.1.1.8 root 1026: IoMem_WriteWord(REG_END_MASK1, BlitterRegs.end_mask_1);
1.1 root 1027: }
1028:
1.1.1.3 root 1029: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1030: /**
1031: * Read blitter endmask 2.
1032: */
1.1.1.3 root 1033: void Blitter_Endmask2_ReadWord(void)
1.1 root 1034: {
1.1.1.8 root 1035: IoMem_WriteWord(REG_END_MASK2, BlitterRegs.end_mask_2);
1.1 root 1036: }
1037:
1.1.1.3 root 1038: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1039: /**
1040: * Read blitter endmask 3.
1041: */
1.1.1.3 root 1042: void Blitter_Endmask3_ReadWord(void)
1.1 root 1043: {
1.1.1.8 root 1044: IoMem_WriteWord(REG_END_MASK3, BlitterRegs.end_mask_3);
1045: }
1046:
1047: /*-----------------------------------------------------------------------*/
1048: /**
1049: * Read blitter destination x increment (0xff8a2E).
1050: */
1051: void Blitter_DestXInc_ReadWord(void)
1052: {
1053: IoMem_WriteWord(REG_DST_X_INC, (Uint16)(BlitterRegs.dst_x_incr));
1054: }
1055:
1056: /*-----------------------------------------------------------------------*/
1057: /**
1058: * Read blitter destination y increment (0xff8a30).
1059: */
1060: void Blitter_DestYInc_ReadWord(void)
1061: {
1062: IoMem_WriteWord(REG_DST_Y_INC, (Uint16)(BlitterRegs.dst_y_incr));
1.1 root 1063: }
1064:
1.1.1.3 root 1065: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1066: /**
1067: * Read blitter destination address.
1068: */
1.1.1.3 root 1069: void Blitter_DestAddr_ReadLong(void)
1.1 root 1070: {
1.1.1.8 root 1071: IoMem_WriteLong(REG_DST_ADDR, BlitterRegs.dst_addr);
1.1 root 1072: }
1073:
1.1.1.3 root 1074: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1075: /**
1076: * Read blitter words-per-line register.
1077: */
1.1.1.3 root 1078: void Blitter_WordsPerLine_ReadWord(void)
1.1 root 1079: {
1.1.1.8 root 1080: IoMem_WriteWord(REG_X_COUNT, (Uint16)(BlitterRegs.words & 0xFFFF));
1.1 root 1081: }
1082:
1.1.1.3 root 1083: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1084: /**
1085: * Read blitter lines-per-bitblock register.
1086: */
1.1.1.3 root 1087: void Blitter_LinesPerBitblock_ReadWord(void)
1.1 root 1088: {
1.1.1.8 root 1089: IoMem_WriteWord(REG_Y_COUNT, (Uint16)(BlitterRegs.lines & 0xFFFF));
1.1 root 1090: }
1091:
1.1.1.3 root 1092: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1093: /**
1094: * Read blitter halftone operation register.
1095: */
1.1.1.3 root 1096: void Blitter_HalftoneOp_ReadByte(void)
1.1 root 1097: {
1.1.1.8 root 1098: IoMem_WriteByte(REG_BLIT_HOP, BlitterRegs.hop);
1.1 root 1099: }
1100:
1.1.1.3 root 1101: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1102: /**
1103: * Read blitter logical operation register.
1104: */
1.1.1.3 root 1105: void Blitter_LogOp_ReadByte(void)
1.1 root 1106: {
1.1.1.8 root 1107: IoMem_WriteByte(REG_BLIT_LOP, BlitterRegs.lop);
1.1 root 1108: }
1109:
1.1.1.3 root 1110: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1111: /**
1112: * Read blitter control register.
1113: */
1.1.1.4 root 1114: void Blitter_Control_ReadByte(void)
1.1 root 1115: {
1.1.1.7 root 1116: /* busy, hog/blit, smudge, n/a, 4bits for line number */
1.1.1.8 root 1117: IoMem_WriteByte(REG_CONTROL, BlitterRegs.ctrl);
1.1 root 1118: }
1119:
1.1.1.3 root 1120: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1121: /**
1122: * Read blitter skew register.
1123: */
1.1.1.3 root 1124: void Blitter_Skew_ReadByte(void)
1.1 root 1125: {
1.1.1.8 root 1126: IoMem_WriteByte(REG_SKEW, BlitterRegs.skew);
1127: }
1128:
1129:
1130: /*-----------------------------------------------------------------------*/
1131: /**
1132: * Write to blitter halftone ram.
1133: */
1134: static void Blitter_Halftone_WriteWord(int index)
1135: {
1136: BlitterHalftone[index] = IoMem_ReadWord(REG_HT_RAM + index + index);
1137: }
1138:
1139: void Blitter_Halftone00_WriteWord(void) { Blitter_Halftone_WriteWord(0); }
1140: void Blitter_Halftone01_WriteWord(void) { Blitter_Halftone_WriteWord(1); }
1141: void Blitter_Halftone02_WriteWord(void) { Blitter_Halftone_WriteWord(2); }
1142: void Blitter_Halftone03_WriteWord(void) { Blitter_Halftone_WriteWord(3); }
1143: void Blitter_Halftone04_WriteWord(void) { Blitter_Halftone_WriteWord(4); }
1144: void Blitter_Halftone05_WriteWord(void) { Blitter_Halftone_WriteWord(5); }
1145: void Blitter_Halftone06_WriteWord(void) { Blitter_Halftone_WriteWord(6); }
1146: void Blitter_Halftone07_WriteWord(void) { Blitter_Halftone_WriteWord(7); }
1147: void Blitter_Halftone08_WriteWord(void) { Blitter_Halftone_WriteWord(8); }
1148: void Blitter_Halftone09_WriteWord(void) { Blitter_Halftone_WriteWord(9); }
1149: void Blitter_Halftone10_WriteWord(void) { Blitter_Halftone_WriteWord(10); }
1150: void Blitter_Halftone11_WriteWord(void) { Blitter_Halftone_WriteWord(11); }
1151: void Blitter_Halftone12_WriteWord(void) { Blitter_Halftone_WriteWord(12); }
1152: void Blitter_Halftone13_WriteWord(void) { Blitter_Halftone_WriteWord(13); }
1153: void Blitter_Halftone14_WriteWord(void) { Blitter_Halftone_WriteWord(14); }
1154: void Blitter_Halftone15_WriteWord(void) { Blitter_Halftone_WriteWord(15); }
1155:
1156: /*-----------------------------------------------------------------------*/
1157: /**
1158: * Write to blitter source x increment.
1159: */
1160: void Blitter_SourceXInc_WriteWord(void)
1161: {
1162: BlitterRegs.src_x_incr = (short)(IoMem_ReadWord(REG_SRC_X_INC) & 0xFFFE);
1.1 root 1163: }
1164:
1.1.1.8 root 1165: /*-----------------------------------------------------------------------*/
1166: /**
1167: * Write to blitter source y increment.
1168: */
1169: void Blitter_SourceYInc_WriteWord(void)
1170: {
1171: BlitterRegs.src_y_incr = (short)(IoMem_ReadWord(REG_SRC_Y_INC) & 0xFFFE);
1172: }
1.1 root 1173:
1.1.1.3 root 1174: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1175: /**
1.1.1.7 root 1176: * Write to blitter source address register (0xff8a24).
1177: */
1178: void Blitter_SourceAddr_WriteLong(void)
1179: {
1.1.1.14 root 1180: if ( ConfigureParams.System.bAddressSpace24 == true )
1181: BlitterRegs.src_addr = IoMem_ReadLong(REG_SRC_ADDR) & 0x00FFFFFE; /* Normal STF/STE */
1182: else
1183: BlitterRegs.src_addr = IoMem_ReadLong(REG_SRC_ADDR) & 0xFFFFFFFE; /* Falcon with extra TT RAM */
1.1.1.7 root 1184: }
1185:
1186: /*-----------------------------------------------------------------------*/
1187: /**
1.1.1.5 root 1188: * Write to blitter endmask 1.
1189: */
1.1.1.3 root 1190: void Blitter_Endmask1_WriteWord(void)
1.1 root 1191: {
1.1.1.8 root 1192: BlitterRegs.end_mask_1 = IoMem_ReadWord(REG_END_MASK1);
1.1 root 1193: }
1194:
1.1.1.3 root 1195: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1196: /**
1197: * Write to blitter endmask 2.
1198: */
1.1.1.3 root 1199: void Blitter_Endmask2_WriteWord(void)
1.1 root 1200: {
1.1.1.8 root 1201: BlitterRegs.end_mask_2 = IoMem_ReadWord(REG_END_MASK2);
1.1 root 1202: }
1203:
1.1.1.3 root 1204: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1205: /**
1206: * Write to blitter endmask 3.
1207: */
1.1.1.3 root 1208: void Blitter_Endmask3_WriteWord(void)
1.1 root 1209: {
1.1.1.8 root 1210: BlitterRegs.end_mask_3 = IoMem_ReadWord(REG_END_MASK3);
1211: }
1212:
1213: /*-----------------------------------------------------------------------*/
1214: /**
1215: * Write to blitter destination x increment.
1216: */
1217: void Blitter_DestXInc_WriteWord(void)
1218: {
1219: BlitterRegs.dst_x_incr = (short)(IoMem_ReadWord(REG_DST_X_INC) & 0xFFFE);
1220: }
1221:
1222: /*-----------------------------------------------------------------------*/
1223: /**
1224: * Write to blitter source y increment.
1225: */
1226: void Blitter_DestYInc_WriteWord(void)
1227: {
1228: BlitterRegs.dst_y_incr = (short)(IoMem_ReadWord(REG_DST_Y_INC) & 0xFFFE);
1.1 root 1229: }
1230:
1.1.1.3 root 1231: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1232: /**
1233: * Write to blitter destination address register.
1234: */
1.1.1.3 root 1235: void Blitter_DestAddr_WriteLong(void)
1236: {
1.1.1.14 root 1237: if ( ConfigureParams.System.bAddressSpace24 == true )
1238: BlitterRegs.dst_addr = IoMem_ReadLong(REG_DST_ADDR) & 0x00FFFFFE; /* Normal STF/STE */
1239: else
1240: BlitterRegs.dst_addr = IoMem_ReadLong(REG_DST_ADDR) & 0xFFFFFFFE; /* Falcon with extra TT RAM */
1.1 root 1241: }
1242:
1.1.1.3 root 1243: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1244: /**
1245: * Write to blitter words-per-line register.
1246: */
1.1.1.3 root 1247: void Blitter_WordsPerLine_WriteWord(void)
1.1 root 1248: {
1.1.1.8 root 1249: Uint32 words = (Uint32)IoMem_ReadWord(REG_X_COUNT);
1250:
1251: if (words == 0)
1252: words = 65536;
1253:
1254: BlitterRegs.words = words;
1255: BlitterVars.dst_words_reset = words;
1.1 root 1256: }
1257:
1.1.1.3 root 1258: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1259: /**
1.1.1.8 root 1260: * Write to blitter lines-per-bitblock register.
1.1.1.5 root 1261: */
1.1.1.3 root 1262: void Blitter_LinesPerBitblock_WriteWord(void)
1.1 root 1263: {
1.1.1.8 root 1264: Uint32 lines = (Uint32)IoMem_ReadWord(REG_Y_COUNT);
1265:
1266: if (lines == 0)
1267: lines = 65536;
1268:
1269: BlitterRegs.lines = lines;
1.1 root 1270: }
1271:
1.1.1.3 root 1272: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1273: /**
1274: * Write to blitter halftone operation register.
1275: */
1.1.1.3 root 1276: void Blitter_HalftoneOp_WriteByte(void)
1.1 root 1277: {
1.1.1.4 root 1278: /* h/ware reg masks out the top 6 bits! */
1.1.1.8 root 1279: BlitterRegs.hop = IoMem_ReadByte(REG_BLIT_HOP) & 3;
1.1 root 1280: }
1281:
1.1.1.3 root 1282: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1283: /**
1284: * Write to blitter logical operation register.
1285: */
1.1.1.3 root 1286: void Blitter_LogOp_WriteByte(void)
1.1.1.7 root 1287: {
1.1.1.4 root 1288: /* h/ware reg masks out the top 4 bits! */
1.1.1.8 root 1289: BlitterRegs.lop = IoMem_ReadByte(REG_BLIT_LOP) & 0xF;
1.1 root 1290: }
1291:
1.1.1.3 root 1292: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1293: /**
1294: * Write to blitter control register.
1295: */
1.1.1.4 root 1296: void Blitter_Control_WriteByte(void)
1297: {
1298: /* Control register bits:
1.1.1.17! root 1299: * 0x80: start/stop bit (write) - busy bit (read)
1.1.1.4 root 1300: * - Turn on Blitter activity and stay "1" until copy finished
1301: * 0x40: Blit-mode bit
1.1.1.16 root 1302: * - 0: Blit mode, CPU and Blitter get 64 bus accesses in turns
1.1.1.4 root 1303: * - 1: HOG Mode, Blitter reserves and hogs the bus for as long
1304: * as the copy takes, CPU and DMA get no Bus access
1305: * 0x20: Smudge mode
1306: * - Which line of the halftone pattern to start with is
1307: * read from the first source word when the copy starts
1308: * 0x10: not used
1309: * 0x0f
1310: *
1311: * The lowest 4 bits contain the Halftone pattern line number
1312: */
1.1.1.7 root 1313:
1.1.1.9 root 1314: if (LOG_TRACE_LEVEL(TRACE_BLITTER))
1.1.1.3 root 1315: {
1.1.1.9 root 1316: int FrameCycles, HblCounterVideo, LineCycles;
1317:
1318: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1319:
1.1.1.16 root 1320: LOG_TRACE_PRINT("blitter write ctrl=%02x ctrl_old=%02x video_cyc=%d %d@%d pc=%x instr_cyc=%d\n" ,
1.1.1.17! root 1321: IoMem_ReadByte(REG_CONTROL) , BlitterRegs.ctrl ,
1.1.1.9 root 1322: FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles );
1.1.1.7 root 1323: }
1.1.1.3 root 1324:
1.1.1.8 root 1325: BlitterRegs.ctrl = IoMem_ReadByte(REG_CONTROL) & 0xEF;
1326:
1327: BlitterVars.hog = BlitterRegs.ctrl & 0x40;
1328: BlitterVars.smudge = BlitterRegs.ctrl & 0x20;
1329: BlitterVars.line = BlitterRegs.ctrl & 0xF;
1.1.1.7 root 1330:
1331: /* Remove old pending update interrupt */
1.1.1.10 root 1332: CycInt_RemovePendingInterrupt(INTERRUPT_BLITTER);
1.1.1.7 root 1333:
1.1.1.17! root 1334: /* Start/Stop bit set ? */
1.1.1.8 root 1335: if (BlitterRegs.ctrl & 0x80)
1.1.1.7 root 1336: {
1.1.1.8 root 1337: if (BlitterRegs.lines == 0)
1.1.1.7 root 1338: {
1.1.1.16 root 1339: /* Blitter transfer is already complete, clear busy and hog bits */
1340: BlitterRegs.ctrl &= ~(0x80|0x40); // TODO : check on real STE, does it clear hog bit too ?
1.1.1.7 root 1341: }
1342: else
1343: {
1.1.1.16 root 1344: /* Start blitter after a small delay */
1345: /* In non-hog mode, the cpu can "restart" the blitter immediately (without waiting */
1.1.1.17! root 1346: /* for 64 cpu bus accesses) by setting "start/stop" bit. The cpu can also "stop" the blitter (PAUSE state) */
! 1347: /* and restart it here (blitter continues from where it was stopped) */
! 1348: /* This means we should reset BlitterState.ContinueLater only if the blitter was stopped before ; */
1.1.1.16 root 1349: /* else if the blitter is restarted we must keep the value of BlitterState.ContinueLater */
1350: if ( BLITTER_RUN_CE )
1351: {
1.1.1.17! root 1352: if ( BlitterPhase == BLITTER_PHASE_STOP ) /* Only when blitter is started (not when restarted) */
1.1.1.16 root 1353: {
1354: M68000_SetBlitter_CE ( true );
1.1.1.17! root 1355: Blitter_FlushWordSrcDest ();
1.1.1.16 root 1356: BlitterState.ContinueLater = 0;
1357: }
1358:
1359: /* 68000 CE : 4 cycles to complete current bus write to ctrl reg + 4 cycles before blitter request the bus */
1360: Blitter_CyclesBeforeStart = 4 + 4;
1361: BlitterPhase = BLITTER_PHASE_PRE_START;
1362: Blitter_HOG_CPU_BusCountError = 0;
1363: }
1364: else
1365: {
1.1.1.17! root 1366: if ( BlitterPhase == BLITTER_PHASE_STOP ) /* Only when blitter is started (not when restarted) */
1.1.1.16 root 1367: {
1.1.1.17! root 1368: Blitter_FlushWordSrcDest ();
1.1.1.16 root 1369: BlitterState.ContinueLater = 0;
1370: }
1371:
1372: /* Non 68000 CE mode : start blitting after the end of current instruction */
1373: CycInt_AddRelativeInterrupt( CurrentInstrCycles+WaitStateCycles, INT_CPU_CYCLE, INTERRUPT_BLITTER);
1374: }
1.1.1.7 root 1375: }
1.1.1.3 root 1376: }
1.1.1.16 root 1377:
1.1.1.17! root 1378: else /* Start/Stop bit clear */
1.1.1.16 root 1379: {
1.1.1.17! root 1380: /* If the blitter was running and "start/stop" bit is forced to 0 (to stop the blitter in non-hog mode) */
! 1381: /* we "pause" the blitter to temporarily stop bus sharing . This does not clear busy bit, it's only */
! 1382: /* when 'y count' reaches 0 that transfer will be complete and busy bit will be cleared */
! 1383: /* If blitter is already stopped, we don't do anything */
! 1384: if ( BlitterPhase == BLITTER_PHASE_COUNT_CPU_BUS )
! 1385: {
! 1386: BlitterPhase = BLITTER_PHASE_PAUSE;
! 1387: BlitterState.ContinueLater = 1; /* Keep all the blitter's states */
! 1388: }
1.1.1.16 root 1389: }
1.1 root 1390: }
1391:
1.1.1.3 root 1392: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1393: /**
1394: * Write to blitter skew register.
1395: */
1.1.1.3 root 1396: void Blitter_Skew_WriteByte(void)
1397: {
1.1.1.8 root 1398: BlitterRegs.skew = IoMem_ReadByte(REG_SKEW);
1399: BlitterVars.fxsr = (BlitterRegs.skew & 0x80)?1:0;
1400: BlitterVars.nfsr = (BlitterRegs.skew & 0x40)?1:0;
1401: BlitterVars.skew = BlitterRegs.skew & 0xF;
1.1 root 1402: }
1.1.1.2 root 1403:
1404:
1405: /*-----------------------------------------------------------------------*/
1.1.1.5 root 1406: /**
1.1.1.16 root 1407: * Handler which continues blitting after 64 bus cycles in non-CE mode
1.1.1.7 root 1408: */
1409: void Blitter_InterruptHandler(void)
1410: {
1.1.1.10 root 1411: CycInt_AcknowledgeInterrupt();
1.1.1.7 root 1412:
1.1.1.8 root 1413: if (BlitterRegs.ctrl & 0x80)
1.1.1.7 root 1414: {
1.1.1.8 root 1415: Blitter_Start();
1.1.1.7 root 1416: }
1.1.1.8 root 1417: }
1.1.1.7 root 1418:
1.1.1.8 root 1419: /*-----------------------------------------------------------------------*/
1420: /**
1421: * Save/Restore snapshot of Blitter variables.
1422: */
1423: void Blitter_MemorySnapShot_Capture(bool bSave)
1424: {
1425: /* Save/Restore details */
1426: MemorySnapShot_Store(&BlitterRegs, sizeof(BlitterRegs));
1427: MemorySnapShot_Store(&BlitterVars, sizeof(BlitterVars));
1428: MemorySnapShot_Store(&BlitterHalftone, sizeof(BlitterHalftone));
1.1.1.16 root 1429: MemorySnapShot_Store(&BlitterState, sizeof(BlitterState));
1430:
1431: MemorySnapShot_Store(&BlitterPhase, sizeof(BlitterPhase));
1432:
1433: if ( !bSave )
1434: {
1435: /* On restore, we set blitter specific CPU functions if needed */
1436: if ( BlitterPhase && BLITTER_RUN_CE )
1437: M68000_SetBlitter_CE ( true );
1438: }
1439:
1.1.1.2 root 1440: }
1.1.1.12 root 1441:
1442: /*-----------------------------------------------------------------------*/
1443: /**
1444: * Show Blitter register values.
1445: */
1.1.1.14 root 1446: void Blitter_Info(FILE *fp, Uint32 dummy)
1.1.1.12 root 1447: {
1448: BLITTERREGS *regs = &BlitterRegs;
1449:
1.1.1.16 root 1450: fprintf(fp, "src addr (0x%x): 0x%06x\n", REG_SRC_ADDR, regs->src_addr);
1451: fprintf(fp, "dst addr (0x%x): 0x%06x\n", REG_DST_ADDR, regs->dst_addr);
1452: fprintf(fp, "words (0x%x): %u\n", REG_X_COUNT, regs->words);
1453: fprintf(fp, "lines (0x%x): %u\n", REG_Y_COUNT, regs->lines);
1454: fprintf(fp, "src X-inc (0x%x): %hd\n", REG_SRC_X_INC, regs->src_x_incr);
1455: fprintf(fp, "src Y-inc (0x%x): %hd\n", REG_SRC_Y_INC, regs->src_y_incr);
1456: fprintf(fp, "dst X-inc (0x%x): %hd\n", REG_DST_X_INC, regs->dst_x_incr);
1457: fprintf(fp, "dst Y-inc (0x%x): %hd\n", REG_DST_Y_INC, regs->dst_y_incr);
1458: fprintf(fp, "end mask1 (0x%x): 0x%04x\n", REG_END_MASK1, regs->end_mask_1);
1459: fprintf(fp, "end mask2 (0x%x): 0x%04x\n", REG_END_MASK2, regs->end_mask_2);
1460: fprintf(fp, "end mask3 (0x%x): 0x%04x\n", REG_END_MASK3, regs->end_mask_3);
1461: fprintf(fp, "HOP (0x%x): 0x%02x\n", REG_BLIT_HOP, regs->hop);
1462: fprintf(fp, "LOP (0x%x): 0x%02x\n", REG_BLIT_LOP, regs->lop);
1463: /* List control bits: busy, hog/blit, smudge, n/a, 4bits for line number ? */
1464: fprintf(fp, "control (0x%x): 0x%02x\n", REG_CONTROL, regs->ctrl);
1465: fprintf(fp, "skew (0x%x): 0x%02x\n", REG_SKEW, regs->skew);
1.1.1.13 root 1466: 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 1467: }
1.1.1.16 root 1468:
1469:
1470:
1471:
1472: /*-----------------------------------------------------------------------*/
1473: /**
1474: * This is called from the CPU emulation before doing a memory access.
1475: */
1476: void Blitter_HOG_CPU_mem_access_before ( int bus_count )
1477: {
1478: //fprintf ( stderr , "cpu_bus before phase=%d bus=%d %x %d cur_cyc=%lu start_acces=%d\n" , BlitterPhase , BusMode , BlitterRegs.ctrl , BlitterState.CountBusCpu , currcycle/cpucycleunit , Blitter_HOG_CPU_BlitterStartDuringBusAccess );
1479:
1480: Blitter_HOG_CPU_FromBusAccess = 1; /* CPU bus access in progress */
1481:
1482: /* NOTE [NP] It seems there's a bug in the blitter when it counts his own bus accesses : */
1483: /* if a CPU bus access happens during the "pre start" blitter phase, then the blitter will wrongly */
1484: /* count it as a blitter bus access and will do only 63 bus accesses during copy instead of 64 in non-hog mode */
1485: if ( BlitterPhase == BLITTER_PHASE_PRE_START )
1486: Blitter_HOG_CPU_BusCountError = 1;
1487:
1488: /* If the bus is accessed by the CPU and we're ignoring CPU cycles that occurred in parallel */
1489: /* during the blitter's transfer, then we disable IGNORE_LAST_CPU_CYCLES as the CPU was stalled */
1490: /* after this point because it couldn't access the bus (which was owned by the blitter) */
1491: else if ( BlitterPhase & BLITTER_PHASE_IGNORE_LAST_CPU_CYCLES )
1492: {
1493: Blitter_Stop_IgnoreLastCpuCycles(); /* No more CPU in parallel, stop ignoring next CPU cycles */
1494: }
1495: }
1496:
1497:
1498:
1499: /*-----------------------------------------------------------------------*/
1500: /**
1501: * This is called from the CPU emulation after doing a memory access.
1502: * Here, we count the number of bus accesses made by the CPU in non-hog mode.
1503: * When the CPU reaches 64 accesses, we restart the blitter.
1504: */
1505: void Blitter_HOG_CPU_mem_access_after ( int bus_count )
1506: {
1507: //fprintf ( stderr , "cpu_bus after phase=%d bus=%d %x %d cur_cyc=%lu start_acces=%d\n" , BlitterPhase , BusMode , BlitterRegs.ctrl , BlitterState.CountBusCpu , currcycle/cpucycleunit,Blitter_HOG_CPU_BlitterStartDuringBusAccess );
1508:
1509: if ( BlitterPhase & BLITTER_PHASE_COUNT_CPU_BUS )
1510: {
1511: if ( Blitter_HOG_CPU_BlitterStartDuringBusAccess )
1512: {
1513: Blitter_HOG_CPU_BlitterStartDuringBusAccess = 0;
1514: return;
1515: }
1516:
1517: BlitterState.CountBusCpu += bus_count;
1518: if ( BlitterState.CountBusCpu >= BLITTER_NONHOG_BUS_CPU )
1519: {
1520: Blitter_CyclesBeforeStart = 4;
1521: BlitterPhase = BLITTER_PHASE_PRE_START;
1522: Blitter_HOG_CPU_BusCountError = 0;
1523: }
1524: }
1525:
1526:
1527: Blitter_HOG_CPU_FromBusAccess = 0; /* CPU bus access is done */
1528: }
1529:
1530:
1531:
1532:
1533: /*-----------------------------------------------------------------------*/
1534: /**
1535: * This is called from the CPU emulation before "do_cycles()" to check
1536: * if part of an instruction was executed simultaneously to the blitter.
1537: * If so, we don't count those CPU cycles (as they were already counted
1538: * during the blitter part) and we skip the "do_cycles()"
1539: * We skip CPU cycles until Blitter_HOG_CPU_IgnoreMaxCpuCycles=0 or until
1540: * we reach a bus access (whichever comes first)
1541: */
1542:
1543: int Blitter_Check_Simultaneous_CPU ( void )
1544: {
1545: static int cpu_skip_cycles = 0;
1546: //fprintf ( stderr , "blitter simult phase=%d bus=%d %x cur_cyc=%lu\n" , BlitterPhase , BusMode , BlitterRegs.ctrl , currcycle/cpucycleunit );
1547:
1548: if ( BlitterPhase & BLITTER_PHASE_IGNORE_LAST_CPU_CYCLES )
1549: {
1550: Blitter_HOG_CPU_IgnoreMaxCpuCycles -= 2;
1551: if ( Blitter_HOG_CPU_IgnoreMaxCpuCycles <= 0 )
1552: Blitter_Stop_IgnoreLastCpuCycles(); /* No more CPU in parallel, stop ignoring next CPU cycles */
1553:
1554: cpu_skip_cycles += 2;
1555: //fprintf ( stderr , "blitter cpu skip %d cycles, max skip %d\n" , cpu_skip_cycles , Blitter_HOG_CPU_IgnoreMaxCpuCycles );
1556: return 1; /* Skip next do_cycles() */
1557: }
1558:
1559: cpu_skip_cycles = 0;
1560: return 0; /* Don't skip next do_cycles() */
1561: }
1562:
1563:
1564:
1565: /*-----------------------------------------------------------------------*/
1566: /**
1567: * This is called from the cpu emulation after "do_cycles()" to count
1568: * the number of cycles since the blitter was (re)started.
1569: * After Blitter_CyclesBeforeStart cycles, we go to the next phase BLITTER_PHASE_START
1570: * to handle bus to the blitter and to copy data.
1571: */
1572: void Blitter_HOG_CPU_do_cycles_after ( int cycles )
1573: {
1574: //fprintf ( stderr , "blitter do_cyc_after phase=%d bus=%d %x cyc=%d cur_cyc=%lu\n" , BlitterPhase , BusMode , BlitterRegs.ctrl , cycles , currcycle/cpucycleunit );
1575:
1576: if ( BlitterPhase == BLITTER_PHASE_PRE_START )
1577: {
1578: Blitter_CyclesBeforeStart -= cycles;
1579: if ( Blitter_CyclesBeforeStart <= 0 )
1580: {
1581: /* This is specific to our cpu emulation, to avoid counting the current */
1582: /* bus access (during which the blitter starts) as the first cpu bus access in non-hog mode */
1583: if ( Blitter_HOG_CPU_FromBusAccess )
1584: Blitter_HOG_CPU_BlitterStartDuringBusAccess = 1;
1585: else
1586: Blitter_HOG_CPU_BlitterStartDuringBusAccess = 0;
1587:
1588: /* Start the main blitter part */
1589: BlitterPhase = BLITTER_PHASE_START;
1590: Blitter_Start();
1591: }
1592: }
1593:
1594: }
1595:
1596:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.