1 | /*****************************************************************************\ |
2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. |
3 | This file is licensed under the Snes9x License. |
4 | For further information, consult the LICENSE file in the root directory. |
5 | \*****************************************************************************/ |
6 | |
7 | #ifndef _FXINST_H_ |
8 | #define _FXINST_H_ |
9 | |
10 | /* |
11 | * FxChip(GSU) register space specification |
12 | * (Register address space 3000-32ff) |
13 | * |
14 | * The 16 generic 16 bit registers: |
15 | * (Some have a special function in special circumstances) |
16 | * 3000 - R0 default source/destination register |
17 | * 3002 - R1 pixel plot X position register |
18 | * 3004 - R2 pixel plot Y position register |
19 | * 3006 - R3 |
20 | * 3008 - R4 lower 16 bit result of lmult |
21 | * 300a - R5 |
22 | * 300c - R6 multiplier for fmult and lmult |
23 | * 300e - R7 fixed point texel X position for merge |
24 | * 3010 - R8 fixed point texel Y position for merge |
25 | * 3012 - R9 |
26 | * 3014 - R10 |
27 | * 3016 - R11 return address set by link |
28 | * 3018 - R12 loop counter |
29 | * 301a - R13 loop point address |
30 | * 301c - R14 rom address for getb, getbh, getbl, getbs |
31 | * 301e - R15 program counter |
32 | * |
33 | * 3020-302f - unused |
34 | * |
35 | * Other internal registers |
36 | * 3030 - SFR status flag register (16bit) |
37 | * 3032 - unused |
38 | * 3033 - BRAMR Backup RAM register (8bit) |
39 | * 3034 - PBR program bank register (8bit) |
40 | * 3035 - unused |
41 | * 3036 - ROMBR rom bank register (8bit) |
42 | * 3037 - CFGR control flags register (8bit) |
43 | * 3038 - SCBR screen base register (8bit) |
44 | * 3039 - CLSR clock speed register (8bit) |
45 | * 303a - SCMR screen mode register (8bit) |
46 | * 303b - VCR version code register (8bit) (read only) |
47 | * 303c - RAMBR ram bank register (8bit) |
48 | * 303d - unused |
49 | * 303e - CBR cache base register (16bit) |
50 | * |
51 | * 3040-30ff - unused |
52 | * |
53 | * 3100-32ff - CACHERAM 512 bytes of GSU cache memory |
54 | * |
55 | * SFR status flag register bits: |
56 | * 0 - |
57 | * 1 Z Zero flag |
58 | * 2 CY Carry flag |
59 | * 3 S Sign flag |
60 | * 4 OV Overflow flag |
61 | * 5 G Go flag (set to 1 when the GSU is running) |
62 | * 6 R Set to 1 when reading ROM using R14 address |
63 | * 7 - |
64 | * 8 ALT1 Mode set-up flag for the next instruction |
65 | * 9 ALT2 Mode set-up flag for the next instruction |
66 | * 10 IL Immediate lower 8-bit flag |
67 | * 11 IH Immediate higher 8-bit flag |
68 | * 12 B Set to 1 when the WITH instruction is executed |
69 | * 13 - |
70 | * 14 - |
71 | * 15 IRQ Set to 1 when GSU caused an interrupt |
72 | * Set to 0 when read by 658c16 |
73 | * |
74 | * BRAMR = 0, BackupRAM is disabled |
75 | * BRAMR = 1, BackupRAM is enabled |
76 | * |
77 | * CFGR control flags register bits: |
78 | * 0 - |
79 | * 1 - |
80 | * 2 - |
81 | * 3 - |
82 | * 4 - |
83 | * 5 MS0 Multiplier speed, 0=standard, 1=high speed |
84 | * 6 - |
85 | * 7 IRQ Set to 1 when GSU interrupt request is masked |
86 | * |
87 | * CLSR clock speed register bits: |
88 | * 0 CLSR clock speed, 0 = 10.7Mhz, 1 = 21.4Mhz |
89 | * |
90 | * SCMR screen mode register bits: |
91 | * 0 MD0 color depth mode bit 0 |
92 | * 1 MD1 color depth mode bit 1 |
93 | * 2 HT0 screen height bit 1 |
94 | * 3 RAN RAM access control |
95 | * 4 RON ROM access control |
96 | * 5 HT1 screen height bit 2 |
97 | * 6 - |
98 | * 7 - |
99 | * |
100 | * RON = 0 SNES CPU has ROM access |
101 | * RON = 1 GSU has ROM access |
102 | * |
103 | * RAN = 0 SNES has game pak RAM access |
104 | * RAN = 1 GSU has game pak RAM access |
105 | * |
106 | * HT1 HT0 Screen height mode |
107 | * 0 0 128 pixels high |
108 | * 0 1 160 pixels high |
109 | * 1 0 192 pixels high |
110 | * 1 1 OBJ mode |
111 | * |
112 | * MD1 MD0 Color depth mode |
113 | * 0 0 4 color mode |
114 | * 0 1 16 color mode |
115 | * 1 0 not used |
116 | * 1 1 256 color mode |
117 | * |
118 | * CBR cache base register bits: |
119 | * 15-4 Specify base address for data to cache from ROM or RAM |
120 | * 3-0 Are 0 when address is read |
121 | * |
122 | * Write access to the program counter (301e) from |
123 | * the SNES-CPU will start the GSU, and it will not |
124 | * stop until it reaches a stop instruction. |
125 | * |
126 | */ |
127 | |
128 | // Number of banks in GSU RAM |
129 | #define FX_RAM_BANKS 4 |
130 | |
131 | // Emulate proper R14 ROM access (slower, but safer) |
132 | #define FX_DO_ROMBUFFER |
133 | |
134 | // Address checking (definately slow) |
135 | //#define FX_ADDRESS_CHECK |
136 | |
137 | struct FxRegs_s |
138 | { |
139 | // FxChip registers |
140 | uint32 avReg[16]; // 16 Generic registers |
141 | uint32 vColorReg; // Internal color register |
142 | uint32 vPlotOptionReg; // Plot option register |
143 | uint32 vStatusReg; // Status register |
144 | uint32 vPrgBankReg; // Program bank index register |
145 | uint32 vRomBankReg; // Rom bank index register |
146 | uint32 vRamBankReg; // Ram bank index register |
147 | uint32 vCacheBaseReg; // Cache base address register |
148 | uint32 vCacheFlags; // Saying what parts of the cache was written to |
149 | uint32 vLastRamAdr; // Last RAM address accessed |
150 | uint32 *pvDreg; // Pointer to current destination register |
151 | uint32 *pvSreg; // Pointer to current source register |
152 | uint8 vRomBuffer; // Current byte read by R14 |
153 | uint8 vPipe; // Instructionset pipe |
154 | uint32 vPipeAdr; // The address of where the pipe was read from |
155 | |
156 | // Status register optimization stuff |
157 | uint32 vSign; // v & 0x8000 |
158 | uint32 vZero; // v == 0 |
159 | uint32 vCarry; // a value of 1 or 0 |
160 | int32 vOverflow; // (v >= 0x8000 || v < -0x8000) |
161 | |
162 | // Other emulator variables |
163 | int32 vErrorCode; |
164 | uint32 vIllegalAddress; |
165 | |
166 | uint8 bBreakPoint; |
167 | uint32 vBreakPoint; |
168 | uint32 vStepPoint; |
169 | |
170 | uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000 |
171 | uint32 nRamBanks; // Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) |
172 | uint8 *pvRam; // Pointer to FxRam |
173 | uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM |
174 | uint8 *pvRom; // Pointer to Cart-ROM |
175 | |
176 | uint32 vMode; // Color depth/mode |
177 | uint32 vPrevMode; // Previous depth |
178 | uint8 *pvScreenBase; |
179 | uint8 *apvScreen[32]; // Pointer to each of the 32 screen colums |
180 | int32 x[32]; |
181 | uint32 vScreenHeight; // 128, 160, 192 or 256 (could be overriden by cmode) |
182 | uint32 vScreenRealHeight; // 128, 160, 192 or 256 |
183 | uint32 vPrevScreenHeight; |
184 | uint32 vScreenSize; |
185 | void (*pfPlot) (void); |
186 | void (*pfRpix) (void); |
187 | |
188 | uint8 *pvRamBank; // Pointer to current RAM-bank |
189 | uint8 *pvRomBank; // Pointer to current ROM-bank |
190 | uint8 *pvPrgBank; // Pointer to current program ROM-bank |
191 | |
192 | uint8 *apvRamBank[FX_RAM_BANKS]; // Ram bank table (max 256kb) |
193 | uint8 *apvRomBank[256]; // Rom bank table |
194 | |
195 | uint8 bCacheActive; |
196 | uint8 *pvCache; // Pointer to the GSU cache |
197 | uint8 avCacheBackup[512]; // Backup of ROM when the cache has replaced it |
198 | uint32 vCounter; |
199 | uint32 vInstCount; |
200 | uint32 vSCBRDirty; // If SCBR is written, our cached screen pointers need updating |
201 | |
202 | uint8 *avRegAddr; // To reference avReg in snapshot.cpp |
203 | }; |
204 | |
205 | extern struct FxRegs_s GSU; |
206 | |
207 | // GSU registers |
208 | #define GSU_R0 0x000 |
209 | #define GSU_R1 0x002 |
210 | #define GSU_R2 0x004 |
211 | #define GSU_R3 0x006 |
212 | #define GSU_R4 0x008 |
213 | #define GSU_R5 0x00a |
214 | #define GSU_R6 0x00c |
215 | #define GSU_R7 0x00e |
216 | #define GSU_R8 0x010 |
217 | #define GSU_R9 0x012 |
218 | #define GSU_R10 0x014 |
219 | #define GSU_R11 0x016 |
220 | #define GSU_R12 0x018 |
221 | #define GSU_R13 0x01a |
222 | #define GSU_R14 0x01c |
223 | #define GSU_R15 0x01e |
224 | #define GSU_SFR 0x030 |
225 | #define GSU_BRAMR 0x033 |
226 | #define GSU_PBR 0x034 |
227 | #define GSU_ROMBR 0x036 |
228 | #define GSU_CFGR 0x037 |
229 | #define GSU_SCBR 0x038 |
230 | #define GSU_CLSR 0x039 |
231 | #define GSU_SCMR 0x03a |
232 | #define GSU_VCR 0x03b |
233 | #define GSU_RAMBR 0x03c |
234 | #define GSU_CBR 0x03e |
235 | #define GSU_CACHERAM 0x100 |
236 | |
237 | // SFR flags |
238 | #define FLG_Z (1 << 1) |
239 | #define FLG_CY (1 << 2) |
240 | #define FLG_S (1 << 3) |
241 | #define FLG_OV (1 << 4) |
242 | #define FLG_G (1 << 5) |
243 | #define FLG_R (1 << 6) |
244 | #define FLG_ALT1 (1 << 8) |
245 | #define FLG_ALT2 (1 << 9) |
246 | #define FLG_IL (1 << 10) |
247 | #define FLG_IH (1 << 11) |
248 | #define FLG_B (1 << 12) |
249 | #define FLG_IRQ (1 << 15) |
250 | |
251 | // Test flag |
252 | #define TF(a) (GSU.vStatusReg & FLG_##a) |
253 | #define CF(a) (GSU.vStatusReg &= ~FLG_##a) |
254 | #define SF(a) (GSU.vStatusReg |= FLG_##a) |
255 | |
256 | // Test and set flag if condition, clear if not |
257 | #define TS(a, b) GSU.vStatusReg = ((GSU.vStatusReg & (~FLG_##a)) | ((!!(##b)) * FLG_##a)) |
258 | |
259 | // Testing ALT1 & ALT2 bits |
260 | #define ALT0 (!TF(ALT1) && !TF(ALT2)) |
261 | #define ALT1 ( TF(ALT1) && !TF(ALT2)) |
262 | #define ALT2 (!TF(ALT1) && TF(ALT2)) |
263 | #define ALT3 ( TF(ALT1) && TF(ALT2)) |
264 | |
265 | // Sign extend from 8/16 bit to 32 bit |
266 | #define SEX8(a) ((int32) ((int8) (a))) |
267 | #define SEX16(a) ((int32) ((int16) (a))) |
268 | |
269 | // Unsign extend from 8/16 bit to 32 bit |
270 | #define USEX8(a) ((uint32) ((uint8) (a))) |
271 | #define USEX16(a) ((uint32) ((uint16) (a))) |
272 | #define SUSEX16(a) ((int32) ((uint16) (a))) |
273 | |
274 | // Set/Clr Sign and Zero flag |
275 | #define TSZ(num) TS(S, ((num) & 0x8000)); TS(Z, (!USEX16(num))) |
276 | |
277 | // Clear flags |
278 | #define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1 | FLG_ALT2 | FLG_B); GSU.pvDreg = GSU.pvSreg = &R0 |
279 | |
280 | // Read current RAM-Bank |
281 | #define RAM(adr) GSU.pvRamBank[USEX16(adr)] |
282 | |
283 | // Read current ROM-Bank |
284 | #define ROM(idx) GSU.pvRomBank[USEX16(idx)] |
285 | |
286 | // Access the current value in the pipe |
287 | #define PIPE GSU.vPipe |
288 | |
289 | // Access data in the current program bank |
290 | #define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)] |
291 | |
292 | // Update pipe from ROM |
293 | #if 0 |
294 | #define FETCHPIPE { PIPE = PRGBANK(R15); GSU.vPipeAdr = (GSU.vPrgBankReg << 16) + R15; } |
295 | #else |
296 | #define FETCHPIPE { PIPE = PRGBANK(R15); } |
297 | #endif |
298 | |
299 | // ABS |
300 | #define ABS(x) ((x) < 0 ? -(x) : (x)) |
301 | |
302 | // Access source register |
303 | #define SREG (*GSU.pvSreg) |
304 | |
305 | // Access destination register |
306 | #define DREG (*GSU.pvDreg) |
307 | |
308 | #ifndef FX_DO_ROMBUFFER |
309 | |
310 | // Don't read R14 |
311 | #define READR14 |
312 | |
313 | // Don't test and/or read R14 |
314 | #define TESTR14 |
315 | |
316 | #else |
317 | |
318 | // Read R14 |
319 | #define READR14 GSU.vRomBuffer = ROM(R14) |
320 | |
321 | // Test and/or read R14 |
322 | #define TESTR14 if (GSU.pvDreg == &R14) READR14 |
323 | |
324 | #endif |
325 | |
326 | // Access to registers |
327 | #define R0 GSU.avReg[0] |
328 | #define R1 GSU.avReg[1] |
329 | #define R2 GSU.avReg[2] |
330 | #define R3 GSU.avReg[3] |
331 | #define R4 GSU.avReg[4] |
332 | #define R5 GSU.avReg[5] |
333 | #define R6 GSU.avReg[6] |
334 | #define R7 GSU.avReg[7] |
335 | #define R8 GSU.avReg[8] |
336 | #define R9 GSU.avReg[9] |
337 | #define R10 GSU.avReg[10] |
338 | #define R11 GSU.avReg[11] |
339 | #define R12 GSU.avReg[12] |
340 | #define R13 GSU.avReg[13] |
341 | #define R14 GSU.avReg[14] |
342 | #define R15 GSU.avReg[15] |
343 | #define SFR GSU.vStatusReg |
344 | #define PBR GSU.vPrgBankReg |
345 | #define ROMBR GSU.vRomBankReg |
346 | #define RAMBR GSU.vRamBankReg |
347 | #define CBR GSU.vCacheBaseReg |
348 | #define SCBR USEX8(GSU.pvRegisters[GSU_SCBR]) |
349 | #define SCMR USEX8(GSU.pvRegisters[GSU_SCMR]) |
350 | #define COLR GSU.vColorReg |
351 | #define POR GSU.vPlotOptionReg |
352 | #define BRAMR USEX8(GSU.pvRegisters[GSU_BRAMR]) |
353 | #define VCR USEX8(GSU.pvRegisters[GSU_VCR]) |
354 | #define CFGR USEX8(GSU.pvRegisters[GSU_CFGR]) |
355 | #define CLSR USEX8(GSU.pvRegisters[GSU_CLSR]) |
356 | |
357 | // Execute instruction from the pipe, and fetch next byte to the pipe |
358 | #define FX_STEP \ |
359 | { \ |
360 | uint32 vOpcode = (uint32) PIPE; \ |
361 | FETCHPIPE; \ |
362 | (*fx_OpcodeTable[(GSU.vStatusReg & 0x300) | vOpcode])(); \ |
363 | } |
364 | |
365 | extern void (*fx_PlotTable[]) (void); |
366 | extern void (*fx_OpcodeTable[]) (void); |
367 | |
368 | // Set this define if branches are relative to the instruction in the delay slot (I think they are) |
369 | #define BRANCH_DELAY_RELATIVE |
370 | |
371 | #endif |
372 | |