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