2 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5 * Jerremy Koot (jkoot@snes9x.com)
7 * Super FX C emulator code
8 * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
10 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
12 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13 * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14 * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
16 * DOS port code contains the works of other authors. See headers in
19 * Snes9x homepage: http://www.snes9x.com
21 * Permission to use, copy, modify and distribute Snes9x in both binary and
22 * source form, for non-commercial purposes, is hereby granted without fee,
23 * providing that this license information and copyright notice appear with
24 * all copies and any derived work.
26 * This software is provided 'as-is', without any express or implied
27 * warranty. In no event shall the authors be held liable for any damages
28 * arising from the use of this software.
30 * Snes9x is freeware for PERSONAL USE only. Commercial users should
31 * seek permission of the copyright holders first. Commercial use includes
32 * charging money for Snes9x or software derived from Snes9x.
34 * The copyright holders request that bug fixes and improvements to the code
35 * should be forwarded to them so everyone can benefit from the modifications
38 * Super NES and Super Nintendo Entertainment System are trademarks of
39 * Nintendo Co., Limited and its subsidiary companies.
45 * FxChip(GSU) register space specification
46 * (Register address space 3000->32ff)
48 * The 16 generic 16 bit registers:
49 * (Some have a special function in special circumstances)
50 * 3000 - R0 default source/destination register
51 * 3002 - R1 pixel plot X position register
52 * 3004 - R2 pixel plot Y position register
54 * 3008 - R4 lower 16 bit result of lmult
56 * 300c - R6 multiplier for fmult and lmult
57 * 300e - R7 fixed point texel X position for merge
58 * 3010 - R8 fixed point texel Y position for merge
61 * 3016 - R11 return address set by link
62 * 3018 - R12 loop counter
63 * 301a - R13 loop point address
64 * 301c - R14 rom address for getb, getbh, getbl, getbs
65 * 301e - R15 program counter
69 * Other internal registers
70 * 3030 - SFR status flag register (16bit)
72 * 3033 - BRAMR Backup RAM register (8bit)
73 * 3034 - PBR program bank register (8bit)
75 * 3036 - ROMBR rom bank register (8bit)
76 * 3037 - CFGR control flags register (8bit)
77 * 3038 - SCBR screen base register (8bit)
78 * 3039 - CLSR clock speed register (8bit)
79 * 303a - SCMR screen mode register (8bit)
80 * 303b - VCR version code register (8bit) (read only)
81 * 303c - RAMBR ram bank register (8bit)
83 * 303e - CBR cache base register (16bit)
87 * 3100-32ff - CACHERAM 512 bytes of GSU cache memory
89 * SFR status flag register bits:
95 * 5 G Go flag (set to 1 when the GSU is running)
96 * 6 R Set to 1 when reading ROM using R14 address
98 * 8 ALT1 Mode set-up flag for the next instruction
99 * 9 ALT2 Mode set-up flag for the next instruction
100 * 10 IL Immediate lower 8-bit flag
101 * 11 IH Immediate higher 8-bit flag
102 * 12 B Set to 1 when the WITH instruction is executed
105 * 15 IRQ Set to 1 when GSU caused an interrupt
106 * Set to 0 when read by 658c16
108 * BRAMR = 0, BackupRAM is disabled
109 * BRAMR = 1, BackupRAM is enabled
111 * CFGR control flags register bits:
117 * 5 MS0 Multiplier speed, 0=standard, 1=high speed
119 * 7 IRQ Set to 1 when GSU interrupt request is masked
121 * CLSR clock speed register bits:
122 * 0 CLSR clock speed, 0 = 10.7Mhz, 1 = 21.4Mhz
124 * SCMR screen mode register bits:
125 * 0 MD0 color depth mode bit 0
126 * 1 MD1 color depth mode bit 1
127 * 2 HT0 screen height bit 1
128 * 3 RAN RAM access control
129 * 4 RON ROM access control
130 * 5 HT1 screen height bit 2
134 * RON = 0 SNES CPU has ROM access
135 * RON = 1 GSU has ROM access
137 * RAN = 0 SNES has game pak RAM access
138 * RAN = 1 GSU has game pak RAM access
140 * HT1 HT0 Screen height mode
141 * 0 0 128 pixels high
142 * 0 1 160 pixels high
143 * 1 0 192 pixels high
146 * MD1 MD0 Color depth mode
152 * CBR cache base register bits:
153 * 15-4 Specify base address for data to cache from ROM or RAM
154 * 3-0 Are 0 when address is read
156 * Write access to the program counter (301e) from
157 * the SNES-CPU will start the GSU, and it will not
158 * stop until it reaches a stop instruction.
162 /* Number of banks in GSU RAM */
163 #define FX_RAM_BANKS 4
165 /* Emulate proper R14 ROM access (slower, but safer) */
166 /* #define FX_DO_ROMBUFFER */
168 /* Address checking (definately slow) */
169 /* #define FX_ADDRESS_CHECK */
173 /* FxChip registers */
174 uint32 avReg[16]; /* 16 Generic registers */
175 uint32 vColorReg; /* Internal color register */
176 uint32 vPlotOptionReg; /* Plot option register */
177 uint32 vStatusReg; /* Status register */
178 uint32 vPrgBankReg; /* Program bank index register */
179 uint32 vRomBankReg; /* Rom bank index register */
180 uint32 vRamBankReg; /* Ram bank index register */
181 uint32 vCacheBaseReg; /* Cache base address register */
182 uint32 vCacheFlags; /* Saying what parts of the cache was written to */
183 uint32 vLastRamAdr; /* Last RAM address accessed */
184 uint32 * pvDreg; /* Pointer to current destination register */
185 uint32 * pvSreg; /* Pointer to current source register */
186 uint8 vRomBuffer; /* Current byte read by R14 */
187 uint8 vPipe; /* Instructionset pipe */
188 uint32 vPipeAdr; /* The address of where the pipe was read from */
190 /* status register optimization stuff */
191 uint32 vSign; /* v & 0x8000 */
192 uint32 vZero; /* v == 0 */
193 uint32 vCarry; /* a value of 1 or 0 */
194 int32 vOverflow; /* (v >= 0x8000 || v < -0x8000) */
196 /* Other emulator variables */
199 uint32 vIllegalAddress;
205 uint8 * pvRegisters; /* 768 bytes located in the memory at address 0x3000 */
206 uint32 nRamBanks; /* Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) */
207 uint8 * pvRam; /* Pointer to FxRam */
208 uint32 nRomBanks; /* Number of 32kb-banks in Cart-ROM */
209 uint8 * pvRom; /* Pointer to Cart-ROM */
211 uint32 vMode; /* Color depth/mode */
212 uint32 vPrevMode; /* Previous depth */
213 uint8 * pvScreenBase;
214 uint8 * apvScreen[32]; /* Pointer to each of the 32 screen colums */
216 uint32 vScreenHeight; /* 128, 160, 192 or 256 (could be overriden by cmode) */
217 uint32 vScreenRealHeight; /* 128, 160, 192 or 256 */
218 uint32 vPrevScreenHeight;
223 uint8 * pvRamBank; /* Pointer to current RAM-bank */
224 uint8 * pvRomBank; /* Pointer to current ROM-bank */
225 uint8 * pvPrgBank; /* Pointer to current program ROM-bank */
227 uint8 * apvRamBank[FX_RAM_BANKS];/* Ram bank table (max 256kb) */
228 uint8 * apvRomBank[256]; /* Rom bank table */
231 uint8 * pvCache; /* Pointer to the GSU cache */
232 uint8 avCacheBackup[512]; /* Backup of ROM when the cache has replaced it */
248 #define GSU_R10 0x014
249 #define GSU_R11 0x016
250 #define GSU_R12 0x018
251 #define GSU_R13 0x01a
252 #define GSU_R14 0x01c
253 #define GSU_R15 0x01e
254 #define GSU_SFR 0x030
255 #define GSU_BRAMR 0x033
256 #define GSU_PBR 0x034
257 #define GSU_ROMBR 0x036
258 #define GSU_CFGR 0x037
259 #define GSU_SCBR 0x038
260 #define GSU_CLSR 0x039
261 #define GSU_SCMR 0x03a
262 #define GSU_VCR 0x03b
263 #define GSU_RAMBR 0x03c
264 #define GSU_CBR 0x03e
265 #define GSU_CACHERAM 0x100
269 #define FLG_CY (1<<2)
271 #define FLG_OV (1<<4)
274 #define FLG_ALT1 (1<<8)
275 #define FLG_ALT2 (1<<9)
276 #define FLG_IL (1<<10)
277 #define FLG_IH (1<<11)
278 #define FLG_B (1<<12)
279 #define FLG_IRQ (1<<15)
282 #define TF(a) (GSU.vStatusReg & FLG_##a )
283 #define CF(a) (GSU.vStatusReg &= ~FLG_##a )
284 #define SF(a) (GSU.vStatusReg |= FLG_##a )
286 /* Test and set flag if condition, clear if not */
287 #define TS(a,b) GSU.vStatusReg = ( (GSU.vStatusReg & (~FLG_##a)) | ( (!!(##b)) * FLG_##a ) )
289 /* Testing ALT1 & ALT2 bits */
290 #define ALT0 (!TF(ALT1)&&!TF(ALT2))
291 #define ALT1 (TF(ALT1)&&!TF(ALT2))
292 #define ALT2 (!TF(ALT1)&&TF(ALT2))
293 #define ALT3 (TF(ALT1)&&TF(ALT2))
295 /* Sign extend from 8/16 bit to 32 bit */
296 #define SEX16(a) ((int32)((int16)(a)))
297 #define SEX8(a) ((int32)((int8)(a)))
299 /* Unsign extend from 8/16 bit to 32 bit */
300 #define USEX16(a) ((uint32)((uint16)(a)))
301 #define USEX8(a) ((uint32)((uint8)(a)))
303 #define SUSEX16(a) ((int32)((uint16)(a)))
305 /* Set/Clr Sign and Zero flag */
306 #define TSZ(num) TS(S, (num & 0x8000)); TS(Z, (!USEX16(num)) )
309 #define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1|FLG_ALT2|FLG_B); GSU.pvDreg = GSU.pvSreg = &R0;
311 /* Read current RAM-Bank */
312 #define RAM(adr) GSU.pvRamBank[USEX16(adr)]
314 /* Read current ROM-Bank */
315 #define ROM(idx) (GSU.pvRomBank[USEX16(idx)])
317 /* Access the current value in the pipe */
318 #define PIPE GSU.vPipe
320 /* Access data in the current program bank */
321 #define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)]
323 /* Update pipe from ROM */
325 #define FETCHPIPE { PIPE = PRGBANK(R15); GSU.vPipeAdr = (GSU.vPrgBankReg<<16) + R15; }
327 #define FETCHPIPE { PIPE = PRGBANK(R15); }
331 #define ABS(x) ((x)<0?-(x):(x))
333 /* Access source register */
334 #define SREG (*GSU.pvSreg)
336 /* Access destination register */
337 #define DREG (*GSU.pvDreg)
339 #ifndef FX_DO_ROMBUFFER
344 /* Don't test and/or read R14 */
350 #define READR14 GSU.vRomBuffer = ROM(R14)
352 /* Test and/or read R14 */
353 #define TESTR14 if(GSU.pvDreg == &R14) READR14
357 /* Access to registers */
358 #define R0 GSU.avReg[0]
359 #define R1 GSU.avReg[1]
360 #define R2 GSU.avReg[2]
361 #define R3 GSU.avReg[3]
362 #define R4 GSU.avReg[4]
363 #define R5 GSU.avReg[5]
364 #define R6 GSU.avReg[6]
365 #define R7 GSU.avReg[7]
366 #define R8 GSU.avReg[8]
367 #define R9 GSU.avReg[9]
368 #define R10 GSU.avReg[10]
369 #define R11 GSU.avReg[11]
370 #define R12 GSU.avReg[12]
371 #define R13 GSU.avReg[13]
372 #define R14 GSU.avReg[14]
373 #define R15 GSU.avReg[15]
374 #define SFR GSU.vStatusReg
375 #define PBR GSU.vPrgBankReg
376 #define ROMBR GSU.vRomBankReg
377 #define RAMBR GSU.vRamBankReg
378 #define CBR GSU.vCacheBaseReg
379 #define SCBR USEX8(GSU.pvRegisters[GSU_SCBR])
380 #define SCMR USEX8(GSU.pvRegisters[GSU_SCMR])
381 #define COLR GSU.vColorReg
382 #define POR GSU.vPlotOptionReg
383 #define BRAMR USEX8(GSU.pvRegisters[GSU_BRAMR])
384 #define VCR USEX8(GSU.pvRegisters[GSU_VCR])
385 #define CFGR USEX8(GSU.pvRegisters[GSU_CFGR])
386 #define CLSR USEX8(GSU.pvRegisters[GSU_CLSR])
388 /* Execute instruction from the pipe, and fetch next byte to the pipe */
390 uint32 vOpcode = (uint32)PIPE; \
392 (*fx_ppfOpcodeTable[ (GSU.vStatusReg & 0x300) | vOpcode ])(); \
395 #define FX_FUNCTION_RUN 0
396 #define FX_FUNCTION_RUN_TO_BREAKPOINT 1
397 #define FX_FUNCTION_STEP_OVER 2
399 extern uint32 (**fx_ppfFunctionTable)(uint32);
400 extern void (**fx_ppfPlotTable)();
401 extern void (**fx_ppfOpcodeTable)();
403 extern uint32 (*fx_apfFunctionTable[])(uint32);
404 extern void (*fx_apfOpcodeTable[])();
405 extern void (*fx_apfPlotTable[])();
406 extern uint32 (*fx_a_apfFunctionTable[])(uint32);
407 extern void (*fx_a_apfOpcodeTable[])();
408 extern void (*fx_a_apfPlotTable[])();
409 extern uint32 (*fx_r_apfFunctionTable[])(uint32);
410 extern void (*fx_r_apfOpcodeTable[])();
411 extern void (*fx_r_apfPlotTable[])();
412 extern uint32 (*fx_ar_apfFunctionTable[])(uint32);
413 extern void (*fx_ar_apfOpcodeTable[])();
414 extern void (*fx_ar_apfPlotTable[])();
416 /* Set this define if branches are relative to the instruction in the delay slot */
417 /* (I think they are) */
418 #define BRANCH_DELAY_RELATIVE