1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <stddef.h>
6 #include <memalign.h>
7 #include <time.h>
8
9 #include "system.h"
10 #include "globals.h"
11
12 #include "port.h"
13 #include "gba.h"
14 #include "memory.h"
15 #include "sound.h"
16
17 #ifdef ELF
18 #include "elf.h"
19 #endif
20
21 #define DEBUG_RENDERER_MODE0 1
22 #define DEBUG_RENDERER_MODE1 1
23 #define DEBUG_RENDERER_MODE2 1
24 #define DEBUG_RENDERER_MODE3 1
25 #define DEBUG_RENDERER_MODE4 1
26 #define DEBUG_RENDERER_MODE5 1
27
28 #define DEBUG_RENDERER_NOSYNC 0
29
30 #define CLOCKTICKS_UPDATE_TYPE16 codeTicksAccessSeq16(bus.armNextPC) + 1
31 #define CLOCKTICKS_UPDATE_TYPE32 codeTicksAccessSeq32(bus.armNextPC) + 1
32 #define CLOCKTICKS_UPDATE_TYPE16P (codeTicksAccessSeq16(bus.armNextPC) << 1) + codeTicksAccess(bus.armNextPC, BITS_16) + 3
33 #define CLOCKTICKS_UPDATE_TYPE32P (codeTicksAccessSeq32(bus.armNextPC) << 1) + codeTicksAccess(bus.armNextPC, BITS_32) + 3
34
35 // Indexes into the line array
36 #define Layer_BG0 0
37 #define Layer_BG1 1
38 #define Layer_BG2 2
39 #define Layer_BG3 3
40 #define Layer_OBJ 4
41 #define Layer_WIN_OBJ 5 // Used by VBA for OBJ opacity tests
42
43 #define LayerMask_BG0 (1 << Layer_BG0)
44 #define LayerMask_BG1 (1 << Layer_BG1)
45 #define LayerMask_BG2 (1 << Layer_BG2)
46 #define LayerMask_BG3 (1 << Layer_BG3)
47 #define LayerMask_OBJ (1 << Layer_OBJ)
48 // Used in R_WIN_* to indicate whether color effects are enabled
49 #define LayerMask_SFX (1 << 5)
50
51 #if USE_FRAME_SKIP
52
53 int fs_count = 0;
54 int fs_type = 0;
55 int fs_type_a = 0;
56 int fs_type_b = 0;
57 bool fs_draw = false;
58
SetFrameskip(int code)59 void SetFrameskip(int code)
60 {
61 fs_type = code;
62 fs_type_a = (0xF0 & fs_type) >> 4;
63 fs_type_b = 0xF & fs_type;
64 }
65 #endif
66
67 typedef void (*renderfunc_t)(void);
68
69 template<int renderer_idx>
70 renderfunc_t GetRenderFunc(int mode, int type);
71
max(int p,int q)72 inline static long max(int p, int q) { return p > q ? p : q; }
min(int p,int q)73 inline static long min(int p, int q) { return p < q ? p : q; }
74
75 uint8_t *rom = 0;
76 uint8_t *bios = 0;
77 uint8_t *vram = 0;
78 uint16_t *pix = 0;
79 uint8_t *oam = 0;
80 uint8_t *ioMem = 0;
81 uint8_t *internalRAM = 0;
82 uint8_t *workRAM = 0;
83 uint8_t *paletteRAM = 0;
84 char cartridgeCode[4];
85
86 int renderfunc_mode = 0;
87 int renderfunc_type = 0;
88
89 #if USE_MOTION_SENSOR
90 hardware_t hardware;
91
hardware_reset()92 static void hardware_reset() {
93 hardware.tilt_x = 0;
94 hardware.tilt_y = 0;
95 hardware.direction = 0;
96 hardware.pinState = 0;
97 hardware.gyroSample = 0;
98 hardware.readWrite = false;
99 hardware.gyroEdge = false;
100 }
101 #endif
102
103 #if THREADED_RENDERER
104
105 //THREADED_RENDERER_COUNT: 1 to 4
106 #if VITA
107 #define THREADED_RENDERER_COUNT 2
108 #else
109 #define THREADED_RENDERER_COUNT 1
110 #endif
111
112 #include "thread.h"
113
114 static int threaded_renderer_idx = 0;
115 static uint32_t threaded_gfxinwin_ver[2] = {1, 1};
116 static volatile uint32_t threaded_background_ver = 0;
117 static volatile int threaded_renderer_ready = 0;
118
119 static void threaded_renderer_loop(void* p);
120 static void threaded_renderer_loop0(void* p);
121
122 typedef struct {
123 thread_t renderer_thread_id;
124
125 volatile int renderer_control;
126 volatile int renderer_state;
127 int renderfunc_mode;
128 int renderfunc_type;
129 int vcount;
130
131 uint32_t background_ver;
132 uint32_t gfxinwin_ver[2];
133
134 uint16_t io_registers[1024 * 16];
135 uint32_t line[6][240];
136 int lineOBJpixleft[128];
137 bool gfxInWin[2][240];
138
139 bool draw_objwin;
140 bool draw_sprites;
141 uint16_t mosaic;
142 uint16_t bldmod;
143 uint16_t layers;
144
145 int bg2c;
146 int bg3c;
147 int bg2x;
148 int bg2y;
149 int bg3x;
150 int bg3y;
151
152 int bg2x_l;
153 int bg2x_h;
154 int bg2y_l;
155 int bg2y_h;
156 int bg3x_l;
157 int bg3x_h;
158 int bg3y_l;
159 int bg3y_h;
160 } renderer_context;
161
init_renderer_context(renderer_context & ctx)162 static void init_renderer_context(renderer_context& ctx) {
163 ctx.renderer_control = 0;
164 ctx.renderer_state = 0;
165 ctx.background_ver = 0;
166 ctx.gfxinwin_ver[0] = 0;
167 ctx.gfxinwin_ver[1] = 0;
168 memset(ctx.line[Layer_BG0], -1, 240 * sizeof(u32));
169 memset(ctx.line[Layer_BG1], -1, 240 * sizeof(u32));
170 memset(ctx.line[Layer_BG2], -1, 240 * sizeof(u32));
171 memset(ctx.line[Layer_BG3], -1, 240 * sizeof(u32));
172 }
173
174 static renderer_context threaded_renderer_contexts[THREADED_RENDERER_COUNT];
175
176 #define INIT_RENDERER_CONTEXT(__renderer_idx__) renderer_context& renderer_ctx = threaded_renderer_contexts[__renderer_idx__]
177
178 #define RENDERER_BG2C renderer_ctx.bg2c
179 #define RENDERER_BG3C renderer_ctx.bg3c
180
181 #define RENDERER_BG2X renderer_ctx.bg2x
182 #define RENDERER_BG2Y renderer_ctx.bg2y
183 #define RENDERER_BG3X renderer_ctx.bg3x
184 #define RENDERER_BG3Y renderer_ctx.bg3y
185
186 #define RENDERER_BG2X_L renderer_ctx.bg2x_l
187 #define RENDERER_BG2X_H renderer_ctx.bg2x_h
188 #define RENDERER_BG2Y_L renderer_ctx.bg2y_l
189 #define RENDERER_BG2Y_H renderer_ctx.bg2y_h
190 #define RENDERER_BG3X_L renderer_ctx.bg3x_l
191 #define RENDERER_BG3X_H renderer_ctx.bg3x_h
192 #define RENDERER_BG3Y_L renderer_ctx.bg3y_l
193 #define RENDERER_BG3Y_H renderer_ctx.bg3y_h
194
195 #define RENDERER_PALETTE paletteRAM
196 #define RENDERER_OAM oam
197
198 #define RENDERER_LINE renderer_ctx.line
199 #define RENDERER_IO_REGISTERS renderer_ctx.io_registers
200 #define RENDERER_MOSAIC renderer_ctx.mosaic
201 #define RENDERER_BLDMOD renderer_ctx.bldmod
202 #define RENDERER_GRAPHICS_LAYERS renderer_ctx.layers
203 #define RENDERER_LINE_OBJ_PIX_LEFT renderer_ctx.lineOBJpixleft
204 #define RENDERER_GFX_IN_WIN renderer_ctx.gfxInWin
205
206 #define RENDERER_R_VCOUNT renderer_ctx.vcount
207 #define RENDERER_R_DISPCNT_Video_Mode renderer_ctx.renderfunc_mode
208
209 #define RENDERER_R_DISPCNT_Screen_Display_BG0 (RENDERER_GRAPHICS_LAYERS & (1 << 8))
210 #define RENDERER_R_DISPCNT_Screen_Display_BG1 (RENDERER_GRAPHICS_LAYERS & (1 << 9))
211 #define RENDERER_R_DISPCNT_Screen_Display_BG2 (RENDERER_GRAPHICS_LAYERS & (1 << 10))
212 #define RENDERER_R_DISPCNT_Screen_Display_BG3 (RENDERER_GRAPHICS_LAYERS & (1 << 11))
213 #define RENDERER_R_DISPCNT_Screen_Display_OBJ (RENDERER_GRAPHICS_LAYERS & (1 << 12))
214 #define RENDERER_R_DISPCNT_Window_0_Display (RENDERER_GRAPHICS_LAYERS & (1 << 13))
215 #define RENDERER_R_DISPCNT_Window_1_Display (RENDERER_GRAPHICS_LAYERS & (1 << 14))
216 #define RENDERER_R_DISPCNT_OBJ_Window_Display (RENDERER_GRAPHICS_LAYERS & (1 << 15))
217
218 #define RENDERER_R_WIN_Window0_X1 (RENDERER_IO_REGISTERS[REG_WIN0H] >> 8)
219 #define RENDERER_R_WIN_Window0_X2 (RENDERER_IO_REGISTERS[REG_WIN0H] & 0xFF)
220 #define RENDERER_R_WIN_Window0_Y1 (RENDERER_IO_REGISTERS[REG_WIN0V] >> 8)
221 #define RENDERER_R_WIN_Window0_Y2 (RENDERER_IO_REGISTERS[REG_WIN0V] & 0xFF)
222
223 #define RENDERER_R_WIN_Window1_X1 (RENDERER_IO_REGISTERS[REG_WIN1H] >> 8)
224 #define RENDERER_R_WIN_Window1_X2 (RENDERER_IO_REGISTERS[REG_WIN1H] & 0xFF)
225 #define RENDERER_R_WIN_Window1_Y1 (RENDERER_IO_REGISTERS[REG_WIN1V] >> 8)
226 #define RENDERER_R_WIN_Window1_Y2 (RENDERER_IO_REGISTERS[REG_WIN1V] & 0xFF)
227
228 #define RENDERER_R_WIN_Window0_Mask (RENDERER_IO_REGISTERS[REG_WININ] & 0xFF)
229 #define RENDERER_R_WIN_Window1_Mask (RENDERER_IO_REGISTERS[REG_WININ] >> 8)
230 #define RENDERER_R_WIN_Outside_Mask (RENDERER_IO_REGISTERS[REG_WINOUT] & 0xFF)
231 #define RENDERER_R_WIN_OBJ_Mask (RENDERER_IO_REGISTERS[REG_WINOUT] >> 8)
232
233 #else
234 #define INIT_RENDERER_CONTEXT(__renderer_idx__) 0
235
236 #define RENDERER_BG2C gfxBG2Changed
237 #define RENDERER_BG3C gfxBG3Changed
238
239 #define RENDERER_BG2X gfxBG2X
240 #define RENDERER_BG2Y gfxBG2Y
241 #define RENDERER_BG3X gfxBG3X
242 #define RENDERER_BG3Y gfxBG3Y
243
244 #define RENDERER_BG2X_L BG2X_L
245 #define RENDERER_BG2X_H BG2X_H
246 #define RENDERER_BG2Y_L BG2Y_L
247 #define RENDERER_BG2Y_H BG2Y_H
248 #define RENDERER_BG3X_L BG3X_L
249 #define RENDERER_BG3X_H BG3X_H
250 #define RENDERER_BG3Y_L BG3Y_L
251 #define RENDERER_BG3Y_H BG3Y_H
252
253 #define RENDERER_PALETTE paletteRAM
254 #define RENDERER_IO_REGISTERS io_registers
255 #define RENDERER_LINE line
256 #define RENDERER_OAM oam
257 #define RENDERER_MOSAIC MOSAIC
258 #define RENDERER_BLDMOD BLDMOD
259 #define RENDERER_GRAPHICS_LAYERS graphics.layerEnable
260 #define RENDERER_LINE_OBJ_PIX_LEFT lineOBJpixleft
261 #define RENDERER_GFX_IN_WIN gfxInWin
262
263 #define RENDERER_R_VCOUNT (RENDERER_IO_REGISTERS[REG_VCOUNT])
264 #define RENDERER_R_DISPCNT_Video_Mode (RENDERER_IO_REGISTERS[REG_DISPCNT] & 7)
265
266 #define RENDERER_R_DISPCNT_Screen_Display_BG0 (RENDERER_GRAPHICS_LAYERS & (1 << 8))
267 #define RENDERER_R_DISPCNT_Screen_Display_BG1 (RENDERER_GRAPHICS_LAYERS & (1 << 9))
268 #define RENDERER_R_DISPCNT_Screen_Display_BG2 (RENDERER_GRAPHICS_LAYERS & (1 << 10))
269 #define RENDERER_R_DISPCNT_Screen_Display_BG3 (RENDERER_GRAPHICS_LAYERS & (1 << 11))
270 #define RENDERER_R_DISPCNT_Screen_Display_OBJ (RENDERER_GRAPHICS_LAYERS & (1 << 12))
271 #define RENDERER_R_DISPCNT_Window_0_Display (RENDERER_GRAPHICS_LAYERS & (1 << 13))
272 #define RENDERER_R_DISPCNT_Window_1_Display (RENDERER_GRAPHICS_LAYERS & (1 << 14))
273 #define RENDERER_R_DISPCNT_OBJ_Window_Display (RENDERER_GRAPHICS_LAYERS & (1 << 15))
274
275 #define RENDERER_R_WIN_Window0_X1 (RENDERER_IO_REGISTERS[REG_WIN0H] >> 8)
276 #define RENDERER_R_WIN_Window0_X2 (RENDERER_IO_REGISTERS[REG_WIN0H] & 0xFF)
277 #define RENDERER_R_WIN_Window0_Y1 (RENDERER_IO_REGISTERS[REG_WIN0V] >> 8)
278 #define RENDERER_R_WIN_Window0_Y2 (RENDERER_IO_REGISTERS[REG_WIN0V] & 0xFF)
279
280 #define RENDERER_R_WIN_Window1_X1 (RENDERER_IO_REGISTERS[REG_WIN1H] >> 8)
281 #define RENDERER_R_WIN_Window1_X2 (RENDERER_IO_REGISTERS[REG_WIN1H] & 0xFF)
282 #define RENDERER_R_WIN_Window1_Y1 (RENDERER_IO_REGISTERS[REG_WIN1V] >> 8)
283 #define RENDERER_R_WIN_Window1_Y2 (RENDERER_IO_REGISTERS[REG_WIN1V] & 0xFF)
284
285 #define RENDERER_R_WIN_Window0_Mask (RENDERER_IO_REGISTERS[REG_WININ] & 0xFF)
286 #define RENDERER_R_WIN_Window1_Mask (RENDERER_IO_REGISTERS[REG_WININ] >> 8)
287 #define RENDERER_R_WIN_Outside_Mask (RENDERER_IO_REGISTERS[REG_WINOUT] & 0xFF)
288 #define RENDERER_R_WIN_OBJ_Mask (RENDERER_IO_REGISTERS[REG_WINOUT] >> 8)
289
290 #endif
291
292 #define RENDERER_BACKDROP (READ16LE(&reinterpret_cast<uint16_t*>(RENDERER_PALETTE)[0]) | 0x30000000)
293 #define RENDERER_R_BLDCNT_Color_Special_Effect ((RENDERER_BLDMOD >> 6) & 3)
294 #define RENDERER_R_BLDCNT_IsTarget1(target) ((target) & (RENDERER_BLDMOD ))
295 #define RENDERER_R_BLDCNT_IsTarget2(target) ((target) & (RENDERER_BLDMOD >> 8))
296
297 /*============================================================
298 GBA INLINE
299 ============================================================ */
300
301 #define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value);
302 #define ARM_PREFETCH_NEXT cpuPrefetch[1] = CPUReadMemoryQuick(bus.armNextPC+4);
303 #define THUMB_PREFETCH_NEXT cpuPrefetch[1] = CPUReadHalfWordQuick(bus.armNextPC+2);
304
305 #define ARM_PREFETCH \
306 {\
307 cpuPrefetch[0] = CPUReadMemoryQuick(bus.armNextPC);\
308 cpuPrefetch[1] = CPUReadMemoryQuick(bus.armNextPC+4);\
309 }
310
311 #define THUMB_PREFETCH \
312 {\
313 cpuPrefetch[0] = CPUReadHalfWordQuick(bus.armNextPC);\
314 cpuPrefetch[1] = CPUReadHalfWordQuick(bus.armNextPC+2);\
315 }
316
317 #define MOSAIC_LOOP(__layer__, __mosaicX__) { \
318 int m = 1; \
319 int i = 0; \
320 for (; i < 239; i++) { \
321 RENDERER_LINE[__layer__][i+1] = RENDERER_LINE[__layer__][i]; \
322 if (++m == __mosaicX__) { m = 1; i++; } \
323 } \
324 }
325
gfxIncreaseBrightness(u32 color,int coeff)326 static INLINE u32 gfxIncreaseBrightness(u32 color, int coeff) {
327 color = (((color & 0xffff) << 16) | (color & 0xffff)) & 0x3E07C1F;
328 color += ((((0x3E07C1F - color) * coeff) >> 4) & 0x3E07C1F);
329 return (color >> 16) | color;
330 }
331
gfxDecreaseBrightness(u32 color,int coeff)332 static INLINE u32 gfxDecreaseBrightness(u32 color, int coeff) {
333 color = (((color & 0xffff) << 16) | (color & 0xffff)) & 0x3E07C1F;
334 color -= (((color * coeff) >> 4) & 0x3E07C1F);
335 return (color >> 16) | color;
336 }
337
338 static u32 AlphaClampLUT[64] =
339 {
340 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
341 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
342 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
343 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F
344 };
345
346 #define GFX_ALPHA_BLEND(color, color2, ca, cb) { \
347 int r = AlphaClampLUT[(((color & 0x1F) * ca) >> 4) + (((color2 & 0x1F) * cb) >> 4)]; \
348 int g = AlphaClampLUT[((((color >> 5) & 0x1F) * ca) >> 4) + ((((color2 >> 5) & 0x1F) * cb) >> 4)]; \
349 int b = AlphaClampLUT[((((color >> 10) & 0x1F) * ca) >> 4) + ((((color2 >> 10) & 0x1F) * cb) >> 4)]; \
350 color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; \
351 }
352
353 #define brightness_switch() \
354 switch(RENDERER_R_BLDCNT_Color_Special_Effect) { \
355 case SpecialEffect_Brightness_Increase: \
356 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); break; \
357 case SpecialEffect_Brightness_Decrease: \
358 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); break; \
359 }
360
361 #define alpha_blend_brightness_switch() \
362 if(RENDERER_R_BLDCNT_IsTarget2(top2)) { \
363 if(color < 0x80000000) { \
364 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); \
365 } else if (RENDERER_R_BLDCNT_IsTarget1(top)) { \
366 brightness_switch(); \
367 } \
368 }
369
370 #ifdef USE_SWITICKS
371 extern int SWITicks;
372 #endif
373 static int cpuNextEvent = 0;
374 static bool holdState = false;
375 static uint32_t cpuPrefetch[2];
376 static int cpuTotalTicks = 0;
377
378 static uint8_t memoryWait[16] =
379 { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 };
380 static uint8_t memoryWaitSeq[16] =
381 { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 };
382 static uint8_t memoryWait32[16] =
383 { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 };
384 static uint8_t memoryWaitSeq32[16] =
385 { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 };
386
387 const int table [0x40] =
388 {
389 0xFF10, 0,0xFF11,0xFF12,0xFF13,0xFF14, 0, 0,
390 0xFF16,0xFF17, 0, 0,0xFF18,0xFF19, 0, 0,
391 0xFF1A, 0,0xFF1B,0xFF1C,0xFF1D,0xFF1E, 0, 0,
392 0xFF20,0xFF21, 0, 0,0xFF22,0xFF23, 0, 0,
393 0xFF24,0xFF25, 0, 0,0xFF26, 0, 0, 0,
394 0, 0, 0, 0, 0, 0, 0, 0,
395 0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,
396 0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F,
397 };
398
399 static int coeff[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
400 11, 12, 13, 14, 15, 16, 16, 16, 16,
401 16, 16, 16, 16, 16, 16, 16, 16, 16,
402 16, 16, 16};
403
404 static uint8_t biosProtected[4];
405 static uint8_t cpuBitsSet[256];
406
407 static void CPUSwitchMode(int mode, bool saveState, bool breakLoop);
408 static bool N_FLAG = 0;
409 static bool C_FLAG = 0;
410 static bool Z_FLAG = 0;
411 static bool V_FLAG = 0;
412 static bool armState = true;
413 static bool armIrqEnable = true;
414 static int armMode = 0x1f;
415
416 typedef enum
417 {
418 REG_DISPCNT = 0x000,
419 REG_DISPSTAT = 0x002,
420 REG_VCOUNT = 0x003,
421 REG_BG0CNT = 0x004,
422 REG_BG1CNT = 0x005,
423 REG_BG2CNT = 0x006,
424 REG_BG3CNT = 0x007,
425 REG_BG0HOFS = 0x08,
426 REG_BG0VOFS = 0x09,
427 REG_BG1HOFS = 0x0A,
428 REG_BG1VOFS = 0x0B,
429 REG_BG2HOFS = 0x0C,
430 REG_BG2VOFS = 0x0D,
431 REG_BG3HOFS = 0x0E,
432 REG_BG3VOFS = 0x0F,
433 REG_BG2PA = 0x10,
434 REG_BG2PB = 0x11,
435 REG_BG2PC = 0x12,
436 REG_BG2PD = 0x13,
437 REG_BG2X_L = 0x14,
438 REG_BG2X_H = 0x15,
439 REG_BG2Y_L = 0x16,
440 REG_BG2Y_H = 0x17,
441 REG_BG3PA = 0x18,
442 REG_BG3PB = 0x19,
443 REG_BG3PC = 0x1A,
444 REG_BG3PD = 0x1B,
445 REG_BG3X_L = 0x1C,
446 REG_BG3X_H = 0x1D,
447 REG_BG3Y_L = 0x1E,
448 REG_BG3Y_H = 0x1F,
449 REG_WIN0H = 0x20,
450 REG_WIN1H = 0x21,
451 REG_WIN0V = 0x22,
452 REG_WIN1V = 0x23,
453 REG_WININ = 0x24,
454 REG_WINOUT = 0x25,
455 REG_BLDCNT = 0x28,
456 REG_BLDALPHA = 0x29,
457 REG_BLDY = 0x2A,
458 REG_TM0D = 0x80,
459 REG_TM0CNT = 0x81,
460 REG_TM1D = 0x82,
461 REG_TM1CNT = 0x83,
462 REG_TM2D = 0x84,
463 REG_TM2CNT = 0x85,
464 REG_TM3D = 0x86,
465 REG_TM3CNT = 0x87,
466 REG_P1 = 0x098,
467 REG_P1CNT = 0x099,
468 REG_RCNT = 0x9A,
469 REG_IE = 0x100,
470 REG_IF = 0x101,
471 REG_IME = 0x104,
472 REG_HALTCNT = 0x180
473 } hardware_register;
474
475 static uint16_t io_registers[1024 * 16];
476
477 // Note: Some comments below are from the GBATEK document
478 // (http://problemkaputt.de/gbatek.htm).
479
480 #define R_DISPCNT_Video_Mode (io_registers[REG_DISPCNT] & 7)
481
482 // By default, BG0-3 and OBJ Display Flags (Bit 8-12) are used to
483 // enable/disable BGs and OBJ. When enabling Window 0 and/or 1
484 // (Bit 13-14), color special effects may be used, and BG0-3 and
485 // OBJ are controlled by the window(s).
486
487 #define R_DISPCNT_Screen_Display_BG0 (graphics.layerEnable & (1 << 8))
488 #define R_DISPCNT_Screen_Display_BG1 (graphics.layerEnable & (1 << 9))
489 #define R_DISPCNT_Screen_Display_BG2 (graphics.layerEnable & (1 << 10))
490 #define R_DISPCNT_Screen_Display_BG3 (graphics.layerEnable & (1 << 11))
491 #define R_DISPCNT_Screen_Display_OBJ (graphics.layerEnable & (1 << 12))
492 #define R_DISPCNT_Window_0_Display (graphics.layerEnable & (1 << 13))
493 #define R_DISPCNT_Window_1_Display (graphics.layerEnable & (1 << 14))
494 #define R_DISPCNT_OBJ_Window_Display (graphics.layerEnable & (1 << 15))
495
496 #define R_WIN_Window0_X1 (io_registers[REG_WIN0H] >> 8)
497 #define R_WIN_Window0_X2 (io_registers[REG_WIN0H] & 0xFF)
498 #define R_WIN_Window0_Y1 (io_registers[REG_WIN0V] >> 8)
499 #define R_WIN_Window0_Y2 (io_registers[REG_WIN0V] & 0xFF)
500
501 #define R_WIN_Window1_X1 (io_registers[REG_WIN1H] >> 8)
502 #define R_WIN_Window1_X2 (io_registers[REG_WIN1H] & 0xFF)
503 #define R_WIN_Window1_Y1 (io_registers[REG_WIN1V] >> 8)
504 #define R_WIN_Window1_Y2 (io_registers[REG_WIN1V] & 0xFF)
505
506 // These return a 6-bit mask which corresponds which layers are
507 // visible in the corresponding window/region:
508 // Bits 0-3 : Whether BG0-BG3 are visible
509 // Bit 4 : Whether OBJ is visible
510 // Bit 5 : Whether special effects are enabled
511
512 #define R_WIN_Window0_Mask (io_registers[REG_WININ] & 0xFF)
513 #define R_WIN_Window1_Mask (io_registers[REG_WININ] >> 8)
514 #define R_WIN_Outside_Mask (io_registers[REG_WINOUT] & 0xFF)
515 #define R_WIN_OBJ_Mask (io_registers[REG_WINOUT] >> 8)
516
517 // Indicates the currently drawn scanline, values in range from
518 // 160..227 indicate 'hidden' scanlines within VBlank area.
519
520 #define R_VCOUNT (io_registers[REG_VCOUNT])
521
522 // Two types of Special Effects are supported:
523 // Alpha Blending (Semi-Transparency) allows to combine colors
524 // of two selected surfaces. Brightness Increase/Decrease
525 // adjust the brightness of the selected surface.
526
527 #define R_BLDCNT_Color_Special_Effect ((BLDMOD >> 6) & 3)
528 #define SpecialEffect_None (0)
529 #define SpecialEffect_Alpha_Blending (1)
530 #define SpecialEffect_Brightness_Increase (2)
531 #define SpecialEffect_Brightness_Decrease (3)
532
533 // Special effect targets.
534 #define R_BLDCNT_IsTarget1(target) ((target) & (BLDMOD ))
535 #define R_BLDCNT_IsTarget2(target) ((target) & (BLDMOD >> 8))
536
537 // The first 5 entries coincide with LayerMask_*.
538 #define SpecialEffectTarget_BG0 (1 << Layer_BG0)
539 #define SpecialEffectTarget_BG1 (1 << Layer_BG1)
540 #define SpecialEffectTarget_BG2 (1 << Layer_BG2)
541 #define SpecialEffectTarget_BG3 (1 << Layer_BG3)
542 #define SpecialEffectTarget_OBJ (1 << Layer_OBJ) // Top-most OBJ
543 #define SpecialEffectTarget_BD (1 << 5 ) // Backdrop
544
545
546 // Fast implementation of ternary operator.
547 // Implemented as a function (as opposed to a macro) to avoid
548 // evaluating the parameters more than once.
SELECT(bool condition,uint32_t ifTrue,uint32_t ifFalse)549 uint32_t FORCE_INLINE SELECT(bool condition, uint32_t ifTrue, uint32_t ifFalse)
550 {
551 // Will be 0 if condition==true or 0xFFFFFFFF
552 // if condition==false.
553 uint32_t testmask = (uint32_t)condition - 1;
554
555 return (testmask & ifFalse) | (~testmask & ifTrue);
556 }
557
558 static u16 MOSAIC;
559
560 static uint16_t BG2X_L = 0x0000;
561 static uint16_t BG2X_H = 0x0000;
562 static uint16_t BG2Y_L = 0x0000;
563 static uint16_t BG2Y_H = 0x0000;
564 static uint16_t BG3X_L = 0x0000;
565 static uint16_t BG3X_H = 0x0000;
566 static uint16_t BG3Y_L = 0x0000;
567 static uint16_t BG3Y_H = 0x0000;
568 static uint16_t BLDMOD = 0x0000; // aka BLDCNT
569 static uint16_t COLEV = 0x0000; // aka BLDALPHA
570 static uint16_t COLY = 0x0000; // aka BLDY
571 static uint16_t DM0SAD_L = 0x0000;
572 static uint16_t DM0SAD_H = 0x0000;
573 static uint16_t DM0DAD_L = 0x0000;
574 static uint16_t DM0DAD_H = 0x0000;
575 static uint16_t DM0CNT_L = 0x0000;
576 static uint16_t DM0CNT_H = 0x0000;
577 static uint16_t DM1SAD_L = 0x0000;
578 static uint16_t DM1SAD_H = 0x0000;
579 static uint16_t DM1DAD_L = 0x0000;
580 static uint16_t DM1DAD_H = 0x0000;
581 static uint16_t DM1CNT_L = 0x0000;
582 static uint16_t DM1CNT_H = 0x0000;
583 static uint16_t DM2SAD_L = 0x0000;
584 static uint16_t DM2SAD_H = 0x0000;
585 static uint16_t DM2DAD_L = 0x0000;
586 static uint16_t DM2DAD_H = 0x0000;
587 static uint16_t DM2CNT_L = 0x0000;
588 static uint16_t DM2CNT_H = 0x0000;
589 static uint16_t DM3SAD_L = 0x0000;
590 static uint16_t DM3SAD_H = 0x0000;
591 static uint16_t DM3DAD_L = 0x0000;
592 static uint16_t DM3DAD_H = 0x0000;
593 static uint16_t DM3CNT_L = 0x0000;
594 static uint16_t DM3CNT_H = 0x0000;
595
596 static uint8_t timerOnOffDelay = 0;
597 static uint16_t timer0Value = 0;
598 static uint32_t dma0Source = 0;
599 static uint32_t dma0Dest = 0;
600 static uint32_t dma1Source = 0;
601 static uint32_t dma1Dest = 0;
602 static uint32_t dma2Source = 0;
603 static uint32_t dma2Dest = 0;
604 static uint32_t dma3Source = 0;
605 static uint32_t dma3Dest = 0;
606 void (*cpuSaveGameFunc)(uint32_t,uint8_t) = flashSaveDecide;
607 static bool fxOn = false;
608 static bool windowOn = false;
609
610 uint32_t mastercode = 0;
611 static int cpuDmaTicksToUpdate = 0;
612
613 static const uint32_t TIMER_TICKS[4] = {0, 6, 8, 10};
614
615 static const uint8_t gamepakRamWaitState[4] = { 4, 3, 2, 8 };
616 static const uint8_t gamepakWaitState[4] = { 4, 3, 2, 8 };
617 static const uint8_t gamepakWaitState0[2] = { 2, 1 };
618 static const uint8_t gamepakWaitState1[2] = { 4, 1 };
619 static const uint8_t gamepakWaitState2[2] = { 8, 1 };
620
621 static int IRQTicks = 0;
622 static bool intState = false;
623
624 static bus_t bus;
625 static graphics_t graphics;
626
627 static memoryMap map[256];
628 static int clockTicks;
629
630 static int romSize = 0x2000000;
631 static uint32_t line[6][240];
632 static bool gfxInWin[2][240];
633 static int lineOBJpixleft[128];
634 uint64_t joy = 0;
635
636 static int gfxBG2Changed = 0;
637 static int gfxBG3Changed = 0;
638
639 static int gfxBG2X = 0;
640 static int gfxBG2Y = 0;
641 static int gfxBG3X = 0;
642 static int gfxBG3Y = 0;
643
644 static bool ioReadable[0x400];
645 static int gbaSaveType = 0; // used to remember the save type on reset
646
647 //static int gfxLastVCOUNT = 0;
648
649 // Waitstates when accessing data
650
651 #define DATATICKS_ACCESS_BUS_PREFETCH(address, value) \
652 int addr = (address >> 24) & 15; \
653 if ((addr>=0x08) || (addr < 0x02)) \
654 { \
655 bus.busPrefetchCount=0; \
656 bus.busPrefetch=false; \
657 } \
658 else if (bus.busPrefetch) \
659 { \
660 int waitState = value; \
661 waitState = (1 & ~waitState) | (waitState & waitState); \
662 bus.busPrefetchCount = ((bus.busPrefetchCount+1)<<waitState) - 1; \
663 }
664
665 /* Waitstates when accessing data */
666
667 #define DATATICKS_ACCESS_32BIT(address) (memoryWait32[(address >> 24) & 15])
668 #define DATATICKS_ACCESS_32BIT_SEQ(address) (memoryWaitSeq32[(address >> 24) & 15])
669 #define DATATICKS_ACCESS_16BIT(address) (memoryWait[(address >> 24) & 15])
670 #define DATATICKS_ACCESS_16BIT_SEQ(address) (memoryWaitSeq[(address >> 24) & 15])
671
672 // Waitstates when executing opcode
codeTicksAccess(u32 address,u8 bit32)673 static INLINE int codeTicksAccess(u32 address, u8 bit32) // THUMB NON SEQ
674 {
675 int addr, ret;
676
677 addr = (address>>24) & 15;
678
679 if (unsigned(addr - 0x08) <= 5)
680 {
681 if (bus.busPrefetchCount&0x1)
682 {
683 if (bus.busPrefetchCount&0x2)
684 {
685 bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>2) | (bus.busPrefetchCount&0xFFFFFF00);
686 return 0;
687 }
688 bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00);
689 return memoryWaitSeq[addr]-1;
690 }
691 }
692 bus.busPrefetchCount = 0;
693
694 if(bit32) /* ARM NON SEQ */
695 ret = memoryWait32[addr];
696 else /* THUMB NON SEQ */
697 ret = memoryWait[addr];
698
699 return ret;
700 }
701
codeTicksAccessSeq16(u32 address)702 static INLINE int codeTicksAccessSeq16(u32 address) // THUMB SEQ
703 {
704 int addr = (address>>24) & 15;
705
706 if (unsigned(addr - 0x08) <= 5)
707 {
708 if (bus.busPrefetchCount&0x1)
709 {
710 bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00);
711 return 0;
712 }
713 else if (bus.busPrefetchCount>0xFF)
714 {
715 bus.busPrefetchCount=0;
716 return memoryWait[addr];
717 }
718 }
719 else
720 bus.busPrefetchCount = 0;
721
722 return memoryWaitSeq[addr];
723 }
724
codeTicksAccessSeq32(u32 address)725 static INLINE int codeTicksAccessSeq32(u32 address) // ARM SEQ
726 {
727 int addr = (address>>24)&15;
728
729 if (unsigned(addr - 0x08) <= 5)
730 {
731 if (bus.busPrefetchCount&0x1)
732 {
733 if (bus.busPrefetchCount&0x2)
734 {
735 bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>2) | (bus.busPrefetchCount&0xFFFFFF00);
736 return 0;
737 }
738 bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00);
739 return memoryWaitSeq[addr];
740 }
741 else if (bus.busPrefetchCount > 0xFF)
742 {
743 bus.busPrefetchCount=0;
744 return memoryWait32[addr];
745 }
746 }
747 return memoryWaitSeq32[addr];
748 }
749
750 #define CPUReadByteQuick(addr) map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
751 #define CPUReadHalfWordQuick(addr) READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
752 #define CPUReadMemoryQuick(addr) READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
753
754 static bool stopState = false;
755 extern bool cpuSramEnabled;
756 extern bool cpuFlashEnabled;
757 extern bool cpuEEPROMEnabled;
758
759 static bool timer0On = false;
760 static int timer0Ticks = 0;
761 static int timer0Reload = 0;
762 static int timer0ClockReload = 0;
763 static uint16_t timer1Value = 0;
764 static bool timer1On = false;
765 static int timer1Ticks = 0;
766 static int timer1Reload = 0;
767 static int timer1ClockReload = 0;
768 static uint16_t timer2Value = 0;
769 static bool timer2On = false;
770 static int timer2Ticks = 0;
771 static int timer2Reload = 0;
772 static int timer2ClockReload = 0;
773 static uint16_t timer3Value = 0;
774 static bool timer3On = false;
775 static int timer3Ticks = 0;
776 static int timer3Reload = 0;
777 static int timer3ClockReload = 0;
778
779 int cpuDmaCount = 0;
780 static uint32_t cpuDmaLast = 0;
781 static uint32_t cpuDmaPC = 0;
782 static bool cpuDmaRunning = false;
783
784 static const uint32_t objTilesAddress [3] = {0x010000, 0x014000, 0x014000};
785
786 #if 0
787 static uint8_t* CPUDecodeAddress(uint32_t address)
788 {
789 switch(address >> 24) {
790 case 0:
791 /* BIOS */
792 if(bus.reg[15].I >> 24) {
793 if(address < 0x4000)
794 return biosProtected;
795 else
796 goto unreadable;
797 } else
798 return bios + (address & 0x3FFC);
799 case 0x02:
800 /* external work RAM */
801 return workRAM + (address & 0x3FFFC);
802 case 0x03:
803 /* internal work RAM */
804 return internalRAM + (address & 0x7ffC);
805 case 0x04:
806 /* I/O registers */
807 if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
808 if(ioReadable[(address & 0x3fc) + 2])
809 return ioMem + (address & 0x3fC);
810 else
811 return ioMem + (address & 0x3fc);
812 }
813 else
814 goto unreadable;
815 break;
816 case 0x05:
817 /* palette RAM */
818 return paletteRAM + (address & 0x3fC);
819 case 0x06:
820 /* VRAM */
821 address = (address & 0x1fffc);
822 if ((R_DISPCNT_Video_Mode >2) && ((address & 0x1C000) == 0x18000))
823 break;
824 if ((address & 0x18000) == 0x18000)
825 address &= 0x17fff;
826 return vram + address;
827 case 0x07:
828 /* OAM RAM */
829 return oam + (address & 0x3FC);
830 case 0x08:
831 case 0x09:
832 case 0x0A:
833 case 0x0B:
834 case 0x0C:
835 /* gamepak ROM */
836 return rom + (address & 0x1FFFFFC);
837 case 0x0D:
838 //value = eepromRead();
839 break;
840 case 14:
841 case 15:
842 //value = flashRead(address) * 0x01010101;
843 break;
844 default:
845 unreadable:
846 /*
847 if(armState)
848 value = CPUReadHalfWordQuick(bus.reg[15].I + (address & 2));
849 else
850 value = CPUReadHalfWordQuick(bus.reg[15].I);
851 */
852 break;
853 }
854
855 return NULL;
856 }
857 #endif
858
CPUReadMemory(u32 address)859 static INLINE u32 CPUReadMemory(u32 address)
860 {
861 u32 value;
862 switch(address >> 24)
863 {
864 case 0:
865 /* BIOS */
866 if(bus.reg[15].I >> 24)
867 {
868 if(address < 0x4000)
869 value = READ32LE(((u32 *)&biosProtected));
870 else goto unreadable;
871 }
872 else
873 value = READ32LE(bios + (address & 0x3FFC));
874 break;
875 case 0x02:
876 /* external work RAM */
877 value = READ32LE(workRAM + (address & 0x3FFFC));
878 break;
879 case 0x03:
880 /* internal work RAM */
881 value = READ32LE(internalRAM + (address & 0x7ffC));
882 break;
883 case 0x04:
884 /* I/O registers */
885 if((address < 0x4000400) && ioReadable[address & 0x3fc])
886 {
887 if(ioReadable[(address & 0x3fc) + 2])
888 value = READ32LE(ioMem + (address & 0x3fC));
889 else
890 value = READ16LE(ioMem + (address & 0x3fc));
891 }
892 else
893 goto unreadable;
894 break;
895 case 0x05:
896 /* palette RAM */
897 value = READ32LE(paletteRAM + (address & 0x3fC));
898 break;
899 case 0x06: {
900 /* VRAM */
901 u32 addr = (address & 0x1fffc);
902 if ((R_DISPCNT_Video_Mode > 2) && ((addr & 0x1C000) == 0x18000))
903 {
904 value = 0;
905 break;
906 }
907 if ((addr & 0x18000) == 0x18000)
908 addr &= 0x17ffc;
909 value = READ32LE(vram + addr);
910 } break;
911 case 0x07:
912 /* OAM RAM */
913 value = READ32LE(oam + (address & 0x3FC));
914 break;
915 case 0x08:
916 case 0x09:
917 case 0x0A:
918 case 0x0B:
919 case 0x0C:
920 /* gamepak ROM */
921 value = READ32LE(rom + (address&0x1FFFFFC));
922 break;
923 case 0x0D:
924 value = eepromRead();
925 break;
926 case 14:
927 case 15:
928 value = flashRead(address) * 0x01010101;
929 break;
930 default:
931 unreadable:
932 if (cpuDmaRunning || ((bus.reg[15].I - cpuDmaPC) == (armState ? 4 : 2))) {
933 value = cpuDmaLast;
934 } else {
935 if (armState)
936 value = CPUReadMemoryQuick(bus.reg[15].I);
937 else
938 value = CPUReadHalfWordQuick(bus.reg[15].I) | CPUReadHalfWordQuick(bus.reg[15].I) << 16;
939 }
940 }
941
942 if(address & 3) {
943 int shift = (address & 3) << 3;
944 value = (value >> shift) | (value << (32 - shift));
945 }
946 return value;
947 }
948
CPUReadHalfWord(u32 address)949 static INLINE u32 CPUReadHalfWord(u32 address)
950 {
951 u32 value;
952
953 switch(address >> 24)
954 {
955 case 0:
956 if (bus.reg[15].I >> 24)
957 {
958 if(address < 0x4000)
959 value = READ16LE(biosProtected + (address & 2));
960 else
961 goto unreadable;
962 }
963 else
964 value = READ16LE(bios + (address & 0x3FFE));
965 break;
966 case 2:
967 value = READ16LE(workRAM + (address & 0x3FFFE));
968 break;
969 case 3:
970 value = READ16LE(internalRAM + (address & 0x7ffe));
971 break;
972 case 4:
973 if((address < 0x4000400) && ioReadable[address & 0x3fe])
974 {
975 value = READ16LE(ioMem + (address & 0x3fe));
976 if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E))
977 {
978 if (((address & 0x3fe) == 0x100) && timer0On)
979 value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload);
980 else
981 if (((address & 0x3fe) == 0x104) && timer1On && !(io_registers[REG_TM1CNT] & 4))
982 value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload);
983 else
984 if (((address & 0x3fe) == 0x108) && timer2On && !(io_registers[REG_TM2CNT] & 4))
985 value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload);
986 else
987 if (((address & 0x3fe) == 0x10C) && timer3On && !(io_registers[REG_TM3CNT] & 4))
988 value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
989 }
990 }
991 else goto unreadable;
992 break;
993 case 5:
994 value = READ16LE(paletteRAM + (address & 0x3fe));
995 break;
996 case 6: {
997 u32 addr = (address & 0x1fffe);
998 if ((R_DISPCNT_Video_Mode > 2) && ((addr & 0x1C000) == 0x18000))
999 {
1000 value = 0;
1001 break;
1002 }
1003 if ((addr & 0x18000) == 0x18000)
1004 addr &= 0x17fff;
1005 value = READ16LE(vram + addr);
1006 } break;
1007 case 7:
1008 value = READ16LE(oam + (address & 0x3fe));
1009 break;
1010 case 8:
1011 case 9:
1012 case 10:
1013 case 11:
1014 case 12:
1015 switch(address) {
1016 case 0x80000c4:
1017 case 0x80000c6:
1018 case 0x80000c8:
1019 #if USE_MOTION_SENSOR
1020 if(hardware.sensor & HARDWARE_SENSOR_GYRO)
1021 return gyroRead(address);
1022 else
1023 #endif
1024 return rtcRead(address);
1025 break;
1026 default:
1027 value = READ16LE(rom + (address & 0x1FFFFFE)); break;
1028 }
1029 break;
1030 case 13:
1031 value = eepromRead();
1032 break;
1033 case 14:
1034 case 15:
1035 value = flashRead(address) * 0x0101;
1036 break;
1037 default:
1038 unreadable:
1039 if (cpuDmaRunning || ((bus.reg[15].I - cpuDmaPC) == (armState ? 4 : 2))) {
1040 value = cpuDmaLast & 0xFFFF;
1041 } else {
1042 int param = bus.reg[15].I;
1043 if(armState)
1044 param += (address & 2);
1045 value = CPUReadHalfWordQuick(param);
1046 }
1047 break;
1048 }
1049
1050 if(address & 1)
1051 value = (value >> 8) | (value << 24);
1052
1053 return value;
1054 }
1055
CPUReadHalfWordSigned(u32 address)1056 static INLINE u16 CPUReadHalfWordSigned(u32 address)
1057 {
1058 u16 value = CPUReadHalfWord(address);
1059 if((address & 1))
1060 value = (s8)value;
1061 return value;
1062 }
1063
CPUReadByte(u32 address)1064 static INLINE u8 CPUReadByte(u32 address)
1065 {
1066 switch(address >> 24)
1067 {
1068 case 0:
1069 if (bus.reg[15].I >> 24)
1070 {
1071 if(address < 0x4000)
1072 return biosProtected[address & 3];
1073 else
1074 goto unreadable;
1075 }
1076 return bios[address & 0x3FFF];
1077 case 2:
1078 return workRAM[address & 0x3FFFF];
1079 case 3:
1080 return internalRAM[address & 0x7fff];
1081 case 4:
1082 if((address < 0x4000400) && ioReadable[address & 0x3ff])
1083 return ioMem[address & 0x3ff];
1084 else goto unreadable;
1085 case 5:
1086 return paletteRAM[address & 0x3ff];
1087 case 6:
1088 address = (address & 0x1ffff);
1089 if ((R_DISPCNT_Video_Mode >2) && ((address & 0x1C000) == 0x18000))
1090 return 0;
1091 if ((address & 0x18000) == 0x18000)
1092 address &= 0x17fff;
1093 return vram[address];
1094 case 7:
1095 return oam[address & 0x3ff];
1096 case 8:
1097 case 9:
1098 case 10:
1099 case 11:
1100 case 12:
1101 return rom[address & 0x1FFFFFF];
1102 case 13:
1103 return eepromRead();
1104 case 14:
1105 case 15:
1106 #ifdef USE_MOTION_SENSOR
1107 if(hardware.sensor)
1108 {
1109 switch(address & 0x00008f00)
1110 {
1111 case 0x8200:
1112 return hardware.tilt_x & 0xFF;
1113 case 0x8300:
1114 return ((hardware.tilt_x >> 8) & 0xF) | 0x80;
1115 case 0x8400:
1116 return hardware.tilt_y & 0xFF;
1117 case 0x8500:
1118 return ((hardware.tilt_y >> 8) & 0xF) | 0x80;
1119 }
1120 }
1121 #endif
1122 return flashRead(address);
1123 default:
1124 unreadable:
1125 if (cpuDmaRunning || ((bus.reg[15].I - cpuDmaPC) == (armState ? 4 : 2))) {
1126 return cpuDmaLast & 0xFF;
1127 } else {
1128 if(armState)
1129 return CPUReadByteQuick(bus.reg[15].I+(address & 3));
1130 else
1131 return CPUReadByteQuick(bus.reg[15].I+(address & 1));
1132 }
1133 }
1134 }
1135
CPUWriteMemory(u32 address,u32 value)1136 static INLINE void CPUWriteMemory(u32 address, u32 value)
1137 {
1138 switch(address >> 24)
1139 {
1140 case 0x02:
1141 WRITE32LE(workRAM + (address & 0x3FFFC), value);
1142 break;
1143 case 0x03:
1144 WRITE32LE(internalRAM + (address & 0x7ffC), value);
1145 break;
1146 case 0x04:
1147 if(address < 0x4000400)
1148 {
1149 CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
1150 CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
1151 }
1152 break;
1153 case 0x05:
1154 WRITE32LE(paletteRAM + (address & 0x3FC), value);
1155 break;
1156 case 0x06:
1157 address = (address & 0x1fffc);
1158 if ((R_DISPCNT_Video_Mode >2) && ((address & 0x1C000) == 0x18000))
1159 return;
1160 if ((address & 0x18000) == 0x18000)
1161 address &= 0x17fff;
1162
1163
1164 WRITE32LE(vram + address, value);
1165 break;
1166 case 0x07:
1167 WRITE32LE(oam + (address & 0x3fc), value);
1168 break;
1169 case 0x0D:
1170 if(cpuEEPROMEnabled) {
1171 eepromWrite(value);
1172 break;
1173 }
1174 break;
1175 case 0x0E:
1176 case 0x0F:
1177 if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)
1178 (*cpuSaveGameFunc)(address, (u8)value);
1179 break;
1180 default:
1181 break;
1182 }
1183 }
1184
CPUWriteHalfWord(u32 address,u16 value)1185 static INLINE void CPUWriteHalfWord(u32 address, u16 value)
1186 {
1187 switch(address >> 24)
1188 {
1189 case 2:
1190 WRITE16LE(workRAM + (address & 0x3FFFE),value);
1191 break;
1192 case 3:
1193 WRITE16LE(internalRAM + (address & 0x7ffe), value);
1194 break;
1195 case 4:
1196 if(address < 0x4000400)
1197 CPUUpdateRegister(address & 0x3fe, value);
1198 break;
1199 case 5:
1200 WRITE16LE(paletteRAM + (address & 0x3fe), value);
1201 break;
1202 case 6:
1203 address = (address & 0x1fffe);
1204 if ((R_DISPCNT_Video_Mode >2) && ((address & 0x1C000) == 0x18000))
1205 return;
1206 if ((address & 0x18000) == 0x18000)
1207 address &= 0x17fff;
1208 WRITE16LE(vram + address, value);
1209 break;
1210 case 7:
1211 WRITE16LE(oam + (address & 0x3fe), value);
1212 break;
1213 case 8:
1214 case 9:
1215 switch(address) {
1216 case 0x80000c4:
1217 case 0x80000c6:
1218 case 0x80000c8:
1219 #if USE_MOTION_SENSOR
1220 if(hardware.sensor & HARDWARE_SENSOR_GYRO)
1221 gyroWrite(address, value);
1222 else
1223 #endif
1224 rtcWrite(address, value);
1225 break;
1226 }
1227 break;
1228 case 13:
1229 if(cpuEEPROMEnabled)
1230 eepromWrite((u8)value);
1231 break;
1232 case 14:
1233 case 15:
1234 if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)
1235 (*cpuSaveGameFunc)(address, (u8)value);
1236 break;
1237 default:
1238 break;
1239 }
1240 }
1241
CPUWriteByte(u32 address,u8 b)1242 static INLINE void CPUWriteByte(u32 address, u8 b)
1243 {
1244 switch(address >> 24)
1245 {
1246 case 2:
1247 workRAM[address & 0x3FFFF] = b;
1248 break;
1249 case 3:
1250 internalRAM[address & 0x7fff] = b;
1251 break;
1252 case 4:
1253 if(address < 0x4000400)
1254 {
1255 switch(address & 0x3FF)
1256 {
1257 case 0x60:
1258 case 0x61:
1259 case 0x62:
1260 case 0x63:
1261 case 0x64:
1262 case 0x65:
1263 case 0x68:
1264 case 0x69:
1265 case 0x6c:
1266 case 0x6d:
1267 case 0x70:
1268 case 0x71:
1269 case 0x72:
1270 case 0x73:
1271 case 0x74:
1272 case 0x75:
1273 case 0x78:
1274 case 0x79:
1275 case 0x7c:
1276 case 0x7d:
1277 case 0x80:
1278 case 0x81:
1279 case 0x84:
1280 case 0x85:
1281 case 0x90:
1282 case 0x91:
1283 case 0x92:
1284 case 0x93:
1285 case 0x94:
1286 case 0x95:
1287 case 0x96:
1288 case 0x97:
1289 case 0x98:
1290 case 0x99:
1291 case 0x9a:
1292 case 0x9b:
1293 case 0x9c:
1294 case 0x9d:
1295 case 0x9e:
1296 case 0x9f:
1297 {
1298 int gb_addr = table[(address & 0xFF) - 0x60];
1299 soundEvent_u8(gb_addr, address&0xFF, b);
1300 }
1301 break;
1302 case 0x301: // HALTCNT, undocumented
1303 if(b == 0x80)
1304 stopState = true;
1305 holdState = 1;
1306 cpuNextEvent = cpuTotalTicks;
1307 break;
1308 default: // every other register
1309 {
1310 u32 lowerBits = address & 0x3fe;
1311 uint16_t param;
1312 if(address & 1)
1313 param = (READ16LE(&ioMem[lowerBits]) & 0x00FF) | (b << 8);
1314 else
1315 param = (READ16LE(&ioMem[lowerBits]) & 0xFF00) | b;
1316
1317 CPUUpdateRegister(lowerBits, param);
1318 }
1319 break;
1320 }
1321 }
1322 break;
1323 case 5:
1324 // no need to switch
1325 *(u16 *)(paletteRAM + (address & 0x3FE)) = (b << 8) | b;
1326 break;
1327 case 6:
1328 address = (address & 0x1fffe);
1329 if ((R_DISPCNT_Video_Mode >2) && ((address & 0x1C000) == 0x18000))
1330 return;
1331 if ((address & 0x18000) == 0x18000)
1332 address &= 0x17fff;
1333
1334 // no need to switch
1335 // byte writes to OBJ VRAM are ignored
1336 if ((address) < objTilesAddress[(R_DISPCNT_Video_Mode+1)>>2])
1337 *(u16 *)(vram + address) = (b << 8) | b;
1338 break;
1339 case 7:
1340 // no need to switch
1341 // byte writes to OAM are ignored
1342 // *((u16 *)&oam[address & 0x3FE]) = (b << 8) | b;
1343 break;
1344 case 13:
1345 if(cpuEEPROMEnabled)
1346 eepromWrite(b);
1347 break;
1348 case 14:
1349 case 15:
1350 if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled))
1351 {
1352 (*cpuSaveGameFunc)(address, b);
1353 break;
1354 }
1355 default:
1356 break;
1357 }
1358 }
1359
1360
1361 /*============================================================
1362 BIOS
1363 ============================================================ */
fast_sin(uint8_t val)1364 static inline int16_t fast_sin(uint8_t val)
1365 {
1366 uint8_t p = 0x7F & val;
1367 int16_t q = 1 - ((0x80 & val) >> 6);
1368 return ((p << 9) + (-4 * p * p)) * q;
1369 }
1370
fast_cos(uint8_t val)1371 static inline int16_t fast_cos(uint8_t val)
1372 {
1373 return fast_sin(val + 0x40);
1374 }
1375
1376 // 2020-08-12 negativeExponent
1377 // ArcTan/ArcTan2 fixes based from mgba hle bios
1378
BIOS_ArcTan(void)1379 static void BIOS_ArcTan (void)
1380 {
1381 s32 i = bus.reg[0].I;
1382 s32 a = -((i * i) >> 14);
1383 s32 b = ((0xA9 * a) >> 14) + 0x390;
1384 b = ((b * a) >> 14) + 0x91C;
1385 b = ((b * a) >> 14) + 0xFB6;
1386 b = ((b * a) >> 14) + 0x16AA;
1387 b = ((b * a) >> 14) + 0x2081;
1388 b = ((b * a) >> 14) + 0x3651;
1389 b = ((b * a) >> 14) + 0xA2F9;
1390 bus.reg[0].I = (i * b) >> 16;
1391 bus.reg[1].I = a;
1392 bus.reg[3].I = b;
1393 }
1394
BIOS_Div(void)1395 static void BIOS_Div (void)
1396 {
1397 int number = bus.reg[0].I;
1398 int denom = bus.reg[1].I;
1399
1400 if(denom != 0)
1401 {
1402 bus.reg[0].I = number / denom;
1403 bus.reg[1].I = number % denom;
1404 s32 temp = (s32)bus.reg[0].I;
1405 bus.reg[3].I = temp < 0 ? (u32)-temp : (u32)temp;
1406 }
1407 }
1408
BIOS_ArcTan2(void)1409 static void BIOS_ArcTan2 (void)
1410 {
1411 s32 x = bus.reg[0].I;
1412 s32 y = bus.reg[1].I;
1413 u32 res = 0;
1414 if (y == 0)
1415 res = ((x>>16) & 0x8000);
1416 else
1417 {
1418 if (x == 0)
1419 res = ((y>>16) & 0x8000) + 0x4000;
1420 else
1421 {
1422 if ((abs(x) > abs(y)) || ((abs(x) == abs(y)) && (!((x<0) && (y<0)))))
1423 {
1424 bus.reg[1].I = x;
1425 bus.reg[0].I = y << 14;
1426 BIOS_Div();
1427 BIOS_ArcTan();
1428 if (x < 0)
1429 res = 0x8000 + bus.reg[0].I;
1430 else
1431 res = (((y>>16) & 0x8000)<<1) + bus.reg[0].I;
1432 }
1433 else
1434 {
1435 bus.reg[0].I = x << 14;
1436 BIOS_Div();
1437 BIOS_ArcTan();
1438 res = (0x4000 + ((y>>16) & 0x8000)) - bus.reg[0].I;
1439 }
1440 }
1441 }
1442 bus.reg[0].I = res;
1443 bus.reg[3].I = 0x170;
1444 }
1445
BIOS_BitUnPack(void)1446 static void BIOS_BitUnPack (void)
1447 {
1448 u32 source = bus.reg[0].I;
1449 u32 dest = bus.reg[1].I;
1450 u32 header = bus.reg[2].I;
1451
1452 int len = CPUReadHalfWord(header);
1453 // check address
1454 if(((source & 0xe000000) == 0) ||
1455 ((source + len) & 0xe000000) == 0)
1456 return;
1457
1458 int bits = CPUReadByte(header+2);
1459 int revbits = 8 - bits;
1460 // u32 value = 0;
1461 u32 base = CPUReadMemory(header+4);
1462 bool addBase = (base & 0x80000000) ? true : false;
1463 base &= 0x7fffffff;
1464 int dataSize = CPUReadByte(header+3);
1465
1466 int data = 0;
1467 int bitwritecount = 0;
1468 while(1)
1469 {
1470 len -= 1;
1471 if(len < 0)
1472 break;
1473 int mask = 0xff >> revbits;
1474 u8 b = CPUReadByte(source);
1475 source++;
1476 int bitcount = 0;
1477 while(1) {
1478 if(bitcount >= 8)
1479 break;
1480 u32 d = b & mask;
1481 u32 temp = d >> bitcount;
1482 if(d || addBase) {
1483 temp += base;
1484 }
1485 data |= temp << bitwritecount;
1486 bitwritecount += dataSize;
1487 if(bitwritecount >= 32) {
1488 CPUWriteMemory(dest, data);
1489 dest += 4;
1490 data = 0;
1491 bitwritecount = 0;
1492 }
1493 mask <<= bits;
1494 bitcount += bits;
1495 }
1496 }
1497 }
1498
BIOS_BgAffineSet(void)1499 static void BIOS_BgAffineSet (void)
1500 {
1501 u32 src = bus.reg[0].I;
1502 u32 dest = bus.reg[1].I;
1503 int num = bus.reg[2].I;
1504
1505 for(int i = 0; i < num; i++)
1506 {
1507 s32 cx = CPUReadMemory(src);
1508 src+=4;
1509 s32 cy = CPUReadMemory(src);
1510 src+=4;
1511 s16 dispx = CPUReadHalfWord(src);
1512 src+=2;
1513 s16 dispy = CPUReadHalfWord(src);
1514 src+=2;
1515 s16 rx = CPUReadHalfWord(src);
1516 src+=2;
1517 s16 ry = CPUReadHalfWord(src);
1518 src+=2;
1519 u16 theta = CPUReadHalfWord(src)>>8;
1520 src+=4; // keep structure alignment
1521 s32 a = fast_cos(theta);
1522 s32 b = fast_sin(theta);
1523
1524 s16 dx = (rx * a)>>14;
1525 s16 dmx = (rx * b)>>14;
1526 s16 dy = (ry * b)>>14;
1527 s16 dmy = (ry * a)>>14;
1528
1529 CPUWriteHalfWord(dest, dx);
1530 dest += 2;
1531 CPUWriteHalfWord(dest, -dmx);
1532 dest += 2;
1533 CPUWriteHalfWord(dest, dy);
1534 dest += 2;
1535 CPUWriteHalfWord(dest, dmy);
1536
1537 dest += 2;
1538
1539 s32 startx = cx - dx * dispx + dmx * dispy;
1540 s32 starty = cy - dy * dispx - dmy * dispy;
1541
1542 CPUWriteMemory(dest, startx);
1543 dest += 4;
1544 CPUWriteMemory(dest, starty);
1545 dest += 4;
1546 }
1547 }
1548
BIOS_CpuSet(void)1549 static void BIOS_CpuSet (void)
1550 {
1551 u32 source = bus.reg[0].I;
1552 u32 dest = bus.reg[1].I;
1553 u32 cnt = bus.reg[2].I;
1554
1555 int count = cnt & 0x1FFFFF;
1556
1557 // 32-bit ?
1558 if((cnt >> 26) & 1)
1559 {
1560 // needed for 32-bit mode!
1561 source &= 0xFFFFFFFC;
1562 dest &= 0xFFFFFFFC;
1563 // fill ?
1564 if((cnt >> 24) & 1) {
1565 u32 value = (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source));
1566 while(count > 0) {
1567 CPUWriteMemory(dest, value);
1568 dest += 4;
1569 count--;
1570 }
1571 } else {
1572 #if USE_TWEAK_MEMFUNC
1573 if(source > 0x0EFFFFFF) {
1574 while(count > 0) {
1575 CPUWriteMemory(dest, 0x1CAD1CAD);
1576 dest += 4;
1577 count--;
1578 }
1579 } else {
1580 while(count > 0) {
1581 CPUWriteMemory(dest, CPUReadMemory(source));
1582 source += 4;
1583 dest += 4;
1584 count--;
1585 }
1586 }
1587 #else
1588 // copy
1589 while(count > 0) {
1590 CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source)));
1591 source += 4;
1592 dest += 4;
1593 count--;
1594 }
1595 #endif
1596 }
1597 }
1598 else
1599 {
1600 // 16-bit fill?
1601 if((cnt >> 24) & 1) {
1602 u16 value = (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source));
1603 while(count > 0) {
1604 CPUWriteHalfWord(dest, value);
1605 dest += 2;
1606 count--;
1607 }
1608 } else {
1609 #if USE_TWEAK_MEMFUNC
1610 if(source > 0x0EFFFFFF) {
1611 while(count > 0) {
1612 CPUWriteHalfWord(dest, 0x1CAD);
1613 dest += 2;
1614 count--;
1615 }
1616 } else {
1617 while(count > 0) {
1618 CPUWriteHalfWord(dest, CPUReadHalfWord(source));
1619 source += 2;
1620 dest += 2;
1621 count--;
1622 }
1623 }
1624 #else
1625 // copy
1626 while(count > 0) {
1627 CPUWriteHalfWord(dest, (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source)));
1628 source += 2;
1629 dest += 2;
1630 count--;
1631 }
1632 #endif
1633 }
1634 }
1635 }
1636
BIOS_CpuFastSet(void)1637 static void BIOS_CpuFastSet (void)
1638 {
1639 u32 source = bus.reg[0].I;
1640 u32 dest = bus.reg[1].I;
1641 u32 cnt = bus.reg[2].I;
1642
1643 // needed for 32-bit mode!
1644 source &= 0xFFFFFFFC;
1645 dest &= 0xFFFFFFFC;
1646
1647 int count = cnt & 0x1FFFFF;
1648
1649 // fill?
1650 if((cnt >> 24) & 1) {
1651 while(count > 0) {
1652 // BIOS always transfers 32 bytes at a time
1653 u32 value = (source>0x0EFFFFFF ? 0xBAFFFFFB : CPUReadMemory(source));
1654 for(int i = 0; i < 8; i++) {
1655 CPUWriteMemory(dest, value);
1656 dest += 4;
1657 }
1658 count -= 8;
1659 }
1660 } else {
1661 #if USE_TWEAK_MEMFUNC
1662 if(source > 0x0EFFFFFF) {
1663 while(count > 0) {
1664 for(int i = 0; i < 8; i++) {
1665 CPUWriteMemory(dest, 0xBAFFFFFB);
1666 dest += 4;
1667 }
1668 count -= 8;
1669 }
1670 } else {
1671 while(count > 0) {
1672 for(int i = 0; i < 8; i++) {
1673 CPUWriteMemory(dest, CPUReadMemory(source));
1674 source += 4;
1675 dest += 4;
1676 }
1677 count -= 8;
1678 }
1679 }
1680 #else
1681 // copy
1682 while(count > 0) {
1683 // BIOS always transfers 32 bytes at a time
1684 for(int i = 0; i < 8; i++) {
1685 CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0xBAFFFFFB :CPUReadMemory(source)));
1686 source += 4;
1687 dest += 4;
1688 }
1689 count -= 8;
1690 }
1691 #endif
1692 }
1693 }
1694
BIOS_Diff8bitUnFilterWram(void)1695 static void BIOS_Diff8bitUnFilterWram (void)
1696 {
1697 u32 source = bus.reg[0].I;
1698 u32 dest = bus.reg[1].I;
1699
1700 u32 header = CPUReadMemory(source);
1701 source += 4;
1702
1703 if(((source & 0xe000000) == 0) ||
1704 (((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0))
1705 return;
1706
1707 int len = header >> 8;
1708
1709 u8 data = CPUReadByte(source++);
1710 CPUWriteByte(dest++, data);
1711 len--;
1712
1713 while(len > 0) {
1714 u8 diff = CPUReadByte(source++);
1715 data += diff;
1716 CPUWriteByte(dest++, data);
1717 len--;
1718 }
1719 }
1720
BIOS_Diff8bitUnFilterVram(void)1721 static void BIOS_Diff8bitUnFilterVram (void)
1722 {
1723 u32 source = bus.reg[0].I;
1724 u32 dest = bus.reg[1].I;
1725
1726 u32 header = CPUReadMemory(source);
1727 source += 4;
1728
1729 if(((source & 0xe000000) == 0) ||
1730 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
1731 return;
1732
1733 int len = header >> 8;
1734
1735 u8 data = CPUReadByte(source++);
1736 u16 writeData = data;
1737 int shift = 8;
1738 int bytes = 1;
1739
1740 while(len >= 2) {
1741 u8 diff = CPUReadByte(source++);
1742 data += diff;
1743 writeData |= (data << shift);
1744 bytes++;
1745 shift += 8;
1746 if(bytes == 2) {
1747 CPUWriteHalfWord(dest, writeData);
1748 dest += 2;
1749 len -= 2;
1750 bytes = 0;
1751 writeData = 0;
1752 shift = 0;
1753 }
1754 }
1755 }
1756
BIOS_Diff16bitUnFilter(void)1757 static void BIOS_Diff16bitUnFilter (void)
1758 {
1759 u32 source = bus.reg[0].I;
1760 u32 dest = bus.reg[1].I;
1761
1762 u32 header = CPUReadMemory(source);
1763 source += 4;
1764
1765 if(((source & 0xe000000) == 0) ||
1766 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
1767 return;
1768
1769 int len = header >> 8;
1770
1771 u16 data = CPUReadHalfWord(source);
1772 source += 2;
1773 CPUWriteHalfWord(dest, data);
1774 dest += 2;
1775 len -= 2;
1776
1777 while(len >= 2) {
1778 u16 diff = CPUReadHalfWord(source);
1779 source += 2;
1780 data += diff;
1781 CPUWriteHalfWord(dest, data);
1782 dest += 2;
1783 len -= 2;
1784 }
1785 }
1786
BIOS_HuffUnComp(void)1787 static void BIOS_HuffUnComp (void)
1788 {
1789 u32 source = bus.reg[0].I;
1790 u32 dest = bus.reg[1].I;
1791
1792 u32 header = CPUReadMemory(source);
1793 source += 4;
1794
1795 if(((source & 0xe000000) == 0) ||
1796 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
1797 return;
1798
1799 u8 treeSize = CPUReadByte(source++);
1800
1801 u32 treeStart = source;
1802
1803 source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte
1804
1805 int len = header >> 8;
1806
1807 u32 mask = 0x80000000;
1808 u32 data = CPUReadMemory(source);
1809 source += 4;
1810
1811 int pos = 0;
1812 u8 rootNode = CPUReadByte(treeStart);
1813 u8 currentNode = rootNode;
1814 bool writeData = false;
1815 int byteShift = 0;
1816 int byteCount = 0;
1817 u32 writeValue = 0;
1818
1819 if((header & 0x0F) == 8) {
1820 while(len > 0) {
1821 // take left
1822 if(pos == 0)
1823 pos++;
1824 else
1825 pos += (((currentNode & 0x3F)+1)<<1);
1826
1827 if(data & mask) {
1828 // right
1829 if(currentNode & 0x40)
1830 writeData = true;
1831 currentNode = CPUReadByte(treeStart+pos+1);
1832 } else {
1833 // left
1834 if(currentNode & 0x80)
1835 writeData = true;
1836 currentNode = CPUReadByte(treeStart+pos);
1837 }
1838
1839 if(writeData) {
1840 writeValue |= (currentNode << byteShift);
1841 byteCount++;
1842 byteShift += 8;
1843
1844 pos = 0;
1845 currentNode = rootNode;
1846 writeData = false;
1847
1848 if(byteCount == 4) {
1849 byteCount = 0;
1850 byteShift = 0;
1851 CPUWriteMemory(dest, writeValue);
1852 writeValue = 0;
1853 dest += 4;
1854 len -= 4;
1855 }
1856 }
1857 mask >>= 1;
1858 if(mask == 0) {
1859 mask = 0x80000000;
1860 data = CPUReadMemory(source);
1861 source += 4;
1862 }
1863 }
1864 } else {
1865 int halfLen = 0;
1866 int value = 0;
1867 while(len > 0) {
1868 // take left
1869 if(pos == 0)
1870 pos++;
1871 else
1872 pos += (((currentNode & 0x3F)+1)<<1);
1873
1874 if((data & mask)) {
1875 // right
1876 if(currentNode & 0x40)
1877 writeData = true;
1878 currentNode = CPUReadByte(treeStart+pos+1);
1879 } else {
1880 // left
1881 if(currentNode & 0x80)
1882 writeData = true;
1883 currentNode = CPUReadByte(treeStart+pos);
1884 }
1885
1886 if(writeData) {
1887 if(halfLen == 0)
1888 value |= currentNode;
1889 else
1890 value |= (currentNode<<4);
1891
1892 halfLen += 4;
1893 if(halfLen == 8) {
1894 writeValue |= (value << byteShift);
1895 byteCount++;
1896 byteShift += 8;
1897
1898 halfLen = 0;
1899 value = 0;
1900
1901 if(byteCount == 4) {
1902 byteCount = 0;
1903 byteShift = 0;
1904 CPUWriteMemory(dest, writeValue);
1905 dest += 4;
1906 writeValue = 0;
1907 len -= 4;
1908 }
1909 }
1910 pos = 0;
1911 currentNode = rootNode;
1912 writeData = false;
1913 }
1914 mask >>= 1;
1915 if(mask == 0) {
1916 mask = 0x80000000;
1917 data = CPUReadMemory(source);
1918 source += 4;
1919 }
1920 }
1921 }
1922 }
1923
BIOS_LZ77UnCompVram(void)1924 static void BIOS_LZ77UnCompVram (void)
1925 {
1926
1927 u32 source = bus.reg[0].I;
1928 u32 dest = bus.reg[1].I;
1929
1930 u32 header = CPUReadMemory(source);
1931 source += 4;
1932
1933 if(((source & 0xe000000) == 0) ||
1934 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
1935 return;
1936
1937 int byteCount = 0;
1938 int byteShift = 0;
1939 u32 writeValue = 0;
1940
1941 int len = header >> 8;
1942
1943 while(len > 0) {
1944 u8 d = CPUReadByte(source++);
1945
1946 if(d) {
1947 for(int i = 0; i < 8; i++) {
1948 if(d & 0x80) {
1949 u16 data = CPUReadByte(source++) << 8;
1950 data |= CPUReadByte(source++);
1951 int length = (data >> 12) + 3;
1952 int offset = (data & 0x0FFF);
1953 u32 windowOffset = dest + byteCount - offset - 1;
1954 for(int i2 = 0; i2 < length; i2++) {
1955 writeValue |= (CPUReadByte(windowOffset++) << byteShift);
1956 byteShift += 8;
1957 byteCount++;
1958
1959 if(byteCount == 2) {
1960 CPUWriteHalfWord(dest, writeValue);
1961 dest += 2;
1962 byteCount = 0;
1963 byteShift = 0;
1964 writeValue = 0;
1965 }
1966 len--;
1967 if(len == 0)
1968 return;
1969 }
1970 } else {
1971 writeValue |= (CPUReadByte(source++) << byteShift);
1972 byteShift += 8;
1973 byteCount++;
1974 if(byteCount == 2) {
1975 CPUWriteHalfWord(dest, writeValue);
1976 dest += 2;
1977 byteCount = 0;
1978 byteShift = 0;
1979 writeValue = 0;
1980 }
1981 len--;
1982 if(len == 0)
1983 return;
1984 }
1985 d <<= 1;
1986 }
1987 } else {
1988 for(int i = 0; i < 8; i++) {
1989 writeValue |= (CPUReadByte(source++) << byteShift);
1990 byteShift += 8;
1991 byteCount++;
1992 if(byteCount == 2) {
1993 CPUWriteHalfWord(dest, writeValue);
1994 dest += 2;
1995 byteShift = 0;
1996 byteCount = 0;
1997 writeValue = 0;
1998 }
1999 len--;
2000 if(len == 0)
2001 return;
2002 }
2003 }
2004 }
2005 }
2006
BIOS_LZ77UnCompWram(void)2007 static void BIOS_LZ77UnCompWram (void)
2008 {
2009 u32 source = bus.reg[0].I;
2010 u32 dest = bus.reg[1].I;
2011
2012 u32 header = CPUReadMemory(source);
2013 source += 4;
2014
2015 if(((source & 0xe000000) == 0) ||
2016 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
2017 return;
2018
2019 int len = header >> 8;
2020
2021 while(len > 0) {
2022 u8 d = CPUReadByte(source++);
2023
2024 if(d) {
2025 for(int i = 0; i < 8; i++) {
2026 if(d & 0x80) {
2027 u16 data = CPUReadByte(source++) << 8;
2028 data |= CPUReadByte(source++);
2029 int length = (data >> 12) + 3;
2030 int offset = (data & 0x0FFF);
2031 u32 windowOffset = dest - offset - 1;
2032 for(int i2 = 0; i2 < length; i2++) {
2033 CPUWriteByte(dest++, CPUReadByte(windowOffset++));
2034 len--;
2035 if(len == 0)
2036 return;
2037 }
2038 } else {
2039 CPUWriteByte(dest++, CPUReadByte(source++));
2040 len--;
2041 if(len == 0)
2042 return;
2043 }
2044 d <<= 1;
2045 }
2046 } else {
2047 for(int i = 0; i < 8; i++) {
2048 CPUWriteByte(dest++, CPUReadByte(source++));
2049 len--;
2050 if(len == 0)
2051 return;
2052 }
2053 }
2054 }
2055 }
2056
BIOS_ObjAffineSet(void)2057 static void BIOS_ObjAffineSet (void)
2058 {
2059 u32 src = bus.reg[0].I;
2060 u32 dest = bus.reg[1].I;
2061 int num = bus.reg[2].I;
2062 int offset = bus.reg[3].I;
2063
2064 for(int i = 0; i < num; i++) {
2065 s16 rx = CPUReadHalfWord(src);
2066 src+=2;
2067 s16 ry = CPUReadHalfWord(src);
2068 src+=2;
2069 u16 theta = CPUReadHalfWord(src)>>8;
2070 src+=4; // keep structure alignment
2071
2072 s32 a = fast_cos(theta);
2073 s32 b = fast_sin(theta);
2074
2075 s16 dx = ((s32)rx * a)>>14;
2076 s16 dmx = ((s32)rx * b)>>14;
2077 s16 dy = ((s32)ry * b)>>14;
2078 s16 dmy = ((s32)ry * a)>>14;
2079
2080 CPUWriteHalfWord(dest, dx);
2081 dest += offset;
2082 CPUWriteHalfWord(dest, -dmx);
2083 dest += offset;
2084 CPUWriteHalfWord(dest, dy);
2085 dest += offset;
2086 CPUWriteHalfWord(dest, dmy);
2087 dest += offset;
2088 }
2089 }
2090
BIOS_RegisterRamReset(u32 flags)2091 static void BIOS_RegisterRamReset(u32 flags)
2092 {
2093 // no need to trace here. this is only called directly from GBA.cpp
2094 // to emulate bios initialization
2095
2096 CPUUpdateRegister(0x0, 0x80);
2097
2098 if(flags)
2099 {
2100 if(flags & 0x01)
2101 memset(workRAM, 0, 0x40000); // clear work RAM
2102
2103 if(flags & 0x02)
2104 memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff, clear internal RAM
2105
2106 if(flags & 0x04)
2107 memset(paletteRAM, 0, 0x400); // clear palette RAM
2108
2109 if(flags & 0x08)
2110 memset(vram, 0, 0x18000); // clear VRAM
2111
2112 if(flags & 0x10)
2113 memset(oam, 0, 0x400); // clean OAM
2114
2115 if(flags & 0x80) {
2116 int i;
2117 for(i = 0; i < 0x10; i++)
2118 CPUUpdateRegister(0x200+i*2, 0);
2119
2120 for(i = 0; i < 0xF; i++)
2121 CPUUpdateRegister(0x4+i*2, 0);
2122
2123 for(i = 0; i < 0x20; i++)
2124 CPUUpdateRegister(0x20+i*2, 0);
2125
2126 for(i = 0; i < 0x18; i++)
2127 CPUUpdateRegister(0xb0+i*2, 0);
2128
2129 CPUUpdateRegister(0x130, 0);
2130 CPUUpdateRegister(0x20, 0x100);
2131 CPUUpdateRegister(0x30, 0x100);
2132 CPUUpdateRegister(0x26, 0x100);
2133 CPUUpdateRegister(0x36, 0x100);
2134 }
2135
2136 if(flags & 0x20) {
2137 int i;
2138 for(i = 0; i < 8; i++)
2139 CPUUpdateRegister(0x110+i*2, 0);
2140 CPUUpdateRegister(0x134, 0x8000);
2141 for(i = 0; i < 7; i++)
2142 CPUUpdateRegister(0x140+i*2, 0);
2143 }
2144
2145 if(flags & 0x40) {
2146 int i;
2147 CPUWriteByte(0x4000084, 0);
2148 CPUWriteByte(0x4000084, 0x80);
2149 CPUWriteMemory(0x4000080, 0x880e0000);
2150 CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
2151 CPUWriteByte(0x4000070, 0x70);
2152 for(i = 0; i < 8; i++)
2153 CPUUpdateRegister(0x90+i*2, 0);
2154 CPUWriteByte(0x4000070, 0);
2155 for(i = 0; i < 8; i++)
2156 CPUUpdateRegister(0x90+i*2, 0);
2157 CPUWriteByte(0x4000084, 0);
2158 }
2159 }
2160 }
2161
BIOS_RLUnCompVram(void)2162 static void BIOS_RLUnCompVram (void)
2163 {
2164 u32 source = bus.reg[0].I;
2165 u32 dest = bus.reg[1].I;
2166
2167 u32 header = CPUReadMemory(source & 0xFFFFFFFC);
2168 source += 4;
2169
2170 if(((source & 0xe000000) == 0) ||
2171 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
2172 return;
2173
2174 int len = header >> 8;
2175 int byteCount = 0;
2176 int byteShift = 0;
2177 u32 writeValue = 0;
2178
2179 while(len > 0)
2180 {
2181 u8 d = CPUReadByte(source++);
2182 int l = d & 0x7F;
2183 if(d & 0x80) {
2184 u8 data = CPUReadByte(source++);
2185 l += 3;
2186 for(int i = 0;i < l; i++) {
2187 writeValue |= (data << byteShift);
2188 byteShift += 8;
2189 byteCount++;
2190
2191 if(byteCount == 2) {
2192 CPUWriteHalfWord(dest, writeValue);
2193 dest += 2;
2194 byteCount = 0;
2195 byteShift = 0;
2196 writeValue = 0;
2197 }
2198 len--;
2199 if(len == 0)
2200 return;
2201 }
2202 } else {
2203 l++;
2204 for(int i = 0; i < l; i++) {
2205 writeValue |= (CPUReadByte(source++) << byteShift);
2206 byteShift += 8;
2207 byteCount++;
2208 if(byteCount == 2) {
2209 CPUWriteHalfWord(dest, writeValue);
2210 dest += 2;
2211 byteCount = 0;
2212 byteShift = 0;
2213 writeValue = 0;
2214 }
2215 len--;
2216 if(len == 0)
2217 return;
2218 }
2219 }
2220 }
2221 }
2222
BIOS_RLUnCompWram(void)2223 static void BIOS_RLUnCompWram (void)
2224 {
2225 u32 source = bus.reg[0].I;
2226 u32 dest = bus.reg[1].I;
2227
2228 u32 header = CPUReadMemory(source & 0xFFFFFFFC);
2229 source += 4;
2230
2231 if(((source & 0xe000000) == 0) ||
2232 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
2233 return;
2234
2235 int len = header >> 8;
2236
2237 while(len > 0) {
2238 u8 d = CPUReadByte(source++);
2239 int l = d & 0x7F;
2240 if(d & 0x80) {
2241 u8 data = CPUReadByte(source++);
2242 l += 3;
2243 for(int i = 0;i < l; i++) {
2244 CPUWriteByte(dest++, data);
2245 len--;
2246 if(len == 0)
2247 return;
2248 }
2249 } else {
2250 l++;
2251 for(int i = 0; i < l; i++) {
2252 CPUWriteByte(dest++, CPUReadByte(source++));
2253 len--;
2254 if(len == 0)
2255 return;
2256 }
2257 }
2258 }
2259 }
2260
BIOS_SoftReset(void)2261 static void BIOS_SoftReset (void)
2262 {
2263 armState = true;
2264 armMode = 0x1F;
2265 armIrqEnable = false;
2266 C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
2267 bus.reg[13].I = 0x03007F00;
2268 bus.reg[14].I = 0x00000000;
2269 bus.reg[16].I = 0x00000000;
2270 bus.reg[R13_IRQ].I = 0x03007FA0;
2271 bus.reg[R14_IRQ].I = 0x00000000;
2272 bus.reg[SPSR_IRQ].I = 0x00000000;
2273 bus.reg[R13_SVC].I = 0x03007FE0;
2274 bus.reg[R14_SVC].I = 0x00000000;
2275 bus.reg[SPSR_SVC].I = 0x00000000;
2276 u8 b = internalRAM[0x7ffa];
2277
2278 memset(&internalRAM[0x7e00], 0, 0x200);
2279
2280 if(b) {
2281 bus.armNextPC = 0x02000000;
2282 bus.reg[15].I = 0x02000004;
2283 } else {
2284 bus.armNextPC = 0x08000000;
2285 bus.reg[15].I = 0x08000004;
2286 }
2287 }
2288
2289 #define BIOS_GET_BIOS_CHECKSUM() bus.reg[0].I=0xBAAE187F;
2290
2291 #define BIOS_REGISTER_RAM_RESET() BIOS_RegisterRamReset(bus.reg[0].I);
2292
2293 #define BIOS_SQRT() bus.reg[0].I = (u32)sqrt((double)bus.reg[0].I);
2294
2295 #define BIOS_MIDI_KEY_2_FREQ() \
2296 { \
2297 int freq = CPUReadMemory(bus.reg[0].I+4); \
2298 double tmp; \
2299 tmp = ((double)(180 - bus.reg[1].I)) - ((double)bus.reg[2].I / 256.f); \
2300 tmp = pow((double)2.f, tmp / 12.f); \
2301 bus.reg[0].I = (int)((double)freq / tmp); \
2302 }
2303
2304 /*
2305 #define BIOS_SND_DRIVER_JMP_TABLE_COPY() \
2306 for(int i = 0; i < 36; i++) \
2307 { \
2308 CPUWriteMemory(bus.reg[0].I, 0x9c); \
2309 bus.reg[0].I += 4; \
2310 }
2311 */
2312
2313 #define BIOS_SND_DRIVER_JMP_TABLE_COPY() \
2314 CPUWriteMemory(bus.reg[0].I, 0x9c); \
2315 bus.reg[0].I += 4;
2316
2317 #define CPU_UPDATE_CPSR() \
2318 { \
2319 uint32_t CPSR; \
2320 CPSR = bus.reg[16].I & 0x40; \
2321 if(N_FLAG) \
2322 CPSR |= 0x80000000; \
2323 if(Z_FLAG) \
2324 CPSR |= 0x40000000; \
2325 if(C_FLAG) \
2326 CPSR |= 0x20000000; \
2327 if(V_FLAG) \
2328 CPSR |= 0x10000000; \
2329 if(!armState) \
2330 CPSR |= 0x00000020; \
2331 if(!armIrqEnable) \
2332 CPSR |= 0x80; \
2333 CPSR |= (armMode & 0x1F); \
2334 bus.reg[16].I = CPSR; \
2335 }
2336
2337 #define CPU_SOFTWARE_INTERRUPT() \
2338 { \
2339 uint32_t PC = bus.reg[15].I; \
2340 bool savedArmState = armState; \
2341 if(armMode != 0x13) \
2342 CPUSwitchMode(0x13, true, false); \
2343 bus.reg[14].I = PC - (savedArmState ? 4 : 2); \
2344 bus.reg[15].I = 0x08; \
2345 armState = true; \
2346 armIrqEnable = false; \
2347 bus.armNextPC = 0x08; \
2348 ARM_PREFETCH; \
2349 bus.reg[15].I += 4; \
2350 }
2351
CPUUpdateFlags(bool breakLoop)2352 static void CPUUpdateFlags(bool breakLoop)
2353 {
2354 uint32_t CPSR = bus.reg[16].I;
2355
2356 N_FLAG = (CPSR & 0x80000000) ? true: false;
2357 Z_FLAG = (CPSR & 0x40000000) ? true: false;
2358 C_FLAG = (CPSR & 0x20000000) ? true: false;
2359 V_FLAG = (CPSR & 0x10000000) ? true: false;
2360 armState = (CPSR & 0x20) ? false : true;
2361 armIrqEnable = (CPSR & 0x80) ? false : true;
2362 if (breakLoop && armIrqEnable && (io_registers[REG_IF] & io_registers[REG_IE]) && (io_registers[REG_IME] & 1))
2363 cpuNextEvent = cpuTotalTicks;
2364 }
2365
CPUSoftwareInterrupt(int comment)2366 static void CPUSoftwareInterrupt(int comment)
2367 {
2368 if(armState)
2369 comment >>= 16;
2370
2371 #ifdef HAVE_HLE_BIOS
2372 if(useBios)
2373 {
2374 CPU_SOFTWARE_INTERRUPT();
2375 return;
2376 }
2377 #endif
2378
2379 switch(comment) {
2380 case 0x00:
2381 BIOS_SoftReset();
2382 ARM_PREFETCH;
2383 break;
2384 case 0x01:
2385 BIOS_REGISTER_RAM_RESET();
2386 break;
2387 case 0x02:
2388 holdState = true;
2389 cpuNextEvent = cpuTotalTicks;
2390 break;
2391 case 0x03:
2392 holdState = true;
2393 stopState = true;
2394 cpuNextEvent = cpuTotalTicks;
2395 break;
2396 case 0x04:
2397 case 0x05:
2398 case 0x06:
2399 case 0x07:
2400 CPU_SOFTWARE_INTERRUPT();
2401 break;
2402 case 0x08:
2403 BIOS_SQRT();
2404 break;
2405 case 0x09:
2406 BIOS_ArcTan();
2407 break;
2408 case 0x0A:
2409 BIOS_ArcTan2();
2410 break;
2411 case 0x0B:
2412 {
2413 #ifdef USE_SWITICKS
2414 int len = (bus.reg[2].I & 0x1FFFFF) >>1;
2415 if (!(((bus.reg[0].I & 0xe000000) == 0) ||
2416 ((bus.reg[0].I + len) & 0xe000000) == 0))
2417 {
2418 if ((bus.reg[2].I >> 24) & 1)
2419 {
2420 if ((bus.reg[2].I >> 26) & 1)
2421 SWITicks = (7 + memoryWait32[(bus.reg[1].I>>24) & 0xF]) * (len>>1);
2422 else
2423 SWITicks = (8 + memoryWait[(bus.reg[1].I>>24) & 0xF]) * (len);
2424 }
2425 else
2426 {
2427 if ((bus.reg[2].I >> 26) & 1)
2428 SWITicks = (10 + memoryWait32[(bus.reg[0].I>>24) & 0xF] +
2429 memoryWait32[(bus.reg[1].I>>24) & 0xF]) * (len>>1);
2430 else
2431 SWITicks = (11 + memoryWait[(bus.reg[0].I>>24) & 0xF] +
2432 memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2433 }
2434 }
2435 #endif
2436 }
2437 if(!(((bus.reg[0].I & 0xe000000) == 0) || ((bus.reg[0].I + (((bus.reg[2].I << 11)>>9) & 0x1fffff)) & 0xe000000) == 0))
2438 BIOS_CpuSet();
2439 break;
2440 case 0x0C:
2441 {
2442 #ifdef USE_SWITICKS
2443 int len = (bus.reg[2].I & 0x1FFFFF) >>5;
2444 if (!(((bus.reg[0].I & 0xe000000) == 0) ||
2445 ((bus.reg[0].I + len) & 0xe000000) == 0))
2446 {
2447 if ((bus.reg[2].I >> 24) & 1)
2448 SWITicks = (6 + memoryWait32[(bus.reg[1].I>>24) & 0xF] +
2449 7 * (memoryWaitSeq32[(bus.reg[1].I>>24) & 0xF] + 1)) * len;
2450 else
2451 SWITicks = (9 + memoryWait32[(bus.reg[0].I>>24) & 0xF] +
2452 memoryWait32[(bus.reg[1].I>>24) & 0xF] +
2453 7 * (memoryWaitSeq32[(bus.reg[0].I>>24) & 0xF] +
2454 memoryWaitSeq32[(bus.reg[1].I>>24) & 0xF] + 2)) * len;
2455 }
2456 #endif
2457 }
2458 if(!(((bus.reg[0].I & 0xe000000) == 0) || ((bus.reg[0].I + (((bus.reg[2].I << 11)>>9) & 0x1fffff)) & 0xe000000) == 0))
2459 BIOS_CpuFastSet();
2460 break;
2461 case 0x0D:
2462 BIOS_GET_BIOS_CHECKSUM();
2463 break;
2464 case 0x0E:
2465 BIOS_BgAffineSet();
2466 break;
2467 case 0x0F:
2468 BIOS_ObjAffineSet();
2469 break;
2470 case 0x10:
2471 {
2472 #ifdef USE_SWITICKS
2473 int len = CPUReadHalfWord(bus.reg[2].I);
2474 if (!(((bus.reg[0].I & 0xe000000) == 0) ||
2475 ((bus.reg[0].I + len) & 0xe000000) == 0))
2476 SWITicks = (32 + memoryWait[(bus.reg[0].I>>24) & 0xF]) * len;
2477 #endif
2478 }
2479 BIOS_BitUnPack();
2480 break;
2481 case 0x11:
2482 #ifdef USE_SWITICKS
2483 {
2484 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 8;
2485 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2486 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2487 SWITicks = (9 + memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2488 }
2489 #endif
2490 BIOS_LZ77UnCompWram();
2491 break;
2492 case 0x12:
2493 #ifdef USE_SWITICKS
2494 {
2495 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 8;
2496 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2497 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2498 SWITicks = (19 + memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2499 }
2500 #endif
2501 BIOS_LZ77UnCompVram();
2502 break;
2503 case 0x13:
2504 #ifdef USE_SWITICKS
2505 {
2506 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 8;
2507 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2508 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2509 SWITicks = (29 + (memoryWait[(bus.reg[0].I>>24) & 0xF]<<1)) * len;
2510 }
2511 #endif
2512 BIOS_HuffUnComp();
2513 break;
2514 case 0x14:
2515 #ifdef USE_SWITICKS
2516 {
2517 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 8;
2518 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2519 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2520 SWITicks = (11 + memoryWait[(bus.reg[0].I>>24) & 0xF] +
2521 memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2522 }
2523 #endif
2524 BIOS_RLUnCompWram();
2525 break;
2526 case 0x15:
2527 #ifdef USE_SWITICKS
2528 {
2529 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 9;
2530 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2531 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2532 SWITicks = (34 + (memoryWait[(bus.reg[0].I>>24) & 0xF] << 1) +
2533 memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2534 }
2535 #endif
2536 BIOS_RLUnCompVram();
2537 break;
2538 case 0x16:
2539 #ifdef USE_SWITICKS
2540 {
2541 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 8;
2542 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2543 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2544 SWITicks = (13 + memoryWait[(bus.reg[0].I>>24) & 0xF] +
2545 memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2546 }
2547 #endif
2548 BIOS_Diff8bitUnFilterWram();
2549 break;
2550 case 0x17:
2551 #ifdef USE_SWITICKS
2552 {
2553 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 9;
2554 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2555 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2556 SWITicks = (39 + (memoryWait[(bus.reg[0].I>>24) & 0xF]<<1) +
2557 memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2558 }
2559 #endif
2560 BIOS_Diff8bitUnFilterVram();
2561 break;
2562 case 0x18:
2563 #ifdef USE_SWITICKS
2564 {
2565 uint32_t len = CPUReadMemory(bus.reg[0].I) >> 9;
2566 if(!(((bus.reg[0].I & 0xe000000) == 0) ||
2567 ((bus.reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
2568 SWITicks = (13 + memoryWait[(bus.reg[0].I>>24) & 0xF] +
2569 memoryWait[(bus.reg[1].I>>24) & 0xF]) * len;
2570 }
2571 #endif
2572 BIOS_Diff16bitUnFilter();
2573 break;
2574 case 0x19:
2575 break;
2576 case 0x1F:
2577 BIOS_MIDI_KEY_2_FREQ();
2578 break;
2579 case 0x2A:
2580 BIOS_SND_DRIVER_JMP_TABLE_COPY();
2581 // let it go, because we don't really emulate this function
2582 default:
2583 break;
2584 }
2585 }
2586
2587 /*============================================================
2588 GBA ARM CORE
2589 ============================================================ */
2590
2591 #ifdef _MSC_VER
2592 // Disable "empty statement" warnings
2593 #pragma warning(disable: 4390)
2594 // Visual C's inline assembler treats "offset" as a reserved word, so we
2595 // tell it otherwise. If you want to use it, write "OFFSET" in capitals.e
2596 #define offset offset_
2597 #endif
2598
armUnknownInsn(u32 opcode)2599 static void armUnknownInsn(u32 opcode)
2600 {
2601 u32 PC = bus.reg[15].I;
2602 bool savedArmState = armState;
2603 if(armMode != 0x1b )
2604 CPUSwitchMode(0x1b, true, false);
2605 bus.reg[14].I = PC - (savedArmState ? 4 : 2);
2606 bus.reg[15].I = 0x04;
2607 armState = true;
2608 armIrqEnable = false;
2609 bus.armNextPC = 0x04;
2610 ARM_PREFETCH;
2611 bus.reg[15].I += 4;
2612 }
2613
2614 // Common macros //////////////////////////////////////////////////////////
2615
2616 #define NEG(i) ((i) >> 31)
2617 #define POS(i) ((~(i)) >> 31)
2618
2619 // The following macros are used for optimization; any not defined for a
2620 // particular compiler/CPU combination default to the C core versions.
2621 //
2622 // ALU_INIT_C: Used at the beginning of ALU instructions (AND/EOR/...).
2623 // (ALU_INIT_NC) Can consist of variable declarations, like the C core,
2624 // or the start of a continued assembly block, like the
2625 // x86-optimized version. The _C version is used when the
2626 // carry flag from the shift operation is needed (logical
2627 // operations that set condition codes, like ANDS); the
2628 // _NC version is used when the carry result is ignored.
2629 // VALUE_XXX: Retrieve the second operand's value for an ALU instruction.
2630 // The _C and _NC versions are used the same way as ALU_INIT.
2631 // OP_XXX: ALU operations. XXX is the instruction name.
2632 // SETCOND_NONE: Used in multiply instructions in place of SETCOND_MUL
2633 // when the condition codes are not set. Usually empty.
2634 // SETCOND_MUL: Used in multiply instructions to set the condition codes.
2635 // ROR_IMM_MSR: Used to rotate the immediate operand for MSR.
2636 // ROR_OFFSET: Used to rotate the `offset' parameter for LDR and STR
2637 // instructions.
2638 // RRX_OFFSET: Used to rotate (RRX) the `offset' parameter for LDR and
2639 // STR instructions.
2640
2641 // C core
2642
2643 #define C_SETCOND_LOGICAL \
2644 N_FLAG = ((s32)res < 0) ? true : false; \
2645 Z_FLAG = (res == 0) ? true : false; \
2646 C_FLAG = C_OUT;
2647 #define C_SETCOND_ADD \
2648 N_FLAG = ((s32)res < 0) ? true : false; \
2649 Z_FLAG = (res == 0) ? true : false; \
2650 V_FLAG = ((NEG(lhs) & NEG(rhs) & POS(res)) | \
2651 (POS(lhs) & POS(rhs) & NEG(res))) ? true : false;\
2652 C_FLAG = ((NEG(lhs) & NEG(rhs)) | \
2653 (NEG(lhs) & POS(res)) | \
2654 (NEG(rhs) & POS(res))) ? true : false;
2655 #define C_SETCOND_SUB \
2656 N_FLAG = ((s32)res < 0) ? true : false; \
2657 Z_FLAG = (res == 0) ? true : false; \
2658 V_FLAG = ((NEG(lhs) & POS(rhs) & POS(res)) | \
2659 (POS(lhs) & NEG(rhs) & NEG(res))) ? true : false;\
2660 C_FLAG = ((NEG(lhs) & POS(rhs)) | \
2661 (NEG(lhs) & POS(res)) | \
2662 (POS(rhs) & POS(res))) ? true : false;
2663
2664 #ifndef ALU_INIT_C
2665 #define ALU_INIT_C \
2666 int dest = (opcode>>12) & 15; \
2667 bool C_OUT = C_FLAG; \
2668 u32 value;
2669 #endif
2670 // OP Rd,Rb,Rm LSL #
2671 #ifndef VALUE_LSL_IMM_C
2672 #define VALUE_LSL_IMM_C \
2673 unsigned int shift = (opcode >> 7) & 0x1F; \
2674 if (!shift) { /* LSL #0 most common? */ \
2675 value = bus.reg[opcode & 0x0F].I; \
2676 } else { \
2677 u32 v = bus.reg[opcode & 0x0F].I; \
2678 C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
2679 value = v << shift; \
2680 }
2681 #endif
2682 // OP Rd,Rb,Rm LSL Rs
2683 #ifndef VALUE_LSL_REG_C
2684 #define VALUE_LSL_REG_C \
2685 u32 shift = bus.reg[(opcode >> 8) & 15].B.B0; \
2686 u32 rm = bus.reg[opcode & 0x0F].I; \
2687 if ((opcode & 0x0F) == 15) { \
2688 rm += 4; \
2689 } \
2690 if (shift) { \
2691 if (shift == 32) { \
2692 value = 0; \
2693 C_OUT = (rm & 1 ? true : false); \
2694 } else if (shift < 32) { \
2695 u32 v = rm; \
2696 C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
2697 value = v << shift; \
2698 } else { \
2699 value = 0; \
2700 C_OUT = false; \
2701 } \
2702 } else { \
2703 value = rm; \
2704 }
2705 #endif
2706 // OP Rd,Rb,Rm LSR #
2707 #ifndef VALUE_LSR_IMM_C
2708 #define VALUE_LSR_IMM_C \
2709 u32 shift = (opcode >> 7) & 0x1F; \
2710 if (shift) { \
2711 u32 v = bus.reg[opcode & 0x0F].I; \
2712 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
2713 value = v >> shift; \
2714 } else { \
2715 value = 0; \
2716 C_OUT = (bus.reg[opcode & 0x0F].I & 0x80000000) ? true : false;\
2717 }
2718 #endif
2719 // OP Rd,Rb,Rm LSR Rs
2720 #ifndef VALUE_LSR_REG_C
2721 #define VALUE_LSR_REG_C \
2722 unsigned int shift = bus.reg[(opcode >> 8) & 15].B.B0; \
2723 u32 rm = bus.reg[opcode & 0x0F].I; \
2724 if ((opcode & 0x0F) == 15) { \
2725 rm += 4; \
2726 } \
2727 if (shift) { \
2728 if (shift == 32) { \
2729 value = 0; \
2730 C_OUT = (rm & 0x80000000 ? true : false); \
2731 } else if (shift < 32) { \
2732 u32 v = rm; \
2733 C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
2734 value = v >> shift; \
2735 } else { \
2736 value = 0; \
2737 C_OUT = false; \
2738 } \
2739 } else { \
2740 value = rm; \
2741 }
2742 #endif
2743 // OP Rd,Rb,Rm ASR #
2744 #ifndef VALUE_ASR_IMM_C
2745 #define VALUE_ASR_IMM_C \
2746 unsigned int shift = (opcode >> 7) & 0x1F; \
2747 if (shift) { \
2748 s32 v = bus.reg[opcode & 0x0F].I; \
2749 C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
2750 value = v >> (int)shift; \
2751 } else { \
2752 if (bus.reg[opcode & 0x0F].I & 0x80000000) { \
2753 value = 0xFFFFFFFF; \
2754 C_OUT = true; \
2755 } else { \
2756 value = 0; \
2757 C_OUT = false; \
2758 } \
2759 }
2760 #endif
2761 // OP Rd,Rb,Rm ASR Rs
2762 #ifndef VALUE_ASR_REG_C
2763 #define VALUE_ASR_REG_C \
2764 unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \
2765 u32 rm = bus.reg[opcode & 0x0F].I; \
2766 if ((opcode & 0x0F) == 15) { \
2767 rm += 4; \
2768 } \
2769 if (shift < 32) { \
2770 if (shift) { \
2771 s32 v = rm; \
2772 C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
2773 value = v >> (int)shift; \
2774 } else { \
2775 value = rm; \
2776 } \
2777 } else { \
2778 if (bus.reg[opcode & 0x0F].I & 0x80000000) { \
2779 value = 0xFFFFFFFF; \
2780 C_OUT = true; \
2781 } else { \
2782 value = 0; \
2783 C_OUT = false; \
2784 } \
2785 }
2786 #endif
2787 // OP Rd,Rb,Rm ROR #
2788 #ifndef VALUE_ROR_IMM_C
2789 #define VALUE_ROR_IMM_C \
2790 unsigned int shift = (opcode >> 7) & 0x1F; \
2791 if (shift) { \
2792 u32 v = bus.reg[opcode & 0x0F].I; \
2793 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
2794 value = ((v << (32 - shift)) | \
2795 (v >> shift)); \
2796 } else { \
2797 u32 v = bus.reg[opcode & 0x0F].I; \
2798 C_OUT = (v & 1) ? true : false; \
2799 value = ((v >> 1) | \
2800 (C_FLAG << 31)); \
2801 }
2802 #endif
2803 // OP Rd,Rb,Rm ROR Rs
2804 #ifndef VALUE_ROR_REG_C
2805 #define VALUE_ROR_REG_C \
2806 unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \
2807 u32 rm = bus.reg[opcode & 0x0F].I; \
2808 if ((opcode & 0x0F) == 15) { \
2809 rm += 4; \
2810 } \
2811 if (shift & 0x1F) { \
2812 u32 v = rm; \
2813 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
2814 value = ((v << (32 - shift)) | \
2815 (v >> shift)); \
2816 } else { \
2817 value = rm; \
2818 if (shift) \
2819 C_OUT = (value & 0x80000000 ? true : false);\
2820 }
2821 #endif
2822 // OP Rd,Rb,# ROR #
2823 #ifndef VALUE_IMM_C
2824 #define VALUE_IMM_C \
2825 int shift = (opcode & 0xF00) >> 7; \
2826 if (shift) { \
2827 u32 v = opcode & 0xFF; \
2828 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
2829 value = ((v << (32 - shift)) | \
2830 (v >> shift)); \
2831 } else { \
2832 value = opcode & 0xFF; \
2833 }
2834 #endif
2835
2836 // Make the non-carry versions default to the carry versions
2837 // (this is fine for C--the compiler will optimize the dead code out)
2838 #ifndef ALU_INIT_NC
2839 #define ALU_INIT_NC ALU_INIT_C
2840 #endif
2841 #ifndef VALUE_LSL_IMM_NC
2842 #define VALUE_LSL_IMM_NC VALUE_LSL_IMM_C
2843 #endif
2844 #ifndef VALUE_LSL_REG_NC
2845 #define VALUE_LSL_REG_NC VALUE_LSL_REG_C
2846 #endif
2847 #ifndef VALUE_LSR_IMM_NC
2848 #define VALUE_LSR_IMM_NC VALUE_LSR_IMM_C
2849 #endif
2850 #ifndef VALUE_LSR_REG_NC
2851 #define VALUE_LSR_REG_NC VALUE_LSR_REG_C
2852 #endif
2853 #ifndef VALUE_ASR_IMM_NC
2854 #define VALUE_ASR_IMM_NC VALUE_ASR_IMM_C
2855 #endif
2856 #ifndef VALUE_ASR_REG_NC
2857 #define VALUE_ASR_REG_NC VALUE_ASR_REG_C
2858 #endif
2859 #ifndef VALUE_ROR_IMM_NC
2860 #define VALUE_ROR_IMM_NC VALUE_ROR_IMM_C
2861 #endif
2862 #ifndef VALUE_ROR_REG_NC
2863 #define VALUE_ROR_REG_NC VALUE_ROR_REG_C
2864 #endif
2865 #ifndef VALUE_IMM_NC
2866 #define VALUE_IMM_NC VALUE_IMM_C
2867 #endif
2868
2869 #define C_CHECK_PC(SETCOND) if (dest != 15) { SETCOND }
2870 #ifndef OP_AND
2871 #define OP_AND \
2872 u32 res = bus.reg[(opcode>>16)&15].I & value; \
2873 bus.reg[dest].I = res;
2874 #endif
2875 #ifndef OP_ANDS
2876 #define OP_ANDS OP_AND C_CHECK_PC(C_SETCOND_LOGICAL)
2877 #endif
2878 #ifndef OP_EOR
2879 #define OP_EOR \
2880 u32 res = bus.reg[(opcode>>16)&15].I ^ value; \
2881 bus.reg[dest].I = res;
2882 #endif
2883 #ifndef OP_EORS
2884 #define OP_EORS OP_EOR C_CHECK_PC(C_SETCOND_LOGICAL)
2885 #endif
2886 #ifndef OP_SUB
2887 #define OP_SUB \
2888 u32 lhs = bus.reg[(opcode>>16)&15].I; \
2889 u32 rhs = value; \
2890 u32 res = lhs - rhs; \
2891 bus.reg[dest].I = res;
2892 #endif
2893 #ifndef OP_SUBS
2894 #define OP_SUBS OP_SUB C_CHECK_PC(C_SETCOND_SUB)
2895 #endif
2896 #ifndef OP_RSB
2897 #define OP_RSB \
2898 u32 lhs = value; \
2899 u32 rhs = bus.reg[(opcode>>16)&15].I; \
2900 u32 res = lhs - rhs; \
2901 bus.reg[dest].I = res;
2902 #endif
2903 #ifndef OP_RSBS
2904 #define OP_RSBS OP_RSB C_CHECK_PC(C_SETCOND_SUB)
2905 #endif
2906 #ifndef OP_ADD
2907 #define OP_ADD \
2908 u32 lhs = bus.reg[(opcode>>16)&15].I; \
2909 u32 rhs = value; \
2910 u32 res = lhs + rhs; \
2911 bus.reg[dest].I = res;
2912 #endif
2913 #ifndef OP_ADDS
2914 #define OP_ADDS OP_ADD C_CHECK_PC(C_SETCOND_ADD)
2915 #endif
2916 #ifndef OP_ADC
2917 #define OP_ADC \
2918 u32 lhs = bus.reg[(opcode>>16)&15].I; \
2919 u32 rhs = value; \
2920 u32 res = lhs + rhs + (u32)C_FLAG; \
2921 bus.reg[dest].I = res;
2922 #endif
2923 #ifndef OP_ADCS
2924 #define OP_ADCS OP_ADC C_CHECK_PC(C_SETCOND_ADD)
2925 #endif
2926 #ifndef OP_SBC
2927 #define OP_SBC \
2928 u32 lhs = bus.reg[(opcode>>16)&15].I; \
2929 u32 rhs = value; \
2930 u32 res = lhs - rhs - !((u32)C_FLAG); \
2931 bus.reg[dest].I = res;
2932 #endif
2933 #ifndef OP_SBCS
2934 #define OP_SBCS OP_SBC C_CHECK_PC(C_SETCOND_SUB)
2935 #endif
2936 #ifndef OP_RSC
2937 #define OP_RSC \
2938 u32 lhs = value; \
2939 u32 rhs = bus.reg[(opcode>>16)&15].I; \
2940 u32 res = lhs - rhs - !((u32)C_FLAG); \
2941 bus.reg[dest].I = res;
2942 #endif
2943 #ifndef OP_RSCS
2944 #define OP_RSCS OP_RSC C_CHECK_PC(C_SETCOND_SUB)
2945 #endif
2946 #ifndef OP_TST
2947 #define OP_TST \
2948 u32 res = bus.reg[(opcode >> 16) & 0x0F].I & value; \
2949 C_SETCOND_LOGICAL;
2950 #endif
2951 #ifndef OP_TEQ
2952 #define OP_TEQ \
2953 u32 res = bus.reg[(opcode >> 16) & 0x0F].I ^ value; \
2954 C_SETCOND_LOGICAL;
2955 #endif
2956 #ifndef OP_CMP
2957 #define OP_CMP \
2958 u32 lhs = bus.reg[(opcode>>16)&15].I; \
2959 u32 rhs = value; \
2960 u32 res = lhs - rhs; \
2961 C_SETCOND_SUB;
2962 #endif
2963 #ifndef OP_CMN
2964 #define OP_CMN \
2965 u32 lhs = bus.reg[(opcode>>16)&15].I; \
2966 u32 rhs = value; \
2967 u32 res = lhs + rhs; \
2968 C_SETCOND_ADD;
2969 #endif
2970 #ifndef OP_ORR
2971 #define OP_ORR \
2972 u32 res = bus.reg[(opcode >> 16) & 0x0F].I | value; \
2973 bus.reg[dest].I = res;
2974 #endif
2975 #ifndef OP_ORRS
2976 #define OP_ORRS OP_ORR C_CHECK_PC(C_SETCOND_LOGICAL)
2977 #endif
2978 #ifndef OP_MOV
2979 #define OP_MOV \
2980 u32 res = value; \
2981 bus.reg[dest].I = res;
2982 #endif
2983 #ifndef OP_MOVS
2984 #define OP_MOVS OP_MOV C_CHECK_PC(C_SETCOND_LOGICAL)
2985 #endif
2986 #ifndef OP_BIC
2987 #define OP_BIC \
2988 u32 res = bus.reg[(opcode >> 16) & 0x0F].I & (~value); \
2989 bus.reg[dest].I = res;
2990 #endif
2991 #ifndef OP_BICS
2992 #define OP_BICS OP_BIC C_CHECK_PC(C_SETCOND_LOGICAL)
2993 #endif
2994 #ifndef OP_MVN
2995 #define OP_MVN \
2996 u32 res = ~value; \
2997 bus.reg[dest].I = res;
2998 #endif
2999 #ifndef OP_MVNS
3000 #define OP_MVNS OP_MVN C_CHECK_PC(C_SETCOND_LOGICAL)
3001 #endif
3002
3003 #ifndef SETCOND_NONE
3004 #define SETCOND_NONE /*nothing*/
3005 #endif
3006 #ifndef SETCOND_MUL
3007 #define SETCOND_MUL \
3008 N_FLAG = ((s32)bus.reg[dest].I < 0) ? true : false; \
3009 Z_FLAG = bus.reg[dest].I ? false : true;
3010 #endif
3011 #ifndef SETCOND_MULL
3012 #define SETCOND_MULL \
3013 N_FLAG = (bus.reg[dest].I & 0x80000000) ? true : false;\
3014 Z_FLAG = bus.reg[dest].I || bus.reg[acc].I ? false : true;
3015 #endif
3016
3017 #ifndef ROR_IMM_MSR
3018 #define ROR_IMM_MSR \
3019 u32 v = opcode & 0xff; \
3020 value = ((v << (32 - shift)) | (v >> shift));
3021 #endif
3022 #ifndef ROR_OFFSET
3023 #define ROR_OFFSET \
3024 offset = ((offset << (32 - shift)) | (offset >> shift));
3025 #endif
3026 #ifndef RRX_OFFSET
3027 #define RRX_OFFSET \
3028 offset = ((offset >> 1) | ((int)C_FLAG << 31));
3029 #endif
3030
3031 // ALU ops (except multiply) //////////////////////////////////////////////
3032
3033 // ALU_INIT: init code (ALU_INIT_C or ALU_INIT_NC)
3034 // GETVALUE: load value and shift/rotate (VALUE_XXX)
3035 // OP: ALU operation (OP_XXX)
3036 // MODECHANGE: MODECHANGE_NO or MODECHANGE_YES
3037 // ISREGSHIFT: 1 for insns of the form ...,Rn LSL/etc Rs; 0 otherwise
3038 // ALU_INIT, GETVALUE and OP are concatenated in order.
3039
3040 #define ALU_INSN(ALU_INIT, GETVALUE, OP, MODECHANGE, ISREGSHIFT) \
3041 ALU_INIT GETVALUE OP; \
3042 if ((opcode & 0x0000F000) != 0x0000F000) { \
3043 clockTicks = CLOCKTICKS_UPDATE_TYPE32 + ISREGSHIFT; \
3044 } else { \
3045 MODECHANGE; \
3046 if (armState) { \
3047 bus.reg[15].I &= 0xFFFFFFFC; \
3048 bus.armNextPC = bus.reg[15].I; \
3049 bus.reg[15].I += 4; \
3050 ARM_PREFETCH; \
3051 } else { \
3052 bus.reg[15].I &= 0xFFFFFFFE; \
3053 bus.armNextPC = bus.reg[15].I; \
3054 bus.reg[15].I += 2; \
3055 THUMB_PREFETCH; \
3056 } \
3057 clockTicks = CLOCKTICKS_UPDATE_TYPE32P + ISREGSHIFT; \
3058 }
3059
3060 #define MODECHANGE_NO /*nothing*/
3061 #define MODECHANGE_YES if(armMode != (bus.reg[17].I & 0x1f)) CPUSwitchMode(bus.reg[17].I & 0x1f, false, true);
3062
3063 #define DEFINE_ALU_INSN_C(CODE1, CODE2, OP, MODECHANGE) \
3064 static void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3065 static void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3066 static void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3067 static void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3068 static void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3069 static void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3070 static void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3071 static void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3072 static void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
3073 #define DEFINE_ALU_INSN_NC(CODE1, CODE2, OP, MODECHANGE) \
3074 static void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3075 static void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3076 static void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3077 static void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3078 static void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3079 static void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3080 static void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
3081 static void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
3082 static void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
3083
3084 // AND
3085 DEFINE_ALU_INSN_NC(00, 20, AND, NO)
3086 // ANDS
3087 DEFINE_ALU_INSN_C (01, 21, ANDS, YES)
3088
3089 // EOR
3090 DEFINE_ALU_INSN_NC(02, 22, EOR, NO)
3091 // EORS
3092 DEFINE_ALU_INSN_C (03, 23, EORS, YES)
3093
3094 // SUB
3095 DEFINE_ALU_INSN_NC(04, 24, SUB, NO)
3096 // SUBS
3097 DEFINE_ALU_INSN_NC(05, 25, SUBS, YES)
3098
3099 // RSB
3100 DEFINE_ALU_INSN_NC(06, 26, RSB, NO)
3101 // RSBS
3102 DEFINE_ALU_INSN_NC(07, 27, RSBS, YES)
3103
3104 // ADD
3105 DEFINE_ALU_INSN_NC(08, 28, ADD, NO)
3106 // ADDS
3107 DEFINE_ALU_INSN_NC(09, 29, ADDS, YES)
3108
3109 // ADC
3110 DEFINE_ALU_INSN_NC(0A, 2A, ADC, NO)
3111 // ADCS
3112 DEFINE_ALU_INSN_NC(0B, 2B, ADCS, YES)
3113
3114 // SBC
3115 DEFINE_ALU_INSN_NC(0C, 2C, SBC, NO)
3116 // SBCS
3117 DEFINE_ALU_INSN_NC(0D, 2D, SBCS, YES)
3118
3119 // RSC
3120 DEFINE_ALU_INSN_NC(0E, 2E, RSC, NO)
3121 // RSCS
3122 DEFINE_ALU_INSN_NC(0F, 2F, RSCS, YES)
3123
3124 // TST
3125 DEFINE_ALU_INSN_C (11, 31, TST, NO)
3126
3127 // TEQ
3128 DEFINE_ALU_INSN_C (13, 33, TEQ, NO)
3129
3130 // CMP
3131 DEFINE_ALU_INSN_NC(15, 35, CMP, NO)
3132
3133 // CMN
3134 DEFINE_ALU_INSN_NC(17, 37, CMN, NO)
3135
3136 // ORR
3137 DEFINE_ALU_INSN_NC(18, 38, ORR, NO)
3138 // ORRS
3139 DEFINE_ALU_INSN_C (19, 39, ORRS, YES)
3140
3141 // MOV
3142 DEFINE_ALU_INSN_NC(1A, 3A, MOV, NO)
3143 // MOVS
3144 DEFINE_ALU_INSN_C (1B, 3B, MOVS, YES)
3145
3146 // BIC
3147 DEFINE_ALU_INSN_NC(1C, 3C, BIC, NO)
3148 // BICS
3149 DEFINE_ALU_INSN_C (1D, 3D, BICS, YES)
3150
3151 // MVN
3152 DEFINE_ALU_INSN_NC(1E, 3E, MVN, NO)
3153 // MVNS
3154 DEFINE_ALU_INSN_C (1F, 3F, MVNS, YES)
3155
3156 // Multiply instructions //////////////////////////////////////////////////
3157
3158 // OP: OP_MUL, OP_MLA etc.
3159 // SETCOND: SETCOND_NONE, SETCOND_MUL, or SETCOND_MULL
3160 // CYCLES: base cycle count (1, 2, or 3)
3161 #define MUL_INSN(OP, SETCOND, CYCLES) \
3162 int mult = (opcode & 0x0F); \
3163 u32 rs = bus.reg[(opcode >> 8) & 0x0F].I; \
3164 int acc = (opcode >> 12) & 0x0F; /* or destLo */ \
3165 int dest = (opcode >> 16) & 0x0F; /* or destHi */ \
3166 OP; \
3167 SETCOND; \
3168 if ((s32)rs < 0) \
3169 rs = ~rs; \
3170 if ((rs & 0xFFFFFF00) == 0) \
3171 clockTicks += 0; \
3172 else if ((rs & 0xFFFF0000) == 0) \
3173 clockTicks += 1; \
3174 else if ((rs & 0xFF000000) == 0) \
3175 clockTicks += 2; \
3176 else \
3177 clockTicks += 3; \
3178 if (bus.busPrefetchCount == 0) \
3179 bus.busPrefetchCount = ((bus.busPrefetchCount+1)<<clockTicks) - 1; \
3180 clockTicks += CYCLES + 1 + codeTicksAccess(bus.armNextPC, BITS_32);
3181
3182 #define OP_MUL \
3183 bus.reg[dest].I = bus.reg[mult].I * rs;
3184 #define OP_MLA \
3185 bus.reg[dest].I = bus.reg[mult].I * rs + bus.reg[acc].I;
3186 #define OP_MULL(SIGN) \
3187 SIGN##64 res = (SIGN##64)(SIGN##32)bus.reg[mult].I \
3188 * (SIGN##64)(SIGN##32)rs; \
3189 bus.reg[acc].I = (u32)res; \
3190 bus.reg[dest].I = (u32)(res >> 32);
3191 #define OP_MLAL(SIGN) \
3192 SIGN##64 res = ((SIGN##64)bus.reg[dest].I<<32 | bus.reg[acc].I)\
3193 + ((SIGN##64)(SIGN##32)bus.reg[mult].I \
3194 * (SIGN##64)(SIGN##32)rs); \
3195 bus.reg[acc].I = (u32)res; \
3196 bus.reg[dest].I = (u32)(res >> 32);
3197 #define OP_UMULL OP_MULL(u)
3198 #define OP_UMLAL OP_MLAL(u)
3199 #define OP_SMULL OP_MULL(s)
3200 #define OP_SMLAL OP_MLAL(s)
3201
3202 // MUL Rd, Rm, Rs
arm009(u32 opcode)3203 static void arm009(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_NONE, 1); }
3204 // MULS Rd, Rm, Rs
arm019(u32 opcode)3205 static void arm019(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_MUL, 1); }
3206
3207 // MLA Rd, Rm, Rs, Rn
arm029(u32 opcode)3208 static void arm029(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_NONE, 2); }
3209 // MLAS Rd, Rm, Rs, Rn
arm039(u32 opcode)3210 static void arm039(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_MUL, 2); }
3211
3212 // UMULL RdLo, RdHi, Rn, Rs
arm089(u32 opcode)3213 static void arm089(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_NONE, 2); }
3214 // UMULLS RdLo, RdHi, Rn, Rs
arm099(u32 opcode)3215 static void arm099(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_MULL, 2); }
3216
3217 // UMLAL RdLo, RdHi, Rn, Rs
arm0A9(u32 opcode)3218 static void arm0A9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_NONE, 3); }
3219 // UMLALS RdLo, RdHi, Rn, Rs
arm0B9(u32 opcode)3220 static void arm0B9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_MULL, 3); }
3221
3222 // SMULL RdLo, RdHi, Rm, Rs
arm0C9(u32 opcode)3223 static void arm0C9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_NONE, 2); }
3224 // SMULLS RdLo, RdHi, Rm, Rs
arm0D9(u32 opcode)3225 static void arm0D9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_MULL, 2); }
3226
3227 // SMLAL RdLo, RdHi, Rm, Rs
arm0E9(u32 opcode)3228 static void arm0E9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_NONE, 3); }
3229 // SMLALS RdLo, RdHi, Rm, Rs
arm0F9(u32 opcode)3230 static void arm0F9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_MULL, 3); }
3231
3232 // Misc instructions //////////////////////////////////////////////////////
3233
3234 // SWP Rd, Rm, [Rn]
arm109(u32 opcode)3235 static void arm109(u32 opcode)
3236 {
3237 u32 address = bus.reg[(opcode >> 16) & 15].I;
3238 u32 temp = CPUReadMemory(address);
3239 CPUWriteMemory(address, bus.reg[opcode&15].I);
3240 bus.reg[(opcode >> 12) & 15].I = temp;
3241 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
3242 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
3243 clockTicks = 4 + (dataticks_value << 1) + codeTicksAccess(bus.armNextPC, BITS_32);
3244 }
3245
3246 // SWPB Rd, Rm, [Rn]
arm149(u32 opcode)3247 static void arm149(u32 opcode)
3248 {
3249 u32 address = bus.reg[(opcode >> 16) & 15].I;
3250 u32 temp = CPUReadByte(address);
3251 CPUWriteByte(address, bus.reg[opcode&15].B.B0);
3252 bus.reg[(opcode>>12)&15].I = temp;
3253 u32 dataticks_value = DATATICKS_ACCESS_32BIT(address);
3254 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
3255 clockTicks = 4 + (dataticks_value << 1) + codeTicksAccess(bus.armNextPC, BITS_32);
3256 }
3257
3258 // MRS Rd, CPSR
arm100(u32 opcode)3259 static void arm100(u32 opcode)
3260 {
3261 if ((opcode & 0x0FFF0FFF) == 0x010F0000)
3262 {
3263 CPU_UPDATE_CPSR();
3264 bus.reg[(opcode >> 12) & 0x0F].I = bus.reg[16].I;
3265 }
3266 else
3267 armUnknownInsn(opcode);
3268 }
3269
3270 // MRS Rd, SPSR
arm140(u32 opcode)3271 static void arm140(u32 opcode)
3272 {
3273 if ((opcode & 0x0FFF0FFF) == 0x014F0000)
3274 bus.reg[(opcode >> 12) & 0x0F].I = bus.reg[17].I;
3275 else
3276 armUnknownInsn(opcode);
3277 }
3278
3279 // MSR CPSR_fields, Rm
arm120(u32 opcode)3280 static void arm120(u32 opcode)
3281 {
3282 if ((opcode & 0x0FF0FFF0) == 0x0120F000)
3283 {
3284 CPU_UPDATE_CPSR();
3285 u32 value = bus.reg[opcode & 15].I;
3286 u32 newValue = bus.reg[16].I;
3287 if (armMode > 0x10) {
3288 if (opcode & 0x00010000)
3289 newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
3290 if (opcode & 0x00020000)
3291 newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
3292 if (opcode & 0x00040000)
3293 newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
3294 }
3295 if (opcode & 0x00080000)
3296 newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
3297 newValue |= 0x10;
3298 if(armMode != (newValue & 0x1F))
3299 CPUSwitchMode(newValue & 0x1F, false, true);
3300 bus.reg[16].I = newValue;
3301 CPUUpdateFlags(1);
3302 if (!armState) { // this should not be allowed, but it seems to work
3303 THUMB_PREFETCH;
3304 bus.reg[15].I = bus.armNextPC + 2;
3305 }
3306 }
3307 else
3308 armUnknownInsn(opcode);
3309 }
3310
3311 // MSR SPSR_fields, Rm
arm160(u32 opcode)3312 static void arm160(u32 opcode)
3313 {
3314 if ((opcode & 0x0FF0FFF0) == 0x0160F000)
3315 {
3316 u32 value = bus.reg[opcode & 15].I;
3317 if (armMode > 0x10 && armMode < 0x1F)
3318 {
3319 if (opcode & 0x00010000)
3320 bus.reg[17].I = (bus.reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
3321 if (opcode & 0x00020000)
3322 bus.reg[17].I = (bus.reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
3323 if (opcode & 0x00040000)
3324 bus.reg[17].I = (bus.reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
3325 if (opcode & 0x00080000)
3326 bus.reg[17].I = (bus.reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
3327 }
3328 }
3329 else
3330 armUnknownInsn(opcode);
3331 }
3332
3333 // MSR CPSR_fields, #
arm320(u32 opcode)3334 static void arm320(u32 opcode)
3335 {
3336 if ((opcode & 0x0FF0F000) == 0x0320F000)
3337 {
3338 CPU_UPDATE_CPSR();
3339 u32 value = opcode & 0xFF;
3340 int shift = (opcode & 0xF00) >> 7;
3341 if (shift) {
3342 ROR_IMM_MSR;
3343 }
3344 u32 newValue = bus.reg[16].I;
3345 if (armMode > 0x10) {
3346 if (opcode & 0x00010000)
3347 newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
3348 if (opcode & 0x00020000)
3349 newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
3350 if (opcode & 0x00040000)
3351 newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
3352 }
3353 if (opcode & 0x00080000)
3354 newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
3355
3356 newValue |= 0x10;
3357
3358 if(armMode != (newValue & 0x1F))
3359 CPUSwitchMode(newValue & 0x1F, false, true);
3360 bus.reg[16].I = newValue;
3361 CPUUpdateFlags(1);
3362 if (!armState) { // this should not be allowed, but it seems to work
3363 THUMB_PREFETCH;
3364 bus.reg[15].I = bus.armNextPC + 2;
3365 }
3366 }
3367 else
3368 armUnknownInsn(opcode);
3369 }
3370
3371 // MSR SPSR_fields, #
arm360(u32 opcode)3372 static void arm360(u32 opcode)
3373 {
3374 if ((opcode & 0x0FF0F000) == 0x0360F000) {
3375 if (armMode > 0x10 && armMode < 0x1F) {
3376 u32 value = opcode & 0xFF;
3377 int shift = (opcode & 0xF00) >> 7;
3378 if (shift) {
3379 ROR_IMM_MSR;
3380 }
3381 if (opcode & 0x00010000)
3382 bus.reg[17].I = (bus.reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
3383 if (opcode & 0x00020000)
3384 bus.reg[17].I = (bus.reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
3385 if (opcode & 0x00040000)
3386 bus.reg[17].I = (bus.reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
3387 if (opcode & 0x00080000)
3388 bus.reg[17].I = (bus.reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
3389 }
3390 }
3391 else
3392 armUnknownInsn(opcode);
3393 }
3394
3395 // BX Rm
arm121(u32 opcode)3396 static void arm121(u32 opcode)
3397 {
3398 if ((opcode & 0x0FFFFFF0) == 0x012FFF10) {
3399 int base = opcode & 0x0F;
3400 bus.busPrefetchCount = 0;
3401 armState = bus.reg[base].I & 1 ? false : true;
3402 if (armState) {
3403 bus.reg[15].I = bus.reg[base].I & 0xFFFFFFFC;
3404 bus.armNextPC = bus.reg[15].I;
3405 bus.reg[15].I += 4;
3406 ARM_PREFETCH;
3407 clockTicks = CLOCKTICKS_UPDATE_TYPE32P;
3408 } else {
3409 bus.reg[15].I = bus.reg[base].I & 0xFFFFFFFE;
3410 bus.armNextPC = bus.reg[15].I;
3411 bus.reg[15].I += 2;
3412 THUMB_PREFETCH;
3413 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
3414 }
3415 }
3416 else
3417 armUnknownInsn(opcode);
3418 }
3419
3420 // Load/store /////////////////////////////////////////////////////////////
3421
3422 #define OFFSET_IMM \
3423 int offset = opcode & 0xFFF;
3424 #define OFFSET_IMM8 \
3425 int offset = ((opcode & 0x0F) | ((opcode>>4) & 0xF0));
3426 #define OFFSET_REG \
3427 int offset = bus.reg[opcode & 15].I;
3428 #define OFFSET_LSL \
3429 int offset = bus.reg[opcode & 15].I << ((opcode>>7) & 31);
3430 #define OFFSET_LSR \
3431 int shift = (opcode >> 7) & 31; \
3432 int offset = shift ? bus.reg[opcode & 15].I >> shift : 0;
3433 #define OFFSET_ASR \
3434 int shift = (opcode >> 7) & 31; \
3435 int offset; \
3436 if (shift) \
3437 offset = (int)((s32)bus.reg[opcode & 15].I >> shift);\
3438 else if (bus.reg[opcode & 15].I & 0x80000000) \
3439 offset = 0xFFFFFFFF; \
3440 else \
3441 offset = 0;
3442 #define OFFSET_ROR \
3443 int shift = (opcode >> 7) & 31; \
3444 u32 offset = bus.reg[opcode & 15].I; \
3445 if (shift) { \
3446 ROR_OFFSET; \
3447 } else { \
3448 RRX_OFFSET; \
3449 }
3450
3451 #define ADDRESS_POST (bus.reg[base].I)
3452 #define ADDRESS_PREDEC (bus.reg[base].I - offset)
3453 #define ADDRESS_PREINC (bus.reg[base].I + offset)
3454
3455 #define OP_STR CPUWriteMemory(address, bus.reg[dest].I)
3456 #define OP_STRH CPUWriteHalfWord(address, bus.reg[dest].W.W0)
3457 #define OP_STRB CPUWriteByte(address, bus.reg[dest].B.B0)
3458 #define OP_LDR bus.reg[dest].I = CPUReadMemory(address)
3459 #define OP_LDRH bus.reg[dest].I = CPUReadHalfWord(address)
3460 #define OP_LDRB bus.reg[dest].I = CPUReadByte(address)
3461 #define OP_LDRSH bus.reg[dest].I = (s16)CPUReadHalfWordSigned(address)
3462 #define OP_LDRSB bus.reg[dest].I = (s8)CPUReadByte(address)
3463
3464 #define WRITEBACK_NONE /*nothing*/
3465 #define WRITEBACK_PRE bus.reg[base].I = address
3466 #define WRITEBACK_POSTDEC bus.reg[base].I = address - offset
3467 #define WRITEBACK_POSTINC bus.reg[base].I = address + offset
3468
3469 #define LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS) \
3470 if (bus.busPrefetchCount == 0) \
3471 bus.busPrefetch = bus.busPrefetchEnable; \
3472 int dest = (opcode >> 12) & 15; \
3473 int base = (opcode >> 16) & 15; \
3474 CALC_OFFSET; \
3475 u32 address = CALC_ADDRESS;
3476
3477 #define STR(CALC_OFFSET, CALC_ADDRESS, STORE_DATA, WRITEBACK1, WRITEBACK2, SIZE) \
3478 LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
3479 WRITEBACK1; \
3480 STORE_DATA; \
3481 WRITEBACK2; \
3482 int dataticks_val; \
3483 if(SIZE == 32) \
3484 dataticks_val = DATATICKS_ACCESS_32BIT(address); \
3485 else \
3486 dataticks_val = DATATICKS_ACCESS_16BIT(address); \
3487 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \
3488 clockTicks = 2 + dataticks_val + codeTicksAccess(bus.armNextPC, BITS_32);
3489
3490 #define LDR(CALC_OFFSET, CALC_ADDRESS, LOAD_DATA, WRITEBACK, SIZE) \
3491 LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
3492 LOAD_DATA; \
3493 if (dest != base) \
3494 { \
3495 WRITEBACK; \
3496 } \
3497 clockTicks = 0; \
3498 int dataticks_value; \
3499 if (dest == 15) { \
3500 bus.reg[15].I &= 0xFFFFFFFC; \
3501 bus.armNextPC = bus.reg[15].I; \
3502 bus.reg[15].I += 4; \
3503 ARM_PREFETCH; \
3504 dataticks_value = DATATICKS_ACCESS_32BIT_SEQ(address); \
3505 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
3506 clockTicks += 2 + (dataticks_value << 1);\
3507 } \
3508 if(SIZE == 32) \
3509 dataticks_value = DATATICKS_ACCESS_32BIT(address); \
3510 else \
3511 dataticks_value = DATATICKS_ACCESS_16BIT(address); \
3512 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
3513 clockTicks += 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_32);
3514 #define STR_POSTDEC(CALC_OFFSET, STORE_DATA, SIZE) \
3515 STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTDEC, SIZE)
3516 #define STR_POSTINC(CALC_OFFSET, STORE_DATA, SIZE) \
3517 STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTINC, SIZE)
3518 #define STR_PREDEC(CALC_OFFSET, STORE_DATA, SIZE) \
3519 STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
3520 #define STR_PREDEC_WB(CALC_OFFSET, STORE_DATA, SIZE) \
3521 STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
3522 #define STR_PREINC(CALC_OFFSET, STORE_DATA, SIZE) \
3523 STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
3524 #define STR_PREINC_WB(CALC_OFFSET, STORE_DATA, SIZE) \
3525 STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
3526 #define LDR_POSTDEC(CALC_OFFSET, LOAD_DATA, SIZE) \
3527 LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTDEC, SIZE)
3528 #define LDR_POSTINC(CALC_OFFSET, LOAD_DATA, SIZE) \
3529 LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTINC, SIZE)
3530 #define LDR_PREDEC(CALC_OFFSET, LOAD_DATA, SIZE) \
3531 LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_NONE, SIZE)
3532 #define LDR_PREDEC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \
3533 LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_PRE, SIZE)
3534 #define LDR_PREINC(CALC_OFFSET, LOAD_DATA, SIZE) \
3535 LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_NONE, SIZE)
3536 #define LDR_PREINC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \
3537 LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_PRE, SIZE)
3538
3539 // STRH Rd, [Rn], -Rm
arm00B(u32 opcode)3540 static void arm00B(u32 opcode) { STR_POSTDEC(OFFSET_REG, OP_STRH, 16); }
3541 // STRH Rd, [Rn], #-offset
arm04B(u32 opcode)3542 static void arm04B(u32 opcode) { STR_POSTDEC(OFFSET_IMM8, OP_STRH, 16); }
3543 // STRH Rd, [Rn], Rm
arm08B(u32 opcode)3544 static void arm08B(u32 opcode) { STR_POSTINC(OFFSET_REG, OP_STRH, 16); }
3545 // STRH Rd, [Rn], #offset
arm0CB(u32 opcode)3546 static void arm0CB(u32 opcode) { STR_POSTINC(OFFSET_IMM8, OP_STRH, 16); }
3547 // STRH Rd, [Rn, -Rm]
arm10B(u32 opcode)3548 static void arm10B(u32 opcode) { STR_PREDEC(OFFSET_REG, OP_STRH, 16); }
3549 // STRH Rd, [Rn, -Rm]!
arm12B(u32 opcode)3550 static void arm12B(u32 opcode) { STR_PREDEC_WB(OFFSET_REG, OP_STRH, 16); }
3551 // STRH Rd, [Rn, -#offset]
arm14B(u32 opcode)3552 static void arm14B(u32 opcode) { STR_PREDEC(OFFSET_IMM8, OP_STRH, 16); }
3553 // STRH Rd, [Rn, -#offset]!
arm16B(u32 opcode)3554 static void arm16B(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM8, OP_STRH, 16); }
3555 // STRH Rd, [Rn, Rm]
arm18B(u32 opcode)3556 static void arm18B(u32 opcode) { STR_PREINC(OFFSET_REG, OP_STRH, 16); }
3557 // STRH Rd, [Rn, Rm]!
arm1AB(u32 opcode)3558 static void arm1AB(u32 opcode) { STR_PREINC_WB(OFFSET_REG, OP_STRH, 16); }
3559 // STRH Rd, [Rn, #offset]
arm1CB(u32 opcode)3560 static void arm1CB(u32 opcode) { STR_PREINC(OFFSET_IMM8, OP_STRH, 16); }
3561 // STRH Rd, [Rn, #offset]!
arm1EB(u32 opcode)3562 static void arm1EB(u32 opcode) { STR_PREINC_WB(OFFSET_IMM8, OP_STRH, 16); }
3563
3564 // LDRH Rd, [Rn], -Rm
arm01B(u32 opcode)3565 static void arm01B(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRH, 16); }
3566 // LDRH Rd, [Rn], #-offset
arm05B(u32 opcode)3567 static void arm05B(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRH, 16); }
3568 // LDRH Rd, [Rn], Rm
arm09B(u32 opcode)3569 static void arm09B(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRH, 16); }
3570 // LDRH Rd, [Rn], #offset
arm0DB(u32 opcode)3571 static void arm0DB(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRH, 16); }
3572 // LDRH Rd, [Rn, -Rm]
arm11B(u32 opcode)3573 static void arm11B(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRH, 16); }
3574 // LDRH Rd, [Rn, -Rm]!
arm13B(u32 opcode)3575 static void arm13B(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRH, 16); }
3576 // LDRH Rd, [Rn, -#offset]
arm15B(u32 opcode)3577 static void arm15B(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRH, 16); }
3578 // LDRH Rd, [Rn, -#offset]!
arm17B(u32 opcode)3579 static void arm17B(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRH, 16); }
3580 // LDRH Rd, [Rn, Rm]
arm19B(u32 opcode)3581 static void arm19B(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRH, 16); }
3582 // LDRH Rd, [Rn, Rm]!
arm1BB(u32 opcode)3583 static void arm1BB(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRH, 16); }
3584 // LDRH Rd, [Rn, #offset]
arm1DB(u32 opcode)3585 static void arm1DB(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRH, 16); }
3586 // LDRH Rd, [Rn, #offset]!
arm1FB(u32 opcode)3587 static void arm1FB(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRH, 16); }
3588
3589 // LDRSB Rd, [Rn], -Rm
arm01D(u32 opcode)3590 static void arm01D(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSB, 16); }
3591 // LDRSB Rd, [Rn], #-offset
arm05D(u32 opcode)3592 static void arm05D(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSB, 16); }
3593 // LDRSB Rd, [Rn], Rm
arm09D(u32 opcode)3594 static void arm09D(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSB, 16); }
3595 // LDRSB Rd, [Rn], #offset
arm0DD(u32 opcode)3596 static void arm0DD(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSB, 16); }
3597 // LDRSB Rd, [Rn, -Rm]
arm11D(u32 opcode)3598 static void arm11D(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSB, 16); }
3599 // LDRSB Rd, [Rn, -Rm]!
arm13D(u32 opcode)3600 static void arm13D(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSB, 16); }
3601 // LDRSB Rd, [Rn, -#offset]
arm15D(u32 opcode)3602 static void arm15D(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSB, 16); }
3603 // LDRSB Rd, [Rn, -#offset]!
arm17D(u32 opcode)3604 static void arm17D(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSB, 16); }
3605 // LDRSB Rd, [Rn, Rm]
arm19D(u32 opcode)3606 static void arm19D(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSB, 16); }
3607 // LDRSB Rd, [Rn, Rm]!
arm1BD(u32 opcode)3608 static void arm1BD(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSB, 16); }
3609 // LDRSB Rd, [Rn, #offset]
arm1DD(u32 opcode)3610 static void arm1DD(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSB, 16); }
3611 // LDRSB Rd, [Rn, #offset]!
arm1FD(u32 opcode)3612 static void arm1FD(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSB, 16); }
3613
3614 // LDRSH Rd, [Rn], -Rm
arm01F(u32 opcode)3615 static void arm01F(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSH, 16); }
3616 // LDRSH Rd, [Rn], #-offset
arm05F(u32 opcode)3617 static void arm05F(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSH, 16); }
3618 // LDRSH Rd, [Rn], Rm
arm09F(u32 opcode)3619 static void arm09F(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSH, 16); }
3620 // LDRSH Rd, [Rn], #offset
arm0DF(u32 opcode)3621 static void arm0DF(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSH, 16); }
3622 // LDRSH Rd, [Rn, -Rm]
arm11F(u32 opcode)3623 static void arm11F(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSH, 16); }
3624 // LDRSH Rd, [Rn, -Rm]!
arm13F(u32 opcode)3625 static void arm13F(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSH, 16); }
3626 // LDRSH Rd, [Rn, -#offset]
arm15F(u32 opcode)3627 static void arm15F(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSH, 16); }
3628 // LDRSH Rd, [Rn, -#offset]!
arm17F(u32 opcode)3629 static void arm17F(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSH, 16); }
3630 // LDRSH Rd, [Rn, Rm]
arm19F(u32 opcode)3631 static void arm19F(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSH, 16); }
3632 // LDRSH Rd, [Rn, Rm]!
arm1BF(u32 opcode)3633 static void arm1BF(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSH, 16); }
3634 // LDRSH Rd, [Rn, #offset]
arm1DF(u32 opcode)3635 static void arm1DF(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSH, 16); }
3636 // LDRSH Rd, [Rn, #offset]!
arm1FF(u32 opcode)3637 static void arm1FF(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSH, 16); }
3638
3639 // STR[T] Rd, [Rn], -#
3640 // Note: STR and STRT do the same thing on the GBA (likewise for LDR/LDRT etc)
arm400(u32 opcode)3641 static void arm400(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STR, 32); }
3642 // LDR[T] Rd, [Rn], -#
arm410(u32 opcode)3643 static void arm410(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDR, 32); }
3644 // STRB[T] Rd, [Rn], -#
arm440(u32 opcode)3645 static void arm440(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STRB, 16); }
3646 // LDRB[T] Rd, [Rn], -#
arm450(u32 opcode)3647 static void arm450(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDRB, 16); }
3648 // STR[T] Rd, [Rn], #
arm480(u32 opcode)3649 static void arm480(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STR, 32); }
3650 // LDR Rd, [Rn], #
arm490(u32 opcode)3651 static void arm490(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDR, 32); }
3652 // STRB[T] Rd, [Rn], #
arm4C0(u32 opcode)3653 static void arm4C0(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STRB, 16); }
3654 // LDRB[T] Rd, [Rn], #
arm4D0(u32 opcode)3655 static void arm4D0(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDRB, 16); }
3656 // STR Rd, [Rn, -#]
arm500(u32 opcode)3657 static void arm500(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STR, 32); }
3658 // LDR Rd, [Rn, -#]
arm510(u32 opcode)3659 static void arm510(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDR, 32); }
3660 // STR Rd, [Rn, -#]!
arm520(u32 opcode)3661 static void arm520(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STR, 32); }
3662 // LDR Rd, [Rn, -#]!
arm530(u32 opcode)3663 static void arm530(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDR, 32); }
3664 // STRB Rd, [Rn, -#]
arm540(u32 opcode)3665 static void arm540(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STRB, 16); }
3666 // LDRB Rd, [Rn, -#]
arm550(u32 opcode)3667 static void arm550(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDRB, 16); }
3668 // STRB Rd, [Rn, -#]!
arm560(u32 opcode)3669 static void arm560(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STRB, 16); }
3670 // LDRB Rd, [Rn, -#]!
arm570(u32 opcode)3671 static void arm570(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDRB, 16); }
3672 // STR Rd, [Rn, #]
arm580(u32 opcode)3673 static void arm580(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STR, 32); }
3674 // LDR Rd, [Rn, #]
arm590(u32 opcode)3675 static void arm590(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDR, 32); }
3676 // STR Rd, [Rn, #]!
arm5A0(u32 opcode)3677 static void arm5A0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STR, 32); }
3678 // LDR Rd, [Rn, #]!
arm5B0(u32 opcode)3679 static void arm5B0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDR, 32); }
3680 // STRB Rd, [Rn, #]
arm5C0(u32 opcode)3681 static void arm5C0(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STRB, 16); }
3682 // LDRB Rd, [Rn, #]
arm5D0(u32 opcode)3683 static void arm5D0(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDRB, 16); }
3684 // STRB Rd, [Rn, #]!
arm5E0(u32 opcode)3685 static void arm5E0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STRB, 16); }
3686 // LDRB Rd, [Rn, #]!
arm5F0(u32 opcode)3687 static void arm5F0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDRB, 16); }
3688
3689 // STR[T] Rd, [Rn], -Rm, LSL #
arm600(u32 opcode)3690 static void arm600(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STR, 32); }
3691 // STR[T] Rd, [Rn], -Rm, LSR #
arm602(u32 opcode)3692 static void arm602(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STR, 32); }
3693 // STR[T] Rd, [Rn], -Rm, ASR #
arm604(u32 opcode)3694 static void arm604(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STR, 32); }
3695 // STR[T] Rd, [Rn], -Rm, ROR #
arm606(u32 opcode)3696 static void arm606(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STR, 32); }
3697 // LDR[T] Rd, [Rn], -Rm, LSL #
arm610(u32 opcode)3698 static void arm610(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDR, 32); }
3699 // LDR[T] Rd, [Rn], -Rm, LSR #
arm612(u32 opcode)3700 static void arm612(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDR, 32); }
3701 // LDR[T] Rd, [Rn], -Rm, ASR #
arm614(u32 opcode)3702 static void arm614(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDR, 32); }
3703 // LDR[T] Rd, [Rn], -Rm, ROR #
arm616(u32 opcode)3704 static void arm616(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDR, 32); }
3705 // STRB[T] Rd, [Rn], -Rm, LSL #
arm640(u32 opcode)3706 static void arm640(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STRB, 16); }
3707 // STRB[T] Rd, [Rn], -Rm, LSR #
arm642(u32 opcode)3708 static void arm642(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STRB, 16); }
3709 // STRB[T] Rd, [Rn], -Rm, ASR #
arm644(u32 opcode)3710 static void arm644(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STRB, 16); }
3711 // STRB[T] Rd, [Rn], -Rm, ROR #
arm646(u32 opcode)3712 static void arm646(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STRB, 16); }
3713 // LDRB[T] Rd, [Rn], -Rm, LSL #
arm650(u32 opcode)3714 static void arm650(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDRB, 16); }
3715 // LDRB[T] Rd, [Rn], -Rm, LSR #
arm652(u32 opcode)3716 static void arm652(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDRB, 16); }
3717 // LDRB[T] Rd, [Rn], -Rm, ASR #
arm654(u32 opcode)3718 static void arm654(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDRB, 16); }
3719 // LDRB Rd, [Rn], -Rm, ROR #
arm656(u32 opcode)3720 static void arm656(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDRB, 16); }
3721 // STR[T] Rd, [Rn], Rm, LSL #
arm680(u32 opcode)3722 static void arm680(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STR, 32); }
3723 // STR[T] Rd, [Rn], Rm, LSR #
arm682(u32 opcode)3724 static void arm682(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STR, 32); }
3725 // STR[T] Rd, [Rn], Rm, ASR #
arm684(u32 opcode)3726 static void arm684(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STR, 32); }
3727 // STR[T] Rd, [Rn], Rm, ROR #
arm686(u32 opcode)3728 static void arm686(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STR, 32); }
3729 // LDR[T] Rd, [Rn], Rm, LSL #
arm690(u32 opcode)3730 static void arm690(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDR, 32); }
3731 // LDR[T] Rd, [Rn], Rm, LSR #
arm692(u32 opcode)3732 static void arm692(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDR, 32); }
3733 // LDR[T] Rd, [Rn], Rm, ASR #
arm694(u32 opcode)3734 static void arm694(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDR, 32); }
3735 // LDR[T] Rd, [Rn], Rm, ROR #
arm696(u32 opcode)3736 static void arm696(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDR, 32); }
3737 // STRB[T] Rd, [Rn], Rm, LSL #
arm6C0(u32 opcode)3738 static void arm6C0(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STRB, 16); }
3739 // STRB[T] Rd, [Rn], Rm, LSR #
arm6C2(u32 opcode)3740 static void arm6C2(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STRB, 16); }
3741 // STRB[T] Rd, [Rn], Rm, ASR #
arm6C4(u32 opcode)3742 static void arm6C4(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STRB, 16); }
3743 // STRB[T] Rd, [Rn], Rm, ROR #
arm6C6(u32 opcode)3744 static void arm6C6(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STRB, 16); }
3745 // LDRB[T] Rd, [Rn], Rm, LSL #
arm6D0(u32 opcode)3746 static void arm6D0(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDRB, 16); }
3747 // LDRB[T] Rd, [Rn], Rm, LSR #
arm6D2(u32 opcode)3748 static void arm6D2(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDRB, 16); }
3749 // LDRB[T] Rd, [Rn], Rm, ASR #
arm6D4(u32 opcode)3750 static void arm6D4(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDRB, 16); }
3751 // LDRB[T] Rd, [Rn], Rm, ROR #
arm6D6(u32 opcode)3752 static void arm6D6(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDRB, 16); }
3753 // STR Rd, [Rn, -Rm, LSL #]
arm700(u32 opcode)3754 static void arm700(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STR, 32); }
3755 // STR Rd, [Rn, -Rm, LSR #]
arm702(u32 opcode)3756 static void arm702(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STR, 32); }
3757 // STR Rd, [Rn, -Rm, ASR #]
arm704(u32 opcode)3758 static void arm704(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STR, 32); }
3759 // STR Rd, [Rn, -Rm, ROR #]
arm706(u32 opcode)3760 static void arm706(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STR, 32); }
3761 // LDR Rd, [Rn, -Rm, LSL #]
arm710(u32 opcode)3762 static void arm710(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDR, 32); }
3763 // LDR Rd, [Rn, -Rm, LSR #]
arm712(u32 opcode)3764 static void arm712(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDR, 32); }
3765 // LDR Rd, [Rn, -Rm, ASR #]
arm714(u32 opcode)3766 static void arm714(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDR, 32); }
3767 // LDR Rd, [Rn, -Rm, ROR #]
arm716(u32 opcode)3768 static void arm716(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDR, 32); }
3769 // STR Rd, [Rn, -Rm, LSL #]!
arm720(u32 opcode)3770 static void arm720(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STR, 32); }
3771 // STR Rd, [Rn, -Rm, LSR #]!
arm722(u32 opcode)3772 static void arm722(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STR, 32); }
3773 // STR Rd, [Rn, -Rm, ASR #]!
arm724(u32 opcode)3774 static void arm724(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STR, 32); }
3775 // STR Rd, [Rn, -Rm, ROR #]!
arm726(u32 opcode)3776 static void arm726(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STR, 32); }
3777 // LDR Rd, [Rn, -Rm, LSL #]!
arm730(u32 opcode)3778 static void arm730(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDR, 32); }
3779 // LDR Rd, [Rn, -Rm, LSR #]!
arm732(u32 opcode)3780 static void arm732(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDR, 32); }
3781 // LDR Rd, [Rn, -Rm, ASR #]!
arm734(u32 opcode)3782 static void arm734(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDR, 32); }
3783 // LDR Rd, [Rn, -Rm, ROR #]!
arm736(u32 opcode)3784 static void arm736(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDR, 32); }
3785 // STRB Rd, [Rn, -Rm, LSL #]
arm740(u32 opcode)3786 static void arm740(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STRB, 16); }
3787 // STRB Rd, [Rn, -Rm, LSR #]
arm742(u32 opcode)3788 static void arm742(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STRB, 16); }
3789 // STRB Rd, [Rn, -Rm, ASR #]
arm744(u32 opcode)3790 static void arm744(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STRB, 16); }
3791 // STRB Rd, [Rn, -Rm, ROR #]
arm746(u32 opcode)3792 static void arm746(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STRB, 16); }
3793 // LDRB Rd, [Rn, -Rm, LSL #]
arm750(u32 opcode)3794 static void arm750(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDRB, 16); }
3795 // LDRB Rd, [Rn, -Rm, LSR #]
arm752(u32 opcode)3796 static void arm752(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDRB, 16); }
3797 // LDRB Rd, [Rn, -Rm, ASR #]
arm754(u32 opcode)3798 static void arm754(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDRB, 16); }
3799 // LDRB Rd, [Rn, -Rm, ROR #]
arm756(u32 opcode)3800 static void arm756(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDRB, 16); }
3801 // STRB Rd, [Rn, -Rm, LSL #]!
arm760(u32 opcode)3802 static void arm760(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STRB, 16); }
3803 // STRB Rd, [Rn, -Rm, LSR #]!
arm762(u32 opcode)3804 static void arm762(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STRB, 16); }
3805 // STRB Rd, [Rn, -Rm, ASR #]!
arm764(u32 opcode)3806 static void arm764(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STRB, 16); }
3807 // STRB Rd, [Rn, -Rm, ROR #]!
arm766(u32 opcode)3808 static void arm766(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STRB, 16); }
3809 // LDRB Rd, [Rn, -Rm, LSL #]!
arm770(u32 opcode)3810 static void arm770(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDRB, 16); }
3811 // LDRB Rd, [Rn, -Rm, LSR #]!
arm772(u32 opcode)3812 static void arm772(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDRB, 16); }
3813 // LDRB Rd, [Rn, -Rm, ASR #]!
arm774(u32 opcode)3814 static void arm774(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDRB, 16); }
3815 // LDRB Rd, [Rn, -Rm, ROR #]!
arm776(u32 opcode)3816 static void arm776(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDRB, 16); }
3817 // STR Rd, [Rn, Rm, LSL #]
arm780(u32 opcode)3818 static void arm780(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STR, 32); }
3819 // STR Rd, [Rn, Rm, LSR #]
arm782(u32 opcode)3820 static void arm782(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STR, 32); }
3821 // STR Rd, [Rn, Rm, ASR #]
arm784(u32 opcode)3822 static void arm784(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STR, 32); }
3823 // STR Rd, [Rn, Rm, ROR #]
arm786(u32 opcode)3824 static void arm786(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STR, 32); }
3825 // LDR Rd, [Rn, Rm, LSL #]
arm790(u32 opcode)3826 static void arm790(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDR, 32); }
3827 // LDR Rd, [Rn, Rm, LSR #]
arm792(u32 opcode)3828 static void arm792(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDR, 32); }
3829 // LDR Rd, [Rn, Rm, ASR #]
arm794(u32 opcode)3830 static void arm794(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDR, 32); }
3831 // LDR Rd, [Rn, Rm, ROR #]
arm796(u32 opcode)3832 static void arm796(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDR, 32); }
3833 // STR Rd, [Rn, Rm, LSL #]!
arm7A0(u32 opcode)3834 static void arm7A0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STR, 32); }
3835 // STR Rd, [Rn, Rm, LSR #]!
arm7A2(u32 opcode)3836 static void arm7A2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STR, 32); }
3837 // STR Rd, [Rn, Rm, ASR #]!
arm7A4(u32 opcode)3838 static void arm7A4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STR, 32); }
3839 // STR Rd, [Rn, Rm, ROR #]!
arm7A6(u32 opcode)3840 static void arm7A6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STR, 32); }
3841 // LDR Rd, [Rn, Rm, LSL #]!
arm7B0(u32 opcode)3842 static void arm7B0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDR, 32); }
3843 // LDR Rd, [Rn, Rm, LSR #]!
arm7B2(u32 opcode)3844 static void arm7B2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDR, 32); }
3845 // LDR Rd, [Rn, Rm, ASR #]!
arm7B4(u32 opcode)3846 static void arm7B4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDR, 32); }
3847 // LDR Rd, [Rn, Rm, ROR #]!
arm7B6(u32 opcode)3848 static void arm7B6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDR, 32); }
3849 // STRB Rd, [Rn, Rm, LSL #]
arm7C0(u32 opcode)3850 static void arm7C0(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STRB, 16); }
3851 // STRB Rd, [Rn, Rm, LSR #]
arm7C2(u32 opcode)3852 static void arm7C2(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STRB, 16); }
3853 // STRB Rd, [Rn, Rm, ASR #]
arm7C4(u32 opcode)3854 static void arm7C4(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STRB, 16); }
3855 // STRB Rd, [Rn, Rm, ROR #]
arm7C6(u32 opcode)3856 static void arm7C6(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STRB, 16); }
3857 // LDRB Rd, [Rn, Rm, LSL #]
arm7D0(u32 opcode)3858 static void arm7D0(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDRB, 16); }
3859 // LDRB Rd, [Rn, Rm, LSR #]
arm7D2(u32 opcode)3860 static void arm7D2(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDRB, 16); }
3861 // LDRB Rd, [Rn, Rm, ASR #]
arm7D4(u32 opcode)3862 static void arm7D4(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDRB, 16); }
3863 // LDRB Rd, [Rn, Rm, ROR #]
arm7D6(u32 opcode)3864 static void arm7D6(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDRB, 16); }
3865 // STRB Rd, [Rn, Rm, LSL #]!
arm7E0(u32 opcode)3866 static void arm7E0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STRB, 16); }
3867 // STRB Rd, [Rn, Rm, LSR #]!
arm7E2(u32 opcode)3868 static void arm7E2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STRB, 16); }
3869 // STRB Rd, [Rn, Rm, ASR #]!
arm7E4(u32 opcode)3870 static void arm7E4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STRB, 16); }
3871 // STRB Rd, [Rn, Rm, ROR #]!
arm7E6(u32 opcode)3872 static void arm7E6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STRB, 16); }
3873 // LDRB Rd, [Rn, Rm, LSL #]!
arm7F0(u32 opcode)3874 static void arm7F0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDRB, 16); }
3875 // LDRB Rd, [Rn, Rm, LSR #]!
arm7F2(u32 opcode)3876 static void arm7F2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDRB, 16); }
3877 // LDRB Rd, [Rn, Rm, ASR #]!
arm7F4(u32 opcode)3878 static void arm7F4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDRB, 16); }
3879 // LDRB Rd, [Rn, Rm, ROR #]!
arm7F6(u32 opcode)3880 static void arm7F6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDRB, 16); }
3881
3882 // STM/LDM ////////////////////////////////////////////////////////////////
3883
3884 #define STM_REG(bit,num) \
3885 if (opcode & (1U<<(bit))) { \
3886 CPUWriteMemory(address, bus.reg[(num)].I); \
3887 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
3888 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
3889 clockTicks += 1 + dataticks_value; \
3890 count++; \
3891 address += 4; \
3892 }
3893 #define STMW_REG(bit,num) \
3894 if (opcode & (1U<<(bit))) { \
3895 CPUWriteMemory(address, bus.reg[(num)].I); \
3896 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
3897 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
3898 clockTicks += 1 + dataticks_value; \
3899 bus.reg[base].I = temp; \
3900 count++; \
3901 address += 4; \
3902 }
3903 #define LDM_REG(bit,num) \
3904 if (opcode & (1U<<(bit))) { \
3905 int dataticks_value; \
3906 bus.reg[(num)].I = CPUReadMemory(address); \
3907 dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
3908 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
3909 clockTicks += 1 + dataticks_value; \
3910 count++; \
3911 address += 4; \
3912 }
3913 #define STM_LOW(STORE_REG) \
3914 STORE_REG(0, 0); \
3915 STORE_REG(1, 1); \
3916 STORE_REG(2, 2); \
3917 STORE_REG(3, 3); \
3918 STORE_REG(4, 4); \
3919 STORE_REG(5, 5); \
3920 STORE_REG(6, 6); \
3921 STORE_REG(7, 7);
3922 #define STM_HIGH(STORE_REG) \
3923 STORE_REG(8, 8); \
3924 STORE_REG(9, 9); \
3925 STORE_REG(10, 10); \
3926 STORE_REG(11, 11); \
3927 STORE_REG(12, 12); \
3928 STORE_REG(13, 13); \
3929 STORE_REG(14, 14);
3930 #define STM_HIGH_2(STORE_REG) \
3931 if (armMode == 0x11) { \
3932 STORE_REG(8, R8_FIQ); \
3933 STORE_REG(9, R9_FIQ); \
3934 STORE_REG(10, R10_FIQ); \
3935 STORE_REG(11, R11_FIQ); \
3936 STORE_REG(12, R12_FIQ); \
3937 } else { \
3938 STORE_REG(8, 8); \
3939 STORE_REG(9, 9); \
3940 STORE_REG(10, 10); \
3941 STORE_REG(11, 11); \
3942 STORE_REG(12, 12); \
3943 } \
3944 if (armMode != 0x10 && armMode != 0x1F) { \
3945 STORE_REG(13, R13_USR); \
3946 STORE_REG(14, R14_USR); \
3947 } else { \
3948 STORE_REG(13, 13); \
3949 STORE_REG(14, 14); \
3950 }
3951 #define STM_PC \
3952 if (opcode & (1U<<15)) { \
3953 CPUWriteMemory(address, bus.reg[15].I+4); \
3954 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
3955 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
3956 clockTicks += 1 + dataticks_value; \
3957 count++; \
3958 }
3959 #define STMW_PC \
3960 if (opcode & (1U<<15)) { \
3961 CPUWriteMemory(address, bus.reg[15].I+4); \
3962 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
3963 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
3964 clockTicks += 1 + dataticks_value; \
3965 bus.reg[base].I = temp; \
3966 count++; \
3967 }
3968 #define LDM_LOW \
3969 LDM_REG(0, 0); \
3970 LDM_REG(1, 1); \
3971 LDM_REG(2, 2); \
3972 LDM_REG(3, 3); \
3973 LDM_REG(4, 4); \
3974 LDM_REG(5, 5); \
3975 LDM_REG(6, 6); \
3976 LDM_REG(7, 7);
3977 #define LDM_HIGH \
3978 LDM_REG(8, 8); \
3979 LDM_REG(9, 9); \
3980 LDM_REG(10, 10); \
3981 LDM_REG(11, 11); \
3982 LDM_REG(12, 12); \
3983 LDM_REG(13, 13); \
3984 LDM_REG(14, 14);
3985 #define LDM_HIGH_2 \
3986 if (armMode == 0x11) { \
3987 LDM_REG(8, R8_FIQ); \
3988 LDM_REG(9, R9_FIQ); \
3989 LDM_REG(10, R10_FIQ); \
3990 LDM_REG(11, R11_FIQ); \
3991 LDM_REG(12, R12_FIQ); \
3992 } else { \
3993 LDM_REG(8, 8); \
3994 LDM_REG(9, 9); \
3995 LDM_REG(10, 10); \
3996 LDM_REG(11, 11); \
3997 LDM_REG(12, 12); \
3998 } \
3999 if (armMode != 0x10 && armMode != 0x1F) { \
4000 LDM_REG(13, R13_USR); \
4001 LDM_REG(14, R14_USR); \
4002 } else { \
4003 LDM_REG(13, 13); \
4004 LDM_REG(14, 14); \
4005 }
4006 #define STM_ALL \
4007 STM_LOW(STM_REG); \
4008 STM_HIGH(STM_REG); \
4009 STM_PC;
4010 #define STMW_ALL \
4011 STM_LOW(STMW_REG); \
4012 STM_HIGH(STMW_REG); \
4013 STMW_PC;
4014 #define LDM_ALL \
4015 LDM_LOW; \
4016 LDM_HIGH; \
4017 if (opcode & (1U<<15)) { \
4018 bus.reg[15].I = CPUReadMemory(address); \
4019 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
4020 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4021 clockTicks += 1 + dataticks_value; \
4022 count++; \
4023 } \
4024 if (opcode & (1U<<15)) { \
4025 bus.armNextPC = bus.reg[15].I; \
4026 bus.reg[15].I += 4; \
4027 ARM_PREFETCH; \
4028 clockTicks += CLOCKTICKS_UPDATE_TYPE32;\
4029 }
4030 #define STM_ALL_2 \
4031 STM_LOW(STM_REG); \
4032 STM_HIGH_2(STM_REG); \
4033 STM_PC;
4034 #define STMW_ALL_2 \
4035 STM_LOW(STMW_REG); \
4036 STM_HIGH_2(STMW_REG); \
4037 STMW_PC;
4038 #define LDM_ALL_2 \
4039 LDM_LOW; \
4040 if (opcode & (1U<<15)) { \
4041 LDM_HIGH; \
4042 bus.reg[15].I = CPUReadMemory(address); \
4043 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
4044 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4045 clockTicks += 1 + dataticks_value; \
4046 count++; \
4047 } else { \
4048 LDM_HIGH_2; \
4049 }
4050 #define LDM_ALL_2B \
4051 if (opcode & (1U<<15)) { \
4052 if(armMode != (bus.reg[17].I & 0x1F)) \
4053 CPUSwitchMode(bus.reg[17].I & 0x1F, false, true); \
4054 if (armState) { \
4055 bus.armNextPC = bus.reg[15].I & 0xFFFFFFFC; \
4056 bus.reg[15].I = bus.armNextPC + 4; \
4057 ARM_PREFETCH; \
4058 } else { \
4059 bus.armNextPC = bus.reg[15].I & 0xFFFFFFFE; \
4060 bus.reg[15].I = bus.armNextPC + 2; \
4061 THUMB_PREFETCH; \
4062 } \
4063 clockTicks += CLOCKTICKS_UPDATE_TYPE32;\
4064 }
4065
4066
4067 // STMDA Rn, {Rlist}
arm800(u32 opcode)4068 static void arm800(u32 opcode)
4069 {
4070 if (bus.busPrefetchCount == 0)
4071 bus.busPrefetch = bus.busPrefetchEnable;
4072 int base = (opcode & 0x000F0000) >> 16;
4073 u32 temp = bus.reg[base].I -
4074 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4075 u32 address = (temp + 4) & 0xFFFFFFFC;
4076 int count = 0;
4077 STM_ALL;
4078 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4079 }
4080
4081 // LDMDA Rn, {Rlist}
arm810(u32 opcode)4082 static void arm810(u32 opcode)
4083 {
4084 if (bus.busPrefetchCount == 0)
4085 bus.busPrefetch = bus.busPrefetchEnable;
4086 int base = (opcode & 0x000F0000) >> 16;
4087 u32 temp = bus.reg[base].I -
4088 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4089 u32 address = (temp + 4) & 0xFFFFFFFC;
4090 int count = 0;
4091 LDM_ALL;
4092 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4093 }
4094
4095 // STMDA Rn!, {Rlist}
arm820(u32 opcode)4096 static void arm820(u32 opcode)
4097 {
4098 if (bus.busPrefetchCount == 0)
4099 bus.busPrefetch = bus.busPrefetchEnable;
4100 int base = (opcode & 0x000F0000) >> 16;
4101 u32 temp = bus.reg[base].I -
4102 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4103 u32 address = (temp+4) & 0xFFFFFFFC;
4104 int count = 0;
4105 STMW_ALL;
4106 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4107 }
4108
4109 // LDMDA Rn!, {Rlist}
arm830(u32 opcode)4110 static void arm830(u32 opcode)
4111 {
4112 if (bus.busPrefetchCount == 0)
4113 bus.busPrefetch = bus.busPrefetchEnable;
4114 int base = (opcode & 0x000F0000) >> 16;
4115 u32 temp = bus.reg[base].I -
4116 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4117 u32 address = (temp + 4) & 0xFFFFFFFC;
4118 int count = 0;
4119 LDM_ALL;
4120 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4121 if (!(opcode & (1U << base)))
4122 bus.reg[base].I = temp;
4123 }
4124
4125 // STMDA Rn, {Rlist}^
arm840(u32 opcode)4126 static void arm840(u32 opcode)
4127 {
4128 if (bus.busPrefetchCount == 0)
4129 bus.busPrefetch = bus.busPrefetchEnable;
4130 int base = (opcode & 0x000F0000) >> 16;
4131 u32 temp = bus.reg[base].I -
4132 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4133 u32 address = (temp+4) & 0xFFFFFFFC;
4134 int count = 0;
4135 STM_ALL_2;
4136 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4137 }
4138
4139 // LDMDA Rn, {Rlist}^
arm850(u32 opcode)4140 static void arm850(u32 opcode)
4141 {
4142 if (bus.busPrefetchCount == 0)
4143 bus.busPrefetch = bus.busPrefetchEnable;
4144 int base = (opcode & 0x000F0000) >> 16;
4145 u32 temp = bus.reg[base].I -
4146 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4147 u32 address = (temp + 4) & 0xFFFFFFFC;
4148 int count = 0;
4149 LDM_ALL_2;
4150 LDM_ALL_2B;
4151 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4152 }
4153
4154 // STMDA Rn!, {Rlist}^
arm860(u32 opcode)4155 static void arm860(u32 opcode)
4156 {
4157 if (bus.busPrefetchCount == 0)
4158 bus.busPrefetch = bus.busPrefetchEnable;
4159 int base = (opcode & 0x000F0000) >> 16;
4160 u32 temp = bus.reg[base].I -
4161 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4162 u32 address = (temp+4) & 0xFFFFFFFC;
4163 int count = 0;
4164 STMW_ALL_2;
4165 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4166 }
4167
4168 // LDMDA Rn!, {Rlist}^
arm870(u32 opcode)4169 static void arm870(u32 opcode)
4170 {
4171 if (bus.busPrefetchCount == 0)
4172 bus.busPrefetch = bus.busPrefetchEnable;
4173 int base = (opcode & 0x000F0000) >> 16;
4174 u32 temp = bus.reg[base].I -
4175 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4176 u32 address = (temp + 4) & 0xFFFFFFFC;
4177 int count = 0;
4178 LDM_ALL_2;
4179 if (!(opcode & (1U << base)))
4180 bus.reg[base].I = temp;
4181 LDM_ALL_2B;
4182 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4183 }
4184
4185 // STMIA Rn, {Rlist}
arm880(u32 opcode)4186 static void arm880(u32 opcode)
4187 {
4188 if (bus.busPrefetchCount == 0)
4189 bus.busPrefetch = bus.busPrefetchEnable;
4190 int base = (opcode & 0x000F0000) >> 16;
4191 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4192 int count = 0;
4193 STM_ALL;
4194 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4195 }
4196
4197 // LDMIA Rn, {Rlist}
arm890(u32 opcode)4198 static void arm890(u32 opcode)
4199 {
4200 if (bus.busPrefetchCount == 0)
4201 bus.busPrefetch = bus.busPrefetchEnable;
4202 int base = (opcode & 0x000F0000) >> 16;
4203 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4204 int count = 0;
4205 LDM_ALL;
4206 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4207 }
4208
4209 // STMIA Rn!, {Rlist}
arm8A0(u32 opcode)4210 static void arm8A0(u32 opcode)
4211 {
4212 if (bus.busPrefetchCount == 0)
4213 bus.busPrefetch = bus.busPrefetchEnable;
4214 int base = (opcode & 0x000F0000) >> 16;
4215 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4216 int count = 0;
4217 u32 temp = bus.reg[base].I +
4218 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
4219 STMW_ALL;
4220 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4221 }
4222
4223 // LDMIA Rn!, {Rlist}
arm8B0(u32 opcode)4224 static void arm8B0(u32 opcode)
4225 {
4226 if (bus.busPrefetchCount == 0)
4227 bus.busPrefetch = bus.busPrefetchEnable;
4228 int base = (opcode & 0x000F0000) >> 16;
4229 u32 temp = bus.reg[base].I +
4230 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4231 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4232 int count = 0;
4233 LDM_ALL;
4234 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4235 if (!(opcode & (1U << base)))
4236 bus.reg[base].I = temp;
4237 }
4238
4239 // STMIA Rn, {Rlist}^
arm8C0(u32 opcode)4240 static void arm8C0(u32 opcode)
4241 {
4242 if (bus.busPrefetchCount == 0)
4243 bus.busPrefetch = bus.busPrefetchEnable;
4244 int base = (opcode & 0x000F0000) >> 16;
4245 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4246 int count = 0;
4247 STM_ALL_2;
4248 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4249 }
4250
4251 // LDMIA Rn, {Rlist}^
arm8D0(u32 opcode)4252 static void arm8D0(u32 opcode)
4253 {
4254 if (bus.busPrefetchCount == 0)
4255 bus.busPrefetch = bus.busPrefetchEnable;
4256 int base = (opcode & 0x000F0000) >> 16;
4257 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4258 int count = 0;
4259 LDM_ALL_2;
4260 LDM_ALL_2B;
4261 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4262 }
4263
4264 // STMIA Rn!, {Rlist}^
arm8E0(u32 opcode)4265 static void arm8E0(u32 opcode)
4266 {
4267 if (bus.busPrefetchCount == 0)
4268 bus.busPrefetch = bus.busPrefetchEnable;
4269 int base = (opcode & 0x000F0000) >> 16;
4270 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4271 int count = 0;
4272 u32 temp = bus.reg[base].I +
4273 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
4274 STMW_ALL_2;
4275 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4276 }
4277
4278 // LDMIA Rn!, {Rlist}^
arm8F0(u32 opcode)4279 static void arm8F0(u32 opcode)
4280 {
4281 if (bus.busPrefetchCount == 0)
4282 bus.busPrefetch = bus.busPrefetchEnable;
4283 int base = (opcode & 0x000F0000) >> 16;
4284 u32 temp = bus.reg[base].I +
4285 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4286 u32 address = bus.reg[base].I & 0xFFFFFFFC;
4287 int count = 0;
4288 LDM_ALL_2;
4289 if (!(opcode & (1U << base)))
4290 bus.reg[base].I = temp;
4291 LDM_ALL_2B;
4292 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4293 }
4294
4295 // STMDB Rn, {Rlist}
arm900(u32 opcode)4296 static void arm900(u32 opcode)
4297 {
4298 if (bus.busPrefetchCount == 0)
4299 bus.busPrefetch = bus.busPrefetchEnable;
4300 int base = (opcode & 0x000F0000) >> 16;
4301 u32 temp = bus.reg[base].I -
4302 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4303 u32 address = temp & 0xFFFFFFFC;
4304 int count = 0;
4305 STM_ALL;
4306 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4307 }
4308
4309 // LDMDB Rn, {Rlist}
arm910(u32 opcode)4310 static void arm910(u32 opcode)
4311 {
4312 if (bus.busPrefetchCount == 0)
4313 bus.busPrefetch = bus.busPrefetchEnable;
4314 int base = (opcode & 0x000F0000) >> 16;
4315 u32 temp = bus.reg[base].I -
4316 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4317 u32 address = temp & 0xFFFFFFFC;
4318 int count = 0;
4319 LDM_ALL;
4320 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4321 }
4322
4323 // STMDB Rn!, {Rlist}
arm920(u32 opcode)4324 static void arm920(u32 opcode)
4325 {
4326 if (bus.busPrefetchCount == 0)
4327 bus.busPrefetch = bus.busPrefetchEnable;
4328 int base = (opcode & 0x000F0000) >> 16;
4329 u32 temp = bus.reg[base].I -
4330 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4331 u32 address = temp & 0xFFFFFFFC;
4332 int count = 0;
4333 STMW_ALL;
4334 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4335 }
4336
4337 // LDMDB Rn!, {Rlist}
arm930(u32 opcode)4338 static void arm930(u32 opcode)
4339 {
4340 if (bus.busPrefetchCount == 0)
4341 bus.busPrefetch = bus.busPrefetchEnable;
4342 int base = (opcode & 0x000F0000) >> 16;
4343 u32 temp = bus.reg[base].I -
4344 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4345 u32 address = temp & 0xFFFFFFFC;
4346 int count = 0;
4347 LDM_ALL;
4348 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4349 if (!(opcode & (1U << base)))
4350 bus.reg[base].I = temp;
4351 }
4352
4353 // STMDB Rn, {Rlist}^
arm940(u32 opcode)4354 static void arm940(u32 opcode)
4355 {
4356 if (bus.busPrefetchCount == 0)
4357 bus.busPrefetch = bus.busPrefetchEnable;
4358 int base = (opcode & 0x000F0000) >> 16;
4359 u32 temp = bus.reg[base].I -
4360 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4361 u32 address = temp & 0xFFFFFFFC;
4362 int count = 0;
4363 STM_ALL_2;
4364 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4365 }
4366
4367 // LDMDB Rn, {Rlist}^
arm950(u32 opcode)4368 static void arm950(u32 opcode)
4369 {
4370 if (bus.busPrefetchCount == 0)
4371 bus.busPrefetch = bus.busPrefetchEnable;
4372 int base = (opcode & 0x000F0000) >> 16;
4373 u32 temp = bus.reg[base].I -
4374 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4375 u32 address = temp & 0xFFFFFFFC;
4376 int count = 0;
4377 LDM_ALL_2;
4378 LDM_ALL_2B;
4379 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4380 }
4381
4382 // STMDB Rn!, {Rlist}^
arm960(u32 opcode)4383 static void arm960(u32 opcode)
4384 {
4385 if (bus.busPrefetchCount == 0)
4386 bus.busPrefetch = bus.busPrefetchEnable;
4387 int base = (opcode & 0x000F0000) >> 16;
4388 u32 temp = bus.reg[base].I -
4389 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4390 u32 address = temp & 0xFFFFFFFC;
4391 int count = 0;
4392 STMW_ALL_2;
4393 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4394 }
4395
4396 // LDMDB Rn!, {Rlist}^
arm970(u32 opcode)4397 static void arm970(u32 opcode)
4398 {
4399 if (bus.busPrefetchCount == 0)
4400 bus.busPrefetch = bus.busPrefetchEnable;
4401 int base = (opcode & 0x000F0000) >> 16;
4402 u32 temp = bus.reg[base].I -
4403 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4404 u32 address = temp & 0xFFFFFFFC;
4405 int count = 0;
4406 LDM_ALL_2;
4407 if (!(opcode & (1U << base)))
4408 bus.reg[base].I = temp;
4409 LDM_ALL_2B;
4410 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4411 }
4412
4413 // STMIB Rn, {Rlist}
arm980(u32 opcode)4414 static void arm980(u32 opcode)
4415 {
4416 if (bus.busPrefetchCount == 0)
4417 bus.busPrefetch = bus.busPrefetchEnable;
4418 int base = (opcode & 0x000F0000) >> 16;
4419 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4420 int count = 0;
4421 STM_ALL;
4422 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4423 }
4424
4425 // LDMIB Rn, {Rlist}
arm990(u32 opcode)4426 static void arm990(u32 opcode)
4427 {
4428 if (bus.busPrefetchCount == 0)
4429 bus.busPrefetch = bus.busPrefetchEnable;
4430 int base = (opcode & 0x000F0000) >> 16;
4431 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4432 int count = 0;
4433 LDM_ALL;
4434 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4435 }
4436
4437 // STMIB Rn!, {Rlist}
arm9A0(u32 opcode)4438 static void arm9A0(u32 opcode)
4439 {
4440 if (bus.busPrefetchCount == 0)
4441 bus.busPrefetch = bus.busPrefetchEnable;
4442 int base = (opcode & 0x000F0000) >> 16;
4443 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4444 int count = 0;
4445 u32 temp = bus.reg[base].I +
4446 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
4447 STMW_ALL;
4448 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4449 }
4450
4451 // LDMIB Rn!, {Rlist}
arm9B0(u32 opcode)4452 static void arm9B0(u32 opcode)
4453 {
4454 if (bus.busPrefetchCount == 0)
4455 bus.busPrefetch = bus.busPrefetchEnable;
4456 int base = (opcode & 0x000F0000) >> 16;
4457 u32 temp = bus.reg[base].I +
4458 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4459 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4460 int count = 0;
4461 LDM_ALL;
4462 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4463 if (!(opcode & (1U << base)))
4464 bus.reg[base].I = temp;
4465 }
4466
4467 // STMIB Rn, {Rlist}^
arm9C0(u32 opcode)4468 static void arm9C0(u32 opcode)
4469 {
4470 if (bus.busPrefetchCount == 0)
4471 bus.busPrefetch = bus.busPrefetchEnable;
4472 int base = (opcode & 0x000F0000) >> 16;
4473 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4474 int count = 0;
4475 STM_ALL_2;
4476 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4477 }
4478
4479 // LDMIB Rn, {Rlist}^
arm9D0(u32 opcode)4480 static void arm9D0(u32 opcode)
4481 {
4482 if (bus.busPrefetchCount == 0)
4483 bus.busPrefetch = bus.busPrefetchEnable;
4484 int base = (opcode & 0x000F0000) >> 16;
4485 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4486 int count = 0;
4487 LDM_ALL_2;
4488 LDM_ALL_2B;
4489 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4490 }
4491
4492 // STMIB Rn!, {Rlist}^
arm9E0(u32 opcode)4493 static void arm9E0(u32 opcode)
4494 {
4495 if (bus.busPrefetchCount == 0)
4496 bus.busPrefetch = bus.busPrefetchEnable;
4497 int base = (opcode & 0x000F0000) >> 16;
4498 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4499 int count = 0;
4500 u32 temp = bus.reg[base].I +
4501 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
4502 STMW_ALL_2;
4503 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4504 }
4505
4506 // LDMIB Rn!, {Rlist}^
arm9F0(u32 opcode)4507 static void arm9F0(u32 opcode)
4508 {
4509 if (bus.busPrefetchCount == 0)
4510 bus.busPrefetch = bus.busPrefetchEnable;
4511 int base = (opcode & 0x000F0000) >> 16;
4512 u32 temp = bus.reg[base].I +
4513 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
4514 u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
4515 int count = 0;
4516 LDM_ALL_2;
4517 if (!(opcode & (1U << base)))
4518 bus.reg[base].I = temp;
4519 LDM_ALL_2B;
4520 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
4521 }
4522
4523 // B/BL/SWI and (unimplemented) coproc support ////////////////////////////
4524
4525 // B <offset>
armA00(u32 opcode)4526 static void armA00(u32 opcode)
4527 {
4528 int offset = opcode & 0x00FFFFFF;
4529 if (offset & 0x00800000)
4530 offset |= 0xFF000000; // negative offset
4531 bus.reg[15].I += offset<<2;
4532 bus.armNextPC = bus.reg[15].I;
4533 bus.reg[15].I += 4;
4534 ARM_PREFETCH;
4535
4536 clockTicks = CLOCKTICKS_UPDATE_TYPE32P;
4537 bus.busPrefetchCount = 0;
4538 }
4539
4540 // BL <offset>
armB00(u32 opcode)4541 static void armB00(u32 opcode)
4542 {
4543 int offset = opcode & 0x00FFFFFF;
4544 if (offset & 0x00800000)
4545 offset |= 0xFF000000; // negative offset
4546 bus.reg[14].I = bus.reg[15].I - 4;
4547 bus.reg[15].I += offset<<2;
4548 bus.armNextPC = bus.reg[15].I;
4549 bus.reg[15].I += 4;
4550 ARM_PREFETCH;
4551
4552 clockTicks = CLOCKTICKS_UPDATE_TYPE32P;
4553 bus.busPrefetchCount = 0;
4554 }
4555
4556 #define armE01 armUnknownInsn
4557
4558 // SWI <comment>
armF00(u32 opcode)4559 static void armF00(u32 opcode)
4560 {
4561 clockTicks = CLOCKTICKS_UPDATE_TYPE32P;
4562 bus.busPrefetchCount = 0;
4563 CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
4564 }
4565
4566 // Instruction table //////////////////////////////////////////////////////
4567
4568 typedef void (*insnfunc_t)(u32 opcode);
4569 #define REP16(insn) \
4570 insn,insn,insn,insn,insn,insn,insn,insn,\
4571 insn,insn,insn,insn,insn,insn,insn,insn
4572 #define REP256(insn) \
4573 REP16(insn),REP16(insn),REP16(insn),REP16(insn),\
4574 REP16(insn),REP16(insn),REP16(insn),REP16(insn),\
4575 REP16(insn),REP16(insn),REP16(insn),REP16(insn),\
4576 REP16(insn),REP16(insn),REP16(insn),REP16(insn)
4577 #define arm_UI armUnknownInsn
4578 #define arm_BP armUnknownInsn
4579
4580 static insnfunc_t armInsnTable[4096] =
4581 {
4582 arm000,arm001,arm002,arm003,arm004,arm005,arm006,arm007, // 000
4583 arm000,arm009,arm002,arm00B,arm004,arm_UI,arm006,arm_UI, // 008
4584 arm010,arm011,arm012,arm013,arm014,arm015,arm016,arm017, // 010
4585 arm010,arm019,arm012,arm01B,arm014,arm01D,arm016,arm01F, // 018
4586 arm020,arm021,arm022,arm023,arm024,arm025,arm026,arm027, // 020
4587 arm020,arm029,arm022,arm_UI,arm024,arm_UI,arm026,arm_UI, // 028
4588 arm030,arm031,arm032,arm033,arm034,arm035,arm036,arm037, // 030
4589 arm030,arm039,arm032,arm_UI,arm034,arm01D,arm036,arm01F, // 038
4590 arm040,arm041,arm042,arm043,arm044,arm045,arm046,arm047, // 040
4591 arm040,arm_UI,arm042,arm04B,arm044,arm_UI,arm046,arm_UI, // 048
4592 arm050,arm051,arm052,arm053,arm054,arm055,arm056,arm057, // 050
4593 arm050,arm_UI,arm052,arm05B,arm054,arm05D,arm056,arm05F, // 058
4594 arm060,arm061,arm062,arm063,arm064,arm065,arm066,arm067, // 060
4595 arm060,arm_UI,arm062,arm_UI,arm064,arm_UI,arm066,arm_UI, // 068
4596 arm070,arm071,arm072,arm073,arm074,arm075,arm076,arm077, // 070
4597 arm070,arm_UI,arm072,arm_UI,arm074,arm05D,arm076,arm05F, // 078
4598 arm080,arm081,arm082,arm083,arm084,arm085,arm086,arm087, // 080
4599 arm080,arm089,arm082,arm08B,arm084,arm_UI,arm086,arm_UI, // 088
4600 arm090,arm091,arm092,arm093,arm094,arm095,arm096,arm097, // 090
4601 arm090,arm099,arm092,arm09B,arm094,arm09D,arm096,arm09F, // 098
4602 arm0A0,arm0A1,arm0A2,arm0A3,arm0A4,arm0A5,arm0A6,arm0A7, // 0A0
4603 arm0A0,arm0A9,arm0A2,arm_UI,arm0A4,arm_UI,arm0A6,arm_UI, // 0A8
4604 arm0B0,arm0B1,arm0B2,arm0B3,arm0B4,arm0B5,arm0B6,arm0B7, // 0B0
4605 arm0B0,arm0B9,arm0B2,arm_UI,arm0B4,arm09D,arm0B6,arm09F, // 0B8
4606 arm0C0,arm0C1,arm0C2,arm0C3,arm0C4,arm0C5,arm0C6,arm0C7, // 0C0
4607 arm0C0,arm0C9,arm0C2,arm0CB,arm0C4,arm_UI,arm0C6,arm_UI, // 0C8
4608 arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7, // 0D0
4609 arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF, // 0D8
4610 arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0
4611 arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8
4612 arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0
4613 arm0F0,arm0F9,arm0F2,arm0DB,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8
4614
4615 arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100
4616 arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108
4617 arm110,arm111,arm112,arm113,arm114,arm115,arm116,arm117, // 110
4618 arm110,arm_UI,arm112,arm11B,arm114,arm11D,arm116,arm11F, // 118
4619 arm120,arm121,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_BP, // 120
4620 arm_UI,arm_UI,arm_UI,arm12B,arm_UI,arm_UI,arm_UI,arm_UI, // 128
4621 arm130,arm131,arm132,arm133,arm134,arm135,arm136,arm137, // 130
4622 arm130,arm_UI,arm132,arm13B,arm134,arm13D,arm136,arm13F, // 138
4623 arm140,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 140
4624 arm_UI,arm149,arm_UI,arm14B,arm_UI,arm_UI,arm_UI,arm_UI, // 148
4625 arm150,arm151,arm152,arm153,arm154,arm155,arm156,arm157, // 150
4626 arm150,arm_UI,arm152,arm15B,arm154,arm15D,arm156,arm15F, // 158
4627 arm160,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 160
4628 arm_UI,arm_UI,arm_UI,arm16B,arm_UI,arm_UI,arm_UI,arm_UI, // 168
4629 arm170,arm171,arm172,arm173,arm174,arm175,arm176,arm177, // 170
4630 arm170,arm_UI,arm172,arm17B,arm174,arm17D,arm176,arm17F, // 178
4631 arm180,arm181,arm182,arm183,arm184,arm185,arm186,arm187, // 180
4632 arm180,arm_UI,arm182,arm18B,arm184,arm_UI,arm186,arm_UI, // 188
4633 arm190,arm191,arm192,arm193,arm194,arm195,arm196,arm197, // 190
4634 arm190,arm_UI,arm192,arm19B,arm194,arm19D,arm196,arm19F, // 198
4635 arm1A0,arm1A1,arm1A2,arm1A3,arm1A4,arm1A5,arm1A6,arm1A7, // 1A0
4636 arm1A0,arm_UI,arm1A2,arm1AB,arm1A4,arm_UI,arm1A6,arm_UI, // 1A8
4637 arm1B0,arm1B1,arm1B2,arm1B3,arm1B4,arm1B5,arm1B6,arm1B7, // 1B0
4638 arm1B0,arm_UI,arm1B2,arm1BB,arm1B4,arm1BD,arm1B6,arm1BF, // 1B8
4639 arm1C0,arm1C1,arm1C2,arm1C3,arm1C4,arm1C5,arm1C6,arm1C7, // 1C0
4640 arm1C0,arm_UI,arm1C2,arm1CB,arm1C4,arm_UI,arm1C6,arm_UI, // 1C8
4641 arm1D0,arm1D1,arm1D2,arm1D3,arm1D4,arm1D5,arm1D6,arm1D7, // 1D0
4642 arm1D0,arm_UI,arm1D2,arm1DB,arm1D4,arm1DD,arm1D6,arm1DF, // 1D8
4643 arm1E0,arm1E1,arm1E2,arm1E3,arm1E4,arm1E5,arm1E6,arm1E7, // 1E0
4644 arm1E0,arm_UI,arm1E2,arm1EB,arm1E4,arm_UI,arm1E6,arm_UI, // 1E8
4645 arm1F0,arm1F1,arm1F2,arm1F3,arm1F4,arm1F5,arm1F6,arm1F7, // 1F0
4646 arm1F0,arm_UI,arm1F2,arm1FB,arm1F4,arm1FD,arm1F6,arm1FF, // 1F8
4647
4648 REP16(arm200),REP16(arm210),REP16(arm220),REP16(arm230), // 200
4649 REP16(arm240),REP16(arm250),REP16(arm260),REP16(arm270), // 240
4650 REP16(arm280),REP16(arm290),REP16(arm2A0),REP16(arm2B0), // 280
4651 REP16(arm2C0),REP16(arm2D0),REP16(arm2E0),REP16(arm2F0), // 2C0
4652 REP16(arm_UI),REP16(arm310),REP16(arm320),REP16(arm330), // 300
4653 REP16(arm_UI),REP16(arm350),REP16(arm360),REP16(arm370), // 340
4654 REP16(arm380),REP16(arm390),REP16(arm3A0),REP16(arm3B0), // 380
4655 REP16(arm3C0),REP16(arm3D0),REP16(arm3E0),REP16(arm3F0), // 3C0
4656
4657 REP16(arm400),REP16(arm410),REP16(arm400),REP16(arm410), // 400
4658 REP16(arm440),REP16(arm450),REP16(arm440),REP16(arm450), // 440
4659 REP16(arm480),REP16(arm490),REP16(arm480),REP16(arm490), // 480
4660 REP16(arm4C0),REP16(arm4D0),REP16(arm4C0),REP16(arm4D0), // 4C0
4661 REP16(arm500),REP16(arm510),REP16(arm520),REP16(arm530), // 500
4662 REP16(arm540),REP16(arm550),REP16(arm560),REP16(arm570), // 540
4663 REP16(arm580),REP16(arm590),REP16(arm5A0),REP16(arm5B0), // 580
4664 REP16(arm5C0),REP16(arm5D0),REP16(arm5E0),REP16(arm5F0), // 5C0
4665
4666 arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 600
4667 arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 608
4668 arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 610
4669 arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 618
4670 arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 620
4671 arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 628
4672 arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 630
4673 arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 638
4674 arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 640
4675 arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 648
4676 arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 650
4677 arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 658
4678 arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 660
4679 arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 668
4680 arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 670
4681 arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 678
4682 arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 680
4683 arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 688
4684 arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 690
4685 arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 698
4686 arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A0
4687 arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A8
4688 arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B0
4689 arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B8
4690 arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C0
4691 arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C8
4692 arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D0
4693 arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D8
4694 arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E0
4695 arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E8
4696 arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F0
4697 arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F8
4698
4699 arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 700
4700 arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 708
4701 arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 710
4702 arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 718
4703 arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 720
4704 arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 728
4705 arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 730
4706 arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 738
4707 arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 740
4708 arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 748
4709 arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 750
4710 arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 758
4711 arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 760
4712 arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 768
4713 arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 770
4714 arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 778
4715 arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 780
4716 arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 788
4717 arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 790
4718 arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 798
4719 arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A0
4720 arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A8
4721 arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B0
4722 arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B8
4723 arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C0
4724 arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C8
4725 arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D0
4726 arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D8
4727 arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E0
4728 arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E8
4729 arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_UI, // 7F0
4730 arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_BP, // 7F8
4731
4732 REP16(arm800),REP16(arm810),REP16(arm820),REP16(arm830), // 800
4733 REP16(arm840),REP16(arm850),REP16(arm860),REP16(arm870), // 840
4734 REP16(arm880),REP16(arm890),REP16(arm8A0),REP16(arm8B0), // 880
4735 REP16(arm8C0),REP16(arm8D0),REP16(arm8E0),REP16(arm8F0), // 8C0
4736 REP16(arm900),REP16(arm910),REP16(arm920),REP16(arm930), // 900
4737 REP16(arm940),REP16(arm950),REP16(arm960),REP16(arm970), // 940
4738 REP16(arm980),REP16(arm990),REP16(arm9A0),REP16(arm9B0), // 980
4739 REP16(arm9C0),REP16(arm9D0),REP16(arm9E0),REP16(arm9F0), // 9C0
4740
4741 REP256(armA00), // A00
4742 REP256(armB00), // B00
4743 REP256(arm_UI), // C00
4744 REP256(arm_UI), // D00
4745
4746 arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E00
4747 arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E08
4748 arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E10
4749 arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E18
4750 REP16(arm_UI), // E20
4751 REP16(arm_UI), // E30
4752 REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E40
4753 REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E80
4754 REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // EC0
4755
4756 REP256(armF00), // F00
4757 };
4758
4759 // Emulates the Cheat System (m) code
cpuMasterCodeCheck()4760 static INLINE void cpuMasterCodeCheck()
4761 {
4762 if((mastercode) && (mastercode == bus.armNextPC))
4763 {
4764 u32 ext = (joy >> 10);
4765 cpuTotalTicks += cheatsCheckKeys(io_registers[REG_P1]^0x3FF, ext);
4766 }
4767 }
4768
4769 // Wrapper routine (execution loop) ///////////////////////////////////////
armExecute(void)4770 static int armExecute (void)
4771 {
4772 int ct = 0;
4773 bool test = false;
4774 u32 cond1 = 0;
4775 u32 cond2 = 0;
4776
4777 CACHE_PREFETCH(clockTicks);
4778
4779 do
4780 {
4781
4782 clockTicks = 0;
4783
4784 #if USE_CHEATS
4785 cpuMasterCodeCheck();
4786 #endif
4787
4788 if ((bus.armNextPC & 0x0803FFFF) == 0x08020000)
4789 bus.busPrefetchCount = 0x100;
4790
4791 u32 opcode = cpuPrefetch[0];
4792 cpuPrefetch[0] = cpuPrefetch[1];
4793
4794 bus.busPrefetch = false;
4795 int32_t busprefetch_mask = ((bus.busPrefetchCount & 0xFFFFFE00) | -(bus.busPrefetchCount & 0xFFFFFE00)) >> 31;
4796 bus.busPrefetchCount = ((0x100 | (bus.busPrefetchCount & 0xFF)) & busprefetch_mask) | (bus.busPrefetchCount & ~busprefetch_mask);
4797 #if 0
4798 if (bus.busPrefetchCount & 0xFFFFFE00)
4799 bus.busPrefetchCount = 0x100 | (bus.busPrefetchCount & 0xFF);
4800 #endif
4801
4802
4803 int oldArmNextPC = bus.armNextPC;
4804
4805 bus.armNextPC = bus.reg[15].I;
4806 bus.reg[15].I += 4;
4807 ARM_PREFETCH_NEXT;
4808
4809 int cond = opcode >> 28;
4810 bool cond_res = true;
4811 if (cond != 0x0E) { // most opcodes are AL (always)
4812 switch(cond) {
4813 case 0x00: // EQ
4814 cond_res = Z_FLAG;
4815 break;
4816 case 0x01: // NE
4817 cond_res = !Z_FLAG;
4818 break;
4819 case 0x02: // CS
4820 cond_res = C_FLAG;
4821 break;
4822 case 0x03: // CC
4823 cond_res = !C_FLAG;
4824 break;
4825 case 0x04: // MI
4826 cond_res = N_FLAG;
4827 break;
4828 case 0x05: // PL
4829 cond_res = !N_FLAG;
4830 break;
4831 case 0x06: // VS
4832 cond_res = V_FLAG;
4833 break;
4834 case 0x07: // VC
4835 cond_res = !V_FLAG;
4836 break;
4837 case 0x08: // HI
4838 cond_res = C_FLAG && !Z_FLAG;
4839 break;
4840 case 0x09: // LS
4841 cond_res = !C_FLAG || Z_FLAG;
4842 break;
4843 case 0x0A: // GE
4844 cond_res = N_FLAG == V_FLAG;
4845 break;
4846 case 0x0B: // LT
4847 cond_res = N_FLAG != V_FLAG;
4848 break;
4849 case 0x0C: // GT
4850 cond_res = !Z_FLAG &&(N_FLAG == V_FLAG);
4851 break;
4852 case 0x0D: // LE
4853 cond_res = Z_FLAG || (N_FLAG != V_FLAG);
4854 break;
4855 case 0x0E: // AL (impossible, checked above)
4856 cond_res = true;
4857 break;
4858 case 0x0F:
4859 default:
4860 // ???
4861 cond_res = false;
4862 break;
4863 }
4864 }
4865
4866 if (cond_res)
4867 {
4868 cond1 = (opcode>>16)&0xFF0;
4869 cond2 = (opcode>>4)&0x0F;
4870
4871 (*armInsnTable[(cond1| cond2)])(opcode);
4872
4873 }
4874 ct = clockTicks;
4875
4876 if (ct < 0)
4877 return 0;
4878
4879 /// better pipelining
4880
4881 if (ct == 0)
4882 clockTicks = 1 + codeTicksAccessSeq32(oldArmNextPC);
4883
4884 cpuTotalTicks += clockTicks;
4885
4886 test = cpuTotalTicks < cpuNextEvent && armState && !holdState;
4887 #ifdef USE_SWITICKS
4888 test = test && !SWITicks;
4889 #endif
4890 }while (test);
4891
4892 return 1;
4893 }
4894
4895 /*============================================================
4896 GBA THUMB CORE
4897 ============================================================ */
4898
thumbUnknownInsn(u32 opcode)4899 static void thumbUnknownInsn(u32 opcode)
4900 {
4901 u32 PC = bus.reg[15].I;
4902 bool savedArmState = armState;
4903 if(armMode != 0x1b)
4904 CPUSwitchMode(0x1b, true, false);
4905 bus.reg[14].I = PC - (savedArmState ? 4 : 2);
4906 bus.reg[15].I = 0x04;
4907 armState = true;
4908 armIrqEnable = false;
4909 bus.armNextPC = 0x04;
4910 ARM_PREFETCH;
4911 bus.reg[15].I += 4;
4912 }
4913
4914 #define NEG(i) ((i) >> 31)
4915 #define POS(i) ((~(i)) >> 31)
4916
4917 // C core
4918 #ifndef ADDCARRY
4919 #define ADDCARRY(a, b, c) \
4920 C_FLAG = ((NEG(a) & NEG(b)) |\
4921 (NEG(a) & POS(c)) |\
4922 (NEG(b) & POS(c))) ? true : false;
4923 #endif
4924
4925 #ifndef ADDOVERFLOW
4926 #define ADDOVERFLOW(a, b, c) \
4927 V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
4928 (POS(a) & POS(b) & NEG(c))) ? true : false;
4929 #endif
4930
4931 #ifndef SUBCARRY
4932 #define SUBCARRY(a, b, c) \
4933 C_FLAG = ((NEG(a) & POS(b)) |\
4934 (NEG(a) & POS(c)) |\
4935 (POS(b) & POS(c))) ? true : false;
4936 #endif
4937
4938 #ifndef SUBOVERFLOW
4939 #define SUBOVERFLOW(a, b, c)\
4940 V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
4941 (POS(a) & NEG(b) & NEG(c))) ? true : false;
4942 #endif
4943
4944 #ifndef ADD_RD_RS_RN
4945 #define ADD_RD_RS_RN(N) \
4946 {\
4947 u32 lhs = bus.reg[source].I;\
4948 u32 rhs = bus.reg[N].I;\
4949 u32 res = lhs + rhs;\
4950 bus.reg[dest].I = res;\
4951 Z_FLAG = (res == 0) ? true : false;\
4952 N_FLAG = NEG(res) ? true : false;\
4953 ADDCARRY(lhs, rhs, res);\
4954 ADDOVERFLOW(lhs, rhs, res);\
4955 }
4956 #endif
4957
4958 #ifndef ADD_RD_RS_O3
4959 #define ADD_RD_RS_O3(N) \
4960 {\
4961 u32 lhs = bus.reg[source].I;\
4962 u32 rhs = N;\
4963 u32 res = lhs + rhs;\
4964 bus.reg[dest].I = res;\
4965 Z_FLAG = (res == 0) ? true : false;\
4966 N_FLAG = NEG(res) ? true : false;\
4967 ADDCARRY(lhs, rhs, res);\
4968 ADDOVERFLOW(lhs, rhs, res);\
4969 }
4970 #endif
4971
4972 #ifndef ADD_RD_RS_O3_0
4973 # define ADD_RD_RS_O3_0 ADD_RD_RS_O3
4974 #endif
4975
4976 #ifndef ADD_RN_O8
4977 #define ADD_RN_O8(d) \
4978 {\
4979 u32 lhs = bus.reg[(d)].I;\
4980 u32 rhs = (opcode & 255);\
4981 u32 res = lhs + rhs;\
4982 bus.reg[(d)].I = res;\
4983 Z_FLAG = (res == 0) ? true : false;\
4984 N_FLAG = NEG(res) ? true : false;\
4985 ADDCARRY(lhs, rhs, res);\
4986 ADDOVERFLOW(lhs, rhs, res);\
4987 }
4988 #endif
4989
4990 #ifndef CMN_RD_RS
4991 #define CMN_RD_RS \
4992 {\
4993 u32 lhs = bus.reg[dest].I;\
4994 u32 rhs = value;\
4995 u32 res = lhs + rhs;\
4996 Z_FLAG = (res == 0) ? true : false;\
4997 N_FLAG = NEG(res) ? true : false;\
4998 ADDCARRY(lhs, rhs, res);\
4999 ADDOVERFLOW(lhs, rhs, res);\
5000 }
5001 #endif
5002
5003 #ifndef ADC_RD_RS
5004 #define ADC_RD_RS \
5005 {\
5006 u32 lhs = bus.reg[dest].I;\
5007 u32 rhs = value;\
5008 u32 res = lhs + rhs + (u32)C_FLAG;\
5009 bus.reg[dest].I = res;\
5010 Z_FLAG = (res == 0) ? true : false;\
5011 N_FLAG = NEG(res) ? true : false;\
5012 ADDCARRY(lhs, rhs, res);\
5013 ADDOVERFLOW(lhs, rhs, res);\
5014 }
5015 #endif
5016
5017 #ifndef SUB_RD_RS_RN
5018 #define SUB_RD_RS_RN(N) \
5019 {\
5020 u32 lhs = bus.reg[source].I;\
5021 u32 rhs = bus.reg[N].I;\
5022 u32 res = lhs - rhs;\
5023 bus.reg[dest].I = res;\
5024 Z_FLAG = (res == 0) ? true : false;\
5025 N_FLAG = NEG(res) ? true : false;\
5026 SUBCARRY(lhs, rhs, res);\
5027 SUBOVERFLOW(lhs, rhs, res);\
5028 }
5029 #endif
5030
5031 #ifndef SUB_RD_RS_O3
5032 #define SUB_RD_RS_O3(N) \
5033 {\
5034 u32 lhs = bus.reg[source].I;\
5035 u32 rhs = N;\
5036 u32 res = lhs - rhs;\
5037 bus.reg[dest].I = res;\
5038 Z_FLAG = (res == 0) ? true : false;\
5039 N_FLAG = NEG(res) ? true : false;\
5040 SUBCARRY(lhs, rhs, res);\
5041 SUBOVERFLOW(lhs, rhs, res);\
5042 }
5043 #endif
5044
5045 #ifndef SUB_RD_RS_O3_0
5046 # define SUB_RD_RS_O3_0 SUB_RD_RS_O3
5047 #endif
5048 #ifndef SUB_RN_O8
5049 #define SUB_RN_O8(d) \
5050 {\
5051 u32 lhs = bus.reg[(d)].I;\
5052 u32 rhs = (opcode & 255);\
5053 u32 res = lhs - rhs;\
5054 bus.reg[(d)].I = res;\
5055 Z_FLAG = (res == 0) ? true : false;\
5056 N_FLAG = NEG(res) ? true : false;\
5057 SUBCARRY(lhs, rhs, res);\
5058 SUBOVERFLOW(lhs, rhs, res);\
5059 }
5060 #endif
5061 #ifndef MOV_RN_O8
5062 #define MOV_RN_O8(d) \
5063 {\
5064 u32 val;\
5065 val = (opcode & 255);\
5066 bus.reg[d].I = val;\
5067 N_FLAG = false;\
5068 Z_FLAG = (val ? false : true);\
5069 }
5070 #endif
5071 #ifndef CMP_RN_O8
5072 #define CMP_RN_O8(d) \
5073 {\
5074 u32 lhs = bus.reg[(d)].I;\
5075 u32 rhs = (opcode & 255);\
5076 u32 res = lhs - rhs;\
5077 Z_FLAG = (res == 0) ? true : false;\
5078 N_FLAG = NEG(res) ? true : false;\
5079 SUBCARRY(lhs, rhs, res);\
5080 SUBOVERFLOW(lhs, rhs, res);\
5081 }
5082 #endif
5083 #ifndef SBC_RD_RS
5084 #define SBC_RD_RS \
5085 {\
5086 u32 lhs = bus.reg[dest].I;\
5087 u32 rhs = value;\
5088 u32 res = lhs - rhs - !((u32)C_FLAG);\
5089 bus.reg[dest].I = res;\
5090 Z_FLAG = (res == 0) ? true : false;\
5091 N_FLAG = NEG(res) ? true : false;\
5092 SUBCARRY(lhs, rhs, res);\
5093 SUBOVERFLOW(lhs, rhs, res);\
5094 }
5095 #endif
5096 #ifndef LSL_RD_RM_I5
5097 #define LSL_RD_RM_I5 \
5098 {\
5099 C_FLAG = (bus.reg[source].I >> (32 - shift)) & 1 ? true : false;\
5100 value = bus.reg[source].I << shift;\
5101 }
5102 #endif
5103 #ifndef LSL_RD_RS
5104 #define LSL_RD_RS \
5105 {\
5106 C_FLAG = (bus.reg[dest].I >> (32 - value)) & 1 ? true : false;\
5107 value = bus.reg[dest].I << value;\
5108 }
5109 #endif
5110 #ifndef LSR_RD_RM_I5
5111 #define LSR_RD_RM_I5 \
5112 {\
5113 C_FLAG = (bus.reg[source].I >> (shift - 1)) & 1 ? true : false;\
5114 value = bus.reg[source].I >> shift;\
5115 }
5116 #endif
5117 #ifndef LSR_RD_RS
5118 #define LSR_RD_RS \
5119 {\
5120 C_FLAG = (bus.reg[dest].I >> (value - 1)) & 1 ? true : false;\
5121 value = bus.reg[dest].I >> value;\
5122 }
5123 #endif
5124 #ifndef ASR_RD_RM_I5
5125 #define ASR_RD_RM_I5 \
5126 {\
5127 C_FLAG = ((s32)bus.reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\
5128 value = (s32)bus.reg[source].I >> (int)shift;\
5129 }
5130 #endif
5131 #ifndef ASR_RD_RS
5132 #define ASR_RD_RS \
5133 {\
5134 C_FLAG = ((s32)bus.reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\
5135 value = (s32)bus.reg[dest].I >> (int)value;\
5136 }
5137 #endif
5138 #ifndef ROR_RD_RS
5139 #define ROR_RD_RS \
5140 {\
5141 C_FLAG = (bus.reg[dest].I >> (value - 1)) & 1 ? true : false;\
5142 value = ((bus.reg[dest].I << (32 - value)) |\
5143 (bus.reg[dest].I >> value));\
5144 }
5145 #endif
5146 #ifndef NEG_RD_RS
5147 #define NEG_RD_RS \
5148 {\
5149 u32 lhs = bus.reg[source].I;\
5150 u32 rhs = 0;\
5151 u32 res = rhs - lhs;\
5152 bus.reg[dest].I = res;\
5153 Z_FLAG = (res == 0) ? true : false;\
5154 N_FLAG = NEG(res) ? true : false;\
5155 SUBCARRY(rhs, lhs, res);\
5156 SUBOVERFLOW(rhs, lhs, res);\
5157 }
5158 #endif
5159 #ifndef CMP_RD_RS
5160 #define CMP_RD_RS \
5161 {\
5162 u32 lhs = bus.reg[dest].I;\
5163 u32 rhs = value;\
5164 u32 res = lhs - rhs;\
5165 Z_FLAG = (res == 0) ? true : false;\
5166 N_FLAG = NEG(res) ? true : false;\
5167 SUBCARRY(lhs, rhs, res);\
5168 SUBOVERFLOW(lhs, rhs, res);\
5169 }
5170 #endif
5171 #ifndef IMM5_INSN
5172 #define IMM5_INSN(OP,N) \
5173 int dest = opcode & 0x07;\
5174 int source = (opcode >> 3) & 0x07;\
5175 u32 value;\
5176 OP(N);\
5177 bus.reg[dest].I = value;\
5178 N_FLAG = (value & 0x80000000 ? true : false);\
5179 Z_FLAG = (value ? false : true);
5180 #define IMM5_INSN_0(OP) \
5181 int dest = opcode & 0x07;\
5182 int source = (opcode >> 3) & 0x07;\
5183 u32 value;\
5184 OP;\
5185 bus.reg[dest].I = value;\
5186 N_FLAG = (value & 0x80000000 ? true : false);\
5187 Z_FLAG = (value ? false : true);
5188 #define IMM5_LSL(N) \
5189 int shift = N;\
5190 LSL_RD_RM_I5;
5191 #define IMM5_LSL_0 \
5192 value = bus.reg[source].I;
5193 #define IMM5_LSR(N) \
5194 int shift = N;\
5195 LSR_RD_RM_I5;
5196 #define IMM5_LSR_0 \
5197 C_FLAG = bus.reg[source].I & 0x80000000 ? true : false;\
5198 value = 0;
5199 #define IMM5_ASR(N) \
5200 int shift = N;\
5201 ASR_RD_RM_I5;
5202 #define IMM5_ASR_0 \
5203 if(bus.reg[source].I & 0x80000000) {\
5204 value = 0xFFFFFFFF;\
5205 C_FLAG = true;\
5206 } else {\
5207 value = 0;\
5208 C_FLAG = false;\
5209 }
5210 #endif
5211 #ifndef THREEARG_INSN
5212 #define THREEARG_INSN(OP,N) \
5213 int dest = opcode & 0x07; \
5214 int source = (opcode >> 3) & 0x07; \
5215 OP(N);
5216 #endif
5217
5218 // Shift instructions /////////////////////////////////////////////////////
5219
5220 #define DEFINE_IMM5_INSN(OP,BASE) \
5221 static void thumb##BASE##_00(u32 opcode) { IMM5_INSN_0(OP##_0); } \
5222 static void thumb##BASE##_01(u32 opcode) { IMM5_INSN(OP, 1); } \
5223 static void thumb##BASE##_02(u32 opcode) { IMM5_INSN(OP, 2); } \
5224 static void thumb##BASE##_03(u32 opcode) { IMM5_INSN(OP, 3); } \
5225 static void thumb##BASE##_04(u32 opcode) { IMM5_INSN(OP, 4); } \
5226 static void thumb##BASE##_05(u32 opcode) { IMM5_INSN(OP, 5); } \
5227 static void thumb##BASE##_06(u32 opcode) { IMM5_INSN(OP, 6); } \
5228 static void thumb##BASE##_07(u32 opcode) { IMM5_INSN(OP, 7); } \
5229 static void thumb##BASE##_08(u32 opcode) { IMM5_INSN(OP, 8); } \
5230 static void thumb##BASE##_09(u32 opcode) { IMM5_INSN(OP, 9); } \
5231 static void thumb##BASE##_0A(u32 opcode) { IMM5_INSN(OP,10); } \
5232 static void thumb##BASE##_0B(u32 opcode) { IMM5_INSN(OP,11); } \
5233 static void thumb##BASE##_0C(u32 opcode) { IMM5_INSN(OP,12); } \
5234 static void thumb##BASE##_0D(u32 opcode) { IMM5_INSN(OP,13); } \
5235 static void thumb##BASE##_0E(u32 opcode) { IMM5_INSN(OP,14); } \
5236 static void thumb##BASE##_0F(u32 opcode) { IMM5_INSN(OP,15); } \
5237 static void thumb##BASE##_10(u32 opcode) { IMM5_INSN(OP,16); } \
5238 static void thumb##BASE##_11(u32 opcode) { IMM5_INSN(OP,17); } \
5239 static void thumb##BASE##_12(u32 opcode) { IMM5_INSN(OP,18); } \
5240 static void thumb##BASE##_13(u32 opcode) { IMM5_INSN(OP,19); } \
5241 static void thumb##BASE##_14(u32 opcode) { IMM5_INSN(OP,20); } \
5242 static void thumb##BASE##_15(u32 opcode) { IMM5_INSN(OP,21); } \
5243 static void thumb##BASE##_16(u32 opcode) { IMM5_INSN(OP,22); } \
5244 static void thumb##BASE##_17(u32 opcode) { IMM5_INSN(OP,23); } \
5245 static void thumb##BASE##_18(u32 opcode) { IMM5_INSN(OP,24); } \
5246 static void thumb##BASE##_19(u32 opcode) { IMM5_INSN(OP,25); } \
5247 static void thumb##BASE##_1A(u32 opcode) { IMM5_INSN(OP,26); } \
5248 static void thumb##BASE##_1B(u32 opcode) { IMM5_INSN(OP,27); } \
5249 static void thumb##BASE##_1C(u32 opcode) { IMM5_INSN(OP,28); } \
5250 static void thumb##BASE##_1D(u32 opcode) { IMM5_INSN(OP,29); } \
5251 static void thumb##BASE##_1E(u32 opcode) { IMM5_INSN(OP,30); } \
5252 static void thumb##BASE##_1F(u32 opcode) { IMM5_INSN(OP,31); }
5253
5254 // LSL Rd, Rm, #Imm 5
5255 DEFINE_IMM5_INSN(IMM5_LSL,00)
5256 // LSR Rd, Rm, #Imm 5
5257 DEFINE_IMM5_INSN(IMM5_LSR,08)
5258 // ASR Rd, Rm, #Imm 5
5259 DEFINE_IMM5_INSN(IMM5_ASR,10)
5260
5261 // 3-argument ADD/SUB /////////////////////////////////////////////////////
5262
5263 #define DEFINE_REG3_INSN(OP,BASE) \
5264 static void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP,0); } \
5265 static void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
5266 static void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
5267 static void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
5268 static void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
5269 static void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
5270 static void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
5271 static void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
5272
5273 #define DEFINE_IMM3_INSN(OP,BASE) \
5274 static void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP##_0,0); } \
5275 static void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
5276 static void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
5277 static void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
5278 static void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
5279 static void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
5280 static void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
5281 static void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
5282
5283 // ADD Rd, Rs, Rn
5284 DEFINE_REG3_INSN(ADD_RD_RS_RN,18)
5285 // SUB Rd, Rs, Rn
5286 DEFINE_REG3_INSN(SUB_RD_RS_RN,1A)
5287 // ADD Rd, Rs, #Offset3
5288 DEFINE_IMM3_INSN(ADD_RD_RS_O3,1C)
5289 // SUB Rd, Rs, #Offset3
5290 DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E)
5291
5292 // MOV/CMP/ADD/SUB immediate //////////////////////////////////////////////
5293
5294 // MOV R0, #Offset8
thumb20(u32 opcode)5295 static void thumb20(u32 opcode) { MOV_RN_O8(0); }
5296 // MOV R1, #Offset8
thumb21(u32 opcode)5297 static void thumb21(u32 opcode) { MOV_RN_O8(1); }
5298 // MOV R2, #Offset8
thumb22(u32 opcode)5299 static void thumb22(u32 opcode) { MOV_RN_O8(2); }
5300 // MOV R3, #Offset8
thumb23(u32 opcode)5301 static void thumb23(u32 opcode) { MOV_RN_O8(3); }
5302 // MOV R4, #Offset8
thumb24(u32 opcode)5303 static void thumb24(u32 opcode) { MOV_RN_O8(4); }
5304 // MOV R5, #Offset8
thumb25(u32 opcode)5305 static void thumb25(u32 opcode) { MOV_RN_O8(5); }
5306 // MOV R6, #Offset8
thumb26(u32 opcode)5307 static void thumb26(u32 opcode) { MOV_RN_O8(6); }
5308 // MOV R7, #Offset8
thumb27(u32 opcode)5309 static void thumb27(u32 opcode) { MOV_RN_O8(7); }
5310
5311 // CMP R0, #Offset8
thumb28(u32 opcode)5312 static void thumb28(u32 opcode) { CMP_RN_O8(0); }
5313 // CMP R1, #Offset8
thumb29(u32 opcode)5314 static void thumb29(u32 opcode) { CMP_RN_O8(1); }
5315 // CMP R2, #Offset8
thumb2A(u32 opcode)5316 static void thumb2A(u32 opcode) { CMP_RN_O8(2); }
5317 // CMP R3, #Offset8
thumb2B(u32 opcode)5318 static void thumb2B(u32 opcode) { CMP_RN_O8(3); }
5319 // CMP R4, #Offset8
thumb2C(u32 opcode)5320 static void thumb2C(u32 opcode) { CMP_RN_O8(4); }
5321 // CMP R5, #Offset8
thumb2D(u32 opcode)5322 static void thumb2D(u32 opcode) { CMP_RN_O8(5); }
5323 // CMP R6, #Offset8
thumb2E(u32 opcode)5324 static void thumb2E(u32 opcode) { CMP_RN_O8(6); }
5325 // CMP R7, #Offset8
thumb2F(u32 opcode)5326 static void thumb2F(u32 opcode) { CMP_RN_O8(7); }
5327
5328 // ADD R0,#Offset8
thumb30(u32 opcode)5329 static void thumb30(u32 opcode) { ADD_RN_O8(0); }
5330 // ADD R1,#Offset8
thumb31(u32 opcode)5331 static void thumb31(u32 opcode) { ADD_RN_O8(1); }
5332 // ADD R2,#Offset8
thumb32(u32 opcode)5333 static void thumb32(u32 opcode) { ADD_RN_O8(2); }
5334 // ADD R3,#Offset8
thumb33(u32 opcode)5335 static void thumb33(u32 opcode) { ADD_RN_O8(3); }
5336 // ADD R4,#Offset8
thumb34(u32 opcode)5337 static void thumb34(u32 opcode) { ADD_RN_O8(4); }
5338 // ADD R5,#Offset8
thumb35(u32 opcode)5339 static void thumb35(u32 opcode) { ADD_RN_O8(5); }
5340 // ADD R6,#Offset8
thumb36(u32 opcode)5341 static void thumb36(u32 opcode) { ADD_RN_O8(6); }
5342 // ADD R7,#Offset8
thumb37(u32 opcode)5343 static void thumb37(u32 opcode) { ADD_RN_O8(7); }
5344
5345 // SUB R0,#Offset8
thumb38(u32 opcode)5346 static void thumb38(u32 opcode) { SUB_RN_O8(0); }
5347 // SUB R1,#Offset8
thumb39(u32 opcode)5348 static void thumb39(u32 opcode) { SUB_RN_O8(1); }
5349 // SUB R2,#Offset8
thumb3A(u32 opcode)5350 static void thumb3A(u32 opcode) { SUB_RN_O8(2); }
5351 // SUB R3,#Offset8
thumb3B(u32 opcode)5352 static void thumb3B(u32 opcode) { SUB_RN_O8(3); }
5353 // SUB R4,#Offset8
thumb3C(u32 opcode)5354 static void thumb3C(u32 opcode) { SUB_RN_O8(4); }
5355 // SUB R5,#Offset8
thumb3D(u32 opcode)5356 static void thumb3D(u32 opcode) { SUB_RN_O8(5); }
5357 // SUB R6,#Offset8
thumb3E(u32 opcode)5358 static void thumb3E(u32 opcode) { SUB_RN_O8(6); }
5359 // SUB R7,#Offset8
thumb3F(u32 opcode)5360 static void thumb3F(u32 opcode) { SUB_RN_O8(7); }
5361
5362 // ALU operations /////////////////////////////////////////////////////////
5363
5364 // AND Rd, Rs
thumb40_0(u32 opcode)5365 static void thumb40_0(u32 opcode)
5366 {
5367 int dest = opcode & 7;
5368 u32 val = (bus.reg[dest].I & bus.reg[(opcode >> 3)&7].I);
5369
5370 //bus.reg[dest].I &= bus.reg[(opcode >> 3)&7].I;
5371 N_FLAG = val & 0x80000000 ? true : false;
5372 Z_FLAG = val ? false : true;
5373
5374 bus.reg[dest].I = val;
5375
5376 }
5377
5378 // EOR Rd, Rs
thumb40_1(u32 opcode)5379 static void thumb40_1(u32 opcode)
5380 {
5381 int dest = opcode & 7;
5382 bus.reg[dest].I ^= bus.reg[(opcode >> 3)&7].I;
5383 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5384 Z_FLAG = bus.reg[dest].I ? false : true;
5385 }
5386
5387 // LSL Rd, Rs
thumb40_2(u32 opcode)5388 static void thumb40_2(u32 opcode)
5389 {
5390 int dest = opcode & 7;
5391 u32 value = bus.reg[(opcode >> 3)&7].B.B0;
5392 u32 val = value;
5393 if(val) {
5394 if(val == 32) {
5395 value = 0;
5396 C_FLAG = (bus.reg[dest].I & 1 ? true : false);
5397 } else if(val < 32) {
5398 LSL_RD_RS;
5399 } else {
5400 value = 0;
5401 C_FLAG = false;
5402 }
5403 bus.reg[dest].I = value;
5404 }
5405 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5406 Z_FLAG = bus.reg[dest].I ? false : true;
5407 clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
5408 }
5409
5410 // LSR Rd, Rs
thumb40_3(u32 opcode)5411 static void thumb40_3(u32 opcode)
5412 {
5413 int dest = opcode & 7;
5414 u32 value = bus.reg[(opcode >> 3)&7].B.B0;
5415 u32 val = value;
5416 if(val) {
5417 if(val == 32) {
5418 value = 0;
5419 C_FLAG = (bus.reg[dest].I & 0x80000000 ? true : false);
5420 } else if(val < 32) {
5421 LSR_RD_RS;
5422 } else {
5423 value = 0;
5424 C_FLAG = false;
5425 }
5426 bus.reg[dest].I = value;
5427 }
5428 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5429 Z_FLAG = bus.reg[dest].I ? false : true;
5430 clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
5431 }
5432
5433 // ASR Rd, Rs
thumb41_0(u32 opcode)5434 static void thumb41_0(u32 opcode)
5435 {
5436 int dest = opcode & 7;
5437 u32 value = bus.reg[(opcode >> 3)&7].B.B0;
5438
5439 if(value) {
5440 if(value < 32) {
5441 ASR_RD_RS;
5442 bus.reg[dest].I = value;
5443 } else {
5444 if(bus.reg[dest].I & 0x80000000){
5445 bus.reg[dest].I = 0xFFFFFFFF;
5446 C_FLAG = true;
5447 } else {
5448 bus.reg[dest].I = 0x00000000;
5449 C_FLAG = false;
5450 }
5451 }
5452 }
5453 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5454 Z_FLAG = bus.reg[dest].I ? false : true;
5455 clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
5456 }
5457
5458 // ADC Rd, Rs
thumb41_1(u32 opcode)5459 static void thumb41_1(u32 opcode)
5460 {
5461 int dest = opcode & 0x07;
5462 u32 value = bus.reg[(opcode >> 3)&7].I;
5463 ADC_RD_RS;
5464 }
5465
5466 // SBC Rd, Rs
thumb41_2(u32 opcode)5467 static void thumb41_2(u32 opcode)
5468 {
5469 int dest = opcode & 0x07;
5470 u32 value = bus.reg[(opcode >> 3)&7].I;
5471 SBC_RD_RS;
5472 }
5473
5474 // ROR Rd, Rs
thumb41_3(u32 opcode)5475 static void thumb41_3(u32 opcode)
5476 {
5477 int dest = opcode & 7;
5478 u32 value = bus.reg[(opcode >> 3)&7].B.B0;
5479 u32 val = value;
5480 if(val) {
5481 value = value & 0x1f;
5482 if(val == 0) {
5483 C_FLAG = (bus.reg[dest].I & 0x80000000 ? true : false);
5484 } else {
5485 ROR_RD_RS;
5486 bus.reg[dest].I = value;
5487 }
5488 }
5489 clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
5490 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5491 Z_FLAG = bus.reg[dest].I ? false : true;
5492 }
5493
5494 // TST Rd, Rs
thumb42_0(u32 opcode)5495 static void thumb42_0(u32 opcode)
5496 {
5497 u32 value = bus.reg[opcode & 7].I & bus.reg[(opcode >> 3) & 7].I;
5498 N_FLAG = value & 0x80000000 ? true : false;
5499 Z_FLAG = value ? false : true;
5500 }
5501
5502 // NEG Rd, Rs
thumb42_1(u32 opcode)5503 static void thumb42_1(u32 opcode)
5504 {
5505 int dest = opcode & 7;
5506 int source = (opcode >> 3) & 7;
5507 NEG_RD_RS;
5508 }
5509
5510 // CMP Rd, Rs
thumb42_2(u32 opcode)5511 static void thumb42_2(u32 opcode)
5512 {
5513 int dest = opcode & 7;
5514 u32 value = bus.reg[(opcode >> 3)&7].I;
5515 CMP_RD_RS;
5516 }
5517
5518 // CMN Rd, Rs
thumb42_3(u32 opcode)5519 static void thumb42_3(u32 opcode)
5520 {
5521 int dest = opcode & 7;
5522 u32 value = bus.reg[(opcode >> 3)&7].I;
5523 CMN_RD_RS;
5524 }
5525
5526 // ORR Rd, Rs
thumb43_0(u32 opcode)5527 static void thumb43_0(u32 opcode)
5528 {
5529 int dest = opcode & 7;
5530 bus.reg[dest].I |= bus.reg[(opcode >> 3) & 7].I;
5531 Z_FLAG = bus.reg[dest].I ? false : true;
5532 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5533 }
5534
5535 // MUL Rd, Rs
thumb43_1(u32 opcode)5536 static void thumb43_1(u32 opcode)
5537 {
5538 clockTicks = 1;
5539 int dest = opcode & 7;
5540 u32 rm = bus.reg[dest].I;
5541 bus.reg[dest].I = bus.reg[(opcode >> 3) & 7].I * rm;
5542 if (((s32)rm) < 0)
5543 rm = ~rm;
5544 if ((rm & 0xFFFFFF00) == 0) {
5545 /* clockTicks += 0; */
5546 } else if ((rm & 0xFFFF0000) == 0)
5547 clockTicks += 1;
5548 else if ((rm & 0xFF000000) == 0)
5549 clockTicks += 2;
5550 else
5551 clockTicks += 3;
5552 bus.busPrefetchCount = (bus.busPrefetchCount<<clockTicks) | (0xFF>>(8-clockTicks));
5553 clockTicks += codeTicksAccess(bus.armNextPC, BITS_16) + 1;
5554 Z_FLAG = bus.reg[dest].I ? false : true;
5555 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5556 }
5557
5558 // BIC Rd, Rs
thumb43_2(u32 opcode)5559 static void thumb43_2(u32 opcode)
5560 {
5561 int dest = opcode & 7;
5562 bus.reg[dest].I &= (~bus.reg[(opcode >> 3) & 7].I);
5563 Z_FLAG = bus.reg[dest].I ? false : true;
5564 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5565 }
5566
5567 // MVN Rd, Rs
thumb43_3(u32 opcode)5568 static void thumb43_3(u32 opcode)
5569 {
5570 int dest = opcode & 7;
5571 bus.reg[dest].I = ~bus.reg[(opcode >> 3) & 7].I;
5572 Z_FLAG = bus.reg[dest].I ? false : true;
5573 N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
5574 }
5575
5576 // High-register instructions and BX //////////////////////////////////////
5577
5578 // ADD Rd, Hs
thumb44_1(u32 opcode)5579 static void thumb44_1(u32 opcode)
5580 {
5581 bus.reg[opcode&7].I += bus.reg[((opcode>>3)&7)+8].I;
5582 }
5583
5584 // ADD Hd, Rs
thumb44_2(u32 opcode)5585 static void thumb44_2(u32 opcode)
5586 {
5587 bus.reg[(opcode&7)+8].I += bus.reg[(opcode>>3)&7].I;
5588 if((opcode&7) == 7) {
5589 bus.reg[15].I &= 0xFFFFFFFE;
5590 bus.armNextPC = bus.reg[15].I;
5591 bus.reg[15].I += 2;
5592 THUMB_PREFETCH;
5593 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
5594 }
5595 }
5596
5597 // ADD Hd, Hs
thumb44_3(u32 opcode)5598 static void thumb44_3(u32 opcode)
5599 {
5600 bus.reg[(opcode&7)+8].I += bus.reg[((opcode>>3)&7)+8].I;
5601 if((opcode&7) == 7) {
5602 bus.reg[15].I &= 0xFFFFFFFE;
5603 bus.armNextPC = bus.reg[15].I;
5604 bus.reg[15].I += 2;
5605 THUMB_PREFETCH;
5606 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
5607 }
5608 }
5609
5610 // CMP Rd, Hs
thumb45_1(u32 opcode)5611 static void thumb45_1(u32 opcode)
5612 {
5613 int dest = opcode & 7;
5614 u32 value = bus.reg[((opcode>>3)&7)+8].I;
5615 CMP_RD_RS;
5616 }
5617
5618 // CMP Hd, Rs
thumb45_2(u32 opcode)5619 static void thumb45_2(u32 opcode)
5620 {
5621 int dest = (opcode & 7) + 8;
5622 u32 value = bus.reg[(opcode>>3)&7].I;
5623 CMP_RD_RS;
5624 }
5625
5626 // CMP Hd, Hs
thumb45_3(u32 opcode)5627 static void thumb45_3(u32 opcode)
5628 {
5629 int dest = (opcode & 7) + 8;
5630 u32 value = bus.reg[((opcode>>3)&7)+8].I;
5631 CMP_RD_RS;
5632 }
5633
5634 // MOV Rd, Rs
thumb46_0(u32 opcode)5635 static void thumb46_0(u32 opcode)
5636 {
5637 bus.reg[opcode&7].I = bus.reg[((opcode>>3)&7)].I;
5638 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
5639 }
5640
5641
5642 // MOV Rd, Hs
thumb46_1(u32 opcode)5643 static void thumb46_1(u32 opcode)
5644 {
5645 bus.reg[opcode&7].I = bus.reg[((opcode>>3)&7)+8].I;
5646 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
5647 }
5648
5649 // MOV Hd, Rs
thumb46_2(u32 opcode)5650 static void thumb46_2(u32 opcode)
5651 {
5652 bus.reg[(opcode&7)+8].I = bus.reg[(opcode>>3)&7].I;
5653 if((opcode&7) == 7) {
5654 bus.reg[15].I &= 0xFFFFFFFE;
5655 bus.armNextPC = bus.reg[15].I;
5656 bus.reg[15].I += 2;
5657 THUMB_PREFETCH;
5658 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
5659 }
5660 }
5661
5662 // MOV Hd, Hs
thumb46_3(u32 opcode)5663 static void thumb46_3(u32 opcode)
5664 {
5665 bus.reg[(opcode&7)+8].I = bus.reg[((opcode>>3)&7)+8].I;
5666 if((opcode&7) == 7) {
5667 bus.reg[15].I &= 0xFFFFFFFE;
5668 bus.armNextPC = bus.reg[15].I;
5669 bus.reg[15].I += 2;
5670 THUMB_PREFETCH;
5671 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
5672 }
5673 }
5674
5675
5676 // BX Rs
thumb47(u32 opcode)5677 static void thumb47(u32 opcode)
5678 {
5679 int base = (opcode >> 3) & 15;
5680 bus.busPrefetchCount=0;
5681 bus.reg[15].I = bus.reg[base].I;
5682 if(bus.reg[base].I & 1) {
5683 armState = false;
5684 bus.reg[15].I &= 0xFFFFFFFE;
5685 bus.armNextPC = bus.reg[15].I;
5686 bus.reg[15].I += 2;
5687 THUMB_PREFETCH;
5688 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
5689
5690 } else {
5691 armState = true;
5692 bus.reg[15].I &= 0xFFFFFFFC;
5693 bus.armNextPC = bus.reg[15].I;
5694 bus.reg[15].I += 4;
5695 ARM_PREFETCH;
5696 clockTicks = CLOCKTICKS_UPDATE_TYPE32P;
5697 }
5698 }
5699
5700 // Load/store instructions ////////////////////////////////////////////////
5701
5702 // LDR R0~R7,[PC, #Imm]
thumb48(u32 opcode)5703 static void thumb48(u32 opcode)
5704 {
5705 u8 regist = (opcode >> 8) & 7;
5706 if (bus.busPrefetchCount == 0)
5707 bus.busPrefetch = bus.busPrefetchEnable;
5708 u32 address = (bus.reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
5709 bus.reg[regist].I = CPUReadMemoryQuick(address);
5710 bus.busPrefetchCount=0;
5711 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5712 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5713 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5714 }
5715
5716 // STR Rd, [Rs, Rn]
thumb50(u32 opcode)5717 static void thumb50(u32 opcode)
5718 {
5719 if (bus.busPrefetchCount == 0)
5720 bus.busPrefetch = bus.busPrefetchEnable;
5721 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
5722 CPUWriteMemory(address, bus.reg[opcode & 7].I);
5723 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5724 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5725 clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
5726 }
5727
5728 // STRH Rd, [Rs, Rn]
thumb52(u32 opcode)5729 static void thumb52(u32 opcode)
5730 {
5731 if (bus.busPrefetchCount == 0)
5732 bus.busPrefetch = bus.busPrefetchEnable;
5733 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
5734 CPUWriteHalfWord(address, bus.reg[opcode&7].W.W0);
5735 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5736 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5737 clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
5738 }
5739
5740 // STRB Rd, [Rs, Rn]
thumb54(u32 opcode)5741 static void thumb54(u32 opcode)
5742 {
5743 if (bus.busPrefetchCount == 0)
5744 bus.busPrefetch = bus.busPrefetchEnable;
5745 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode >>6)&7].I;
5746 CPUWriteByte(address, bus.reg[opcode & 7].B.B0);
5747 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5748 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5749 clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
5750 }
5751
5752 // LDSB Rd, [Rs, Rn]
thumb56(u32 opcode)5753 static void thumb56(u32 opcode)
5754 {
5755 if (bus.busPrefetchCount == 0)
5756 bus.busPrefetch = bus.busPrefetchEnable;
5757 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
5758 bus.reg[opcode&7].I = (s8)CPUReadByte(address);
5759 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5760 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5761 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5762 }
5763
5764 // LDR Rd, [Rs, Rn]
thumb58(u32 opcode)5765 static void thumb58(u32 opcode)
5766 {
5767 if (bus.busPrefetchCount == 0)
5768 bus.busPrefetch = bus.busPrefetchEnable;
5769 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
5770 bus.reg[opcode&7].I = CPUReadMemory(address);
5771 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5772 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5773 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5774 }
5775
5776 // LDRH Rd, [Rs, Rn]
thumb5A(u32 opcode)5777 static void thumb5A(u32 opcode)
5778 {
5779 if (bus.busPrefetchCount == 0)
5780 bus.busPrefetch = bus.busPrefetchEnable;
5781 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
5782 bus.reg[opcode&7].I = CPUReadHalfWord(address);
5783 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5784 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5785 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5786 }
5787
5788 // LDRB Rd, [Rs, Rn]
thumb5C(u32 opcode)5789 static void thumb5C(u32 opcode)
5790 {
5791 if (bus.busPrefetchCount == 0)
5792 bus.busPrefetch = bus.busPrefetchEnable;
5793 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
5794 bus.reg[opcode&7].I = CPUReadByte(address);
5795 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5796 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5797 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5798 }
5799
5800 // LDSH Rd, [Rs, Rn]
thumb5E(u32 opcode)5801 static void thumb5E(u32 opcode)
5802 {
5803 if (bus.busPrefetchCount == 0)
5804 bus.busPrefetch = bus.busPrefetchEnable;
5805 u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
5806 bus.reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
5807 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5808 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5809 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5810 }
5811
5812 // STR Rd, [Rs, #Imm]
thumb60(u32 opcode)5813 static void thumb60(u32 opcode)
5814 {
5815 if (bus.busPrefetchCount == 0)
5816 bus.busPrefetch = bus.busPrefetchEnable;
5817 u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
5818 CPUWriteMemory(address, bus.reg[opcode&7].I);
5819 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5820 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5821 clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
5822 }
5823
5824 // LDR Rd, [Rs, #Imm]
thumb68(u32 opcode)5825 static void thumb68(u32 opcode)
5826 {
5827 if (bus.busPrefetchCount == 0)
5828 bus.busPrefetch = bus.busPrefetchEnable;
5829 u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
5830 bus.reg[opcode&7].I = CPUReadMemory(address);
5831 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5832 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5833 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5834 }
5835
5836 // STRB Rd, [Rs, #Imm]
thumb70(u32 opcode)5837 static void thumb70(u32 opcode)
5838 {
5839 if (bus.busPrefetchCount == 0)
5840 bus.busPrefetch = bus.busPrefetchEnable;
5841 u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31));
5842 CPUWriteByte(address, bus.reg[opcode&7].B.B0);
5843 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5844 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5845 clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
5846 }
5847
5848 // LDRB Rd, [Rs, #Imm]
thumb78(u32 opcode)5849 static void thumb78(u32 opcode)
5850 {
5851 if (bus.busPrefetchCount == 0)
5852 bus.busPrefetch = bus.busPrefetchEnable;
5853 u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31));
5854 bus.reg[opcode&7].I = CPUReadByte(address);
5855 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5856 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5857 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5858 }
5859
5860 // STRH Rd, [Rs, #Imm]
thumb80(u32 opcode)5861 static void thumb80(u32 opcode)
5862 {
5863 if (bus.busPrefetchCount == 0)
5864 bus.busPrefetch = bus.busPrefetchEnable;
5865 u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
5866 CPUWriteHalfWord(address, bus.reg[opcode&7].W.W0);
5867 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5868 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5869 clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
5870 }
5871
5872 // LDRH Rd, [Rs, #Imm]
thumb88(u32 opcode)5873 static void thumb88(u32 opcode)
5874 {
5875 if (bus.busPrefetchCount == 0)
5876 bus.busPrefetch = bus.busPrefetchEnable;
5877 u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
5878 bus.reg[opcode&7].I = CPUReadHalfWord(address);
5879 int dataticks_value = DATATICKS_ACCESS_16BIT(address);
5880 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5881 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5882 }
5883
5884 // STR R0~R7, [SP, #Imm]
thumb90(u32 opcode)5885 static void thumb90(u32 opcode)
5886 {
5887 u8 regist = (opcode >> 8) & 7;
5888 if (bus.busPrefetchCount == 0)
5889 bus.busPrefetch = bus.busPrefetchEnable;
5890 u32 address = bus.reg[13].I + ((opcode&255)<<2);
5891 CPUWriteMemory(address, bus.reg[regist].I);
5892 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5893 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5894 clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
5895 }
5896
5897 // LDR R0~R7, [SP, #Imm]
thumb98(u32 opcode)5898 static void thumb98(u32 opcode)
5899 {
5900 u8 regist = (opcode >> 8) & 7;
5901 if (bus.busPrefetchCount == 0)
5902 bus.busPrefetch = bus.busPrefetchEnable;
5903 u32 address = bus.reg[13].I + ((opcode&255)<<2);
5904 bus.reg[regist].I = CPUReadMemoryQuick(address);
5905 int dataticks_value = DATATICKS_ACCESS_32BIT(address);
5906 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
5907 clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
5908 }
5909
5910 // PC/stack-related ///////////////////////////////////////////////////////
5911
5912 // ADD R0~R7, PC, Imm
thumbA0(u32 opcode)5913 static void thumbA0(u32 opcode)
5914 {
5915 u8 regist = (opcode >> 8) & 7;
5916 bus.reg[regist].I = (bus.reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
5917 clockTicks = 1 + codeTicksAccess(bus.armNextPC, BITS_16);
5918 }
5919
5920 // ADD R0~R7, SP, Imm
thumbA8(u32 opcode)5921 static void thumbA8(u32 opcode)
5922 {
5923 u8 regist = (opcode >> 8) & 7;
5924 bus.reg[regist].I = bus.reg[13].I + ((opcode&255)<<2);
5925 clockTicks = 1 + codeTicksAccess(bus.armNextPC, BITS_16);
5926 }
5927
5928 // ADD SP, Imm
thumbB0(u32 opcode)5929 static void thumbB0(u32 opcode)
5930 {
5931 int offset = (opcode & 127) << 2;
5932 if(opcode & 0x80)
5933 offset = -offset;
5934 bus.reg[13].I += offset;
5935 clockTicks = 1 + codeTicksAccess(bus.armNextPC, BITS_16);
5936 }
5937
5938 // Push and pop ///////////////////////////////////////////////////////////
5939
5940 #define PUSH_REG(val, r) \
5941 if (opcode & (val)) { \
5942 CPUWriteMemory(address, bus.reg[(r)].I); \
5943 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
5944 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
5945 clockTicks += 1 + dataticks_value; \
5946 count++; \
5947 address += 4; \
5948 }
5949
5950 #define POP_REG(val, r) \
5951 if (opcode & (val)) { \
5952 bus.reg[(r)].I = CPUReadMemory(address); \
5953 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
5954 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
5955 clockTicks += 1 + dataticks_value; \
5956 count++; \
5957 address += 4; \
5958 }
5959
5960 // PUSH {Rlist}
thumbB4(u32 opcode)5961 static void thumbB4(u32 opcode)
5962 {
5963 if (bus.busPrefetchCount == 0)
5964 bus.busPrefetch = bus.busPrefetchEnable;
5965 int count = 0;
5966 u32 temp = bus.reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
5967 u32 address = temp & 0xFFFFFFFC;
5968 PUSH_REG(1, 0);
5969 PUSH_REG(2, 1);
5970 PUSH_REG(4, 2);
5971 PUSH_REG(8, 3);
5972 PUSH_REG(16, 4);
5973 PUSH_REG(32, 5);
5974 PUSH_REG(64, 6);
5975 PUSH_REG(128, 7);
5976 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_16);
5977 bus.reg[13].I = temp;
5978 }
5979
5980 // PUSH {Rlist, LR}
thumbB5(u32 opcode)5981 static void thumbB5(u32 opcode)
5982 {
5983 if (bus.busPrefetchCount == 0)
5984 bus.busPrefetch = bus.busPrefetchEnable;
5985 int count = 0;
5986 u32 temp = bus.reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
5987 u32 address = temp & 0xFFFFFFFC;
5988 PUSH_REG(1, 0);
5989 PUSH_REG(2, 1);
5990 PUSH_REG(4, 2);
5991 PUSH_REG(8, 3);
5992 PUSH_REG(16, 4);
5993 PUSH_REG(32, 5);
5994 PUSH_REG(64, 6);
5995 PUSH_REG(128, 7);
5996 PUSH_REG(256, 14);
5997 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_16);
5998 bus.reg[13].I = temp;
5999 }
6000
6001 // POP {Rlist}
thumbBC(u32 opcode)6002 static void thumbBC(u32 opcode)
6003 {
6004 if (bus.busPrefetchCount == 0)
6005 bus.busPrefetch = bus.busPrefetchEnable;
6006 int count = 0;
6007 u32 address = bus.reg[13].I & 0xFFFFFFFC;
6008 u32 temp = bus.reg[13].I + 4*cpuBitsSet[opcode & 0xFF];
6009 POP_REG(1, 0);
6010 POP_REG(2, 1);
6011 POP_REG(4, 2);
6012 POP_REG(8, 3);
6013 POP_REG(16, 4);
6014 POP_REG(32, 5);
6015 POP_REG(64, 6);
6016 POP_REG(128, 7);
6017 bus.reg[13].I = temp;
6018 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_16);
6019 }
6020
6021 // POP {Rlist, PC}
thumbBD(u32 opcode)6022 static void thumbBD(u32 opcode)
6023 {
6024 if (bus.busPrefetchCount == 0)
6025 bus.busPrefetch = bus.busPrefetchEnable;
6026 int count = 0;
6027 u32 address = bus.reg[13].I & 0xFFFFFFFC;
6028 u32 temp = bus.reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF];
6029 POP_REG(1, 0);
6030 POP_REG(2, 1);
6031 POP_REG(4, 2);
6032 POP_REG(8, 3);
6033 POP_REG(16, 4);
6034 POP_REG(32, 5);
6035 POP_REG(64, 6);
6036 POP_REG(128, 7);
6037 bus.reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
6038 int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address);
6039 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6040 clockTicks += 1 + dataticks_value;
6041 count++;
6042 bus.armNextPC = bus.reg[15].I;
6043 bus.reg[15].I += 2;
6044 bus.reg[13].I = temp;
6045 THUMB_PREFETCH;
6046 bus.busPrefetchCount = 0;
6047 clockTicks += 3 + (codeTicksAccess(bus.armNextPC, BITS_16) << 1);
6048 }
6049
6050 // Load/store multiple ////////////////////////////////////////////////////
6051
6052 #define THUMB_STM_REG(val,r,b) \
6053 if(opcode & (val)) { \
6054 CPUWriteMemory(address, bus.reg[(r)].I); \
6055 bus.reg[(b)].I = temp; \
6056 int dataticks_val = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
6057 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \
6058 clockTicks += 1 + dataticks_val; \
6059 count++; \
6060 address += 4; \
6061 }
6062
6063 #define THUMB_LDM_REG(val,r) \
6064 if(opcode & (val)) { \
6065 bus.reg[(r)].I = CPUReadMemory(address); \
6066 int dataticks_val = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
6067 DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \
6068 clockTicks += 1 + dataticks_val; \
6069 count++; \
6070 address += 4; \
6071 }
6072
6073 // STM R0~7!, {Rlist}
thumbC0(u32 opcode)6074 static void thumbC0(u32 opcode)
6075 {
6076 u8 regist = (opcode >> 8) & 7;
6077 if (bus.busPrefetchCount == 0)
6078 bus.busPrefetch = bus.busPrefetchEnable;
6079 u32 address = bus.reg[regist].I & 0xFFFFFFFC;
6080 u32 temp = bus.reg[regist].I + 4*cpuBitsSet[opcode & 0xff];
6081 int count = 0;
6082 // store
6083 THUMB_STM_REG(1, 0, regist);
6084 THUMB_STM_REG(2, 1, regist);
6085 THUMB_STM_REG(4, 2, regist);
6086 THUMB_STM_REG(8, 3, regist);
6087 THUMB_STM_REG(16, 4, regist);
6088 THUMB_STM_REG(32, 5, regist);
6089 THUMB_STM_REG(64, 6, regist);
6090 THUMB_STM_REG(128, 7, regist);
6091 clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_16);
6092 }
6093
6094 // LDM R0~R7!, {Rlist}
thumbC8(u32 opcode)6095 static void thumbC8(u32 opcode)
6096 {
6097 u8 regist = (opcode >> 8) & 7;
6098 if (bus.busPrefetchCount == 0)
6099 bus.busPrefetch = bus.busPrefetchEnable;
6100 u32 address = bus.reg[regist].I & 0xFFFFFFFC;
6101 u32 temp = bus.reg[regist].I + 4*cpuBitsSet[opcode & 0xFF];
6102 int count = 0;
6103 // load
6104 THUMB_LDM_REG(1, 0);
6105 THUMB_LDM_REG(2, 1);
6106 THUMB_LDM_REG(4, 2);
6107 THUMB_LDM_REG(8, 3);
6108 THUMB_LDM_REG(16, 4);
6109 THUMB_LDM_REG(32, 5);
6110 THUMB_LDM_REG(64, 6);
6111 THUMB_LDM_REG(128, 7);
6112 clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_16);
6113 if(!(opcode & (1<<regist)))
6114 bus.reg[regist].I = temp;
6115 }
6116
6117 // Conditional branches ///////////////////////////////////////////////////
6118
6119 // BEQ offset
thumbD0(u32 opcode)6120 static void thumbD0(u32 opcode)
6121 {
6122 #if !USE_TWEAK_SPEEDHACK
6123 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6124 #endif
6125 if(Z_FLAG)
6126 {
6127 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6128 bus.armNextPC = bus.reg[15].I;
6129 bus.reg[15].I += 2;
6130 THUMB_PREFETCH;
6131 #if USE_TWEAK_SPEEDHACK
6132 clockTicks = 30;
6133 #else
6134 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6135 #endif
6136 bus.busPrefetchCount=0;
6137 }
6138 }
6139
6140 // BNE offset
thumbD1(u32 opcode)6141 static void thumbD1(u32 opcode)
6142 {
6143 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6144 if(!Z_FLAG) {
6145 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6146 bus.armNextPC = bus.reg[15].I;
6147 bus.reg[15].I += 2;
6148 THUMB_PREFETCH;
6149 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6150 bus.busPrefetchCount=0;
6151 }
6152 }
6153
6154 // BCS offset
thumbD2(u32 opcode)6155 static void thumbD2(u32 opcode)
6156 {
6157 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6158 if(C_FLAG) {
6159 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6160 bus.armNextPC = bus.reg[15].I;
6161 bus.reg[15].I += 2;
6162 THUMB_PREFETCH;
6163 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6164 bus.busPrefetchCount=0;
6165 }
6166 }
6167
6168 // BCC offset
thumbD3(u32 opcode)6169 static void thumbD3(u32 opcode)
6170 {
6171 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6172 if(!C_FLAG) {
6173 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6174 bus.armNextPC = bus.reg[15].I;
6175 bus.reg[15].I += 2;
6176 THUMB_PREFETCH;
6177 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6178 bus.busPrefetchCount=0;
6179 }
6180 }
6181
6182 // BMI offset
thumbD4(u32 opcode)6183 static void thumbD4(u32 opcode)
6184 {
6185 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6186 if(N_FLAG) {
6187 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6188 bus.armNextPC = bus.reg[15].I;
6189 bus.reg[15].I += 2;
6190 THUMB_PREFETCH;
6191 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6192 bus.busPrefetchCount=0;
6193 }
6194 }
6195
6196 // BPL offset
thumbD5(u32 opcode)6197 static void thumbD5(u32 opcode)
6198 {
6199 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6200 if(!N_FLAG) {
6201 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6202 bus.armNextPC = bus.reg[15].I;
6203 bus.reg[15].I += 2;
6204 THUMB_PREFETCH;
6205 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6206 bus.busPrefetchCount=0;
6207 }
6208 }
6209
6210 // BVS offset
thumbD6(u32 opcode)6211 static void thumbD6(u32 opcode)
6212 {
6213 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6214 if(V_FLAG) {
6215 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6216 bus.armNextPC = bus.reg[15].I;
6217 bus.reg[15].I += 2;
6218 THUMB_PREFETCH;
6219 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6220 bus.busPrefetchCount=0;
6221 }
6222 }
6223
6224 // BVC offset
thumbD7(u32 opcode)6225 static void thumbD7(u32 opcode)
6226 {
6227 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6228 if(!V_FLAG) {
6229 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6230 bus.armNextPC = bus.reg[15].I;
6231 bus.reg[15].I += 2;
6232 THUMB_PREFETCH;
6233 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6234 bus.busPrefetchCount=0;
6235 }
6236 }
6237
6238 // BHI offset
thumbD8(u32 opcode)6239 static void thumbD8(u32 opcode)
6240 {
6241 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6242 if(C_FLAG && !Z_FLAG) {
6243 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6244 bus.armNextPC = bus.reg[15].I;
6245 bus.reg[15].I += 2;
6246 THUMB_PREFETCH;
6247 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6248 bus.busPrefetchCount=0;
6249 }
6250 }
6251
6252 // BLS offset
thumbD9(u32 opcode)6253 static void thumbD9(u32 opcode)
6254 {
6255 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6256 if(!C_FLAG || Z_FLAG) {
6257 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6258 bus.armNextPC = bus.reg[15].I;
6259 bus.reg[15].I += 2;
6260 THUMB_PREFETCH;
6261 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6262 bus.busPrefetchCount=0;
6263 }
6264 }
6265
6266 // BGE offset
thumbDA(u32 opcode)6267 static void thumbDA(u32 opcode)
6268 {
6269 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6270 if(N_FLAG == V_FLAG) {
6271 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6272 bus.armNextPC = bus.reg[15].I;
6273 bus.reg[15].I += 2;
6274 THUMB_PREFETCH;
6275 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6276 bus.busPrefetchCount=0;
6277 }
6278 }
6279
6280 // BLT offset
thumbDB(u32 opcode)6281 static void thumbDB(u32 opcode)
6282 {
6283 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6284 if(N_FLAG != V_FLAG) {
6285 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6286 bus.armNextPC = bus.reg[15].I;
6287 bus.reg[15].I += 2;
6288 THUMB_PREFETCH;
6289 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6290 bus.busPrefetchCount=0;
6291 }
6292 }
6293
6294 // BGT offset
thumbDC(u32 opcode)6295 static void thumbDC(u32 opcode)
6296 {
6297 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6298 if(!Z_FLAG && (N_FLAG == V_FLAG)) {
6299 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6300 bus.armNextPC = bus.reg[15].I;
6301 bus.reg[15].I += 2;
6302 THUMB_PREFETCH;
6303 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6304 bus.busPrefetchCount=0;
6305 }
6306 }
6307
6308 // BLE offset
thumbDD(u32 opcode)6309 static void thumbDD(u32 opcode)
6310 {
6311 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6312 if(Z_FLAG || (N_FLAG != V_FLAG)) {
6313 bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6314 bus.armNextPC = bus.reg[15].I;
6315 bus.reg[15].I += 2;
6316 THUMB_PREFETCH;
6317 clockTicks += codeTicksAccessSeq16(bus.armNextPC) + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6318 bus.busPrefetchCount=0;
6319 }
6320 }
6321
6322 // SWI, B, BL /////////////////////////////////////////////////////////////
6323
6324 // SWI #comment
thumbDF(u32 opcode)6325 static void thumbDF(u32 opcode)
6326 {
6327 clockTicks = 3;
6328 bus.busPrefetchCount=0;
6329 CPUSoftwareInterrupt(opcode & 0xFF);
6330 }
6331
6332 // B offset
thumbE0(u32 opcode)6333 static void thumbE0(u32 opcode)
6334 {
6335 int offset = (opcode & 0x3FF) << 1;
6336 if(opcode & 0x0400)
6337 offset |= 0xFFFFF800;
6338 bus.reg[15].I += offset;
6339 bus.armNextPC = bus.reg[15].I;
6340 bus.reg[15].I += 2;
6341 THUMB_PREFETCH;
6342 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
6343 bus.busPrefetchCount=0;
6344 }
6345
6346 // BLL #offset (forward)
thumbF0(u32 opcode)6347 static void thumbF0(u32 opcode)
6348 {
6349 int offset = (opcode & 0x7FF);
6350 bus.reg[14].I = bus.reg[15].I + (offset << 12);
6351 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6352 }
6353
6354 // BLL #offset (backward)
thumbF4(u32 opcode)6355 static void thumbF4(u32 opcode)
6356 {
6357 int offset = (opcode & 0x7FF);
6358 bus.reg[14].I = bus.reg[15].I + ((offset << 12) | 0xFF800000);
6359 clockTicks = CLOCKTICKS_UPDATE_TYPE16;
6360 }
6361
6362 // BLH #offset
thumbF8(u32 opcode)6363 static void thumbF8(u32 opcode)
6364 {
6365 int offset = (opcode & 0x7FF);
6366 u32 temp = bus.reg[15].I-2;
6367 bus.reg[15].I = (bus.reg[14].I + (offset<<1))&0xFFFFFFFE;
6368 bus.armNextPC = bus.reg[15].I;
6369 bus.reg[15].I += 2;
6370 bus.reg[14].I = temp|1;
6371 THUMB_PREFETCH;
6372 clockTicks = CLOCKTICKS_UPDATE_TYPE16P;
6373 bus.busPrefetchCount = 0;
6374 }
6375
6376 // Instruction table //////////////////////////////////////////////////////
6377
6378 typedef void (*insnfunc_t)(u32 opcode);
6379 #define thumbUI thumbUnknownInsn
6380 #define thumbBP thumbUnknownInsn
6381
6382 static insnfunc_t thumbInsnTable[1024] =
6383 {
6384 thumb00_00,thumb00_01,thumb00_02,thumb00_03,thumb00_04,thumb00_05,thumb00_06,thumb00_07, // 00
6385 thumb00_08,thumb00_09,thumb00_0A,thumb00_0B,thumb00_0C,thumb00_0D,thumb00_0E,thumb00_0F,
6386 thumb00_10,thumb00_11,thumb00_12,thumb00_13,thumb00_14,thumb00_15,thumb00_16,thumb00_17,
6387 thumb00_18,thumb00_19,thumb00_1A,thumb00_1B,thumb00_1C,thumb00_1D,thumb00_1E,thumb00_1F,
6388 thumb08_00,thumb08_01,thumb08_02,thumb08_03,thumb08_04,thumb08_05,thumb08_06,thumb08_07, // 08
6389 thumb08_08,thumb08_09,thumb08_0A,thumb08_0B,thumb08_0C,thumb08_0D,thumb08_0E,thumb08_0F,
6390 thumb08_10,thumb08_11,thumb08_12,thumb08_13,thumb08_14,thumb08_15,thumb08_16,thumb08_17,
6391 thumb08_18,thumb08_19,thumb08_1A,thumb08_1B,thumb08_1C,thumb08_1D,thumb08_1E,thumb08_1F,
6392 thumb10_00,thumb10_01,thumb10_02,thumb10_03,thumb10_04,thumb10_05,thumb10_06,thumb10_07, // 10
6393 thumb10_08,thumb10_09,thumb10_0A,thumb10_0B,thumb10_0C,thumb10_0D,thumb10_0E,thumb10_0F,
6394 thumb10_10,thumb10_11,thumb10_12,thumb10_13,thumb10_14,thumb10_15,thumb10_16,thumb10_17,
6395 thumb10_18,thumb10_19,thumb10_1A,thumb10_1B,thumb10_1C,thumb10_1D,thumb10_1E,thumb10_1F,
6396 thumb18_0,thumb18_1,thumb18_2,thumb18_3,thumb18_4,thumb18_5,thumb18_6,thumb18_7, // 18
6397 thumb1A_0,thumb1A_1,thumb1A_2,thumb1A_3,thumb1A_4,thumb1A_5,thumb1A_6,thumb1A_7,
6398 thumb1C_0,thumb1C_1,thumb1C_2,thumb1C_3,thumb1C_4,thumb1C_5,thumb1C_6,thumb1C_7,
6399 thumb1E_0,thumb1E_1,thumb1E_2,thumb1E_3,thumb1E_4,thumb1E_5,thumb1E_6,thumb1E_7,
6400 thumb20,thumb20,thumb20,thumb20,thumb21,thumb21,thumb21,thumb21, // 20
6401 thumb22,thumb22,thumb22,thumb22,thumb23,thumb23,thumb23,thumb23,
6402 thumb24,thumb24,thumb24,thumb24,thumb25,thumb25,thumb25,thumb25,
6403 thumb26,thumb26,thumb26,thumb26,thumb27,thumb27,thumb27,thumb27,
6404 thumb28,thumb28,thumb28,thumb28,thumb29,thumb29,thumb29,thumb29, // 28
6405 thumb2A,thumb2A,thumb2A,thumb2A,thumb2B,thumb2B,thumb2B,thumb2B,
6406 thumb2C,thumb2C,thumb2C,thumb2C,thumb2D,thumb2D,thumb2D,thumb2D,
6407 thumb2E,thumb2E,thumb2E,thumb2E,thumb2F,thumb2F,thumb2F,thumb2F,
6408 thumb30,thumb30,thumb30,thumb30,thumb31,thumb31,thumb31,thumb31, // 30
6409 thumb32,thumb32,thumb32,thumb32,thumb33,thumb33,thumb33,thumb33,
6410 thumb34,thumb34,thumb34,thumb34,thumb35,thumb35,thumb35,thumb35,
6411 thumb36,thumb36,thumb36,thumb36,thumb37,thumb37,thumb37,thumb37,
6412 thumb38,thumb38,thumb38,thumb38,thumb39,thumb39,thumb39,thumb39, // 38
6413 thumb3A,thumb3A,thumb3A,thumb3A,thumb3B,thumb3B,thumb3B,thumb3B,
6414 thumb3C,thumb3C,thumb3C,thumb3C,thumb3D,thumb3D,thumb3D,thumb3D,
6415 thumb3E,thumb3E,thumb3E,thumb3E,thumb3F,thumb3F,thumb3F,thumb3F,
6416 thumb40_0,thumb40_1,thumb40_2,thumb40_3,thumb41_0,thumb41_1,thumb41_2,thumb41_3, // 40
6417 thumb42_0,thumb42_1,thumb42_2,thumb42_3,thumb43_0,thumb43_1,thumb43_2,thumb43_3,
6418 thumbUI,thumb44_1,thumb44_2,thumb44_3,thumbUI,thumb45_1,thumb45_2,thumb45_3,
6419 thumb46_0,thumb46_1,thumb46_2,thumb46_3,thumb47,thumb47,thumbUI,thumbUI,
6420 thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48, // 48
6421 thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
6422 thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
6423 thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
6424 thumb50,thumb50,thumb50,thumb50,thumb50,thumb50,thumb50,thumb50, // 50
6425 thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,
6426 thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,
6427 thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,
6428 thumb58,thumb58,thumb58,thumb58,thumb58,thumb58,thumb58,thumb58, // 58
6429 thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,
6430 thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,
6431 thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,
6432 thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60, // 60
6433 thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
6434 thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
6435 thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
6436 thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68, // 68
6437 thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
6438 thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
6439 thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
6440 thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70, // 70
6441 thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
6442 thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
6443 thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
6444 thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78, // 78
6445 thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
6446 thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
6447 thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
6448 thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80, // 80
6449 thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
6450 thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
6451 thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
6452 thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88, // 88
6453 thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
6454 thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
6455 thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
6456 thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90, // 90
6457 thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
6458 thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
6459 thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
6460 thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98, // 98
6461 thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
6462 thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
6463 thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
6464 thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0, // A0
6465 thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
6466 thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
6467 thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
6468 thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8, // A8
6469 thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
6470 thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
6471 thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
6472 thumbB0,thumbB0,thumbB0,thumbB0,thumbUI,thumbUI,thumbUI,thumbUI, // B0
6473 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
6474 thumbB4,thumbB4,thumbB4,thumbB4,thumbB5,thumbB5,thumbB5,thumbB5,
6475 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
6476 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI, // B8
6477 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
6478 thumbBC,thumbBC,thumbBC,thumbBC,thumbBD,thumbBD,thumbBD,thumbBD,
6479 thumbBP,thumbBP,thumbBP,thumbBP,thumbUI,thumbUI,thumbUI,thumbUI,
6480 thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0, // C0
6481 thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
6482 thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
6483 thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
6484 thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8, // C8
6485 thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
6486 thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
6487 thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
6488 thumbD0,thumbD0,thumbD0,thumbD0,thumbD1,thumbD1,thumbD1,thumbD1, // D0
6489 thumbD2,thumbD2,thumbD2,thumbD2,thumbD3,thumbD3,thumbD3,thumbD3,
6490 thumbD4,thumbD4,thumbD4,thumbD4,thumbD5,thumbD5,thumbD5,thumbD5,
6491 thumbD6,thumbD6,thumbD6,thumbD6,thumbD7,thumbD7,thumbD7,thumbD7,
6492 thumbD8,thumbD8,thumbD8,thumbD8,thumbD9,thumbD9,thumbD9,thumbD9, // D8
6493 thumbDA,thumbDA,thumbDA,thumbDA,thumbDB,thumbDB,thumbDB,thumbDB,
6494 thumbDC,thumbDC,thumbDC,thumbDC,thumbDD,thumbDD,thumbDD,thumbDD,
6495 thumbUI,thumbUI,thumbUI,thumbUI,thumbDF,thumbDF,thumbDF,thumbDF,
6496 thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0, // E0
6497 thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
6498 thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
6499 thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
6500 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI, // E8
6501 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
6502 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
6503 thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
6504 thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0, // F0
6505 thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,
6506 thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,
6507 thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,
6508 thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8, // F8
6509 thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
6510 thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
6511 thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
6512 };
6513
6514 // Wrapper routine (execution loop) ///////////////////////////////////////
6515
6516
thumbExecute(void)6517 static int thumbExecute (void)
6518 {
6519 int ct = 0;
6520 bool test = false;
6521
6522 CACHE_PREFETCH(clockTicks);
6523
6524 do
6525 {
6526 clockTicks = 0;
6527
6528 #if USE_CHEATS
6529 cpuMasterCodeCheck();
6530 #endif
6531
6532 #if 0
6533 if ((bus.armNextPC & 0x0803FFFF) == 0x08020000)
6534 bus.busPrefetchCount=0x100;
6535 #endif
6536
6537 u32 opcode = cpuPrefetch[0];
6538 cpuPrefetch[0] = cpuPrefetch[1];
6539
6540 bus.busPrefetch = false;
6541 #if 0
6542 if (bus.busPrefetchCount & 0xFFFFFF00)
6543 bus.busPrefetchCount = 0x100 | (bus.busPrefetchCount & 0xFF);
6544 #endif
6545
6546 u32 oldArmNextPC = bus.armNextPC;
6547
6548 bus.armNextPC = bus.reg[15].I;
6549 bus.reg[15].I += 2;
6550 THUMB_PREFETCH_NEXT;
6551
6552 (*thumbInsnTable[opcode>>6])(opcode);
6553
6554 ct = clockTicks;
6555
6556 if (ct < 0)
6557 return 0;
6558
6559 /// better pipelining
6560 if (ct==0)
6561 clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1;
6562
6563 cpuTotalTicks += clockTicks;
6564
6565
6566 test = cpuTotalTicks < cpuNextEvent && !armState && !holdState;
6567 #ifdef USE_SWITICKS
6568 test = test && !SWITicks;
6569 #endif
6570 }while (test);
6571
6572 return 1;
6573 }
6574
6575 /*============================================================
6576 GBA GFX
6577 ============================================================ */
6578
6579 static u32 map_widths[] = { 256, 512, 256, 512 };
6580 static u32 map_heights[] = { 256, 256, 512, 512 };
6581
6582 #ifdef TILED_RENDERING
6583 #ifdef _MSC_VER
6584 union u8h
6585 {
6586 __pragma( pack(push, 1));
6587 struct
6588 {
6589 #ifdef MSB_FIRST
6590 /* 4*/ unsigned char hi:4;
6591 /* 0*/ unsigned char lo:4;
6592 #else
6593 /* 0*/ unsigned char lo:4;
6594 /* 4*/ unsigned char hi:4;
6595 #endif
6596 }
6597 __pragma(pack(pop));
6598 u8 val;
6599 };
6600 #else
6601 union u8h
6602 {
6603 struct
6604 {
6605 #ifdef MSB_FIRST
6606 /* 4*/ unsigned char hi:4;
6607 /* 0*/ unsigned char lo:4;
6608 #else
6609 /* 0*/ unsigned char lo:4;
6610 /* 4*/ unsigned char hi:4;
6611 #endif
6612 } __attribute__ ((packed));
6613 u8 val;
6614 };
6615 #endif
6616
6617 union TileEntry
6618 {
6619 struct
6620 {
6621 #ifdef MSB_FIRST
6622 /*14*/ unsigned palette:4;
6623 /*13*/ unsigned vFlip:1;
6624 /*12*/ unsigned hFlip:1;
6625 /* 0*/ unsigned tileNum:10;
6626 #else
6627 /* 0*/ unsigned tileNum:10;
6628 /*12*/ unsigned hFlip:1;
6629 /*13*/ unsigned vFlip:1;
6630 /*14*/ unsigned palette:4;
6631 #endif
6632 };
6633 u16 val;
6634 };
6635
6636 struct TileLine
6637 {
6638 u32 pixels[8];
6639 };
6640
6641 typedef const TileLine (*TileReader) (const u16 *, const int, const u8 *, u16 *, const u32);
6642
gfxDrawPixel(u32 * dest,const u8 color,const u16 * palette,const u32 prio)6643 static inline void gfxDrawPixel(u32 *dest, const u8 color, const u16 *palette, const u32 prio)
6644 {
6645 *dest = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
6646 }
6647
gfxReadTile(const u16 * screenSource,const int yyy,const u8 * charBase,u16 * palette,const u32 prio)6648 inline const TileLine gfxReadTile(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
6649 {
6650 TileEntry tile;
6651 tile.val = READ16LE(screenSource);
6652
6653 int tileY = yyy & 7;
6654 if (tile.vFlip) tileY = 7 - tileY;
6655 TileLine tileLine;
6656
6657 const u8 *tileBase = &charBase[tile.tileNum * 64 + tileY * 8];
6658
6659 if (!tile.hFlip)
6660 {
6661 gfxDrawPixel(&tileLine.pixels[0], tileBase[0], palette, prio);
6662 gfxDrawPixel(&tileLine.pixels[1], tileBase[1], palette, prio);
6663 gfxDrawPixel(&tileLine.pixels[2], tileBase[2], palette, prio);
6664 gfxDrawPixel(&tileLine.pixels[3], tileBase[3], palette, prio);
6665 gfxDrawPixel(&tileLine.pixels[4], tileBase[4], palette, prio);
6666 gfxDrawPixel(&tileLine.pixels[5], tileBase[5], palette, prio);
6667 gfxDrawPixel(&tileLine.pixels[6], tileBase[6], palette, prio);
6668 gfxDrawPixel(&tileLine.pixels[7], tileBase[7], palette, prio);
6669 }
6670 else
6671 {
6672 gfxDrawPixel(&tileLine.pixels[0], tileBase[7], palette, prio);
6673 gfxDrawPixel(&tileLine.pixels[1], tileBase[6], palette, prio);
6674 gfxDrawPixel(&tileLine.pixels[2], tileBase[5], palette, prio);
6675 gfxDrawPixel(&tileLine.pixels[3], tileBase[4], palette, prio);
6676 gfxDrawPixel(&tileLine.pixels[4], tileBase[3], palette, prio);
6677 gfxDrawPixel(&tileLine.pixels[5], tileBase[2], palette, prio);
6678 gfxDrawPixel(&tileLine.pixels[6], tileBase[1], palette, prio);
6679 gfxDrawPixel(&tileLine.pixels[7], tileBase[0], palette, prio);
6680 }
6681
6682 return tileLine;
6683 }
6684
gfxReadTilePal(const u16 * screenSource,const int yyy,const u8 * charBase,u16 * palette,const u32 prio)6685 inline const TileLine gfxReadTilePal(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
6686 {
6687 TileEntry tile;
6688 tile.val = READ16LE(screenSource);
6689
6690 int tileY = yyy & 7;
6691 if (tile.vFlip) tileY = 7 - tileY;
6692 palette += tile.palette * 16;
6693 TileLine tileLine;
6694
6695 const u8h *tileBase = (u8h*) &charBase[tile.tileNum * 32 + tileY * 4];
6696
6697 if (!tile.hFlip)
6698 {
6699 gfxDrawPixel(&tileLine.pixels[0], tileBase[0].lo, palette, prio);
6700 gfxDrawPixel(&tileLine.pixels[1], tileBase[0].hi, palette, prio);
6701 gfxDrawPixel(&tileLine.pixels[2], tileBase[1].lo, palette, prio);
6702 gfxDrawPixel(&tileLine.pixels[3], tileBase[1].hi, palette, prio);
6703 gfxDrawPixel(&tileLine.pixels[4], tileBase[2].lo, palette, prio);
6704 gfxDrawPixel(&tileLine.pixels[5], tileBase[2].hi, palette, prio);
6705 gfxDrawPixel(&tileLine.pixels[6], tileBase[3].lo, palette, prio);
6706 gfxDrawPixel(&tileLine.pixels[7], tileBase[3].hi, palette, prio);
6707 }
6708 else
6709 {
6710 gfxDrawPixel(&tileLine.pixels[0], tileBase[3].hi, palette, prio);
6711 gfxDrawPixel(&tileLine.pixels[1], tileBase[3].lo, palette, prio);
6712 gfxDrawPixel(&tileLine.pixels[2], tileBase[2].hi, palette, prio);
6713 gfxDrawPixel(&tileLine.pixels[3], tileBase[2].lo, palette, prio);
6714 gfxDrawPixel(&tileLine.pixels[4], tileBase[1].hi, palette, prio);
6715 gfxDrawPixel(&tileLine.pixels[5], tileBase[1].lo, palette, prio);
6716 gfxDrawPixel(&tileLine.pixels[6], tileBase[0].hi, palette, prio);
6717 gfxDrawPixel(&tileLine.pixels[7], tileBase[0].lo, palette, prio);
6718 }
6719
6720 return tileLine;
6721 }
6722
gfxDrawTile(const TileLine & tileLine,u32 * _line)6723 static inline void gfxDrawTile(const TileLine &tileLine, u32* _line)
6724 {
6725 #if HAVE_NEON
6726 neon_memcpy(_line, tileLine.pixels, sizeof(tileLine.pixels));
6727 #else
6728 memcpy(_line, tileLine.pixels, sizeof(tileLine.pixels));
6729 #endif
6730 }
6731
gfxDrawTileClipped(const TileLine & tileLine,u32 * _line,const int start,int w)6732 static inline void gfxDrawTileClipped(const TileLine &tileLine, u32* _line, const int start, int w)
6733 {
6734 #if HAVE_NEON
6735 neon_memcpy(_line, tileLine.pixels + start, w * sizeof(u32));
6736 #else
6737 memcpy(_line, tileLine.pixels + start, w * sizeof(u32));
6738 #endif
6739 }
6740
6741 template<TileReader readTile, int layer, int renderer_idx>
gfxDrawTextScreen(u16 control,u16 hofs,u16 vofs)6742 static void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs)
6743 {
6744 INIT_RENDERER_CONTEXT(renderer_idx);
6745
6746 u16 *palette = (u16 *)RENDERER_PALETTE;
6747 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
6748 u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
6749 u32 prio = ((control & 3)<<25) + 0x1000000;
6750 int sizeX = 256;
6751 int sizeY = 256;
6752 switch ((control >> 14) & 3)
6753 {
6754 case 0:
6755 break;
6756 case 1:
6757 sizeX = 512;
6758 break;
6759 case 2:
6760 sizeY = 512;
6761 break;
6762 case 3:
6763 sizeX = 512;
6764 sizeY = 512;
6765 break;
6766 }
6767
6768 int maskX = sizeX-1;
6769 int maskY = sizeY-1;
6770
6771 bool mosaicOn = (control & 0x40) ? true : false;
6772
6773 int xxx = hofs & maskX;
6774 int yyy = (vofs + RENDERER_R_VCOUNT) & maskY;
6775 int mosaicX = (RENDERER_MOSAIC & 0x000F)+1;
6776 int mosaicY = ((RENDERER_MOSAIC & 0x00F0)>>4)+1;
6777
6778 if (mosaicOn)
6779 {
6780 if ((RENDERER_R_VCOUNT % mosaicY) != 0)
6781 {
6782 mosaicY = RENDERER_R_VCOUNT - (RENDERER_R_VCOUNT % mosaicY);
6783 yyy = (vofs + mosaicY) & maskY;
6784 }
6785 }
6786
6787 if (yyy > 255 && sizeY > 256)
6788 {
6789 yyy &= 255;
6790 screenBase += 0x400;
6791 if (sizeX > 256)
6792 screenBase += 0x400;
6793 }
6794
6795 int yshift = ((yyy>>3)<<5);
6796
6797 u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
6798 int x = 0;
6799 const int firstTileX = xxx & 7;
6800
6801 // First tile, if clipped
6802 if (firstTileX)
6803 {
6804 gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &RENDERER_LINE[layer][x], firstTileX, 8 - firstTileX);
6805 screenSource++;
6806 x += 8 - firstTileX;
6807 xxx += 8 - firstTileX;
6808
6809 if (xxx == 256 && sizeX > 256)
6810 {
6811 screenSource = screenBase + 0x400 + yshift;
6812 }
6813 else if (xxx >= sizeX)
6814 {
6815 xxx = 0;
6816 screenSource = screenBase + yshift;
6817 }
6818 }
6819
6820 // Middle tiles, full
6821 while (x < 240 - firstTileX)
6822 {
6823 gfxDrawTile(readTile(screenSource, yyy, charBase, palette, prio), &RENDERER_LINE[layer][x]);
6824 screenSource++;
6825 xxx += 8;
6826 x += 8;
6827
6828 if (xxx == 256 && sizeX > 256)
6829 {
6830 screenSource = screenBase + 0x400 + yshift;
6831 }
6832 else if (xxx >= sizeX)
6833 {
6834 xxx = 0;
6835 screenSource = screenBase + yshift;
6836 }
6837 }
6838
6839 // Last tile, if clipped
6840 if (firstTileX)
6841 {
6842 gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &RENDERER_LINE[layer][x], 0, firstTileX);
6843 }
6844
6845 if (mosaicOn)
6846 {
6847 if (mosaicX > 1)
6848 {
6849 MOSAIC_LOOP(layer, mosaicX);
6850 }
6851 }
6852 }
6853
6854 template<int layer, int renderer_idx>
gfxDrawTextScreen(u16 control,u16 hofs,u16 vofs)6855 void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs)
6856 {
6857 if (control & 0x80) // 1 pal / 256 col
6858 gfxDrawTextScreen<gfxReadTile, layer, renderer_idx>(control, hofs, vofs);
6859 else // 16 pal / 16 col
6860 gfxDrawTextScreen<gfxReadTilePal, layer, renderer_idx>(control, hofs, vofs);
6861 }
6862 #else
6863
6864 template<int layer, int renderer_idx>
gfxDrawTextScreen(u16 control,u16 hofs,u16 vofs)6865 static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs)
6866 {
6867 u16 *palette = (u16 *)RENDERER_PALETTE;
6868 u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
6869 u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
6870 u32 prio = ((control & 3)<<25) + 0x1000000;
6871 int sizeX = 256;
6872 int sizeY = 256;
6873 switch((control >> 14) & 3) {
6874 case 0:
6875 break;
6876 case 1:
6877 sizeX = 512;
6878 break;
6879 case 2:
6880 sizeY = 512;
6881 break;
6882 case 3:
6883 sizeX = 512;
6884 sizeY = 512;
6885 break;
6886 }
6887
6888 int maskX = sizeX-1;
6889 int maskY = sizeY-1;
6890
6891 bool mosaicOn = (control & 0x40) ? true : false;
6892
6893 int xxx = hofs & maskX;
6894 int yyy = (vofs + RENDERER_R_VCOUNT) & maskY;
6895 int mosaicX = (RENDERER_MOSAIC & 0x000F)+1;
6896 int mosaicY = ((RENDERER_MOSAIC & 0x00F0)>>4)+1;
6897
6898 if(mosaicOn) {
6899 if((RENDERER_R_VCOUNT % mosaicY) != 0) {
6900 mosaicY = RENDERER_R_VCOUNT - (RENDERER_R_VCOUNT % mosaicY);
6901 yyy = (vofs + mosaicY) & maskY;
6902 }
6903 }
6904
6905 if(yyy > 255 && sizeY > 256) {
6906 yyy &= 255;
6907 screenBase += 0x400;
6908 if(sizeX > 256)
6909 screenBase += 0x400;
6910 }
6911
6912 int yshift = ((yyy>>3)<<5);
6913 if((control) & 0x80) {
6914 u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
6915 for(int x = 0; x < 240; x++) {
6916 u16 data = READ16LE(screenSource);
6917
6918 int tile = data & 0x3FF;
6919 int tileX = (xxx & 7);
6920 int tileY = yyy & 7;
6921
6922 if(tileX == 7)
6923 screenSource++;
6924
6925 if(data & 0x0400)
6926 tileX = 7 - tileX;
6927 if(data & 0x0800)
6928 tileY = 7 - tileY;
6929
6930 u8 color = charBase[tile * 64 + tileY * 8 + tileX];
6931
6932 RENDERER_LINE[layer][x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
6933
6934 xxx++;
6935 if(xxx == 256) {
6936 if(sizeX > 256)
6937 screenSource = screenBase + 0x400 + yshift;
6938 else {
6939 screenSource = screenBase + yshift;
6940 xxx = 0;
6941 }
6942 } else if(xxx >= sizeX) {
6943 xxx = 0;
6944 screenSource = screenBase + yshift;
6945 }
6946 }
6947 } else {
6948 u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) +
6949 yshift;
6950 for(int x = 0; x < 240; x++) {
6951 u16 data = READ16LE(screenSource);
6952
6953 int tile = data & 0x3FF;
6954 int tileX = (xxx & 7);
6955 int tileY = yyy & 7;
6956
6957 if(tileX == 7)
6958 screenSource++;
6959
6960 if(data & 0x0400)
6961 tileX = 7 - tileX;
6962 if(data & 0x0800)
6963 tileY = 7 - tileY;
6964
6965 u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)];
6966
6967 if(tileX & 1) {
6968 color = (color >> 4);
6969 } else {
6970 color &= 0x0F;
6971 }
6972
6973 int pal = (data>>8) & 0xF0;
6974 RENDERER_LINE[layer][x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000;
6975
6976 xxx++;
6977 if(xxx == 256) {
6978 if(sizeX > 256)
6979 screenSource = screenBase + 0x400 + yshift;
6980 else {
6981 screenSource = screenBase + yshift;
6982 xxx = 0;
6983 }
6984 } else if(xxx >= sizeX) {
6985 xxx = 0;
6986 screenSource = screenBase + yshift;
6987 }
6988 }
6989 }
6990 if(mosaicOn) {
6991 if(mosaicX > 1) {
6992 MOSAIC_LOOP(layer, mosaicX);
6993 }
6994 }
6995 }
6996 #endif
6997
6998 static u32 map_sizes_rot[] = { 128, 256, 512, 1024 };
6999
7000 #if THREADED_RENDERER
fetchDrawRotScreen(u16 control,u16 x_l,u16 x_h,u16 y_l,u16 y_h,u16 pa,u16 pb,u16 pc,u16 pd,int & currentX,int & currentY,int changed)7001 static INLINE void fetchDrawRotScreen(u16 control, u16 x_l, u16 x_h, u16 y_l, u16 y_h, u16 pa, u16 pb, u16 pc, u16 pd, int& currentX, int& currentY, int changed)
7002 {
7003 #ifdef BRANCHLESS_GBA_GFX
7004 int dx = pa & 0x7FFF;
7005 int dmx = pb & 0x7FFF;
7006 int dy = pc & 0x7FFF;
7007 int dmy = pd & 0x7FFF;
7008
7009 dx |= isel(-(pa & 0x8000), 0, 0xFFFF8000);
7010
7011 dmx |= isel(-(pb & 0x8000), 0, 0xFFFF8000);
7012
7013 dy |= isel(-(pc & 0x8000), 0, 0xFFFF8000);
7014
7015 dmy |= isel(-(pd & 0x8000), 0, 0xFFFF8000);
7016 #else
7017 int dx = pa & 0x7FFF;
7018 if(pa & 0x8000)
7019 dx |= 0xFFFF8000;
7020 int dmx = pb & 0x7FFF;
7021 if(pb & 0x8000)
7022 dmx |= 0xFFFF8000;
7023 int dy = pc & 0x7FFF;
7024 if(pc & 0x8000)
7025 dy |= 0xFFFF8000;
7026 int dmy = pd & 0x7FFF;
7027 if(pd & 0x8000)
7028 dmy |= 0xFFFF8000;
7029 #endif
7030
7031 if(io_registers[REG_VCOUNT] == 0)
7032 changed = 3;
7033
7034 currentX += dmx;
7035 currentY += dmy;
7036
7037 if(changed & 1)
7038 {
7039 currentX = (x_l) | ((x_h & 0x07FF)<<16);
7040 if(x_h & 0x0800)
7041 currentX |= 0xF8000000;
7042 }
7043
7044 if(changed & 2)
7045 {
7046 currentY = (y_l) | ((y_h & 0x07FF)<<16);
7047 if(y_h & 0x0800)
7048 currentY |= 0xF8000000;
7049 }
7050 }
7051
fetchDrawRotScreen16Bit(int & currentX,int & currentY,int changed)7052 static INLINE void fetchDrawRotScreen16Bit( int& currentX, int& currentY, int changed)
7053 {
7054 #ifdef BRANCHLESS_GBA_GFX
7055 int dx = io_registers[REG_BG2PA] & 0x7FFF;
7056 dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7057
7058 int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7059 dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7060
7061 int dy = io_registers[REG_BG2PC] & 0x7FFF;
7062 dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7063
7064 int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7065 dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7066 #else
7067 int dx = io_registers[REG_BG2PA] & 0x7FFF;
7068 if(io_registers[REG_BG2PA] & 0x8000)
7069 dx |= 0xFFFF8000;
7070 int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7071 if(io_registers[REG_BG2PB] & 0x8000)
7072 dmx |= 0xFFFF8000;
7073 int dy = io_registers[REG_BG2PC] & 0x7FFF;
7074 if(io_registers[REG_BG2PC] & 0x8000)
7075 dy |= 0xFFFF8000;
7076 int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7077 if(io_registers[REG_BG2PD] & 0x8000)
7078 dmy |= 0xFFFF8000;
7079 #endif
7080
7081 if(io_registers[REG_VCOUNT] == 0)
7082 changed = 3;
7083
7084 currentX += dmx;
7085 currentY += dmy;
7086
7087 if(changed & 1)
7088 {
7089 currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7090 if(BG2X_H & 0x0800)
7091 currentX |= 0xF8000000;
7092 }
7093
7094 if(changed & 2)
7095 {
7096 currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7097 if(BG2Y_H & 0x0800)
7098 currentY |= 0xF8000000;
7099 }
7100 }
7101
fetchDrawRotScreen256(int & currentX,int & currentY,int changed)7102 static INLINE void fetchDrawRotScreen256(int ¤tX, int& currentY, int changed)
7103 {
7104 #ifdef BRANCHLESS_GBA_GFX
7105 int dx = io_registers[REG_BG2PA] & 0x7FFF;
7106 dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7107
7108 int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7109 dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7110
7111 int dy = io_registers[REG_BG2PC] & 0x7FFF;
7112 dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7113
7114 int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7115 dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7116 #else
7117 int dx = io_registers[REG_BG2PA] & 0x7FFF;
7118 if(io_registers[REG_BG2PA] & 0x8000)
7119 dx |= 0xFFFF8000;
7120 int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7121 if(io_registers[REG_BG2PB] & 0x8000)
7122 dmx |= 0xFFFF8000;
7123 int dy = io_registers[REG_BG2PC] & 0x7FFF;
7124 if(io_registers[REG_BG2PC] & 0x8000)
7125 dy |= 0xFFFF8000;
7126 int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7127 if(io_registers[REG_BG2PD] & 0x8000)
7128 dmy |= 0xFFFF8000;
7129 #endif
7130
7131 if(io_registers[REG_VCOUNT] == 0)
7132 changed = 3;
7133
7134 currentX += dmx;
7135 currentY += dmy;
7136
7137 if(changed & 1)
7138 {
7139 currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7140 if(BG2X_H & 0x0800)
7141 currentX |= 0xF8000000;
7142 }
7143
7144 if(changed & 2)
7145 {
7146 currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7147 if(BG2Y_H & 0x0800)
7148 currentY |= 0xF8000000;
7149 }
7150 }
7151
fetchDrawRotScreen16Bit160(int & currentX,int & currentY,int changed)7152 static INLINE void fetchDrawRotScreen16Bit160(int& currentX, int& currentY, int changed)
7153 {
7154 #ifdef BRANCHLESS_GBA_GFX
7155 int dx = io_registers[REG_BG2PA] & 0x7FFF;
7156 dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7157
7158 int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7159 dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7160
7161 int dy = io_registers[REG_BG2PC] & 0x7FFF;
7162 dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7163
7164 int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7165 dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7166 #else
7167 int dx = io_registers[REG_BG2PA] & 0x7FFF;
7168 if(io_registers[REG_BG2PA] & 0x8000)
7169 dx |= 0xFFFF8000;
7170 int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7171 if(io_registers[REG_BG2PB] & 0x8000)
7172 dmx |= 0xFFFF8000;
7173 int dy = io_registers[REG_BG2PC] & 0x7FFF;
7174 if(io_registers[REG_BG2PC] & 0x8000)
7175 dy |= 0xFFFF8000;
7176 int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7177 if(io_registers[REG_BG2PD] & 0x8000)
7178 dmy |= 0xFFFF8000;
7179 #endif
7180
7181 if(io_registers[REG_VCOUNT] == 0)
7182 changed = 3;
7183
7184 currentX += dmx;
7185 currentY += dmy;
7186
7187 if(changed & 1)
7188 {
7189 currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7190 if(BG2X_H & 0x0800)
7191 currentX |= 0xF8000000;
7192 }
7193
7194 if(changed & 2)
7195 {
7196 currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7197 if(BG2Y_H & 0x0800)
7198 currentY |= 0xF8000000;
7199 }
7200 }
7201 #endif
7202
7203 template<int layer, int renderer_idx>
gfxDrawRotScreen(u16 control,u16 x_l,u16 x_h,u16 y_l,u16 y_h,u16 pa,u16 pb,u16 pc,u16 pd,int & currentX,int & currentY,int changed)7204 static INLINE void gfxDrawRotScreen(u16 control, u16 x_l, u16 x_h, u16 y_l, u16 y_h,
7205 u16 pa, u16 pb, u16 pc, u16 pd, int& currentX, int& currentY, int changed)
7206 {
7207 INIT_RENDERER_CONTEXT(renderer_idx);
7208
7209 u16 *palette = (u16 *)RENDERER_PALETTE;
7210 u8 *charBase = &vram[((control >> 2) & 0x03) << 14];
7211 u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) << 11];
7212 int prio = ((control & 3) << 25) + 0x1000000;
7213
7214 u32 map_size = (control >> 14) & 3;
7215 u32 sizeX = map_sizes_rot[map_size];
7216 u32 sizeY = map_sizes_rot[map_size];
7217
7218 int maskX = sizeX-1;
7219 int maskY = sizeY-1;
7220
7221 int yshift = ((control >> 14) & 3)+4;
7222
7223 #ifdef BRANCHLESS_GBA_GFX
7224 int dx = pa & 0x7FFF;
7225 int dmx = pb & 0x7FFF;
7226 int dy = pc & 0x7FFF;
7227 int dmy = pd & 0x7FFF;
7228
7229 dx |= isel(-(pa & 0x8000), 0, 0xFFFF8000);
7230
7231 dmx |= isel(-(pb & 0x8000), 0, 0xFFFF8000);
7232
7233 dy |= isel(-(pc & 0x8000), 0, 0xFFFF8000);
7234
7235 dmy |= isel(-(pd & 0x8000), 0, 0xFFFF8000);
7236 #else
7237 int dx = pa & 0x7FFF;
7238 if(pa & 0x8000)
7239 dx |= 0xFFFF8000;
7240 int dmx = pb & 0x7FFF;
7241 if(pb & 0x8000)
7242 dmx |= 0xFFFF8000;
7243 int dy = pc & 0x7FFF;
7244 if(pc & 0x8000)
7245 dy |= 0xFFFF8000;
7246 int dmy = pd & 0x7FFF;
7247 if(pd & 0x8000)
7248 dmy |= 0xFFFF8000;
7249 #endif
7250
7251 if(RENDERER_R_VCOUNT == 0)
7252 changed = 3;
7253
7254 currentX += dmx;
7255 currentY += dmy;
7256
7257 if(changed & 1)
7258 {
7259 currentX = (x_l) | ((x_h & 0x07FF)<<16);
7260 if(x_h & 0x0800)
7261 currentX |= 0xF8000000;
7262 }
7263
7264 if(changed & 2)
7265 {
7266 currentY = (y_l) | ((y_h & 0x07FF)<<16);
7267 if(y_h & 0x0800)
7268 currentY |= 0xF8000000;
7269 }
7270
7271 int realX = currentX;
7272 int realY = currentY;
7273
7274 if(control & 0x40)
7275 {
7276 int mosaicY = ((RENDERER_MOSAIC & 0xF0)>>4) + 1;
7277 int y = (RENDERER_R_VCOUNT % mosaicY);
7278 realX -= y*dmx;
7279 realY -= y*dmy;
7280 }
7281
7282 memset(RENDERER_LINE[layer], -1, 240 * sizeof(u32));
7283 if(control & 0x2000) // Wraparound
7284 {
7285 if(dx > 0 && dy == 0) // Common subcase: no rotation or flipping
7286 {
7287 unsigned yyy = (realY >> 8) & maskY;
7288 unsigned yyyshift = (yyy>>3)<<yshift;
7289 unsigned tileY = yyy & 7;
7290 unsigned tileYshift = (tileY<<3);
7291
7292 for(u32 x = 0; x < 240u; ++x)
7293 {
7294 unsigned xxx = (realX >> 8) & maskX;
7295
7296 unsigned tile = screenBase[(xxx>>3) | yyyshift];
7297
7298 unsigned tileX = (xxx & 7);
7299
7300 u8 color = charBase[(tile<<6) | tileYshift | tileX];
7301
7302 if(color) RENDERER_LINE[layer][x] = (READ16LE(&palette[color])|prio);
7303
7304 realX += dx;
7305 }
7306 }
7307 else
7308 for(u32 x = 0; x < 240u; ++x)
7309 {
7310 unsigned xxx = (realX >> 8) & maskX;
7311 unsigned yyy = (realY >> 8) & maskY;
7312
7313 unsigned tile = screenBase[(xxx>>3) | ((yyy>>3)<<yshift)];
7314
7315 unsigned tileX = (xxx & 7);
7316 unsigned tileY = yyy & 7;
7317
7318 u8 color = charBase[(tile<<6) | (tileY<<3) | tileX];
7319
7320 if(color) RENDERER_LINE[layer][x] = (READ16LE(&palette[color])|prio);
7321
7322 realX += dx;
7323 realY += dy;
7324 }
7325 }
7326 else // Culling
7327 {
7328 if(dx > 0 && dy == 0) // Common subcase: no rotation or flipping
7329 {
7330 unsigned yyy = (realY >> 8);
7331 if (yyy >= sizeY)
7332 goto skipLine;
7333 unsigned yyyshift = (yyy>>3)<<yshift;
7334 unsigned tileY = yyy & 7;
7335 unsigned tileYshift = (tileY<<3);
7336
7337 s32 x0 = max( 0, (s32)( + (-realX + dx - 1)) / dx);
7338 s32 x1 = min(240, (s32)((sizeX << 8) + (-realX + dx - 1)) / dx);
7339
7340 realX += dx * x0;
7341
7342 for(s32 x = x0; x < x1; ++x)
7343 {
7344 unsigned xxx = (realX >> 8);
7345
7346 unsigned tile = screenBase[(xxx>>3) | yyyshift];
7347
7348 unsigned tileX = (xxx & 7);
7349
7350 u8 color = charBase[(tile<<6) | tileYshift | tileX];
7351
7352 if(color) RENDERER_LINE[layer][x] = (READ16LE(&palette[color])|prio);
7353
7354 realX += dx;
7355 }
7356 }
7357 else
7358 for(u32 x = 0; x < 240u; ++x)
7359 {
7360 unsigned xxx = (realX >> 8);
7361 unsigned yyy = (realY >> 8);
7362
7363 if(xxx < sizeX && yyy < sizeY)
7364 {
7365 unsigned tile = screenBase[(xxx>>3) | ((yyy>>3)<<yshift)];
7366
7367 unsigned tileX = (xxx & 7);
7368 unsigned tileY = yyy & 7;
7369
7370 u8 color = charBase[(tile<<6) | (tileY<<3) | tileX];
7371
7372 if(color) RENDERER_LINE[layer][x] = (READ16LE(&palette[color])|prio);
7373 }
7374
7375 realX += dx;
7376 realY += dy;
7377 }
7378 }
7379 skipLine:
7380
7381 if(control & 0x40)
7382 {
7383 int mosaicX = (RENDERER_MOSAIC & 0xF) + 1;
7384 if(mosaicX > 1)
7385 {
7386 MOSAIC_LOOP(layer, mosaicX);
7387 }
7388 }
7389 }
7390
7391 template<int renderer_idx>
gfxDrawRotScreen16Bit(int & currentX,int & currentY,int changed)7392 static INLINE void gfxDrawRotScreen16Bit( int& currentX, int& currentY, int changed)
7393 {
7394 INIT_RENDERER_CONTEXT(renderer_idx);
7395
7396 u16 *screenBase = (u16 *)&vram[0];
7397 int prio = ((RENDERER_IO_REGISTERS[REG_BG2CNT] & 3) << 25) + 0x1000000;
7398
7399 u32 sizeX = 240;
7400 u32 sizeY = 160;
7401
7402 int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7403 if(BG2X_H & 0x0800)
7404 startX |= 0xF8000000;
7405 int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7406 if(BG2Y_H & 0x0800)
7407 startY |= 0xF8000000;
7408
7409 #ifdef BRANCHLESS_GBA_GFX
7410 int dx = RENDERER_IO_REGISTERS[REG_BG2PA] & 0x7FFF;
7411 dx |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7412
7413 int dmx = RENDERER_IO_REGISTERS[REG_BG2PB] & 0x7FFF;
7414 dmx |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7415
7416 int dy = RENDERER_IO_REGISTERS[REG_BG2PC] & 0x7FFF;
7417 dy |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7418
7419 int dmy = RENDERER_IO_REGISTERS[REG_BG2PD] & 0x7FFF;
7420 dmy |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7421 #else
7422 int dx = RENDERER_IO_REGISTERS[REG_BG2PA] & 0x7FFF;
7423 if(RENDERER_IO_REGISTERS[REG_BG2PA] & 0x8000)
7424 dx |= 0xFFFF8000;
7425 int dmx = RENDERER_IO_REGISTERS[REG_BG2PB] & 0x7FFF;
7426 if(RENDERER_IO_REGISTERS[REG_BG2PB] & 0x8000)
7427 dmx |= 0xFFFF8000;
7428 int dy = RENDERER_IO_REGISTERS[REG_BG2PC] & 0x7FFF;
7429 if(RENDERER_IO_REGISTERS[REG_BG2PC] & 0x8000)
7430 dy |= 0xFFFF8000;
7431 int dmy = RENDERER_IO_REGISTERS[REG_BG2PD] & 0x7FFF;
7432 if(RENDERER_IO_REGISTERS[REG_BG2PD] & 0x8000)
7433 dmy |= 0xFFFF8000;
7434 #endif
7435
7436 if(RENDERER_R_VCOUNT == 0)
7437 changed = 3;
7438
7439 currentX += dmx;
7440 currentY += dmy;
7441
7442 if(changed & 1)
7443 {
7444 currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7445 if(BG2X_H & 0x0800)
7446 currentX |= 0xF8000000;
7447 }
7448
7449 if(changed & 2)
7450 {
7451 currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7452 if(BG2Y_H & 0x0800)
7453 currentY |= 0xF8000000;
7454 }
7455
7456 int realX = currentX;
7457 int realY = currentY;
7458
7459 if(RENDERER_IO_REGISTERS[REG_BG2CNT] & 0x40) {
7460 int mosaicY = ((RENDERER_MOSAIC & 0xF0)>>4) + 1;
7461 int y = (RENDERER_R_VCOUNT % mosaicY);
7462 realX -= y*dmx;
7463 realY -= y*dmy;
7464 }
7465
7466 unsigned xxx = (realX >> 8);
7467 unsigned yyy = (realY >> 8);
7468
7469 memset(RENDERER_LINE[Layer_BG2], -1, 240 * sizeof(u32));
7470 for(u32 x = 0; x < 240u; ++x)
7471 {
7472 if(xxx < sizeX && yyy < sizeY)
7473 RENDERER_LINE[Layer_BG2][x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
7474
7475 realX += dx;
7476 realY += dy;
7477
7478 xxx = (realX >> 8);
7479 yyy = (realY >> 8);
7480 }
7481
7482 if(RENDERER_IO_REGISTERS[REG_BG2CNT] & 0x40) {
7483 int mosaicX = (MOSAIC & 0xF) + 1;
7484 if(mosaicX > 1) {
7485 MOSAIC_LOOP(Layer_BG2, mosaicX);
7486 }
7487 }
7488 }
7489
7490 template<int renderer_idx>
gfxDrawRotScreen256(int & currentX,int & currentY,int changed)7491 static INLINE void gfxDrawRotScreen256(int ¤tX, int& currentY, int changed)
7492 {
7493 INIT_RENDERER_CONTEXT(renderer_idx);
7494
7495 u16 *palette = (u16 *)RENDERER_PALETTE;
7496 u8 *screenBase = (RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x0010) ? &vram[0xA000] : &vram[0x0000];
7497 int prio = ((RENDERER_IO_REGISTERS[REG_BG2CNT] & 3) << 25) + 0x1000000;
7498 u32 sizeX = 240;
7499 u32 sizeY = 160;
7500
7501 int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7502 if(BG2X_H & 0x0800)
7503 startX |= 0xF8000000;
7504 int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7505 if(BG2Y_H & 0x0800)
7506 startY |= 0xF8000000;
7507
7508 #ifdef BRANCHLESS_GBA_GFX
7509 int dx = RENDERER_IO_REGISTERS[REG_BG2PA] & 0x7FFF;
7510 dx |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7511
7512 int dmx = RENDERER_IO_REGISTERS[REG_BG2PB] & 0x7FFF;
7513 dmx |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7514
7515 int dy = RENDERER_IO_REGISTERS[REG_BG2PC] & 0x7FFF;
7516 dy |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7517
7518 int dmy = RENDERER_IO_REGISTERS[REG_BG2PD] & 0x7FFF;
7519 dmy |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7520 #else
7521 int dx = RENDERER_IO_REGISTERS[REG_BG2PA] & 0x7FFF;
7522 if(RENDERER_IO_REGISTERS[REG_BG2PA] & 0x8000)
7523 dx |= 0xFFFF8000;
7524 int dmx = RENDERER_IO_REGISTERS[REG_BG2PB] & 0x7FFF;
7525 if(RENDERER_IO_REGISTERS[REG_BG2PB] & 0x8000)
7526 dmx |= 0xFFFF8000;
7527 int dy = RENDERER_IO_REGISTERS[REG_BG2PC] & 0x7FFF;
7528 if(RENDERER_IO_REGISTERS[REG_BG2PC] & 0x8000)
7529 dy |= 0xFFFF8000;
7530 int dmy = RENDERER_IO_REGISTERS[REG_BG2PD] & 0x7FFF;
7531 if(RENDERER_IO_REGISTERS[REG_BG2PD] & 0x8000)
7532 dmy |= 0xFFFF8000;
7533 #endif
7534
7535 if(RENDERER_R_VCOUNT == 0)
7536 changed = 3;
7537
7538 currentX += dmx;
7539 currentY += dmy;
7540
7541 if(changed & 1)
7542 {
7543 currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7544 if(BG2X_H & 0x0800)
7545 currentX |= 0xF8000000;
7546 }
7547
7548 if(changed & 2)
7549 {
7550 currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7551 if(BG2Y_H & 0x0800)
7552 currentY |= 0xF8000000;
7553 }
7554
7555 int realX = currentX;
7556 int realY = currentY;
7557
7558 if(RENDERER_IO_REGISTERS[REG_BG2CNT] & 0x40) {
7559 int mosaicY = ((RENDERER_MOSAIC & 0xF0)>>4) + 1;
7560 int y = RENDERER_R_VCOUNT - (RENDERER_R_VCOUNT % mosaicY);
7561 realX = startX + y*dmx;
7562 realY = startY + y*dmy;
7563 }
7564
7565 int xxx = (realX >> 8);
7566 int yyy = (realY >> 8);
7567
7568 memset(RENDERER_LINE[Layer_BG2], -1, 240 * sizeof(u32));
7569 for(u32 x = 0; x < 240; ++x)
7570 {
7571 if(unsigned(xxx) < sizeX && unsigned(yyy) < sizeY) {
7572 u8 color = screenBase[yyy * 240 + xxx];
7573 if (color) RENDERER_LINE[Layer_BG2][x] = (READ16LE(&palette[color]) | prio);
7574 }
7575 realX += dx;
7576 realY += dy;
7577
7578 xxx = (realX >> 8);
7579 yyy = (realY >> 8);
7580 }
7581
7582 if(RENDERER_IO_REGISTERS[REG_BG2CNT] & 0x40)
7583 {
7584 int mosaicX = (RENDERER_MOSAIC & 0xF) + 1;
7585 if(mosaicX > 1)
7586 {
7587 MOSAIC_LOOP(Layer_BG2, mosaicX);
7588 }
7589 }
7590 }
7591
7592 template<int renderer_idx>
gfxDrawRotScreen16Bit160(int & currentX,int & currentY,int changed)7593 static INLINE void gfxDrawRotScreen16Bit160(int& currentX, int& currentY, int changed)
7594 {
7595 INIT_RENDERER_CONTEXT(renderer_idx);
7596
7597 u16 *screenBase = (RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x0010) ? (u16 *)&vram[0xa000] :
7598 (u16 *)&vram[0];
7599 int prio = ((RENDERER_IO_REGISTERS[REG_BG2CNT] & 3) << 25) + 0x1000000;
7600 u32 sizeX = 160;
7601 u32 sizeY = 128;
7602
7603 int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7604 if(BG2X_H & 0x0800)
7605 startX |= 0xF8000000;
7606 int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7607 if(BG2Y_H & 0x0800)
7608 startY |= 0xF8000000;
7609
7610 #ifdef BRANCHLESS_GBA_GFX
7611 int dx = RENDERER_IO_REGISTERS[REG_BG2PA] & 0x7FFF;
7612 dx |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7613
7614 int dmx = RENDERER_IO_REGISTERS[REG_BG2PB] & 0x7FFF;
7615 dmx |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7616
7617 int dy = RENDERER_IO_REGISTERS[REG_BG2PC] & 0x7FFF;
7618 dy |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7619
7620 int dmy = RENDERER_IO_REGISTERS[REG_BG2PD] & 0x7FFF;
7621 dmy |= isel(-(RENDERER_IO_REGISTERS[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7622 #else
7623 int dx = RENDERER_IO_REGISTERS[REG_BG2PA] & 0x7FFF;
7624 if(RENDERER_IO_REGISTERS[REG_BG2PA] & 0x8000)
7625 dx |= 0xFFFF8000;
7626 int dmx = RENDERER_IO_REGISTERS[REG_BG2PB] & 0x7FFF;
7627 if(RENDERER_IO_REGISTERS[REG_BG2PB] & 0x8000)
7628 dmx |= 0xFFFF8000;
7629 int dy = RENDERER_IO_REGISTERS[REG_BG2PC] & 0x7FFF;
7630 if(RENDERER_IO_REGISTERS[REG_BG2PC] & 0x8000)
7631 dy |= 0xFFFF8000;
7632 int dmy = RENDERER_IO_REGISTERS[REG_BG2PD] & 0x7FFF;
7633 if(RENDERER_IO_REGISTERS[REG_BG2PD] & 0x8000)
7634 dmy |= 0xFFFF8000;
7635 #endif
7636
7637 if(RENDERER_R_VCOUNT == 0)
7638 changed = 3;
7639
7640 currentX += dmx;
7641 currentY += dmy;
7642
7643 if(changed & 1)
7644 {
7645 currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7646 if(BG2X_H & 0x0800)
7647 currentX |= 0xF8000000;
7648 }
7649
7650 if(changed & 2)
7651 {
7652 currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7653 if(BG2Y_H & 0x0800)
7654 currentY |= 0xF8000000;
7655 }
7656
7657 int realX = currentX;
7658 int realY = currentY;
7659
7660 if(RENDERER_IO_REGISTERS[REG_BG2CNT] & 0x40) {
7661 int mosaicY = ((RENDERER_MOSAIC & 0xF0)>>4) + 1;
7662 int y = RENDERER_R_VCOUNT - (RENDERER_R_VCOUNT % mosaicY);
7663 realX = startX + y*dmx;
7664 realY = startY + y*dmy;
7665 }
7666
7667 int xxx = (realX >> 8);
7668 int yyy = (realY >> 8);
7669
7670 memset(RENDERER_LINE[Layer_BG2], -1, 240 * sizeof(u32));
7671 for(u32 x = 0; x < 240u; ++x)
7672 {
7673 if(unsigned(xxx) < sizeX && unsigned(yyy) < sizeY)
7674 RENDERER_LINE[Layer_BG2][x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
7675
7676 realX += dx;
7677 realY += dy;
7678
7679 xxx = (realX >> 8);
7680 yyy = (realY >> 8);
7681 }
7682
7683
7684 int mosaicX = (RENDERER_MOSAIC & 0xF) + 1;
7685 if(RENDERER_IO_REGISTERS[REG_BG2CNT] & 0x40 && (mosaicX > 1))
7686 {
7687 MOSAIC_LOOP(Layer_BG2, mosaicX);
7688 }
7689 }
7690
7691 /* lineOBJpix is used to keep track of the drawn OBJs
7692 and to stop drawing them if the 'maximum number of OBJ per line'
7693 has been reached. */
7694
7695 template<int renderer_idx>
gfxDrawSprites(void)7696 static void gfxDrawSprites (void)
7697 {
7698 INIT_RENDERER_CONTEXT(renderer_idx);
7699
7700 unsigned lineOBJpix, m;
7701
7702 lineOBJpix = (RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x20) ? 954 : 1226;
7703 m = 0;
7704
7705 u16 *sprites = (u16 *)RENDERER_OAM;
7706 u16 *spritePalette = &((u16 *)RENDERER_PALETTE)[256];
7707 int mosaicY = ((RENDERER_MOSAIC & 0xF000)>>12) + 1;
7708 int mosaicX = ((RENDERER_MOSAIC & 0xF00)>>8) + 1;
7709 for(u32 x = 0; x < 128; x++)
7710 {
7711 u16 a0 = READ16LE(sprites++);
7712 u16 a1 = READ16LE(sprites++);
7713 u16 a2 = READ16LE(sprites++);
7714 ++sprites;
7715
7716 RENDERER_LINE_OBJ_PIX_LEFT[x]=lineOBJpix;
7717
7718 lineOBJpix-=2;
7719 if (lineOBJpix<=0)
7720 return;
7721
7722 if ((a0 & 0x0c00) == 0x0c00)
7723 a0 &=0xF3FF;
7724
7725 u16 a0val = a0>>14;
7726
7727 if (a0val == 3)
7728 {
7729 a0 &= 0x3FFF;
7730 a1 &= 0x3FFF;
7731 }
7732
7733 u32 sizeX = 8<<(a1>>14);
7734 u32 sizeY = sizeX;
7735
7736
7737 if (a0val & 1)
7738 {
7739 #ifdef BRANCHLESS_GBA_GFX
7740 sizeX <<= isel(-(sizeX & (~31u)), 1, 0);
7741 sizeY >>= isel(-(sizeY>8), 0, 1);
7742 #else
7743 if (sizeX<32)
7744 sizeX<<=1;
7745 if (sizeY>8)
7746 sizeY>>=1;
7747 #endif
7748 }
7749 else if (a0val & 2)
7750 {
7751 #ifdef BRANCHLESS_GBA_GFX
7752 sizeX >>= isel(-(sizeX>8), 0, 1);
7753 sizeY <<= isel(-(sizeY & (~31u)), 1, 0);
7754 #else
7755 if (sizeX>8)
7756 sizeX>>=1;
7757 if (sizeY<32)
7758 sizeY<<=1;
7759 #endif
7760
7761 }
7762
7763
7764 int sy = (a0 & 255);
7765 int sx = (a1 & 0x1FF);
7766
7767 // computes ticks used by OBJ-WIN if OBJWIN is enabled
7768 if (((a0 & 0x0c00) == 0x0800) && (RENDERER_R_DISPCNT_OBJ_Window_Display))
7769 {
7770 if ((a0 & 0x0300) == 0x0300)
7771 {
7772 sizeX<<=1;
7773 sizeY<<=1;
7774 }
7775
7776 #ifdef BRANCHLESS_GBA_GFX
7777 sy -= isel(256 - sy - sizeY, 0, 256);
7778 sx -= isel(512 - sx - sizeX, 0, 512);
7779 #else
7780 if((sy+sizeY) > 256)
7781 sy -= 256;
7782 if ((sx+sizeX)> 512)
7783 sx -= 512;
7784 #endif
7785
7786 if (sx < 0)
7787 {
7788 sizeX+=sx;
7789 sx = 0;
7790 }
7791 else if ((sx+sizeX)>240)
7792 sizeX=240-sx;
7793
7794 if ((RENDERER_R_VCOUNT>=sy) && (RENDERER_R_VCOUNT<sy+sizeY) && (sx<240))
7795 {
7796 lineOBJpix -= (sizeX-2);
7797
7798 if (a0 & 0x0100)
7799 lineOBJpix -= (10+sizeX);
7800 }
7801 continue;
7802 }
7803
7804 // else ignores OBJ-WIN if OBJWIN is disabled, and ignored disabled OBJ
7805 else if(((a0 & 0x0c00) == 0x0800) || ((a0 & 0x0300) == 0x0200))
7806 continue;
7807
7808 if(a0 & 0x0100)
7809 {
7810 u32 fieldX = sizeX;
7811 u32 fieldY = sizeY;
7812 if(a0 & 0x0200)
7813 {
7814 fieldX <<= 1;
7815 fieldY <<= 1;
7816 }
7817 if((sy+fieldY) > 256)
7818 sy -= 256;
7819 int t = RENDERER_R_VCOUNT - sy;
7820 if(unsigned(t) < fieldY)
7821 {
7822 u32 startpix = 0;
7823 if ((sx+fieldX)> 512)
7824 startpix=512-sx;
7825
7826 if (lineOBJpix && ((sx < 240) || startpix))
7827 {
7828 lineOBJpix-=8;
7829 int rot = (((a1 >> 9) & 0x1F) << 4);
7830 u16 *OAM = (u16 *)RENDERER_OAM;
7831 int dx = READ16LE(&OAM[3 + rot]);
7832 if(dx & 0x8000)
7833 dx |= 0xFFFF8000;
7834 int dmx = READ16LE(&OAM[7 + rot]);
7835 if(dmx & 0x8000)
7836 dmx |= 0xFFFF8000;
7837 int dy = READ16LE(&OAM[11 + rot]);
7838 if(dy & 0x8000)
7839 dy |= 0xFFFF8000;
7840 int dmy = READ16LE(&OAM[15 + rot]);
7841 if(dmy & 0x8000)
7842 dmy |= 0xFFFF8000;
7843
7844 if(a0 & 0x1000)
7845 t -= (t % mosaicY);
7846
7847 int realX = ((sizeX) << 7) - (fieldX >> 1)*dx + ((t - (fieldY>>1))* dmx);
7848 int realY = ((sizeY) << 7) - (fieldX >> 1)*dy + ((t - (fieldY>>1))* dmy);
7849
7850 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
7851
7852 int c = (a2 & 0x3FF);
7853 if(RENDERER_R_DISPCNT_Video_Mode > 2 && (c < 512))
7854 continue;
7855
7856 if(a0 & 0x2000)
7857 {
7858 int inc = 32;
7859 if(RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x40)
7860 inc = sizeX >> 2;
7861 else
7862 c &= 0x3FE;
7863 for(u32 x = 0; x < fieldX; x++)
7864 {
7865 if (x >= startpix)
7866 lineOBJpix-=2;
7867 unsigned xxx = realX >> 8;
7868 unsigned yyy = realY >> 8;
7869 if(xxx < sizeX && yyy < sizeY && sx < 240)
7870 {
7871
7872 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
7873 + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + (xxx & 7))&0x7FFF)];
7874
7875 if ((color==0) && (((prio >> 25)&3) < ((RENDERER_LINE[Layer_OBJ][sx]>>25)&3)))
7876 {
7877 RENDERER_LINE[Layer_OBJ][sx] = (RENDERER_LINE[Layer_OBJ][sx] & 0xF9FFFFFF) | prio;
7878 if((a0 & 0x1000) && m)
7879 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
7880 }
7881 else if((color) && (prio < (RENDERER_LINE[Layer_OBJ][sx]&0xFF000000)))
7882 {
7883 RENDERER_LINE[Layer_OBJ][sx] = READ16LE(&spritePalette[color]) | prio;
7884 if((a0 & 0x1000) && m)
7885 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
7886 }
7887
7888 if ((a0 & 0x1000) && ((m+1) == mosaicX))
7889 m = 0;
7890 }
7891 sx = (sx+1)&511;
7892 realX += dx;
7893 realY += dy;
7894 }
7895 }
7896 else
7897 {
7898 int inc = 32;
7899 if(RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x40)
7900 inc = sizeX >> 3;
7901 int palette = (a2 >> 8) & 0xF0;
7902 for(u32 x = 0; x < fieldX; ++x)
7903 {
7904 if (x >= startpix)
7905 lineOBJpix-=2;
7906 unsigned xxx = realX >> 8;
7907 unsigned yyy = realY >> 8;
7908 if(xxx < sizeX && yyy < sizeY && sx < 240)
7909 {
7910
7911 u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
7912 + ((yyy & 7)<<2) + ((xxx >> 3)<<5)
7913 + ((xxx & 7)>>1))&0x7FFF)];
7914 if(xxx & 1)
7915 color >>= 4;
7916 else
7917 color &= 0x0F;
7918
7919 if ((color==0) && (((prio >> 25)&3) <
7920 ((RENDERER_LINE[Layer_OBJ][sx]>>25)&3)))
7921 {
7922 RENDERER_LINE[Layer_OBJ][sx] = (RENDERER_LINE[Layer_OBJ][sx] & 0xF9FFFFFF) | prio;
7923 if((a0 & 0x1000) && m)
7924 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
7925 }
7926 else if((color) && (prio < (RENDERER_LINE[Layer_OBJ][sx]&0xFF000000)))
7927 {
7928 RENDERER_LINE[Layer_OBJ][sx] = READ16LE(&spritePalette[palette+color]) | prio;
7929 if((a0 & 0x1000) && m)
7930 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
7931 }
7932 }
7933 if((a0 & 0x1000) && m)
7934 {
7935 if (++m==mosaicX)
7936 m=0;
7937 }
7938
7939 sx = (sx+1)&511;
7940 realX += dx;
7941 realY += dy;
7942
7943 }
7944 }
7945 }
7946 }
7947 }
7948 else
7949 {
7950 if(sy+sizeY > 256)
7951 sy -= 256;
7952 int t = RENDERER_R_VCOUNT - sy;
7953 if(unsigned(t) < sizeY)
7954 {
7955 u32 startpix = 0;
7956 if ((sx+sizeX)> 512)
7957 startpix=512-sx;
7958
7959 if((sx < 240) || startpix)
7960 {
7961 lineOBJpix+=2;
7962
7963 if(a1 & 0x2000)
7964 t = sizeY - t - 1;
7965
7966 int c = (a2 & 0x3FF);
7967 if(RENDERER_R_DISPCNT_Video_Mode > 2 && (c < 512))
7968 continue;
7969
7970 int inc = 32;
7971 int xxx = 0;
7972 if(a1 & 0x1000)
7973 xxx = sizeX-1;
7974
7975 if(a0 & 0x1000)
7976 t -= (t % mosaicY);
7977
7978 if(a0 & 0x2000)
7979 {
7980 if(RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x40)
7981 inc = sizeX >> 2;
7982 else
7983 c &= 0x3FE;
7984
7985 int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
7986 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF);
7987
7988 if(a1 & 0x1000)
7989 xxx = 7;
7990 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
7991
7992 for(u32 xx = 0; xx < sizeX; xx++)
7993 {
7994 if (xx >= startpix)
7995 --lineOBJpix;
7996 if(sx < 240)
7997 {
7998 u8 color = vram[address];
7999 if ((color==0) && (((prio >> 25)&3) <
8000 ((RENDERER_LINE[Layer_OBJ][sx]>>25)&3)))
8001 {
8002 RENDERER_LINE[Layer_OBJ][sx] = (RENDERER_LINE[Layer_OBJ][sx] & 0xF9FFFFFF) | prio;
8003 if((a0 & 0x1000) && m)
8004 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
8005 }
8006 else if((color) && (prio < (RENDERER_LINE[Layer_OBJ][sx]&0xFF000000)))
8007 {
8008 RENDERER_LINE[Layer_OBJ][sx] = READ16LE(&spritePalette[color]) | prio;
8009 if((a0 & 0x1000) && m)
8010 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
8011 }
8012
8013 if ((a0 & 0x1000) && ((m+1) == mosaicX))
8014 m = 0;
8015 }
8016
8017 sx = (sx+1) & 511;
8018 if(a1 & 0x1000)
8019 {
8020 --address;
8021 if(--xxx == -1)
8022 {
8023 address -= 56;
8024 xxx = 7;
8025 }
8026 if(address < 0x10000)
8027 address += 0x8000;
8028 }
8029 else
8030 {
8031 ++address;
8032 if(++xxx == 8)
8033 {
8034 address += 56;
8035 xxx = 0;
8036 }
8037 if(address > 0x17fff)
8038 address -= 0x8000;
8039 }
8040 }
8041 }
8042 else
8043 {
8044 if(RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x40)
8045 inc = sizeX >> 3;
8046
8047 int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
8048 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF);
8049
8050 u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
8051 int palette = (a2 >> 8) & 0xF0;
8052 if(a1 & 0x1000)
8053 {
8054 xxx = 7;
8055 int xx = sizeX - 1;
8056 do
8057 {
8058 if (xx >= (int)(startpix))
8059 --lineOBJpix;
8060 //if (lineOBJpix<0)
8061 // continue;
8062 if(sx < 240)
8063 {
8064 u8 color = vram[address];
8065 if(xx & 1)
8066 color >>= 4;
8067 else
8068 color &= 0x0F;
8069
8070 if ((color==0) && (((prio >> 25)&3) <
8071 ((RENDERER_LINE[Layer_OBJ][sx]>>25)&3)))
8072 {
8073 RENDERER_LINE[Layer_OBJ][sx] = (RENDERER_LINE[Layer_OBJ][sx] & 0xF9FFFFFF) | prio;
8074 if((a0 & 0x1000) && m)
8075 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
8076 }
8077 else if((color) && (prio < (RENDERER_LINE[Layer_OBJ][sx]&0xFF000000)))
8078 {
8079 RENDERER_LINE[Layer_OBJ][sx] = READ16LE(&spritePalette[palette + color]) | prio;
8080 if((a0 & 0x1000) && m)
8081 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
8082 }
8083 }
8084
8085 if ((a0 & 0x1000) && ((m+1) == mosaicX))
8086 m=0;
8087
8088 sx = (sx+1) & 511;
8089 if(!(xx & 1))
8090 --address;
8091 if(--xxx == -1)
8092 {
8093 xxx = 7;
8094 address -= 28;
8095 }
8096 if(address < 0x10000)
8097 address += 0x8000;
8098 }while(--xx >= 0);
8099 }
8100 else
8101 {
8102 for(u32 xx = 0; xx < sizeX; ++xx)
8103 {
8104 if (xx >= startpix)
8105 --lineOBJpix;
8106 //if (lineOBJpix<0)
8107 // continue;
8108 if(sx < 240)
8109 {
8110 u8 color = vram[address];
8111 if(xx & 1)
8112 color >>= 4;
8113 else
8114 color &= 0x0F;
8115
8116 if ((color==0) && (((prio >> 25)&3) <
8117 ((RENDERER_LINE[Layer_OBJ][sx]>>25)&3)))
8118 {
8119 RENDERER_LINE[Layer_OBJ][sx] = (RENDERER_LINE[Layer_OBJ][sx] & 0xF9FFFFFF) | prio;
8120 if((a0 & 0x1000) && m)
8121 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
8122 }
8123 else if((color) && (prio < (RENDERER_LINE[Layer_OBJ][sx]&0xFF000000)))
8124 {
8125 RENDERER_LINE[Layer_OBJ][sx] = READ16LE(&spritePalette[palette + color]) | prio;
8126 if((a0 & 0x1000) && m)
8127 RENDERER_LINE[Layer_OBJ][sx]=(RENDERER_LINE[Layer_OBJ][sx-1] & 0xF9FFFFFF) | prio;
8128
8129 }
8130 }
8131 if ((a0 & 0x1000) && ((m+1) == mosaicX))
8132 m=0;
8133
8134 sx = (sx+1) & 511;
8135 if(xx & 1)
8136 ++address;
8137 if(++xxx == 8)
8138 {
8139 address += 28;
8140 xxx = 0;
8141 }
8142 if(address > 0x17fff)
8143 address -= 0x8000;
8144 }
8145 }
8146 }
8147 }
8148 }
8149 }
8150 }
8151 }
8152
8153 template<int renderer_idx>
gfxDrawOBJWin(void)8154 static void gfxDrawOBJWin (void)
8155 {
8156 INIT_RENDERER_CONTEXT(renderer_idx);
8157
8158 u16 *sprites = (u16 *)RENDERER_OAM;
8159 for(int x = 0; x < 128 ; x++)
8160 {
8161 int lineOBJpix = RENDERER_LINE_OBJ_PIX_LEFT[x];
8162 u16 a0 = READ16LE(sprites++);
8163 u16 a1 = READ16LE(sprites++);
8164 u16 a2 = READ16LE(sprites++);
8165 sprites++;
8166
8167 if (lineOBJpix<=0)
8168 return;
8169
8170 // ignores non OBJ-WIN and disabled OBJ-WIN
8171 if(((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200))
8172 continue;
8173
8174 u16 a0val = a0>>14;
8175
8176 if ((a0 & 0x0c00) == 0x0c00)
8177 a0 &=0xF3FF;
8178
8179 if (a0val == 3)
8180 {
8181 a0 &= 0x3FFF;
8182 a1 &= 0x3FFF;
8183 }
8184
8185 int sizeX = 8<<(a1>>14);
8186 int sizeY = sizeX;
8187
8188 if (a0val & 1)
8189 {
8190 #ifdef BRANCHLESS_GBA_GFX
8191 sizeX <<= isel(-(sizeX & (~31u)), 1, 0);
8192 sizeY >>= isel(-(sizeY>8), 0, 1);
8193 #else
8194 if (sizeX<32)
8195 sizeX<<=1;
8196 if (sizeY>8)
8197 sizeY>>=1;
8198 #endif
8199 }
8200 else if (a0val & 2)
8201 {
8202 #ifdef BRANCHLESS_GBA_GFX
8203 sizeX >>= isel(-(sizeX>8), 0, 1);
8204 sizeY <<= isel(-(sizeY & (~31u)), 1, 0);
8205 #else
8206 if (sizeX>8)
8207 sizeX>>=1;
8208 if (sizeY<32)
8209 sizeY<<=1;
8210 #endif
8211
8212 }
8213
8214 int sy = (a0 & 255);
8215
8216 if(a0 & 0x0100)
8217 {
8218 int fieldX = sizeX;
8219 int fieldY = sizeY;
8220 if(a0 & 0x0200)
8221 {
8222 fieldX <<= 1;
8223 fieldY <<= 1;
8224 }
8225 if((sy+fieldY) > 256)
8226 sy -= 256;
8227 int t = RENDERER_R_VCOUNT - sy;
8228 if((t >= 0) && (t < fieldY))
8229 {
8230 int sx = (a1 & 0x1FF);
8231 int startpix = 0;
8232 if ((sx+fieldX)> 512)
8233 startpix=512-sx;
8234
8235 if((sx < 240) || startpix)
8236 {
8237 lineOBJpix-=8;
8238 // int t2 = t - (fieldY >> 1);
8239 int rot = (a1 >> 9) & 0x1F;
8240 u16 *OAM = (u16 *)RENDERER_OAM;
8241 int dx = READ16LE(&OAM[3 + (rot << 4)]);
8242 if(dx & 0x8000)
8243 dx |= 0xFFFF8000;
8244 int dmx = READ16LE(&OAM[7 + (rot << 4)]);
8245 if(dmx & 0x8000)
8246 dmx |= 0xFFFF8000;
8247 int dy = READ16LE(&OAM[11 + (rot << 4)]);
8248 if(dy & 0x8000)
8249 dy |= 0xFFFF8000;
8250 int dmy = READ16LE(&OAM[15 + (rot << 4)]);
8251 if(dmy & 0x8000)
8252 dmy |= 0xFFFF8000;
8253
8254 int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
8255 + t * dmx;
8256 int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
8257 + t * dmy;
8258
8259 int c = (a2 & 0x3FF);
8260 if(RENDERER_R_DISPCNT_Video_Mode > 2 && (c < 512))
8261 continue;
8262
8263 int inc = 32;
8264 bool condition1 = a0 & 0x2000;
8265
8266 if(RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x40)
8267 inc = sizeX >> 3;
8268
8269 for(int x = 0; x < fieldX; x++)
8270 {
8271 bool cont = true;
8272 if (x >= startpix)
8273 lineOBJpix-=2;
8274 if (lineOBJpix<0)
8275 continue;
8276 int xxx = realX >> 8;
8277 int yyy = realY >> 8;
8278
8279 if(xxx < 0 || xxx >= sizeX || yyy < 0 || yyy >= sizeY || sx >= 240)
8280 cont = false;
8281
8282 if(cont)
8283 {
8284 u32 color;
8285 if(condition1)
8286 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
8287 + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
8288 (xxx & 7))&0x7fff)];
8289 else
8290 {
8291 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
8292 + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
8293 ((xxx & 7)>>1))&0x7fff)];
8294 if(xxx & 1)
8295 color >>= 4;
8296 else
8297 color &= 0x0F;
8298 }
8299
8300 if(color)
8301 RENDERER_LINE[Layer_WIN_OBJ][sx] = 1;
8302 }
8303 sx = (sx+1)&511;
8304 realX += dx;
8305 realY += dy;
8306 }
8307 }
8308 }
8309 }
8310 else
8311 {
8312 if((sy+sizeY) > 256)
8313 sy -= 256;
8314 int t = RENDERER_R_VCOUNT - sy;
8315 if((t >= 0) && (t < sizeY))
8316 {
8317 int sx = (a1 & 0x1FF);
8318 int startpix = 0;
8319 if ((sx+sizeX)> 512)
8320 startpix=512-sx;
8321
8322 if((sx < 240) || startpix)
8323 {
8324 lineOBJpix+=2;
8325 if(a1 & 0x2000)
8326 t = sizeY - t - 1;
8327 int c = (a2 & 0x3FF);
8328 if(RENDERER_R_DISPCNT_Video_Mode > 2 && (c < 512))
8329 continue;
8330 if(a0 & 0x2000)
8331 {
8332
8333 int inc = 32;
8334 if(RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x40)
8335 inc = sizeX >> 2;
8336 else
8337 c &= 0x3FE;
8338
8339 int xxx = 0;
8340 if(a1 & 0x1000)
8341 xxx = sizeX-1;
8342 int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
8343 + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff);
8344 if(a1 & 0x1000)
8345 xxx = 7;
8346 for(int xx = 0; xx < sizeX; xx++)
8347 {
8348 if (xx >= startpix)
8349 lineOBJpix--;
8350 if (lineOBJpix<0)
8351 continue;
8352 if(sx < 240)
8353 {
8354 u8 color = vram[address];
8355 if(color)
8356 RENDERER_LINE[Layer_WIN_OBJ][sx] = 1;
8357 }
8358
8359 sx = (sx+1) & 511;
8360 if(a1 & 0x1000) {
8361 xxx--;
8362 address--;
8363 if(xxx == -1) {
8364 address -= 56;
8365 xxx = 7;
8366 }
8367 if(address < 0x10000)
8368 address += 0x8000;
8369 } else {
8370 xxx++;
8371 address++;
8372 if(xxx == 8) {
8373 address += 56;
8374 xxx = 0;
8375 }
8376 if(address > 0x17fff)
8377 address -= 0x8000;
8378 }
8379 }
8380 }
8381 else
8382 {
8383 int inc = 32;
8384 if(RENDERER_IO_REGISTERS[REG_DISPCNT] & 0x40)
8385 inc = sizeX >> 3;
8386 int xxx = 0;
8387 if(a1 & 0x1000)
8388 xxx = sizeX - 1;
8389 int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
8390 + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff);
8391 // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
8392 // int palette = (a2 >> 8) & 0xF0;
8393 if(a1 & 0x1000)
8394 {
8395 xxx = 7;
8396 for(int xx = sizeX - 1; xx >= 0; xx--)
8397 {
8398 if (xx >= startpix)
8399 lineOBJpix--;
8400 if (lineOBJpix<0)
8401 continue;
8402 if(sx < 240)
8403 {
8404 u8 color = vram[address];
8405 if(xx & 1)
8406 color = (color >> 4);
8407 else
8408 color &= 0x0F;
8409
8410 if(color)
8411 RENDERER_LINE[Layer_WIN_OBJ][sx] = 1;
8412 }
8413 sx = (sx+1) & 511;
8414 xxx--;
8415 if(!(xx & 1))
8416 address--;
8417 if(xxx == -1) {
8418 xxx = 7;
8419 address -= 28;
8420 }
8421 if(address < 0x10000)
8422 address += 0x8000;
8423 }
8424 }
8425 else
8426 {
8427 for(int xx = 0; xx < sizeX; xx++)
8428 {
8429 if (xx >= startpix)
8430 lineOBJpix--;
8431 if (lineOBJpix<0)
8432 continue;
8433 if(sx < 240)
8434 {
8435 u8 color = vram[address];
8436 if(xx & 1)
8437 color = (color >> 4);
8438 else
8439 color &= 0x0F;
8440
8441 if(color)
8442 RENDERER_LINE[Layer_WIN_OBJ][sx] = 1;
8443 }
8444 sx = (sx+1) & 511;
8445 xxx++;
8446 if(xx & 1)
8447 address++;
8448 if(xxx == 8) {
8449 address += 28;
8450 xxx = 0;
8451 }
8452 if(address > 0x17fff)
8453 address -= 0x8000;
8454 }
8455 }
8456 }
8457 }
8458 }
8459 }
8460 }
8461 }
8462
8463 /*============================================================
8464 GBA.CPP
8465 ============================================================ */
8466 int saveType = 0;
8467 bool useBios = false;
8468 bool skipBios = false;
8469 bool cpuIsMultiBoot = false;
8470 int cpuSaveType = 0;
8471 bool enableRtc = false;
8472 bool mirroringEnable = false;
8473 bool skipSaveGameBattery = false;
8474
8475 #ifdef USE_SWITICKS
8476 int SWITicks = 0;
8477 #endif
8478
8479 bool cpuSramEnabled = true;
8480 bool cpuFlashEnabled = true;
8481 bool cpuEEPROMEnabled = true;
8482
8483 #ifdef MSB_FIRST
8484 bool cpuBiosSwapped = false;
8485 #endif
8486
8487 uint32_t myROM[] = {
8488 0xEA000006,
8489 0xEA000093,
8490 0xEA000006,
8491 0x00000000,
8492 0x00000000,
8493 0x00000000,
8494 0xEA000088,
8495 0x00000000,
8496 0xE3A00302,
8497 0xE1A0F000,
8498 0xE92D5800,
8499 0xE55EC002,
8500 0xE28FB03C,
8501 0xE79BC10C,
8502 0xE14FB000,
8503 0xE92D0800,
8504 0xE20BB080,
8505 0xE38BB01F,
8506 0xE129F00B,
8507 0xE92D4004,
8508 0xE1A0E00F,
8509 0xE12FFF1C,
8510 0xE8BD4004,
8511 0xE3A0C0D3,
8512 0xE129F00C,
8513 0xE8BD0800,
8514 0xE169F00B,
8515 0xE8BD5800,
8516 0xE1B0F00E,
8517 0x0000009C,
8518 0x0000009C,
8519 0x0000009C,
8520 0x0000009C,
8521 0x000001F8,
8522 0x000001F0,
8523 0x000000AC,
8524 0x000000A0,
8525 0x000000FC,
8526 0x00000168,
8527 0xE12FFF1E,
8528 0xE1A03000,
8529 0xE1A00001,
8530 0xE1A01003,
8531 0xE2113102,
8532 0x42611000,
8533 0xE033C040,
8534 0x22600000,
8535 0xE1B02001,
8536 0xE15200A0,
8537 0x91A02082,
8538 0x3AFFFFFC,
8539 0xE1500002,
8540 0xE0A33003,
8541 0x20400002,
8542 0xE1320001,
8543 0x11A020A2,
8544 0x1AFFFFF9,
8545 0xE1A01000,
8546 0xE1A00003,
8547 0xE1B0C08C,
8548 0x22600000,
8549 0x42611000,
8550 0xE12FFF1E,
8551 0xE92D0010,
8552 0xE1A0C000,
8553 0xE3A01001,
8554 0xE1500001,
8555 0x81A000A0,
8556 0x81A01081,
8557 0x8AFFFFFB,
8558 0xE1A0000C,
8559 0xE1A04001,
8560 0xE3A03000,
8561 0xE1A02001,
8562 0xE15200A0,
8563 0x91A02082,
8564 0x3AFFFFFC,
8565 0xE1500002,
8566 0xE0A33003,
8567 0x20400002,
8568 0xE1320001,
8569 0x11A020A2,
8570 0x1AFFFFF9,
8571 0xE0811003,
8572 0xE1B010A1,
8573 0xE1510004,
8574 0x3AFFFFEE,
8575 0xE1A00004,
8576 0xE8BD0010,
8577 0xE12FFF1E,
8578 0xE0010090,
8579 0xE1A01741,
8580 0xE2611000,
8581 0xE3A030A9,
8582 0xE0030391,
8583 0xE1A03743,
8584 0xE2833E39,
8585 0xE0030391,
8586 0xE1A03743,
8587 0xE2833C09,
8588 0xE283301C,
8589 0xE0030391,
8590 0xE1A03743,
8591 0xE2833C0F,
8592 0xE28330B6,
8593 0xE0030391,
8594 0xE1A03743,
8595 0xE2833C16,
8596 0xE28330AA,
8597 0xE0030391,
8598 0xE1A03743,
8599 0xE2833A02,
8600 0xE2833081,
8601 0xE0030391,
8602 0xE1A03743,
8603 0xE2833C36,
8604 0xE2833051,
8605 0xE0030391,
8606 0xE1A03743,
8607 0xE2833CA2,
8608 0xE28330F9,
8609 0xE0000093,
8610 0xE1A00840,
8611 0xE12FFF1E,
8612 0xE3A00001,
8613 0xE3A01001,
8614 0xE92D4010,
8615 0xE3A03000,
8616 0xE3A04001,
8617 0xE3500000,
8618 0x1B000004,
8619 0xE5CC3301,
8620 0xEB000002,
8621 0x0AFFFFFC,
8622 0xE8BD4010,
8623 0xE12FFF1E,
8624 0xE3A0C301,
8625 0xE5CC3208,
8626 0xE15C20B8,
8627 0xE0110002,
8628 0x10222000,
8629 0x114C20B8,
8630 0xE5CC4208,
8631 0xE12FFF1E,
8632 0xE92D500F,
8633 0xE3A00301,
8634 0xE1A0E00F,
8635 0xE510F004,
8636 0xE8BD500F,
8637 0xE25EF004,
8638 0xE59FD044,
8639 0xE92D5000,
8640 0xE14FC000,
8641 0xE10FE000,
8642 0xE92D5000,
8643 0xE3A0C302,
8644 0xE5DCE09C,
8645 0xE35E00A5,
8646 0x1A000004,
8647 0x05DCE0B4,
8648 0x021EE080,
8649 0xE28FE004,
8650 0x159FF018,
8651 0x059FF018,
8652 0xE59FD018,
8653 0xE8BD5000,
8654 0xE169F00C,
8655 0xE8BD5000,
8656 0xE25EF004,
8657 0x03007FF0,
8658 0x09FE2000,
8659 0x09FFC000,
8660 0x03007FE0
8661 };
8662
8663 static variable_desc saveGameStruct[] = {
8664 { &io_registers[REG_DISPCNT] , sizeof(uint16_t) },
8665 { &io_registers[REG_DISPSTAT] , sizeof(uint16_t) },
8666 { &io_registers[REG_VCOUNT] , sizeof(uint16_t) },
8667 { &io_registers[REG_BG0CNT] , sizeof(uint16_t) },
8668 { &io_registers[REG_BG1CNT] , sizeof(uint16_t) },
8669 { &io_registers[REG_BG2CNT] , sizeof(uint16_t) },
8670 { &io_registers[REG_BG3CNT] , sizeof(uint16_t) },
8671 { &io_registers[REG_BG0HOFS] , sizeof(uint16_t) },
8672 { &io_registers[REG_BG0VOFS] , sizeof(uint16_t) },
8673 { &io_registers[REG_BG1HOFS] , sizeof(uint16_t) },
8674 { &io_registers[REG_BG1VOFS] , sizeof(uint16_t) },
8675 { &io_registers[REG_BG2HOFS] , sizeof(uint16_t) },
8676 { &io_registers[REG_BG2VOFS] , sizeof(uint16_t) },
8677 { &io_registers[REG_BG3HOFS] , sizeof(uint16_t) },
8678 { &io_registers[REG_BG3VOFS] , sizeof(uint16_t) },
8679 { &io_registers[REG_BG2PA] , sizeof(uint16_t) },
8680 { &io_registers[REG_BG2PB] , sizeof(uint16_t) },
8681 { &io_registers[REG_BG2PC] , sizeof(uint16_t) },
8682 { &io_registers[REG_BG2PD] , sizeof(uint16_t) },
8683 { &BG2X_L , sizeof(uint16_t) },
8684 { &BG2X_H , sizeof(uint16_t) },
8685 { &BG2Y_L , sizeof(uint16_t) },
8686 { &BG2Y_H , sizeof(uint16_t) },
8687 { &io_registers[REG_BG3PA] , sizeof(uint16_t) },
8688 { &io_registers[REG_BG3PB] , sizeof(uint16_t) },
8689 { &io_registers[REG_BG3PC] , sizeof(uint16_t) },
8690 { &io_registers[REG_BG3PD] , sizeof(uint16_t) },
8691 { &BG3X_L , sizeof(uint16_t) },
8692 { &BG3X_H , sizeof(uint16_t) },
8693 { &BG3Y_L , sizeof(uint16_t) },
8694 { &BG3Y_H , sizeof(uint16_t) },
8695 { &io_registers[REG_WIN0H] , sizeof(uint16_t) },
8696 { &io_registers[REG_WIN1H] , sizeof(uint16_t) },
8697 { &io_registers[REG_WIN0V] , sizeof(uint16_t) },
8698 { &io_registers[REG_WIN1V] , sizeof(uint16_t) },
8699 { &io_registers[REG_WININ] , sizeof(uint16_t) },
8700 { &io_registers[REG_WINOUT] , sizeof(uint16_t) },
8701 { &MOSAIC , sizeof(uint16_t) },
8702 { &BLDMOD , sizeof(uint16_t) },
8703 { &COLEV , sizeof(uint16_t) },
8704 { &COLY , sizeof(uint16_t) },
8705 { &DM0SAD_L , sizeof(uint16_t) },
8706 { &DM0SAD_H , sizeof(uint16_t) },
8707 { &DM0DAD_L , sizeof(uint16_t) },
8708 { &DM0DAD_H , sizeof(uint16_t) },
8709 { &DM0CNT_L , sizeof(uint16_t) },
8710 { &DM0CNT_H , sizeof(uint16_t) },
8711 { &DM1SAD_L , sizeof(uint16_t) },
8712 { &DM1SAD_H , sizeof(uint16_t) },
8713 { &DM1DAD_L , sizeof(uint16_t) },
8714 { &DM1DAD_H , sizeof(uint16_t) },
8715 { &DM1CNT_L , sizeof(uint16_t) },
8716 { &DM1CNT_H , sizeof(uint16_t) },
8717 { &DM2SAD_L , sizeof(uint16_t) },
8718 { &DM2SAD_H , sizeof(uint16_t) },
8719 { &DM2DAD_L , sizeof(uint16_t) },
8720 { &DM2DAD_H , sizeof(uint16_t) },
8721 { &DM2CNT_L , sizeof(uint16_t) },
8722 { &DM2CNT_H , sizeof(uint16_t) },
8723 { &DM3SAD_L , sizeof(uint16_t) },
8724 { &DM3SAD_H , sizeof(uint16_t) },
8725 { &DM3DAD_L , sizeof(uint16_t) },
8726 { &DM3DAD_H , sizeof(uint16_t) },
8727 { &DM3CNT_L , sizeof(uint16_t) },
8728 { &DM3CNT_H , sizeof(uint16_t) },
8729 { &io_registers[REG_TM0D] , sizeof(uint16_t) },
8730 { &io_registers[REG_TM0CNT] , sizeof(uint16_t) },
8731 { &io_registers[REG_TM1D] , sizeof(uint16_t) },
8732 { &io_registers[REG_TM1CNT] , sizeof(uint16_t) },
8733 { &io_registers[REG_TM2D] , sizeof(uint16_t) },
8734 { &io_registers[REG_TM2CNT] , sizeof(uint16_t) },
8735 { &io_registers[REG_TM3D] , sizeof(uint16_t) },
8736 { &io_registers[REG_TM3CNT] , sizeof(uint16_t) },
8737 { &io_registers[REG_P1] , sizeof(uint16_t) },
8738 { &io_registers[REG_IE] , sizeof(uint16_t) },
8739 { &io_registers[REG_IF] , sizeof(uint16_t) },
8740 { &io_registers[REG_IME] , sizeof(uint16_t) },
8741 { &holdState, sizeof(bool) },
8742 { &graphics.lcdTicks, sizeof(int) },
8743 { &timer0On , sizeof(bool) },
8744 { &timer0Ticks , sizeof(int) },
8745 { &timer0Reload , sizeof(int) },
8746 { &timer0ClockReload , sizeof(int) },
8747 { &timer1On , sizeof(bool) },
8748 { &timer1Ticks , sizeof(int) },
8749 { &timer1Reload , sizeof(int) },
8750 { &timer1ClockReload , sizeof(int) },
8751 { &timer2On , sizeof(bool) },
8752 { &timer2Ticks , sizeof(int) },
8753 { &timer2Reload , sizeof(int) },
8754 { &timer2ClockReload , sizeof(int) },
8755 { &timer3On , sizeof(bool) },
8756 { &timer3Ticks , sizeof(int) },
8757 { &timer3Reload , sizeof(int) },
8758 { &timer3ClockReload , sizeof(int) },
8759 { &dma0Source , sizeof(uint32_t) },
8760 { &dma0Dest , sizeof(uint32_t) },
8761 { &dma1Source , sizeof(uint32_t) },
8762 { &dma1Dest , sizeof(uint32_t) },
8763 { &dma2Source , sizeof(uint32_t) },
8764 { &dma2Dest , sizeof(uint32_t) },
8765 { &dma3Source , sizeof(uint32_t) },
8766 { &dma3Dest , sizeof(uint32_t) },
8767 { &fxOn, sizeof(bool) },
8768 { &windowOn, sizeof(bool) },
8769 { &N_FLAG , sizeof(bool) },
8770 { &C_FLAG , sizeof(bool) },
8771 { &Z_FLAG , sizeof(bool) },
8772 { &V_FLAG , sizeof(bool) },
8773 { &armState , sizeof(bool) },
8774 { &armIrqEnable , sizeof(bool) },
8775 { &bus.armNextPC , sizeof(uint32_t) },
8776 { &armMode , sizeof(int) },
8777 { &saveType , sizeof(int) },
8778 { NULL, 0 }
8779 };
8780
CPUUpdateTicks(void)8781 static INLINE int CPUUpdateTicks (void)
8782 {
8783 int cpuLoopTicks = graphics.lcdTicks;
8784
8785 if(soundTicks < cpuLoopTicks)
8786 cpuLoopTicks = soundTicks;
8787
8788 if(timer0On && (timer0Ticks < cpuLoopTicks))
8789 cpuLoopTicks = timer0Ticks;
8790
8791 if(timer1On && !(io_registers[REG_TM1CNT] & 4) && (timer1Ticks < cpuLoopTicks))
8792 cpuLoopTicks = timer1Ticks;
8793
8794 if(timer2On && !(io_registers[REG_TM2CNT] & 4) && (timer2Ticks < cpuLoopTicks))
8795 cpuLoopTicks = timer2Ticks;
8796
8797 if(timer3On && !(io_registers[REG_TM3CNT] & 4) && (timer3Ticks < cpuLoopTicks))
8798 cpuLoopTicks = timer3Ticks;
8799
8800 #ifdef USE_SWITICKS
8801 if (SWITicks)
8802 {
8803 if (SWITicks < cpuLoopTicks)
8804 cpuLoopTicks = SWITicks;
8805 }
8806 #endif
8807
8808 if (IRQTicks)
8809 {
8810 if (IRQTicks < cpuLoopTicks)
8811 cpuLoopTicks = IRQTicks;
8812 }
8813
8814 return cpuLoopTicks;
8815 }
8816
8817 #if THREADED_RENDERER
8818
8819 #define CPUUpdateWindow0() \
8820 { \
8821 int x00_window0 = R_WIN_Window0_X1; \
8822 int x01_window0 = R_WIN_Window0_X2; \
8823 int x00_lte_x01 = x00_window0 <= x01_window0; \
8824 for(int i = 0; i < 240; i++) \
8825 gfxInWin[0][i] = ((i >= x00_window0 && i < x01_window0) & x00_lte_x01) | ((i >= x00_window0 || i < x01_window0) & ~x00_lte_x01); \
8826 ++threaded_gfxinwin_ver[0]; \
8827 }
8828
8829 #define CPUUpdateWindow1() \
8830 { \
8831 int x00_window1 = R_WIN_Window1_X1; \
8832 int x01_window1 = R_WIN_Window1_X2; \
8833 int x00_lte_x01 = x00_window1 <= x01_window1; \
8834 for(int i = 0; i < 240; i++) \
8835 gfxInWin[1][i] = ((i >= x00_window1 && i < x01_window1) & x00_lte_x01) | ((i >= x00_window1 || i < x01_window1) & ~x00_lte_x01); \
8836 ++threaded_gfxinwin_ver[1]; \
8837 }
8838
8839 #else
8840
8841 #define CPUUpdateWindow0() \
8842 { \
8843 int x00_window0 = R_WIN_Window0_X1; \
8844 int x01_window0 = R_WIN_Window0_X2; \
8845 int x00_lte_x01 = x00_window0 <= x01_window0; \
8846 for(int i = 0; i < 240; i++) \
8847 gfxInWin[0][i] = ((i >= x00_window0 && i < x01_window0) & x00_lte_x01) | ((i >= x00_window0 || i < x01_window0) & ~x00_lte_x01); \
8848 }
8849
8850 #define CPUUpdateWindow1() \
8851 { \
8852 int x00_window1 = R_WIN_Window1_X1; \
8853 int x01_window1 = R_WIN_Window1_X2; \
8854 int x00_lte_x01 = x00_window1 <= x01_window1; \
8855 for(int i = 0; i < 240; i++) \
8856 gfxInWin[1][i] = ((i >= x00_window1 && i < x01_window1) & x00_lte_x01) | ((i >= x00_window1 || i < x01_window1) & ~x00_lte_x01); \
8857 }
8858
8859 #endif
8860
8861 #define CPUCompareVCOUNT() \
8862 if(R_VCOUNT == (io_registers[REG_DISPSTAT] >> 8)) \
8863 { \
8864 io_registers[REG_DISPSTAT] |= 4; \
8865 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); \
8866 if(io_registers[REG_DISPSTAT] & 0x20) \
8867 { \
8868 io_registers[REG_IF] |= 4; \
8869 UPDATE_REG(0x202, io_registers[REG_IF]); \
8870 } \
8871 } \
8872 else \
8873 { \
8874 io_registers[REG_DISPSTAT] &= 0xFFFB; \
8875 UPDATE_REG(0x4, io_registers[REG_DISPSTAT]); \
8876 } \
8877 if (graphics.layerEnableDelay > 0) \
8878 { \
8879 graphics.layerEnableDelay--; \
8880 if (graphics.layerEnableDelay == 1) \
8881 graphics.layerEnable = io_registers[REG_DISPCNT]; \
8882 }
8883
8884
CPUWriteState(uint8_t * data,unsigned size)8885 unsigned CPUWriteState(uint8_t* data, unsigned size)
8886 {
8887 uint8_t *orig = data;
8888
8889 utilWriteIntMem(data, SAVE_GAME_VERSION);
8890 utilWriteMem(data, &rom[0xa0], 16);
8891 utilWriteIntMem(data, useBios);
8892 utilWriteMem(data, &bus.reg[0], sizeof(bus.reg));
8893
8894 utilWriteDataMem(data, saveGameStruct);
8895
8896 utilWriteIntMem(data, stopState);
8897 utilWriteIntMem(data, IRQTicks);
8898
8899 utilWriteMem(data, internalRAM, 0x8000);
8900 utilWriteMem(data, paletteRAM, 0x400);
8901 utilWriteMem(data, workRAM, 0x40000);
8902 utilWriteMem(data, vram, 0x20000);
8903 utilWriteMem(data, oam, 0x400);
8904 utilWriteMem(data, pix, 4 * PIX_BUFFER_SCREEN_WIDTH * 160);
8905 utilWriteMem(data, ioMem, 0x400);
8906
8907 eepromSaveGameMem(data);
8908 flashSaveGameMem(data);
8909 soundSaveGameMem(data);
8910 rtcSaveGameMem(data);
8911
8912 return (ptrdiff_t)data - (ptrdiff_t)orig;
8913 }
8914
CPUWriteBatteryFile(const char * fileName)8915 bool CPUWriteBatteryFile(const char *fileName)
8916 {
8917 if(gbaSaveType == 0)
8918 {
8919 if(eepromInUse)
8920 gbaSaveType = 3;
8921 else
8922 switch(saveType)
8923 {
8924 case 1:
8925 gbaSaveType = 1;
8926 break;
8927 case 2:
8928 gbaSaveType = 2;
8929 break;
8930 }
8931 }
8932
8933 if((gbaSaveType) && (gbaSaveType!=5))
8934 {
8935 FILE *file = fopen(fileName, "wb");
8936
8937 if(!file) {
8938 systemMessage("Error creating file %s", fileName);
8939 return false;
8940 }
8941
8942 // only save if Flash/Sram in use or EEprom in use
8943 if(gbaSaveType != 3) {
8944 if(gbaSaveType == 2) {
8945 if(fwrite(flashSaveMemory, 1, flashSize, file) != (size_t)flashSize) {
8946 fclose(file);
8947 return false;
8948 }
8949 } else {
8950 if(fwrite(flashSaveMemory, 1, 0x10000, file) != 0x10000) {
8951 fclose(file);
8952 return false;
8953 }
8954 }
8955 } else {
8956 if(fwrite(eepromData, 1, eepromSize, file) != (size_t)eepromSize) {
8957 fclose(file);
8958 return false;
8959 }
8960 }
8961 fclose(file);
8962 }
8963 return true;
8964 }
8965
CPUReadBatteryFile(const char * fileName)8966 bool CPUReadBatteryFile(const char *fileName)
8967 {
8968 FILE *file = fopen(fileName, "rb");
8969
8970 if(!file)
8971 return false;
8972
8973 // check file size to know what we should read
8974 fseek(file, 0, SEEK_END);
8975
8976 long size = ftell(file);
8977 fseek(file, 0, SEEK_SET);
8978
8979 if(size == 512 || size == 0x2000) {
8980 if(fread(eepromData, 1, size, file) != (size_t)size) {
8981 fclose(file);
8982 return false;
8983 }
8984 } else {
8985 if(size == 0x20000) {
8986 if(fread(flashSaveMemory, 1, 0x20000, file) != 0x20000) {
8987 fclose(file);
8988 return false;
8989 }
8990 flashSetSize(0x20000);
8991 } else {
8992 if(fread(flashSaveMemory, 1, 0x10000, file) != 0x10000) {
8993 fclose(file);
8994 return false;
8995 }
8996 flashSetSize(0x10000);
8997 }
8998 }
8999 fclose(file);
9000 return true;
9001 }
9002
9003 #ifdef HAVE_HLE_BIOS
CPUIsGBABios(const char * file)9004 static bool CPUIsGBABios(const char * file)
9005 {
9006 if(strlen(file) > 4)
9007 {
9008 const char * p = strrchr(file,'.');
9009
9010 if(p != NULL)
9011 {
9012 if(strcasecmp(p, ".gba") == 0)
9013 return true;
9014 if(strcasecmp(p, ".agb") == 0)
9015 return true;
9016 if(strcasecmp(p, ".bin") == 0)
9017 return true;
9018 if(strcasecmp(p, ".bios") == 0)
9019 return true;
9020 if(strcasecmp(p, ".rom") == 0)
9021 return true;
9022 }
9023 }
9024
9025 return false;
9026 }
9027 #endif
9028
9029 #ifdef ELF
CPUIsELF(const char * file)9030 static bool CPUIsELF(const char *file)
9031 {
9032 if(file == NULL)
9033 return false;
9034
9035 if(strlen(file) > 4)
9036 {
9037 const char * p = strrchr(file,'.');
9038
9039 if(p != NULL)
9040 {
9041 if(strcasecmp(p, ".elf") == 0)
9042 return true;
9043 }
9044 }
9045 return false;
9046 }
9047 #endif
9048
CPUCleanUp(void)9049 void CPUCleanUp (void)
9050 {
9051 if(rom != NULL) {
9052 memalign_free(rom);
9053 rom = NULL;
9054 }
9055
9056 if(vram != NULL) {
9057 memalign_free(vram);
9058 vram = NULL;
9059 }
9060
9061 if(paletteRAM != NULL) {
9062 memalign_free(paletteRAM);
9063 paletteRAM = NULL;
9064 }
9065
9066 if(internalRAM != NULL) {
9067 memalign_free(internalRAM);
9068 internalRAM = NULL;
9069 }
9070
9071 if(workRAM != NULL) {
9072 memalign_free(workRAM);
9073 workRAM = NULL;
9074 }
9075
9076 if(bios != NULL) {
9077 memalign_free(bios);
9078 bios = NULL;
9079 }
9080
9081 if(pix != NULL) {
9082 memalign_free(pix);
9083 pix = NULL;
9084 }
9085
9086 if(oam != NULL) {
9087 memalign_free(oam);
9088 oam = NULL;
9089 }
9090
9091 if(ioMem != NULL) {
9092 memalign_free(ioMem);
9093 ioMem = NULL;
9094 }
9095
9096 }
9097
CPUSetupBuffers()9098 bool CPUSetupBuffers()
9099 {
9100 romSize = 0x2000000;
9101 if(rom != NULL)
9102 CPUCleanUp();
9103
9104 //systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
9105
9106 rom = (uint8_t *)memalign_alloc_aligned(0x2000000);
9107 workRAM = (uint8_t *)memalign_alloc_aligned(0x40000);
9108 bios = (uint8_t *)memalign_alloc_aligned(0x4000);
9109 internalRAM = (uint8_t *)memalign_alloc_aligned(0x8000);
9110 paletteRAM = (uint8_t *)memalign_alloc_aligned(0x400);
9111 vram = (uint8_t *)memalign_alloc_aligned(0x20000);
9112 oam = (uint8_t *)memalign_alloc_aligned(0x400);
9113 pix = (uint16_t *)memalign_alloc_aligned(4 * PIX_BUFFER_SCREEN_WIDTH * 160);
9114 ioMem = (uint8_t *)memalign_alloc_aligned(0x400);
9115
9116 memset(rom, 0, 0x2000000);
9117 memset(workRAM, 1, 0x40000);
9118 memset(bios, 1, 0x4000);
9119 memset(internalRAM, 1, 0x8000);
9120 memset(paletteRAM, 1, 0x400);
9121 memset(vram, 1, 0x20000);
9122 memset(oam, 1, 0x400);
9123 memset(pix, 1, 4 * PIX_BUFFER_SCREEN_WIDTH * 160);
9124 memset(ioMem, 1, 0x400);
9125
9126 if(rom == NULL || workRAM == NULL || bios == NULL ||
9127 internalRAM == NULL || paletteRAM == NULL ||
9128 vram == NULL || oam == NULL || pix == NULL || ioMem == NULL) {
9129 CPUCleanUp();
9130 return false;
9131 }
9132
9133 flashInit();
9134 eepromInit();
9135
9136 //CPUUpdateRenderBuffers(true);
9137 #if !THREADED_RENDERER
9138 memset(line[Layer_BG0], -1, 240 * sizeof(u32));
9139 memset(line[Layer_BG1], -1, 240 * sizeof(u32));
9140 memset(line[Layer_BG2], -1, 240 * sizeof(u32));
9141 memset(line[Layer_BG3], -1, 240 * sizeof(u32));
9142 #endif
9143
9144 return true;
9145 }
9146
applyCartridgeOverride(char * code)9147 static void applyCartridgeOverride(char* code) {
9148 #if USE_MOTION_SENSOR
9149 hardware.sensor = HARDWARE_SENSOR_NONE;
9150
9151 do {
9152 // Koro Koro Puzzle - Happy Panechu!
9153 if(memcmp(code, "KHPJ", 4) == 0) {
9154 hardware.sensor = HARDWARE_SENSOR_TILT;
9155 break;
9156 }
9157
9158 // Yoshi's Universal Gravitation
9159 if(memcmp(code, "KYGJ", 4) == 0 || memcmp(code, "KYGE", 4) == 0 || memcmp(code, "KYGP", 4) == 0) {
9160 hardware.sensor = HARDWARE_SENSOR_TILT;
9161 break;
9162 }
9163
9164 // Wario Ware Twisted
9165 if(memcmp(code, "RZWJ", 4) == 0 || memcmp(code, "RZWE", 4) == 0 || memcmp(code, "RZWP", 4) == 0) {
9166 hardware.sensor = HARDWARE_SENSOR_GYRO;
9167 break;
9168 }
9169 } while(0);
9170
9171 systemSetSensorState(hardware.sensor);
9172
9173 if(hardware.sensor) {
9174 hardware.tilt_x = 0xFFF;
9175 hardware.tilt_y = 0xFFF;
9176 }
9177
9178 //if(hardware.sensor) while(1);
9179 #endif
9180 }
9181
CPULoadRom(const char * file)9182 int CPULoadRom(const char * file)
9183 {
9184 if (!CPUSetupBuffers()) return 0;
9185
9186 uint8_t *whereToLoad = cpuIsMultiBoot ? workRAM : rom;
9187
9188 if(file != NULL)
9189 {
9190 if(!utilLoad(file,
9191 utilIsGBAImage,
9192 whereToLoad,
9193 romSize)) {
9194 memalign_free(rom);
9195 rom = NULL;
9196 memalign_free(workRAM);
9197 workRAM = NULL;
9198 return 0;
9199 }
9200 }
9201
9202 //load cartridge code
9203 memcpy(cartridgeCode, whereToLoad + 0xAC, 4);
9204 applyCartridgeOverride(cartridgeCode);
9205
9206 uint16_t *temp = (uint16_t *)(rom+((romSize+1)&~1));
9207 int i;
9208
9209 for(i = (romSize+1)&~1; i < 0x2000000; i+=2) {
9210 WRITE16LE(temp, (i >> 1) & 0xFFFF);
9211 temp++;
9212 }
9213
9214 return romSize;
9215 }
9216
CPULoadRomData(const char * data,int size)9217 int CPULoadRomData(const char *data, int size)
9218 {
9219 if (!CPUSetupBuffers()) return 0;
9220
9221 uint8_t *whereToLoad = cpuIsMultiBoot ? workRAM : rom;
9222
9223 romSize = size % 2 == 0 ? size : size + 1;
9224 memcpy(whereToLoad, data, size);
9225
9226 //load cartridge code
9227 memcpy(cartridgeCode, whereToLoad + 0xAC, 4);
9228 applyCartridgeOverride(cartridgeCode);
9229
9230 uint16_t *temp = (u16 *)(rom+((romSize+1)&~1));
9231 int i;
9232
9233 for(i = (romSize+1)&~1; i < 0x2000000; i+=2) {
9234 WRITE16LE(temp, (i >> 1) & 0xFFFF);
9235 temp++;
9236 }
9237
9238 return romSize;
9239 }
9240
doMirroring(bool b)9241 void doMirroring (bool b)
9242 {
9243 uint32_t mirroredRomSize = (((romSize)>>20) & 0x3F)<<20;
9244 uint32_t mirroredRomAddress = romSize;
9245 if ((mirroredRomSize <=0x800000) && (b))
9246 {
9247 mirroredRomAddress = mirroredRomSize;
9248 if (mirroredRomSize==0)
9249 mirroredRomSize=0x100000;
9250 while (mirroredRomAddress<0x01000000)
9251 {
9252 memcpy((uint16_t *)(rom+mirroredRomAddress), (uint16_t *)(rom), mirroredRomSize);
9253 mirroredRomAddress+=mirroredRomSize;
9254 }
9255 }
9256 }
9257
9258 #if THREADED_RENDERER
ThreadedRendererStart()9259 void ThreadedRendererStart() {
9260 for(int u = 0; u < THREADED_RENDERER_COUNT; ++u) {
9261 init_renderer_context(threaded_renderer_contexts[u]);
9262 threaded_renderer_contexts[u].renderer_control = 1;
9263
9264 threaded_renderer_contexts[u].renderer_thread_id =
9265 thread_run((u == 0) ? threaded_renderer_loop0 : threaded_renderer_loop, reinterpret_cast<void*>(intptr_t(u)),
9266 #if VITA
9267 (u == 0) ? THREAD_PRIORITY_NORMAL : THREAD_PRIORITY_LOW);
9268 #else
9269 THREAD_PRIORITY_NORMAL);
9270 #endif
9271 }
9272 }
9273
ThreadedRendererStop()9274 void ThreadedRendererStop() {
9275 for(int u = 0; u < THREADED_RENDERER_COUNT; ++u) {
9276 threaded_renderer_contexts[u].renderer_control = 2;
9277 }
9278 _join:;
9279 for(int u = 0; u < THREADED_RENDERER_COUNT; ++u) {
9280 if(threaded_renderer_contexts[u].renderer_control == 2) goto _join;
9281 }
9282 }
9283 #endif
9284
9285 /* we only use 16bit color depth */
9286 #if THREADED_RENDERER
9287 #define GET_LINE_MIX (pix + PIX_BUFFER_SCREEN_WIDTH * RENDERER_R_VCOUNT)
9288 #else
9289 #define GET_LINE_MIX (pix + PIX_BUFFER_SCREEN_WIDTH * R_VCOUNT)
9290 #endif
9291
9292 template<int renderer_idx>
mode0RenderLine(void)9293 static void mode0RenderLine (void)
9294 {
9295 INIT_RENDERER_CONTEXT(renderer_idx);
9296
9297 #if !DEBUG_RENDERER_MODE0
9298 return;
9299 #endif
9300 #ifdef REPORT_VIDEO_MODES
9301 fprintf(stderr, "MODE 0: Render Line\n");
9302 #endif
9303 uint16_t* lineMix = GET_LINE_MIX;
9304
9305 uint32_t backdrop = RENDERER_BACKDROP;
9306
9307 if(RENDERER_R_DISPCNT_Screen_Display_BG0) {
9308 gfxDrawTextScreen<Layer_BG0, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG0CNT], RENDERER_IO_REGISTERS[REG_BG0HOFS], RENDERER_IO_REGISTERS[REG_BG0VOFS]);
9309 }
9310
9311 if(RENDERER_R_DISPCNT_Screen_Display_BG1) {
9312 gfxDrawTextScreen<Layer_BG1, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG1CNT], RENDERER_IO_REGISTERS[REG_BG1HOFS], RENDERER_IO_REGISTERS[REG_BG1VOFS]);
9313 }
9314
9315 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
9316 gfxDrawTextScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_IO_REGISTERS[REG_BG2HOFS], RENDERER_IO_REGISTERS[REG_BG2VOFS]);
9317 }
9318
9319 if(RENDERER_R_DISPCNT_Screen_Display_BG3) {
9320 gfxDrawTextScreen<Layer_BG3, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG3CNT], RENDERER_IO_REGISTERS[REG_BG3HOFS], RENDERER_IO_REGISTERS[REG_BG3VOFS]);
9321 }
9322
9323 for(int x = 0; x < 240; x++)
9324 {
9325 uint32_t color = backdrop;
9326 uint8_t top = SpecialEffectTarget_BD;
9327
9328 if(RENDERER_LINE[Layer_BG0][x] < color) {
9329 color = RENDERER_LINE[Layer_BG0][x];
9330 top = SpecialEffectTarget_BG0;
9331 }
9332
9333 if((uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(color >> 24)) {
9334 color = RENDERER_LINE[Layer_BG1][x];
9335 top = SpecialEffectTarget_BG1;
9336 }
9337
9338 if((uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(color >> 24)) {
9339 color = RENDERER_LINE[Layer_BG2][x];
9340 top = SpecialEffectTarget_BG2;
9341 }
9342
9343 if((uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(color >> 24)) {
9344 color = RENDERER_LINE[Layer_BG3][x];
9345 top = SpecialEffectTarget_BG3;
9346 }
9347
9348 if((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >> 24)) {
9349 color = RENDERER_LINE[Layer_OBJ][x];
9350 top = SpecialEffectTarget_OBJ;
9351
9352 if(color & 0x00010000) {
9353 // semi-transparent OBJ
9354 uint32_t back = backdrop;
9355 uint8_t top2 = SpecialEffectTarget_BD;
9356
9357 if((uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24) < (uint8_t)(back >> 24)) {
9358 back = RENDERER_LINE[Layer_BG0][x];
9359 top2 = SpecialEffectTarget_BG0;
9360 }
9361
9362 if((uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(back >> 24)) {
9363 back = RENDERER_LINE[Layer_BG1][x];
9364 top2 = SpecialEffectTarget_BG1;
9365 }
9366
9367 if((uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(back >> 24)) {
9368 back = RENDERER_LINE[Layer_BG2][x];
9369 top2 = SpecialEffectTarget_BG2;
9370 }
9371
9372 if((uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(back >> 24)) {
9373 back = RENDERER_LINE[Layer_BG3][x];
9374 top2 = SpecialEffectTarget_BG3;
9375 }
9376
9377 alpha_blend_brightness_switch();
9378 }
9379 }
9380
9381
9382 lineMix[x] = CONVERT_COLOR(color);
9383 }
9384 }
9385
9386 template<int renderer_idx>
mode0RenderLineNoWindow(void)9387 static void mode0RenderLineNoWindow (void)
9388 {
9389 INIT_RENDERER_CONTEXT(renderer_idx);
9390
9391 #if !DEBUG_RENDERER_MODE0
9392 return;
9393 #endif
9394 #ifdef REPORT_VIDEO_MODES
9395 fprintf(stderr, "MODE 0: Render Line No Window\n");
9396 #endif
9397 uint16_t* lineMix = GET_LINE_MIX;
9398
9399 uint32_t backdrop = RENDERER_BACKDROP;
9400
9401 if(RENDERER_R_DISPCNT_Screen_Display_BG0) {
9402 gfxDrawTextScreen<Layer_BG0, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG0CNT], RENDERER_IO_REGISTERS[REG_BG0HOFS], RENDERER_IO_REGISTERS[REG_BG0VOFS]);
9403 }
9404
9405 if(RENDERER_R_DISPCNT_Screen_Display_BG1) {
9406 gfxDrawTextScreen<Layer_BG1, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG1CNT], RENDERER_IO_REGISTERS[REG_BG1HOFS], RENDERER_IO_REGISTERS[REG_BG1VOFS]);
9407 }
9408
9409 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
9410 gfxDrawTextScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_IO_REGISTERS[REG_BG2HOFS], RENDERER_IO_REGISTERS[REG_BG2VOFS]);
9411 }
9412
9413 if(RENDERER_R_DISPCNT_Screen_Display_BG3) {
9414 gfxDrawTextScreen<Layer_BG3, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG3CNT], RENDERER_IO_REGISTERS[REG_BG3HOFS], RENDERER_IO_REGISTERS[REG_BG3VOFS]);
9415 }
9416
9417 for(int x = 0; x < 240; x++) {
9418 uint32_t color = backdrop;
9419 uint8_t top = SpecialEffectTarget_BD;
9420
9421 if(RENDERER_LINE[Layer_BG0][x] < color) {
9422 color = RENDERER_LINE[Layer_BG0][x];
9423 top = SpecialEffectTarget_BG0;
9424 }
9425
9426 if(RENDERER_LINE[Layer_BG1][x] < (color & 0xFF000000)) {
9427 color = RENDERER_LINE[Layer_BG1][x];
9428 top = SpecialEffectTarget_BG1;
9429 }
9430
9431 if(RENDERER_LINE[Layer_BG2][x] < (color & 0xFF000000)) {
9432 color = RENDERER_LINE[Layer_BG2][x];
9433 top = SpecialEffectTarget_BG2;
9434 }
9435
9436 if(RENDERER_LINE[Layer_BG3][x] < (color & 0xFF000000)) {
9437 color = RENDERER_LINE[Layer_BG3][x];
9438 top = SpecialEffectTarget_BG3;
9439 }
9440
9441 if(RENDERER_LINE[Layer_OBJ][x] < (color & 0xFF000000)) {
9442 color = RENDERER_LINE[Layer_OBJ][x];
9443 top = SpecialEffectTarget_OBJ;
9444 }
9445
9446 if(!(color & 0x00010000)) {
9447 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
9448 {
9449 case SpecialEffect_None:
9450 break;
9451 case SpecialEffect_Alpha_Blending:
9452 if(RENDERER_R_BLDCNT_IsTarget1(top))
9453 {
9454 uint32_t back = backdrop;
9455 uint8_t top2 = SpecialEffectTarget_BD;
9456 if((RENDERER_LINE[Layer_BG0][x] < back) && (top != SpecialEffectTarget_BG0))
9457 {
9458 back = RENDERER_LINE[Layer_BG0][x];
9459 top2 = SpecialEffectTarget_BG0;
9460 }
9461
9462 if((RENDERER_LINE[Layer_BG1][x] < (back & 0xFF000000)) && (top != SpecialEffectTarget_BG1))
9463 {
9464 back = RENDERER_LINE[Layer_BG1][x];
9465 top2 = SpecialEffectTarget_BG1;
9466 }
9467
9468 if((RENDERER_LINE[Layer_BG2][x] < (back & 0xFF000000)) && (top != SpecialEffectTarget_BG2))
9469 {
9470 back = RENDERER_LINE[Layer_BG2][x];
9471 top2 = SpecialEffectTarget_BG2;
9472 }
9473
9474 if((RENDERER_LINE[Layer_BG3][x] < (back & 0xFF000000)) && (top != SpecialEffectTarget_BG3))
9475 {
9476 back = RENDERER_LINE[Layer_BG3][x];
9477 top2 = SpecialEffectTarget_BG3;
9478 }
9479
9480 if((RENDERER_LINE[Layer_OBJ][x] < (back & 0xFF000000)) && (top != SpecialEffectTarget_OBJ))
9481 {
9482 back = RENDERER_LINE[Layer_OBJ][x];
9483 top2 = SpecialEffectTarget_OBJ;
9484 }
9485
9486 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
9487 {
9488 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
9489 }
9490
9491 }
9492 break;
9493 case SpecialEffect_Brightness_Increase:
9494 if(RENDERER_R_BLDCNT_IsTarget1(top))
9495 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
9496 break;
9497 case SpecialEffect_Brightness_Decrease:
9498 if(RENDERER_R_BLDCNT_IsTarget1(top))
9499 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
9500 break;
9501 }
9502 } else {
9503 // semi-transparent OBJ
9504 uint32_t back = backdrop;
9505 uint8_t top2 = SpecialEffectTarget_BD;
9506
9507 if(RENDERER_LINE[Layer_BG0][x] < back) {
9508 back = RENDERER_LINE[Layer_BG0][x];
9509 top2 = SpecialEffectTarget_BG0;
9510 }
9511
9512 if(RENDERER_LINE[Layer_BG1][x] < (back & 0xFF000000)) {
9513 back = RENDERER_LINE[Layer_BG1][x];
9514 top2 = SpecialEffectTarget_BG1;
9515 }
9516
9517 if(RENDERER_LINE[Layer_BG2][x] < (back & 0xFF000000)) {
9518 back = RENDERER_LINE[Layer_BG2][x];
9519 top2 = SpecialEffectTarget_BG2;
9520 }
9521
9522 if(RENDERER_LINE[Layer_BG3][x] < (back & 0xFF000000)) {
9523 back = RENDERER_LINE[Layer_BG3][x];
9524 top2 = SpecialEffectTarget_BG3;
9525 }
9526
9527 alpha_blend_brightness_switch();
9528 }
9529
9530 lineMix[x] = CONVERT_COLOR(color);
9531 }
9532 }
9533
9534 template<int renderer_idx>
mode0RenderLineAll(void)9535 static void mode0RenderLineAll (void)
9536 {
9537 INIT_RENDERER_CONTEXT(renderer_idx);
9538
9539 #if !DEBUG_RENDERER_MODE0
9540 return;
9541 #endif
9542 #ifdef REPORT_VIDEO_MODES
9543 fprintf(stderr, "MODE 0: Render Line All\n");
9544 #endif
9545 uint16_t* lineMix = GET_LINE_MIX;
9546
9547 uint32_t backdrop = RENDERER_BACKDROP;
9548
9549 bool inWindow0 = false;
9550 bool inWindow1 = false;
9551
9552 if(RENDERER_R_DISPCNT_Window_0_Display) {
9553 uint8_t v0 = RENDERER_R_WIN_Window0_Y1;
9554 uint8_t v1 = RENDERER_R_WIN_Window0_Y2;
9555 inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
9556 if(v1 >= v0)
9557 inWindow0 |= (RENDERER_R_VCOUNT >= v0 && RENDERER_R_VCOUNT < v1);
9558 else
9559 inWindow0 |= (RENDERER_R_VCOUNT >= v0 || RENDERER_R_VCOUNT < v1);
9560 }
9561 if(RENDERER_R_DISPCNT_Window_1_Display) {
9562 uint8_t v0 = RENDERER_R_WIN_Window1_Y1;
9563 uint8_t v1 = RENDERER_R_WIN_Window1_Y2;
9564 inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
9565 if(v1 >= v0)
9566 inWindow1 |= (RENDERER_R_VCOUNT >= v0 && RENDERER_R_VCOUNT < v1);
9567 else
9568 inWindow1 |= (RENDERER_R_VCOUNT >= v0 || RENDERER_R_VCOUNT < v1);
9569 }
9570
9571 if(RENDERER_R_DISPCNT_Screen_Display_BG0) {
9572 gfxDrawTextScreen<Layer_BG0, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG0CNT], RENDERER_IO_REGISTERS[REG_BG0HOFS], RENDERER_IO_REGISTERS[REG_BG0VOFS]);
9573 }
9574
9575 if(RENDERER_R_DISPCNT_Screen_Display_BG1) {
9576 gfxDrawTextScreen<Layer_BG1, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG1CNT], RENDERER_IO_REGISTERS[REG_BG1HOFS], RENDERER_IO_REGISTERS[REG_BG1VOFS]);
9577 }
9578
9579 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
9580 gfxDrawTextScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_IO_REGISTERS[REG_BG2HOFS], RENDERER_IO_REGISTERS[REG_BG2VOFS]);
9581 }
9582
9583 if(RENDERER_R_DISPCNT_Screen_Display_BG3) {
9584 gfxDrawTextScreen<Layer_BG3, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG3CNT], RENDERER_IO_REGISTERS[REG_BG3HOFS], RENDERER_IO_REGISTERS[REG_BG3VOFS]);
9585 }
9586
9587 uint8_t inWin0Mask = RENDERER_R_WIN_Window0_Mask;
9588 uint8_t inWin1Mask = RENDERER_R_WIN_Window1_Mask;
9589 uint8_t outMask = RENDERER_R_WIN_Outside_Mask;
9590
9591 for(int x = 0; x < 240; x++) {
9592 uint32_t color = backdrop;
9593 uint8_t top = SpecialEffectTarget_BD;
9594 uint8_t mask = outMask;
9595
9596 if(!(RENDERER_LINE[Layer_WIN_OBJ][x] & 0x80000000)) {
9597 mask = RENDERER_R_WIN_OBJ_Mask;
9598 }
9599
9600 mask = SELECT(inWindow1 && RENDERER_GFX_IN_WIN[1][x], inWin1Mask, mask);
9601 mask = SELECT(inWindow0 && RENDERER_GFX_IN_WIN[0][x], inWin0Mask, mask);
9602
9603 if((mask & LayerMask_BG0) && (RENDERER_LINE[Layer_BG0][x] < color)) {
9604 color = RENDERER_LINE[Layer_BG0][x];
9605 top = SpecialEffectTarget_BG0;
9606 }
9607
9608 if((mask & LayerMask_BG1) && ((uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(color >> 24))) {
9609 color = RENDERER_LINE[Layer_BG1][x];
9610 top = SpecialEffectTarget_BG1;
9611 }
9612
9613 if((mask & LayerMask_BG2) && ((uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(color >> 24))) {
9614 color = RENDERER_LINE[Layer_BG2][x];
9615 top = SpecialEffectTarget_BG2;
9616 }
9617
9618 if((mask & LayerMask_BG3) && ((uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(color >> 24))) {
9619 color = RENDERER_LINE[Layer_BG3][x];
9620 top = SpecialEffectTarget_BG3;
9621 }
9622
9623 if((mask & LayerMask_OBJ) && ((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >> 24))) {
9624 color = RENDERER_LINE[Layer_OBJ][x];
9625 top = SpecialEffectTarget_OBJ;
9626 }
9627
9628 if(color & 0x00010000)
9629 {
9630 // semi-transparent OBJ
9631 uint32_t back = backdrop;
9632 uint8_t top2 = SpecialEffectTarget_BD;
9633
9634 if((mask & LayerMask_BG0) && ((uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24) < (uint8_t)(back >> 24))) {
9635 back = RENDERER_LINE[Layer_BG0][x];
9636 top2 = SpecialEffectTarget_BG0;
9637 }
9638
9639 if((mask & LayerMask_BG1) && ((uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(back >> 24))) {
9640 back = RENDERER_LINE[Layer_BG1][x];
9641 top2 = SpecialEffectTarget_BG1;
9642 }
9643
9644 if((mask & LayerMask_BG2) && ((uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(back >> 24))) {
9645 back = RENDERER_LINE[Layer_BG2][x];
9646 top2 = SpecialEffectTarget_BG2;
9647 }
9648
9649 if((mask & LayerMask_BG3) && ((uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(back >> 24))) {
9650 back = RENDERER_LINE[Layer_BG3][x];
9651 top2 = SpecialEffectTarget_BG3;
9652 }
9653
9654 alpha_blend_brightness_switch();
9655 }
9656 else if((mask & LayerMask_SFX) && (RENDERER_R_BLDCNT_IsTarget1(top)))
9657 {
9658 // special FX on in the window
9659 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
9660 {
9661 case SpecialEffect_None:
9662 break;
9663 case SpecialEffect_Alpha_Blending:
9664 {
9665 uint32_t back = backdrop;
9666 uint8_t top2 = SpecialEffectTarget_BD;
9667 if(((mask & LayerMask_BG0) && (uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24) < (uint8_t)(back >> 24)) && top != SpecialEffectTarget_BG0)
9668 {
9669 back = RENDERER_LINE[Layer_BG0][x];
9670 top2 = SpecialEffectTarget_BG0;
9671 }
9672
9673 if(((mask & LayerMask_BG1) && (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(back >> 24)) && top != SpecialEffectTarget_BG1)
9674 {
9675 back = RENDERER_LINE[Layer_BG1][x];
9676 top2 = SpecialEffectTarget_BG1;
9677 }
9678
9679 if(((mask & LayerMask_BG2) && (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(back >> 24)) && top != SpecialEffectTarget_BG2)
9680 {
9681 back = RENDERER_LINE[Layer_BG2][x];
9682 top2 = SpecialEffectTarget_BG2;
9683 }
9684
9685 if(((mask & LayerMask_BG3) && (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(back >> 24)) && top != SpecialEffectTarget_BG3)
9686 {
9687 back = RENDERER_LINE[Layer_BG3][x];
9688 top2 = SpecialEffectTarget_BG3;
9689 }
9690
9691 if(((mask & LayerMask_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) && top != SpecialEffectTarget_OBJ) {
9692 back = RENDERER_LINE[Layer_OBJ][x];
9693 top2 = SpecialEffectTarget_OBJ;
9694 }
9695
9696 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
9697 {
9698 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
9699 }
9700 }
9701 break;
9702 case SpecialEffect_Brightness_Increase:
9703 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
9704 break;
9705 case SpecialEffect_Brightness_Decrease:
9706 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
9707 break;
9708 }
9709 }
9710
9711 lineMix[x] = CONVERT_COLOR(color);
9712 }
9713 }
9714
9715 /*
9716 Mode 1 is a tiled graphics mode, but with background layer 2 supporting scaling and rotation.
9717 There is no layer 3 in this mode.
9718 Layers 0 and 1 can be either 16 colours (with 16 different palettes) or 256 colours.
9719 There are 1024 tiles available.
9720 Layer 2 is 256 colours and allows only 256 tiles.
9721
9722 These routines only render a single line at a time, because of the way the GBA does events.
9723 */
9724
9725 template<int renderer_idx>
mode1RenderLine(void)9726 static void mode1RenderLine (void)
9727 {
9728 INIT_RENDERER_CONTEXT(renderer_idx);
9729
9730 #if !DEBUG_RENDERER_MODE1
9731 return;
9732 #endif
9733 #ifdef REPORT_VIDEO_MODES
9734 fprintf(stderr, "MODE 1: Render Line\n");
9735 #endif
9736 uint16_t* lineMix = GET_LINE_MIX;
9737
9738 uint32_t backdrop = RENDERER_BACKDROP;
9739
9740 if(RENDERER_R_DISPCNT_Screen_Display_BG0) {
9741 gfxDrawTextScreen<Layer_BG0, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG0CNT], RENDERER_IO_REGISTERS[REG_BG0HOFS], RENDERER_IO_REGISTERS[REG_BG0VOFS]);
9742 }
9743
9744 if(RENDERER_R_DISPCNT_Screen_Display_BG1) {
9745 gfxDrawTextScreen<Layer_BG1, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG1CNT], RENDERER_IO_REGISTERS[REG_BG1HOFS], RENDERER_IO_REGISTERS[REG_BG1VOFS]);
9746 }
9747
9748 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
9749 gfxDrawRotScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_BG2X_L, RENDERER_BG2X_H, RENDERER_BG2Y_L, RENDERER_BG2Y_H,
9750 RENDERER_IO_REGISTERS[REG_BG2PA], RENDERER_IO_REGISTERS[REG_BG2PB], RENDERER_IO_REGISTERS[REG_BG2PC], RENDERER_IO_REGISTERS[REG_BG2PD],
9751 RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
9752 }
9753
9754 for(uint32_t x = 0; x < 240u; ++x) {
9755 uint32_t color = backdrop;
9756 uint8_t top = SpecialEffectTarget_BD;
9757
9758 uint8_t li1 = (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24);
9759 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
9760 uint8_t li4 = (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24);
9761
9762 uint8_t r = (li2 < li1) ? (li2) : (li1);
9763
9764 if(li4 < r){
9765 r = (li4);
9766 }
9767
9768 if(RENDERER_LINE[Layer_BG0][x] < backdrop) {
9769 color = RENDERER_LINE[Layer_BG0][x];
9770 top = SpecialEffectTarget_BG0;
9771 }
9772
9773 if(r < (uint8_t)(color >> 24)) {
9774 if(r == li1){
9775 color = RENDERER_LINE[Layer_BG1][x];
9776 top = SpecialEffectTarget_BG1;
9777 }else if(r == li2){
9778 color = RENDERER_LINE[Layer_BG2][x];
9779 top = SpecialEffectTarget_BG2;
9780 }else if(r == li4){
9781 color = RENDERER_LINE[Layer_OBJ][x];
9782 top = SpecialEffectTarget_OBJ;
9783 if((color & 0x00010000))
9784 {
9785 // semi-transparent OBJ
9786 uint32_t back = backdrop;
9787 uint8_t top2 = SpecialEffectTarget_BD;
9788
9789 uint8_t li0 = (uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24);
9790 uint8_t li1 = (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24);
9791 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
9792 uint8_t r = (li1 < li0) ? (li1) : (li0);
9793
9794 if(li2 < r) {
9795 r = (li2);
9796 }
9797
9798 if(r < (uint8_t)(back >> 24)) {
9799 if(r == li0){
9800 back = RENDERER_LINE[Layer_BG0][x];
9801 top2 = SpecialEffectTarget_BG0;
9802 }else if(r == li1){
9803 back = RENDERER_LINE[Layer_BG1][x];
9804 top2 = SpecialEffectTarget_BG1;
9805 }else if(r == li2){
9806 back = RENDERER_LINE[Layer_BG2][x];
9807 top2 = SpecialEffectTarget_BG2;
9808 }
9809 }
9810
9811 alpha_blend_brightness_switch();
9812 }
9813 }
9814 }
9815
9816
9817 lineMix[x] = CONVERT_COLOR(color);
9818 }
9819
9820 #if !THREADED_RENDERER
9821 RENDERER_BG2C = 0;
9822 #endif
9823 }
9824
9825 template<int renderer_idx>
mode1RenderLineNoWindow(void)9826 static void mode1RenderLineNoWindow (void)
9827 {
9828 INIT_RENDERER_CONTEXT(renderer_idx);
9829
9830 #if !DEBUG_RENDERER_MODE1
9831 return;
9832 #endif
9833 #ifdef REPORT_VIDEO_MODES
9834 fprintf(stderr, "MODE 1: Render Line No Window\n");
9835 #endif
9836 uint16_t* lineMix = GET_LINE_MIX;
9837
9838 uint32_t backdrop = RENDERER_BACKDROP;
9839
9840 if(RENDERER_R_DISPCNT_Screen_Display_BG0) {
9841 gfxDrawTextScreen<Layer_BG0, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG0CNT], RENDERER_IO_REGISTERS[REG_BG0HOFS], RENDERER_IO_REGISTERS[REG_BG0VOFS]);
9842 }
9843
9844 if(RENDERER_R_DISPCNT_Screen_Display_BG1) {
9845 gfxDrawTextScreen<Layer_BG1, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG1CNT], RENDERER_IO_REGISTERS[REG_BG1HOFS], RENDERER_IO_REGISTERS[REG_BG1VOFS]);
9846 }
9847
9848 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
9849 gfxDrawRotScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_BG2X_L, RENDERER_BG2X_H, RENDERER_BG2Y_L, RENDERER_BG2Y_H,
9850 RENDERER_IO_REGISTERS[REG_BG2PA], RENDERER_IO_REGISTERS[REG_BG2PB], RENDERER_IO_REGISTERS[REG_BG2PC], RENDERER_IO_REGISTERS[REG_BG2PD],
9851 RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
9852 }
9853
9854 for(int x = 0; x < 240; ++x) {
9855 uint32_t color = backdrop;
9856 uint8_t top = SpecialEffectTarget_BD;
9857
9858 uint8_t li1 = (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24);
9859 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
9860 uint8_t li4 = (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24);
9861
9862 uint8_t r = (li2 < li1) ? (li2) : (li1);
9863
9864 if(li4 < r){
9865 r = (li4);
9866 }
9867
9868 if(RENDERER_LINE[Layer_BG0][x] < backdrop) {
9869 color = RENDERER_LINE[Layer_BG0][x];
9870 top = SpecialEffectTarget_BG0;
9871 }
9872
9873 if(r < (uint8_t)(color >> 24)) {
9874 if(r == li1){
9875 color = RENDERER_LINE[Layer_BG1][x];
9876 top = SpecialEffectTarget_BG1;
9877 }else if(r == li2){
9878 color = RENDERER_LINE[Layer_BG2][x];
9879 top = SpecialEffectTarget_BG2;
9880 }else if(r == li4){
9881 color = RENDERER_LINE[Layer_OBJ][x];
9882 top = SpecialEffectTarget_OBJ;
9883 }
9884 }
9885
9886 if(!(color & 0x00010000)) {
9887 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
9888 {
9889 case SpecialEffect_None:
9890 break;
9891 case SpecialEffect_Alpha_Blending:
9892 if(RENDERER_R_BLDCNT_IsTarget1(top))
9893 {
9894 uint32_t back = backdrop;
9895 uint8_t top2 = SpecialEffectTarget_BD;
9896
9897 if((top != SpecialEffectTarget_BG0) && (uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24) < (uint8_t)(back >> 24)) {
9898 back = RENDERER_LINE[Layer_BG0][x];
9899 top2 = SpecialEffectTarget_BG0;
9900 }
9901
9902 if((top != SpecialEffectTarget_BG1) && (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(back >> 24)) {
9903 back = RENDERER_LINE[Layer_BG1][x];
9904 top2 = SpecialEffectTarget_BG1;
9905 }
9906
9907 if((top != SpecialEffectTarget_BG2) && (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(back >> 24)) {
9908 back = RENDERER_LINE[Layer_BG2][x];
9909 top2 = SpecialEffectTarget_BG2;
9910 }
9911
9912 if((top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
9913 back = RENDERER_LINE[Layer_OBJ][x];
9914 top2 = SpecialEffectTarget_OBJ;
9915 }
9916
9917 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
9918 {
9919 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
9920 }
9921 }
9922 break;
9923 case SpecialEffect_Brightness_Increase:
9924 if(RENDERER_R_BLDCNT_IsTarget1(top))
9925 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
9926 break;
9927 case SpecialEffect_Brightness_Decrease:
9928 if(RENDERER_R_BLDCNT_IsTarget1(top))
9929 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
9930 break;
9931 }
9932 } else {
9933 // semi-transparent OBJ
9934 uint32_t back = backdrop;
9935 uint8_t top2 = SpecialEffectTarget_BD;
9936
9937 uint8_t li0 = (uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24);
9938 uint8_t li1 = (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24);
9939 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
9940
9941 uint8_t r = (li1 < li0) ? (li1) : (li0);
9942
9943 if(li2 < r) {
9944 r = (li2);
9945 }
9946
9947 if(r < (uint8_t)(back >> 24))
9948 {
9949 if(r == li0)
9950 {
9951 back = RENDERER_LINE[Layer_BG0][x];
9952 top2 = SpecialEffectTarget_BG0;
9953 }
9954 else if(r == li1)
9955 {
9956 back = RENDERER_LINE[Layer_BG1][x];
9957 top2 = SpecialEffectTarget_BG1;
9958 }
9959 else if(r == li2)
9960 {
9961 back = RENDERER_LINE[Layer_BG2][x];
9962 top2 = SpecialEffectTarget_BG2;
9963 }
9964 }
9965
9966 alpha_blend_brightness_switch();
9967 }
9968
9969 lineMix[x] = CONVERT_COLOR(color);
9970 }
9971
9972 #if !THREADED_RENDERER
9973 RENDERER_BG2C = 0;
9974 #endif
9975 }
9976
9977 template<int renderer_idx>
mode1RenderLineAll(void)9978 static void mode1RenderLineAll (void)
9979 {
9980 INIT_RENDERER_CONTEXT(renderer_idx);
9981
9982 #if !DEBUG_RENDERER_MODE1
9983 return;
9984 #endif
9985 #ifdef REPORT_VIDEO_MODES
9986 fprintf(stderr, "MODE 1: Render Line All\n");
9987 #endif
9988 uint16_t* lineMix = GET_LINE_MIX;
9989
9990 uint32_t backdrop = RENDERER_BACKDROP;
9991
9992 bool inWindow0 = false;
9993 bool inWindow1 = false;
9994
9995 if(RENDERER_R_DISPCNT_Window_0_Display)
9996 {
9997 uint8_t v0 = RENDERER_R_WIN_Window0_Y1;
9998 uint8_t v1 = RENDERER_R_WIN_Window0_Y2;
9999 inWindow0 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10000 }
10001 if(RENDERER_R_DISPCNT_Window_1_Display)
10002 {
10003 uint8_t v0 = RENDERER_R_WIN_Window1_Y1;
10004 uint8_t v1 = RENDERER_R_WIN_Window1_Y2;
10005 inWindow1 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10006 }
10007
10008 if(RENDERER_R_DISPCNT_Screen_Display_BG0) {
10009 gfxDrawTextScreen<Layer_BG0, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG0CNT], RENDERER_IO_REGISTERS[REG_BG0HOFS], RENDERER_IO_REGISTERS[REG_BG0VOFS]);
10010 }
10011
10012 if(RENDERER_R_DISPCNT_Screen_Display_BG1) {
10013 gfxDrawTextScreen<Layer_BG1, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG1CNT], RENDERER_IO_REGISTERS[REG_BG1HOFS], RENDERER_IO_REGISTERS[REG_BG1VOFS]);
10014 }
10015
10016 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10017 gfxDrawRotScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_BG2X_L, RENDERER_BG2X_H, RENDERER_BG2Y_L, RENDERER_BG2Y_H,
10018 RENDERER_IO_REGISTERS[REG_BG2PA], RENDERER_IO_REGISTERS[REG_BG2PB], RENDERER_IO_REGISTERS[REG_BG2PC], RENDERER_IO_REGISTERS[REG_BG2PD],
10019 RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10020 }
10021
10022 uint8_t inWin0Mask = RENDERER_R_WIN_Window0_Mask;
10023 uint8_t inWin1Mask = RENDERER_R_WIN_Window1_Mask;
10024 uint8_t outMask = RENDERER_R_WIN_Outside_Mask;
10025
10026 for(int x = 0; x < 240; ++x) {
10027 uint32_t color = backdrop;
10028 uint8_t top = SpecialEffectTarget_BD;
10029 uint8_t mask = outMask;
10030
10031 if(!(RENDERER_LINE[Layer_WIN_OBJ][x] & 0x80000000)) {
10032 mask = RENDERER_R_WIN_OBJ_Mask;
10033 }
10034
10035 mask = SELECT(inWindow1 && RENDERER_GFX_IN_WIN[1][x], inWin1Mask, mask);
10036 mask = SELECT(inWindow0 && RENDERER_GFX_IN_WIN[0][x], inWin0Mask, mask);
10037
10038 // At the very least, move the inexpensive 'mask' operation up front
10039 if((mask & LayerMask_BG0) && RENDERER_LINE[Layer_BG0][x] < backdrop) {
10040 color = RENDERER_LINE[Layer_BG0][x];
10041 top = SpecialEffectTarget_BG0;
10042 }
10043
10044 if((mask & LayerMask_BG1) && (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(color >> 24)) {
10045 color = RENDERER_LINE[Layer_BG1][x];
10046 top = SpecialEffectTarget_BG1;
10047 }
10048
10049 if((mask & LayerMask_BG2) && (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(color >> 24)) {
10050 color = RENDERER_LINE[Layer_BG2][x];
10051 top = SpecialEffectTarget_BG2;
10052 }
10053
10054 if((mask & LayerMask_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >> 24)) {
10055 color = RENDERER_LINE[Layer_OBJ][x];
10056 top = SpecialEffectTarget_OBJ;
10057 }
10058
10059 if(color & 0x00010000) {
10060 // semi-transparent OBJ
10061 uint32_t back = backdrop;
10062 uint8_t top2 = SpecialEffectTarget_BD;
10063
10064 if((mask & LayerMask_BG0) && (uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24) < (uint8_t)(backdrop >> 24)) {
10065 back = RENDERER_LINE[Layer_BG0][x];
10066 top2 = SpecialEffectTarget_BG0;
10067 }
10068
10069 if((mask & LayerMask_BG1) && (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(back >> 24)) {
10070 back = RENDERER_LINE[Layer_BG1][x];
10071 top2 = SpecialEffectTarget_BG1;
10072 }
10073
10074 if((mask & LayerMask_BG2) && (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(back >> 24)) {
10075 back = RENDERER_LINE[Layer_BG2][x];
10076 top2 = SpecialEffectTarget_BG2;
10077 }
10078
10079 alpha_blend_brightness_switch();
10080 } else if(mask & LayerMask_SFX) {
10081 // special FX on the window
10082 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
10083 {
10084 case SpecialEffect_None:
10085 break;
10086 case SpecialEffect_Alpha_Blending:
10087 if(RENDERER_R_BLDCNT_IsTarget1(top))
10088 {
10089 uint32_t back = backdrop;
10090 uint8_t top2 = SpecialEffectTarget_BD;
10091
10092 if((mask & LayerMask_BG0) && (top != SpecialEffectTarget_BG0) && (uint8_t)(RENDERER_LINE[Layer_BG0][x]>>24) < (uint8_t)(backdrop >> 24)) {
10093 back = RENDERER_LINE[Layer_BG0][x];
10094 top2 = SpecialEffectTarget_BG0;
10095 }
10096
10097 if((mask & LayerMask_BG1) && (top != SpecialEffectTarget_BG1) && (uint8_t)(RENDERER_LINE[Layer_BG1][x]>>24) < (uint8_t)(back >> 24)) {
10098 back = RENDERER_LINE[Layer_BG1][x];
10099 top2 = SpecialEffectTarget_BG1;
10100 }
10101
10102 if((mask & LayerMask_BG2) && (top != SpecialEffectTarget_BG2) && (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(back >> 24)) {
10103 back = RENDERER_LINE[Layer_BG2][x];
10104 top2 = SpecialEffectTarget_BG2;
10105 }
10106
10107 if((mask & LayerMask_OBJ) && (top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
10108 back = RENDERER_LINE[Layer_OBJ][x];
10109 top2 = SpecialEffectTarget_OBJ;
10110 }
10111
10112 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
10113 {
10114 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10115 }
10116 }
10117 break;
10118 case SpecialEffect_Brightness_Increase:
10119 if(RENDERER_R_BLDCNT_IsTarget1(top))
10120 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10121 break;
10122 case SpecialEffect_Brightness_Decrease:
10123 if(RENDERER_R_BLDCNT_IsTarget1(top))
10124 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10125 break;
10126 }
10127 }
10128
10129 lineMix[x] = CONVERT_COLOR(color);
10130 }
10131
10132 #if !THREADED_RENDERER
10133 RENDERER_BG2C = 0;
10134 #endif
10135 }
10136
10137 /*
10138 Mode 2 is a 256 colour tiled graphics mode which supports scaling and rotation.
10139 There is no background layer 0 or 1 in this mode. Only background layers 2 and 3.
10140 There are 256 tiles available.
10141 It does not support flipping.
10142
10143 These routines only render a single line at a time, because of the way the GBA does events.
10144 */
10145
10146 template<int renderer_idx>
mode2RenderLine(void)10147 static void mode2RenderLine (void)
10148 {
10149 INIT_RENDERER_CONTEXT(renderer_idx);
10150
10151 #if !DEBUG_RENDERER_MODE2
10152 return;
10153 #endif
10154 #ifdef REPORT_VIDEO_MODES
10155 fprintf(stderr, "MODE 2: Render Line\n");
10156 #endif
10157 uint16_t* lineMix = GET_LINE_MIX;
10158
10159 uint32_t backdrop = RENDERER_BACKDROP;
10160
10161 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10162 gfxDrawRotScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_BG2X_L, RENDERER_BG2X_H, RENDERER_BG2Y_L, RENDERER_BG2Y_H,
10163 RENDERER_IO_REGISTERS[REG_BG2PA], RENDERER_IO_REGISTERS[REG_BG2PB], RENDERER_IO_REGISTERS[REG_BG2PC], RENDERER_IO_REGISTERS[REG_BG2PD],
10164 RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10165 }
10166
10167 if(RENDERER_R_DISPCNT_Screen_Display_BG3) {
10168 gfxDrawRotScreen<Layer_BG3, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG3CNT], RENDERER_BG3X_L, RENDERER_BG3X_H, RENDERER_BG3Y_L, RENDERER_BG3Y_H,
10169 RENDERER_IO_REGISTERS[REG_BG3PA], RENDERER_IO_REGISTERS[REG_BG3PB], RENDERER_IO_REGISTERS[REG_BG3PC], RENDERER_IO_REGISTERS[REG_BG3PD],
10170 RENDERER_BG3X, RENDERER_BG3Y, RENDERER_BG3C);
10171 }
10172
10173 for(int x = 0; x < 240; ++x) {
10174 uint32_t color = backdrop;
10175 uint8_t top = SpecialEffectTarget_BD;
10176
10177 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
10178 uint8_t li3 = (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24);
10179 uint8_t li4 = (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24);
10180
10181 uint8_t r = (li3 < li2) ? (li3) : (li2);
10182
10183 if(li4 < r){
10184 r = (li4);
10185 }
10186
10187 if(r < (uint8_t)(color >> 24)) {
10188 if(r == li2){
10189 color = RENDERER_LINE[Layer_BG2][x];
10190 top = SpecialEffectTarget_BG2;
10191 }else if(r == li3){
10192 color = RENDERER_LINE[Layer_BG3][x];
10193 top = SpecialEffectTarget_BG3;
10194 }else if(r == li4){
10195 color = RENDERER_LINE[Layer_OBJ][x];
10196 top = SpecialEffectTarget_OBJ;
10197
10198 if(color & 0x00010000) {
10199 // semi-transparent OBJ
10200 uint32_t back = backdrop;
10201 uint8_t top2 = SpecialEffectTarget_BD;
10202
10203 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
10204 uint8_t li3 = (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24);
10205 uint8_t r = (li3 < li2) ? (li3) : (li2);
10206
10207 if(r < (uint8_t)(back >> 24)) {
10208 if(r == li2){
10209 back = RENDERER_LINE[Layer_BG2][x];
10210 top2 = SpecialEffectTarget_BG2;
10211 }else if(r == li3){
10212 back = RENDERER_LINE[Layer_BG3][x];
10213 top2 = SpecialEffectTarget_BG3;
10214 }
10215 }
10216
10217 alpha_blend_brightness_switch();
10218 }
10219 }
10220 }
10221
10222
10223 lineMix[x] = CONVERT_COLOR(color);
10224 }
10225
10226 #if !THREADED_RENDERER
10227 RENDERER_BG2C = 0;
10228 RENDERER_BG3C = 0;
10229 #endif
10230 }
10231
10232 template<int renderer_idx>
mode2RenderLineNoWindow(void)10233 static void mode2RenderLineNoWindow (void)
10234 {
10235 INIT_RENDERER_CONTEXT(renderer_idx);
10236
10237 #if !DEBUG_RENDERER_MODE2
10238 return;
10239 #endif
10240 #ifdef REPORT_VIDEO_MODES
10241 fprintf(stderr, "MODE 2: Render Line No Window\n");
10242 #endif
10243 uint16_t* lineMix = GET_LINE_MIX;
10244
10245 uint32_t backdrop = RENDERER_BACKDROP;
10246
10247 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10248 gfxDrawRotScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_BG2X_L, RENDERER_BG2X_H, RENDERER_BG2Y_L, RENDERER_BG2Y_H,
10249 RENDERER_IO_REGISTERS[REG_BG2PA], RENDERER_IO_REGISTERS[REG_BG2PB], RENDERER_IO_REGISTERS[REG_BG2PC], RENDERER_IO_REGISTERS[REG_BG2PD],
10250 RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10251 }
10252
10253 if(RENDERER_R_DISPCNT_Screen_Display_BG3) {
10254 gfxDrawRotScreen<Layer_BG3, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG3CNT], RENDERER_BG3X_L, RENDERER_BG3X_H, RENDERER_BG3Y_L, RENDERER_BG3Y_H,
10255 RENDERER_IO_REGISTERS[REG_BG3PA], RENDERER_IO_REGISTERS[REG_BG3PB], RENDERER_IO_REGISTERS[REG_BG3PC], RENDERER_IO_REGISTERS[REG_BG3PD],
10256 RENDERER_BG3X, RENDERER_BG3Y, RENDERER_BG3C);
10257 }
10258
10259 for(int x = 0; x < 240; ++x) {
10260 uint32_t color = backdrop;
10261 uint8_t top = SpecialEffectTarget_BD;
10262
10263 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
10264 uint8_t li3 = (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24);
10265 uint8_t li4 = (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24);
10266
10267 uint8_t r = (li3 < li2) ? (li3) : (li2);
10268
10269 if(li4 < r){
10270 r = (li4);
10271 }
10272
10273 if(r < (uint8_t)(color >> 24)) {
10274 if(r == li2){
10275 color = RENDERER_LINE[Layer_BG2][x];
10276 top = SpecialEffectTarget_BG2;
10277 }else if(r == li3){
10278 color = RENDERER_LINE[Layer_BG3][x];
10279 top = SpecialEffectTarget_BG3;
10280 }else if(r == li4){
10281 color = RENDERER_LINE[Layer_OBJ][x];
10282 top = SpecialEffectTarget_OBJ;
10283 }
10284 }
10285
10286 if(!(color & 0x00010000)) {
10287 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
10288 {
10289 case SpecialEffect_None:
10290 break;
10291 case SpecialEffect_Alpha_Blending:
10292 if(RENDERER_R_BLDCNT_IsTarget1(top))
10293 {
10294 uint32_t back = backdrop;
10295 uint8_t top2 = SpecialEffectTarget_BD;
10296
10297 if((top != SpecialEffectTarget_BG2) && (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24) < (uint8_t)(back >> 24)) {
10298 back = RENDERER_LINE[Layer_BG2][x];
10299 top2 = SpecialEffectTarget_BG2;
10300 }
10301
10302 if((top != SpecialEffectTarget_BG3) && (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(back >> 24)) {
10303 back = RENDERER_LINE[Layer_BG3][x];
10304 top2 = SpecialEffectTarget_BG3;
10305 }
10306
10307 if((top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
10308 back = RENDERER_LINE[Layer_OBJ][x];
10309 top2 = SpecialEffectTarget_OBJ;
10310 }
10311
10312 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
10313 {
10314 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10315 }
10316 }
10317 break;
10318 case SpecialEffect_Brightness_Increase:
10319 if(RENDERER_R_BLDCNT_IsTarget1(top))
10320 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10321 break;
10322 case SpecialEffect_Brightness_Decrease:
10323 if(RENDERER_R_BLDCNT_IsTarget1(top))
10324 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10325 break;
10326 }
10327 } else {
10328 // semi-transparent OBJ
10329 uint32_t back = backdrop;
10330 uint8_t top2 = SpecialEffectTarget_BD;
10331
10332 uint8_t li2 = (uint8_t)(RENDERER_LINE[Layer_BG2][x]>>24);
10333 uint8_t li3 = (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24);
10334 uint8_t r = (li3 < li2) ? (li3) : (li2);
10335
10336 if(r < (uint8_t)(back >> 24)) {
10337 if(r == li2){
10338 back = RENDERER_LINE[Layer_BG2][x];
10339 top2 = SpecialEffectTarget_BG2;
10340 }else if(r == li3){
10341 back = RENDERER_LINE[Layer_BG3][x];
10342 top2 = SpecialEffectTarget_BG3;
10343 }
10344 }
10345
10346 alpha_blend_brightness_switch();
10347 }
10348
10349 lineMix[x] = CONVERT_COLOR(color);
10350 }
10351
10352 #if !THREADED_RENDERER
10353 RENDERER_BG2C = 0;
10354 RENDERER_BG3C = 0;
10355 #endif
10356 }
10357
10358 template<int renderer_idx>
mode2RenderLineAll(void)10359 static void mode2RenderLineAll (void)
10360 {
10361 INIT_RENDERER_CONTEXT(renderer_idx);
10362
10363 #if !DEBUG_RENDERER_MODE2
10364 return;
10365 #endif
10366 #ifdef REPORT_VIDEO_MODES
10367 fprintf(stderr, "MODE 2: Render Line All\n");
10368 #endif
10369 uint16_t* lineMix = GET_LINE_MIX;
10370
10371 uint32_t backdrop = RENDERER_BACKDROP;
10372
10373 bool inWindow0 = false;
10374 bool inWindow1 = false;
10375
10376 if(RENDERER_R_DISPCNT_Window_0_Display)
10377 {
10378 uint8_t v0 = RENDERER_R_WIN_Window0_Y1;
10379 uint8_t v1 = RENDERER_R_WIN_Window0_Y2;
10380 inWindow0 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10381 }
10382 if(RENDERER_R_DISPCNT_Window_1_Display)
10383 {
10384 uint8_t v0 = RENDERER_R_WIN_Window1_Y1;
10385 uint8_t v1 = RENDERER_R_WIN_Window1_Y2;
10386 inWindow1 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10387 }
10388
10389 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10390 gfxDrawRotScreen<Layer_BG2, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG2CNT], RENDERER_BG2X_L, RENDERER_BG2X_H, RENDERER_BG2Y_L, RENDERER_BG2Y_H,
10391 RENDERER_IO_REGISTERS[REG_BG2PA], RENDERER_IO_REGISTERS[REG_BG2PB], RENDERER_IO_REGISTERS[REG_BG2PC], RENDERER_IO_REGISTERS[REG_BG2PD],
10392 RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10393 }
10394
10395 if(RENDERER_R_DISPCNT_Screen_Display_BG3) {
10396 gfxDrawRotScreen<Layer_BG3, renderer_idx>(RENDERER_IO_REGISTERS[REG_BG3CNT], RENDERER_BG3X_L, RENDERER_BG3X_H, RENDERER_BG3Y_L, RENDERER_BG3Y_H,
10397 RENDERER_IO_REGISTERS[REG_BG3PA], RENDERER_IO_REGISTERS[REG_BG3PB], RENDERER_IO_REGISTERS[REG_BG3PC], RENDERER_IO_REGISTERS[REG_BG3PD],
10398 RENDERER_BG3X, RENDERER_BG3Y, RENDERER_BG3C);
10399 }
10400
10401 uint8_t inWin0Mask = RENDERER_R_WIN_Window0_Mask;
10402 uint8_t inWin1Mask = RENDERER_R_WIN_Window1_Mask;
10403 uint8_t outMask = RENDERER_R_WIN_Outside_Mask;
10404
10405 for(int x = 0; x < 240; x++) {
10406 uint32_t color = backdrop;
10407 uint8_t top = SpecialEffectTarget_BD;
10408 uint8_t mask = outMask;
10409
10410 if(!(RENDERER_LINE[Layer_WIN_OBJ][x] & 0x80000000)) {
10411 mask = RENDERER_R_WIN_OBJ_Mask;
10412 }
10413
10414 mask = SELECT(inWindow1 && RENDERER_GFX_IN_WIN[1][x], inWin1Mask, mask);
10415 mask = SELECT(inWindow0 && RENDERER_GFX_IN_WIN[0][x], inWin0Mask, mask);
10416
10417 if((mask & LayerMask_BG2) && RENDERER_LINE[Layer_BG2][x] < color) {
10418 color = RENDERER_LINE[Layer_BG2][x];
10419 top = SpecialEffectTarget_BG2;
10420 }
10421
10422 if((mask & LayerMask_BG3) && (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(color >> 24)) {
10423 color = RENDERER_LINE[Layer_BG3][x];
10424 top = SpecialEffectTarget_BG3;
10425 }
10426
10427 if((mask & LayerMask_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >> 24)) {
10428 color = RENDERER_LINE[Layer_OBJ][x];
10429 top = SpecialEffectTarget_OBJ;
10430 }
10431
10432 if(color & 0x00010000) {
10433 // semi-transparent OBJ
10434 uint32_t back = backdrop;
10435 uint8_t top2 = SpecialEffectTarget_BD;
10436
10437 if((mask & LayerMask_BG2) && RENDERER_LINE[Layer_BG2][x] < back) {
10438 back = RENDERER_LINE[Layer_BG2][x];
10439 top2 = SpecialEffectTarget_BG2;
10440 }
10441
10442 if((mask & LayerMask_BG3) && (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(back >> 24)) {
10443 back = RENDERER_LINE[Layer_BG3][x];
10444 top2 = SpecialEffectTarget_BG3;
10445 }
10446
10447 alpha_blend_brightness_switch();
10448 } else if(mask & LayerMask_SFX) {
10449 // special FX on the window
10450 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
10451 {
10452 case SpecialEffect_None:
10453 break;
10454 case SpecialEffect_Alpha_Blending:
10455 if(RENDERER_R_BLDCNT_IsTarget1(top))
10456 {
10457 uint32_t back = backdrop;
10458 uint8_t top2 = SpecialEffectTarget_BD;
10459
10460 if((mask & LayerMask_BG2) && (top != SpecialEffectTarget_BG2) && RENDERER_LINE[Layer_BG2][x] < back) {
10461 back = RENDERER_LINE[Layer_BG2][x];
10462 top2 = SpecialEffectTarget_BG2;
10463 }
10464
10465 if((mask & LayerMask_BG3) && (top != SpecialEffectTarget_BG3) && (uint8_t)(RENDERER_LINE[Layer_BG3][x]>>24) < (uint8_t)(back >> 24)) {
10466 back = RENDERER_LINE[Layer_BG3][x];
10467 top2 = SpecialEffectTarget_BG3;
10468 }
10469
10470 if((mask & LayerMask_OBJ) && (top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
10471 back = RENDERER_LINE[Layer_OBJ][x];
10472 top2 = SpecialEffectTarget_OBJ;
10473 }
10474
10475 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
10476 {
10477 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10478 }
10479 }
10480 break;
10481 case SpecialEffect_Brightness_Increase:
10482 if(RENDERER_R_BLDCNT_IsTarget1(top))
10483 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10484 break;
10485 case SpecialEffect_Brightness_Decrease:
10486 if(RENDERER_R_BLDCNT_IsTarget1(top))
10487 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10488 break;
10489 }
10490 }
10491
10492 lineMix[x] = CONVERT_COLOR(color);
10493 }
10494
10495 #if !THREADED_RENDERER
10496 RENDERER_BG2C = 0;
10497 RENDERER_BG3C = 0;
10498 #endif
10499 }
10500
10501 /*
10502 Mode 3 is a 15-bit (32768) colour bitmap graphics mode.
10503 It has a single layer, background layer 2, the same size as the screen.
10504 It doesn't support paging, scrolling, flipping, rotation or tiles.
10505
10506 These routines only render a single line at a time, because of the way the GBA does events.
10507 */
10508
10509 template<int renderer_idx>
mode3RenderLine(void)10510 static void mode3RenderLine (void)
10511 {
10512 INIT_RENDERER_CONTEXT(renderer_idx);
10513
10514 #if !DEBUG_RENDERER_MODE3
10515 return;
10516 #endif
10517 #ifdef REPORT_VIDEO_MODES
10518 fprintf(stderr, "MODE 3: Render Line\n");
10519 #endif
10520 uint16_t* lineMix = GET_LINE_MIX;
10521 uint32_t background = RENDERER_BACKDROP;
10522
10523 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10524 gfxDrawRotScreen16Bit<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10525 }
10526
10527 for(int x = 0; x < 240; ++x) {
10528 uint32_t color = background;
10529 uint8_t top = SpecialEffectTarget_BD;
10530
10531 if(RENDERER_LINE[Layer_BG2][x] < color) {
10532 color = RENDERER_LINE[Layer_BG2][x];
10533 top = SpecialEffectTarget_BG2;
10534 }
10535
10536 if((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >>24)) {
10537 color = RENDERER_LINE[Layer_OBJ][x];
10538 top = SpecialEffectTarget_OBJ;
10539
10540 if(color & 0x00010000) {
10541 // semi-transparent OBJ
10542 uint32_t back = background;
10543 uint8_t top2 = SpecialEffectTarget_BD;
10544
10545 if(RENDERER_LINE[Layer_BG2][x] < background) {
10546 back = RENDERER_LINE[Layer_BG2][x];
10547 top2 = SpecialEffectTarget_BG2;
10548 }
10549
10550 alpha_blend_brightness_switch();
10551 }
10552 }
10553
10554
10555 lineMix[x] = CONVERT_COLOR(color);
10556 }
10557
10558 #if !THREADED_RENDERER
10559 RENDERER_BG2C = 0;
10560 #endif
10561 }
10562
10563 template<int renderer_idx>
mode3RenderLineNoWindow(void)10564 static void mode3RenderLineNoWindow (void)
10565 {
10566 INIT_RENDERER_CONTEXT(renderer_idx);
10567
10568 #if !DEBUG_RENDERER_MODE3
10569 return;
10570 #endif
10571 #ifdef REPORT_VIDEO_MODES
10572 fprintf(stderr, "MODE 3: Render Line No Window\n");
10573 #endif
10574 uint16_t* lineMix = GET_LINE_MIX;
10575 uint32_t background = RENDERER_BACKDROP;
10576
10577 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10578 gfxDrawRotScreen16Bit<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10579 }
10580
10581 for(int x = 0; x < 240; ++x) {
10582 uint32_t color = background;
10583 uint8_t top = SpecialEffectTarget_BD;
10584
10585 if(RENDERER_LINE[Layer_BG2][x] < background) {
10586 color = RENDERER_LINE[Layer_BG2][x];
10587 top = SpecialEffectTarget_BG2;
10588 }
10589
10590 if((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >>24)) {
10591 color = RENDERER_LINE[Layer_OBJ][x];
10592 top = SpecialEffectTarget_OBJ;
10593 }
10594
10595 if(!(color & 0x00010000)) {
10596 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
10597 {
10598 case SpecialEffect_None:
10599 break;
10600 case SpecialEffect_Alpha_Blending:
10601 if(RENDERER_R_BLDCNT_IsTarget1(top))
10602 {
10603 uint32_t back = background;
10604 uint8_t top2 = SpecialEffectTarget_BD;
10605
10606 if(top != SpecialEffectTarget_BG2 && (RENDERER_LINE[Layer_BG2][x] < background) ) {
10607 back = RENDERER_LINE[Layer_BG2][x];
10608 top2 = SpecialEffectTarget_BG2;
10609 }
10610
10611 if(top != SpecialEffectTarget_OBJ && ((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24))) {
10612 back = RENDERER_LINE[Layer_OBJ][x];
10613 top2 = SpecialEffectTarget_OBJ;
10614 }
10615
10616 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
10617 {
10618 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10619 }
10620
10621 }
10622 break;
10623 case SpecialEffect_Brightness_Increase:
10624 if(RENDERER_R_BLDCNT_IsTarget1(top))
10625 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10626 break;
10627 case SpecialEffect_Brightness_Decrease:
10628 if(RENDERER_R_BLDCNT_IsTarget1(top))
10629 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10630 break;
10631 }
10632 } else {
10633 // semi-transparent OBJ
10634 uint32_t back = background;
10635 uint8_t top2 = SpecialEffectTarget_BD;
10636
10637 if(RENDERER_LINE[Layer_BG2][x] < background) {
10638 back = RENDERER_LINE[Layer_BG2][x];
10639 top2 = SpecialEffectTarget_BG2;
10640 }
10641
10642 alpha_blend_brightness_switch();
10643 }
10644
10645 lineMix[x] = CONVERT_COLOR(color);
10646 }
10647
10648 #if !THREADED_RENDERER
10649 RENDERER_BG2C = 0;
10650 #endif
10651 }
10652
10653 template<int renderer_idx>
mode3RenderLineAll(void)10654 static void mode3RenderLineAll (void)
10655 {
10656 INIT_RENDERER_CONTEXT(renderer_idx);
10657
10658 #if !DEBUG_RENDERER_MODE3
10659 return;
10660 #endif
10661 #ifdef REPORT_VIDEO_MODES
10662 fprintf(stderr, "MODE 3: Render Line All\n");
10663 #endif
10664 uint16_t* lineMix = GET_LINE_MIX;
10665 uint32_t background = RENDERER_BACKDROP;
10666
10667 bool inWindow0 = false;
10668 bool inWindow1 = false;
10669
10670 if(RENDERER_R_DISPCNT_Window_0_Display)
10671 {
10672 uint8_t v0 = RENDERER_R_WIN_Window0_Y1;
10673 uint8_t v1 = RENDERER_R_WIN_Window0_Y2;
10674 inWindow0 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10675 }
10676
10677 if(RENDERER_R_DISPCNT_Window_1_Display)
10678 {
10679 uint8_t v0 = RENDERER_R_WIN_Window1_Y1;
10680 uint8_t v1 = RENDERER_R_WIN_Window1_Y2;
10681 inWindow1 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10682 }
10683
10684 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10685 gfxDrawRotScreen16Bit<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10686 }
10687
10688 uint8_t inWin0Mask = RENDERER_R_WIN_Window0_Mask;
10689 uint8_t inWin1Mask = RENDERER_R_WIN_Window1_Mask;
10690 uint8_t outMask = RENDERER_R_WIN_Outside_Mask;
10691
10692 for(int x = 0; x < 240; ++x) {
10693 uint32_t color = background;
10694 uint8_t top = SpecialEffectTarget_BD;
10695 uint8_t mask = outMask;
10696
10697 if(!(RENDERER_LINE[Layer_WIN_OBJ][x] & 0x80000000)) {
10698 mask = RENDERER_R_WIN_OBJ_Mask;
10699 }
10700
10701 mask = SELECT(inWindow1 && RENDERER_GFX_IN_WIN[1][x], inWin1Mask, mask);
10702 mask = SELECT(inWindow0 && RENDERER_GFX_IN_WIN[0][x], inWin0Mask, mask);
10703
10704 if((mask & LayerMask_BG2) && RENDERER_LINE[Layer_BG2][x] < background) {
10705 color = RENDERER_LINE[Layer_BG2][x];
10706 top = SpecialEffectTarget_BG2;
10707 }
10708
10709 if((mask & LayerMask_OBJ) && ((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >>24))) {
10710 color = RENDERER_LINE[Layer_OBJ][x];
10711 top = SpecialEffectTarget_OBJ;
10712 }
10713
10714 if(color & 0x00010000) {
10715 // semi-transparent OBJ
10716 uint32_t back = background;
10717 uint8_t top2 = SpecialEffectTarget_BD;
10718
10719 if((mask & LayerMask_BG2) && RENDERER_LINE[Layer_BG2][x] < background) {
10720 back = RENDERER_LINE[Layer_BG2][x];
10721 top2 = SpecialEffectTarget_BG2;
10722 }
10723
10724 alpha_blend_brightness_switch();
10725 } else if(mask & LayerMask_SFX) {
10726 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
10727 {
10728 case SpecialEffect_None:
10729 break;
10730 case SpecialEffect_Alpha_Blending:
10731 if(RENDERER_R_BLDCNT_IsTarget1(top))
10732 {
10733 uint32_t back = background;
10734 uint8_t top2 = SpecialEffectTarget_BD;
10735
10736 if((mask & LayerMask_BG2) && (top != SpecialEffectTarget_BG2) && RENDERER_LINE[Layer_BG2][x] < back) {
10737 back = RENDERER_LINE[Layer_BG2][x];
10738 top2 = SpecialEffectTarget_BG2;
10739 }
10740
10741 if((mask & LayerMask_OBJ) && (top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
10742 back = RENDERER_LINE[Layer_OBJ][x];
10743 top2 = SpecialEffectTarget_OBJ;
10744 }
10745
10746 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
10747 {
10748 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10749 }
10750 }
10751 break;
10752 case SpecialEffect_Brightness_Increase:
10753 if(RENDERER_R_BLDCNT_IsTarget1(top))
10754 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10755 break;
10756 case SpecialEffect_Brightness_Decrease:
10757 if(RENDERER_R_BLDCNT_IsTarget1(top))
10758 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10759 break;
10760 }
10761 }
10762
10763 lineMix[x] = CONVERT_COLOR(color);
10764 }
10765
10766 #if !THREADED_RENDERER
10767 RENDERER_BG2C = 0;
10768 #endif
10769 }
10770
10771 /*
10772 Mode 4 is a 256 colour bitmap graphics mode with 2 swappable pages.
10773 It has a single layer, background layer 2, the same size as the screen.
10774 It doesn't support scrolling, flipping, rotation or tiles.
10775
10776 These routines only render a single line at a time, because of the way the GBA does events.
10777 */
10778
10779 template<int renderer_idx>
mode4RenderLine(void)10780 static void mode4RenderLine (void)
10781 {
10782 INIT_RENDERER_CONTEXT(renderer_idx);
10783
10784 #if !DEBUG_RENDERER_MODE4
10785 return;
10786 #endif
10787 #ifdef REPORT_VIDEO_MODES
10788 fprintf(stderr, "MODE 4: Render Line\n");
10789 #endif
10790 uint16_t* lineMix = GET_LINE_MIX;
10791 uint32_t backdrop = RENDERER_BACKDROP;
10792
10793 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10794 gfxDrawRotScreen256<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10795 }
10796
10797 for(int x = 0; x < 240; ++x)
10798 {
10799 uint32_t color = backdrop;
10800 uint8_t top = SpecialEffectTarget_BD;
10801
10802 if(RENDERER_LINE[Layer_BG2][x] < backdrop) {
10803 color = RENDERER_LINE[Layer_BG2][x];
10804 top = SpecialEffectTarget_BG2;
10805 }
10806
10807 if((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >> 24)) {
10808 color = RENDERER_LINE[Layer_OBJ][x];
10809 top = SpecialEffectTarget_OBJ;
10810
10811 if(color & 0x00010000) {
10812 // semi-transparent OBJ
10813 uint32_t back = backdrop;
10814 uint8_t top2 = SpecialEffectTarget_BD;
10815
10816 if(RENDERER_LINE[Layer_BG2][x] < backdrop) {
10817 back = RENDERER_LINE[Layer_BG2][x];
10818 top2 = SpecialEffectTarget_BG2;
10819 }
10820
10821 alpha_blend_brightness_switch();
10822 }
10823 }
10824
10825 lineMix[x] = CONVERT_COLOR(color);
10826 }
10827
10828 #if !THREADED_RENDERER
10829 RENDERER_BG2C = 0;
10830 #endif
10831 }
10832
10833 template<int renderer_idx>
mode4RenderLineNoWindow(void)10834 static void mode4RenderLineNoWindow (void)
10835 {
10836 INIT_RENDERER_CONTEXT(renderer_idx);
10837
10838 #if !DEBUG_RENDERER_MODE4
10839 return;
10840 #endif
10841 #ifdef REPORT_VIDEO_MODES
10842 fprintf(stderr, "MODE 4: Render Line No Window\n");
10843 #endif
10844 uint16_t* lineMix = GET_LINE_MIX;
10845 uint32_t backdrop = RENDERER_BACKDROP;
10846
10847 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10848 gfxDrawRotScreen256<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10849 }
10850
10851 for(int x = 0; x < 240; ++x)
10852 {
10853 uint32_t color = backdrop;
10854 uint8_t top = SpecialEffectTarget_BD;
10855
10856 if(RENDERER_LINE[Layer_BG2][x] < backdrop) {
10857 color = RENDERER_LINE[Layer_BG2][x];
10858 top = SpecialEffectTarget_BG2;
10859 }
10860
10861 if((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >> 24)) {
10862 color = RENDERER_LINE[Layer_OBJ][x];
10863 top = SpecialEffectTarget_OBJ;
10864 }
10865
10866 if(!(color & 0x00010000)) {
10867 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
10868 {
10869 case SpecialEffect_None:
10870 break;
10871 case SpecialEffect_Alpha_Blending:
10872 if(RENDERER_R_BLDCNT_IsTarget1(top))
10873 {
10874 uint32_t back = backdrop;
10875 uint8_t top2 = SpecialEffectTarget_BD;
10876
10877 if((top != SpecialEffectTarget_BG2) && RENDERER_LINE[Layer_BG2][x] < backdrop) {
10878 back = RENDERER_LINE[Layer_BG2][x];
10879 top2 = SpecialEffectTarget_BG2;
10880 }
10881
10882 if((top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
10883 back = RENDERER_LINE[Layer_OBJ][x];
10884 top2 = SpecialEffectTarget_OBJ;
10885 }
10886
10887 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
10888 {
10889 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10890 }
10891 }
10892 break;
10893 case SpecialEffect_Brightness_Increase:
10894 if(RENDERER_R_BLDCNT_IsTarget1(top))
10895 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10896 break;
10897 case SpecialEffect_Brightness_Decrease:
10898 if(RENDERER_R_BLDCNT_IsTarget1(top))
10899 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10900 break;
10901 }
10902 } else {
10903 // semi-transparent OBJ
10904 uint32_t back = backdrop;
10905 uint8_t top2 = SpecialEffectTarget_BD;
10906
10907 if(RENDERER_LINE[Layer_BG2][x] < back) {
10908 back = RENDERER_LINE[Layer_BG2][x];
10909 top2 = SpecialEffectTarget_BG2;
10910 }
10911
10912 alpha_blend_brightness_switch();
10913 }
10914
10915 lineMix[x] = CONVERT_COLOR(color);
10916 }
10917
10918 #if !THREADED_RENDERER
10919 RENDERER_BG2C = 0;
10920 #endif
10921 }
10922
10923 template<int renderer_idx>
mode4RenderLineAll(void)10924 static void mode4RenderLineAll (void)
10925 {
10926 INIT_RENDERER_CONTEXT(renderer_idx);
10927
10928 #if !DEBUG_RENDERER_MODE4
10929 return;
10930 #endif
10931 #ifdef REPORT_VIDEO_MODES
10932 fprintf(stderr, "MODE 4: Render Line All\n");
10933 #endif
10934 uint16_t* lineMix = GET_LINE_MIX;
10935 uint32_t backdrop = RENDERER_BACKDROP;
10936
10937 bool inWindow0 = false;
10938 bool inWindow1 = false;
10939
10940 if(RENDERER_R_DISPCNT_Window_0_Display)
10941 {
10942 uint8_t v0 = RENDERER_R_WIN_Window0_Y1;
10943 uint8_t v1 = RENDERER_R_WIN_Window0_Y2;
10944 inWindow0 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10945 }
10946
10947 if(RENDERER_R_DISPCNT_Window_1_Display)
10948 {
10949 uint8_t v0 = RENDERER_R_WIN_Window1_Y1;
10950 uint8_t v1 = RENDERER_R_WIN_Window1_Y2;
10951 inWindow1 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
10952 }
10953
10954 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
10955 gfxDrawRotScreen256<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
10956 }
10957
10958 uint8_t inWin0Mask = RENDERER_R_WIN_Window0_Mask;
10959 uint8_t inWin1Mask = RENDERER_R_WIN_Window1_Mask;
10960 uint8_t outMask = RENDERER_R_WIN_Outside_Mask;
10961
10962 for(int x = 0; x < 240; ++x) {
10963 uint32_t color = backdrop;
10964 uint8_t top = SpecialEffectTarget_BD;
10965 uint8_t mask = outMask;
10966
10967 if(!(RENDERER_LINE[Layer_WIN_OBJ][x] & 0x80000000))
10968 mask = RENDERER_R_WIN_OBJ_Mask;
10969
10970 mask = SELECT(inWindow1 && RENDERER_GFX_IN_WIN[1][x], inWin1Mask, mask);
10971 mask = SELECT(inWindow0 && RENDERER_GFX_IN_WIN[0][x], inWin0Mask, mask);
10972
10973 if((mask & LayerMask_BG2) && (RENDERER_LINE[Layer_BG2][x] < backdrop))
10974 {
10975 color = RENDERER_LINE[Layer_BG2][x];
10976 top = SpecialEffectTarget_BG2;
10977 }
10978
10979 if((mask & LayerMask_OBJ) && ((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >>24)))
10980 {
10981 color = RENDERER_LINE[Layer_OBJ][x];
10982 top = SpecialEffectTarget_OBJ;
10983 }
10984
10985 if(color & 0x00010000) {
10986 // semi-transparent OBJ
10987 uint32_t back = backdrop;
10988 uint8_t top2 = SpecialEffectTarget_BD;
10989
10990 if((mask & LayerMask_BG2) && RENDERER_LINE[Layer_BG2][x] < back) {
10991 back = RENDERER_LINE[Layer_BG2][x];
10992 top2 = SpecialEffectTarget_BG2;
10993 }
10994
10995 alpha_blend_brightness_switch();
10996 } else if(mask & LayerMask_SFX) {
10997 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
10998 {
10999 case SpecialEffect_None:
11000 break;
11001 case SpecialEffect_Alpha_Blending:
11002 if(RENDERER_R_BLDCNT_IsTarget1(top))
11003 {
11004 uint32_t back = backdrop;
11005 uint8_t top2 = SpecialEffectTarget_BD;
11006
11007 if((mask & LayerMask_BG2) && (top != SpecialEffectTarget_BG2) && (RENDERER_LINE[Layer_BG2][x] < backdrop)) {
11008 back = RENDERER_LINE[Layer_BG2][x];
11009 top2 = SpecialEffectTarget_BG2;
11010 }
11011
11012 if((mask & LayerMask_OBJ) && (top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
11013 back = RENDERER_LINE[Layer_OBJ][x];
11014 top2 = SpecialEffectTarget_OBJ;
11015 }
11016
11017 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
11018 {
11019 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
11020 }
11021 }
11022 break;
11023 case SpecialEffect_Brightness_Increase:
11024 if(RENDERER_R_BLDCNT_IsTarget1(top))
11025 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
11026 break;
11027 case SpecialEffect_Brightness_Decrease:
11028 if(RENDERER_R_BLDCNT_IsTarget1(top))
11029 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
11030 break;
11031 }
11032 }
11033
11034 lineMix[x] = CONVERT_COLOR(color);
11035 }
11036
11037 #if !THREADED_RENDERER
11038 RENDERER_BG2C = 0;
11039 #endif
11040 }
11041
11042 /*
11043 Mode 5 is a low resolution (160x128) 15-bit colour bitmap graphics mode
11044 with 2 swappable pages!
11045 It has a single layer, background layer 2, lower resolution than the screen.
11046 It doesn't support scrolling, flipping, rotation or tiles.
11047
11048 These routines only render a single line at a time, because of the way the GBA does events.
11049 */
11050
11051 template<int renderer_idx>
mode5RenderLine(void)11052 static void mode5RenderLine (void)
11053 {
11054 INIT_RENDERER_CONTEXT(renderer_idx);
11055
11056 #if !DEBUG_RENDERER_MODE5
11057 return;
11058 #endif
11059 #ifdef REPORT_VIDEO_MODES
11060 fprintf(stderr, "MODE 5: Render Line\n");
11061 #endif
11062 uint16_t* lineMix = GET_LINE_MIX;
11063 uint32_t background = RENDERER_BACKDROP;
11064
11065 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
11066 gfxDrawRotScreen16Bit160<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
11067 }
11068
11069 for(int x = 0; x < 240; ++x) {
11070 uint32_t color = background;
11071 uint8_t top = SpecialEffectTarget_BD;
11072
11073 if(RENDERER_LINE[Layer_BG2][x] < background) {
11074 color = RENDERER_LINE[Layer_BG2][x];
11075 top = SpecialEffectTarget_BG2;
11076 }
11077
11078 if((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >>24)) {
11079 color = RENDERER_LINE[Layer_OBJ][x];
11080 top = SpecialEffectTarget_OBJ;
11081
11082 if(color & 0x00010000) {
11083 // semi-transparent OBJ
11084 uint32_t back = background;
11085 uint8_t top2 = SpecialEffectTarget_BD;
11086
11087 if(RENDERER_LINE[Layer_BG2][x] < back) {
11088 back = RENDERER_LINE[Layer_BG2][x];
11089 top2 = SpecialEffectTarget_BG2;
11090 }
11091
11092 alpha_blend_brightness_switch();
11093 }
11094 }
11095
11096 lineMix[x] = CONVERT_COLOR(color);
11097 }
11098
11099 #if !THREADED_RENDERER
11100 RENDERER_BG2C = 0;
11101 #endif
11102 }
11103
11104 template<int renderer_idx>
mode5RenderLineNoWindow(void)11105 static void mode5RenderLineNoWindow (void)
11106 {
11107 INIT_RENDERER_CONTEXT(renderer_idx);
11108
11109 #if !DEBUG_RENDERER_MODE5
11110 return;
11111 #endif
11112 #ifdef REPORT_VIDEO_MODES
11113 fprintf(stderr, "MODE 5: Render Line No Window\n");
11114 #endif
11115 uint16_t* lineMix = GET_LINE_MIX;
11116 uint32_t background = RENDERER_BACKDROP;
11117
11118 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
11119 gfxDrawRotScreen16Bit160<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
11120 }
11121
11122 for(int x = 0; x < 240; ++x) {
11123 uint32_t color = background;
11124 uint8_t top = SpecialEffectTarget_BD;
11125
11126 if(RENDERER_LINE[Layer_BG2][x] < background) {
11127 color = RENDERER_LINE[Layer_BG2][x];
11128 top = SpecialEffectTarget_BG2;
11129 }
11130
11131 if((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >>24)) {
11132 color = RENDERER_LINE[Layer_OBJ][x];
11133 top = SpecialEffectTarget_OBJ;
11134 }
11135
11136 if(!(color & 0x00010000)) {
11137 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
11138 {
11139 case SpecialEffect_None:
11140 break;
11141 case SpecialEffect_Alpha_Blending:
11142 if(RENDERER_R_BLDCNT_IsTarget1(top))
11143 {
11144 uint32_t back = background;
11145 uint8_t top2 = SpecialEffectTarget_BD;
11146
11147 if((top != SpecialEffectTarget_BG2) && RENDERER_LINE[Layer_BG2][x] < background) {
11148 back = RENDERER_LINE[Layer_BG2][x];
11149 top2 = SpecialEffectTarget_BG2;
11150 }
11151
11152 if((top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
11153 back = RENDERER_LINE[Layer_OBJ][x];
11154 top2 = SpecialEffectTarget_OBJ;
11155 }
11156
11157 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
11158 {
11159 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
11160 }
11161
11162 }
11163 break;
11164 case SpecialEffect_Brightness_Increase:
11165 if(RENDERER_R_BLDCNT_IsTarget1(top))
11166 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
11167 break;
11168 case SpecialEffect_Brightness_Decrease:
11169 if(RENDERER_R_BLDCNT_IsTarget1(top))
11170 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
11171 break;
11172 }
11173 } else {
11174 // semi-transparent OBJ
11175 uint32_t back = background;
11176 uint8_t top2 = SpecialEffectTarget_BD;
11177
11178 if(RENDERER_LINE[Layer_BG2][x] < back) {
11179 back = RENDERER_LINE[Layer_BG2][x];
11180 top2 = SpecialEffectTarget_BG2;
11181 }
11182
11183 alpha_blend_brightness_switch();
11184 }
11185
11186 lineMix[x] = CONVERT_COLOR(color);
11187 }
11188
11189 #if !THREADED_RENDERER
11190 RENDERER_BG2C = 0;
11191 #endif
11192 }
11193
11194 template<int renderer_idx>
mode5RenderLineAll(void)11195 static void mode5RenderLineAll (void)
11196 {
11197 INIT_RENDERER_CONTEXT(renderer_idx);
11198
11199 #if !DEBUG_RENDERER_MODE5
11200 return;
11201 #endif
11202 #ifdef REPORT_VIDEO_MODES
11203 fprintf(stderr, "MODE 5: Render Line All\n");
11204 #endif
11205 uint16_t* lineMix = GET_LINE_MIX;
11206 uint32_t background = RENDERER_BACKDROP;
11207
11208 if(RENDERER_R_DISPCNT_Screen_Display_BG2) {
11209 gfxDrawRotScreen16Bit160<renderer_idx>(RENDERER_BG2X, RENDERER_BG2Y, RENDERER_BG2C);
11210 }
11211
11212 bool inWindow0 = false;
11213 bool inWindow1 = false;
11214
11215 if(RENDERER_R_DISPCNT_Window_0_Display)
11216 {
11217 uint8_t v0 = RENDERER_R_WIN_Window0_Y1;
11218 uint8_t v1 = RENDERER_R_WIN_Window0_Y2;
11219 inWindow0 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
11220 }
11221
11222 if(RENDERER_R_DISPCNT_Window_1_Display)
11223 {
11224 uint8_t v0 = RENDERER_R_WIN_Window1_Y1;
11225 uint8_t v1 = RENDERER_R_WIN_Window1_Y2;
11226 inWindow1 = (uint8_t)(RENDERER_R_VCOUNT - v0) < (uint8_t)(v1 - v0) || ((v0 == v1) && (v0 >= 0xe8));
11227 }
11228
11229 uint8_t inWin0Mask = RENDERER_R_WIN_Window0_Mask;
11230 uint8_t inWin1Mask = RENDERER_R_WIN_Window1_Mask;
11231 uint8_t outMask = RENDERER_R_WIN_Outside_Mask;
11232
11233 for(int x = 0; x < 240; ++x) {
11234 uint32_t color = background;
11235 uint8_t top = SpecialEffectTarget_BD;
11236 uint8_t mask = outMask;
11237
11238 if(!(RENDERER_LINE[Layer_WIN_OBJ][x] & 0x80000000)) {
11239 mask = RENDERER_R_WIN_OBJ_Mask;
11240 }
11241
11242 mask = SELECT(inWindow1 && RENDERER_GFX_IN_WIN[1][x], inWin1Mask, mask);
11243 mask = SELECT(inWindow0 && RENDERER_GFX_IN_WIN[0][x], inWin0Mask, mask);
11244
11245 if((mask & LayerMask_BG2) && (RENDERER_LINE[Layer_BG2][x] < background)) {
11246 color = RENDERER_LINE[Layer_BG2][x];
11247 top = SpecialEffectTarget_BG2;
11248 }
11249
11250 if((mask & LayerMask_OBJ) && ((uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(color >>24))) {
11251 color = RENDERER_LINE[Layer_OBJ][x];
11252 top = SpecialEffectTarget_OBJ;
11253 }
11254
11255 if(color & 0x00010000) {
11256 // semi-transparent OBJ
11257 uint32_t back = background;
11258 uint8_t top2 = SpecialEffectTarget_BD;
11259
11260 if((mask & LayerMask_BG2) && RENDERER_LINE[Layer_BG2][x] < back) {
11261 back = RENDERER_LINE[Layer_BG2][x];
11262 top2 = SpecialEffectTarget_BG2;
11263 }
11264
11265 alpha_blend_brightness_switch();
11266 } else if(mask & LayerMask_SFX) {
11267 switch(RENDERER_R_BLDCNT_Color_Special_Effect)
11268 {
11269 case SpecialEffect_None:
11270 break;
11271 case SpecialEffect_Alpha_Blending:
11272 if(RENDERER_R_BLDCNT_IsTarget1(top))
11273 {
11274 uint32_t back = background;
11275 uint8_t top2 = SpecialEffectTarget_BD;
11276
11277 if((mask & LayerMask_BG2) && (top != SpecialEffectTarget_BG2) && (RENDERER_LINE[Layer_BG2][x] < background)) {
11278 back = RENDERER_LINE[Layer_BG2][x];
11279 top2 = SpecialEffectTarget_BG2;
11280 }
11281
11282 if((mask & LayerMask_OBJ) && (top != SpecialEffectTarget_OBJ) && (uint8_t)(RENDERER_LINE[Layer_OBJ][x]>>24) < (uint8_t)(back >> 24)) {
11283 back = RENDERER_LINE[Layer_OBJ][x];
11284 top2 = SpecialEffectTarget_OBJ;
11285 }
11286
11287 if(RENDERER_R_BLDCNT_IsTarget2(top2) && color < 0x80000000)
11288 {
11289 GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
11290 }
11291 }
11292 break;
11293 case SpecialEffect_Brightness_Increase:
11294 if(RENDERER_R_BLDCNT_IsTarget1(top))
11295 color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
11296 break;
11297 case SpecialEffect_Brightness_Decrease:
11298 if(RENDERER_R_BLDCNT_IsTarget1(top))
11299 color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
11300 break;
11301 }
11302 }
11303
11304 lineMix[x] = CONVERT_COLOR(color);
11305 }
11306
11307 #if !THREADED_RENDERER
11308 RENDERER_BG2C = 0;
11309 #endif
11310 }
11311
11312 #if THREADED_RENDERER
11313 #define threaded_renderer_loop_impl() \
11314 do { \
11315 if(renderer_ctx.renderer_state == 0) continue; \
11316 \
11317 if(renderer_ctx.background_ver < threaded_background_ver) { \
11318 renderer_ctx.background_ver = threaded_background_ver; \
11319 if(!RENDERER_R_DISPCNT_Screen_Display_BG0) \
11320 memset(renderer_ctx.line[Layer_BG0], -1, 240 * sizeof(u32)); \
11321 if(!RENDERER_R_DISPCNT_Screen_Display_BG1) \
11322 memset(renderer_ctx.line[Layer_BG1], -1, 240 * sizeof(u32)); \
11323 if(!RENDERER_R_DISPCNT_Screen_Display_BG2) \
11324 memset(renderer_ctx.line[Layer_BG2], -1, 240 * sizeof(u32)); \
11325 if(!RENDERER_R_DISPCNT_Screen_Display_BG3) \
11326 memset(renderer_ctx.line[Layer_BG3], -1, 240 * sizeof(u32)); \
11327 } \
11328 \
11329 memset(RENDERER_LINE[Layer_OBJ], -1, 240 * sizeof(u32)); \
11330 if(renderer_ctx.draw_sprites) (*drawSprites)(); \
11331 \
11332 if(renderer_ctx.renderfunc_type == 2) { \
11333 memset(RENDERER_LINE[Layer_WIN_OBJ], -1, 240 * sizeof(u32)); \
11334 if(renderer_ctx.draw_objwin) (*drawOBJWin)(); \
11335 } \
11336 \
11337 (*getRenderFunc)(renderer_ctx.renderfunc_mode, renderer_ctx.renderfunc_type)(); \
11338 \
11339 renderer_ctx.renderer_state = 0;\
11340 } while (0)
11341
threaded_renderer_loop0(void * p)11342 static void threaded_renderer_loop0(void* p) {
11343 int renderer_idx = 0;
11344 INIT_RENDERER_CONTEXT(renderer_idx);
11345
11346 renderfunc_t drawSprites = gfxDrawSprites<0>;
11347 renderfunc_t drawOBJWin = gfxDrawOBJWin<0>;
11348 renderfunc_t (*getRenderFunc)(int, int) = GetRenderFunc<0>;
11349
11350 while(renderer_ctx.renderer_control == 1) {
11351 if(threaded_renderer_ready) {
11352 threaded_renderer_ready = 0;
11353 systemDrawScreen();
11354 }
11355 threaded_renderer_loop_impl();
11356 }
11357
11358 renderer_ctx.renderer_control = 0; //loop is terminated.
11359 }
11360
threaded_renderer_loop(void * p)11361 static void threaded_renderer_loop(void* p) {
11362 int renderer_idx = reinterpret_cast<intptr_t>(p);
11363 INIT_RENDERER_CONTEXT(renderer_idx);
11364
11365 renderfunc_t drawSprites = NULL;
11366 renderfunc_t drawOBJWin = NULL;
11367 renderfunc_t (*getRenderFunc)(int, int) = NULL;
11368
11369 switch(renderer_idx) {
11370 case 1:
11371 drawSprites = gfxDrawSprites<1>;
11372 drawOBJWin = gfxDrawOBJWin<1>;
11373 getRenderFunc = GetRenderFunc<1>;
11374 break;
11375 case 2:
11376 drawSprites = gfxDrawSprites<2>;
11377 drawOBJWin = gfxDrawOBJWin<2>;
11378 getRenderFunc = GetRenderFunc<2>;
11379 break;
11380 case 3:
11381 drawSprites = gfxDrawSprites<3>;
11382 drawOBJWin = gfxDrawOBJWin<3>;
11383 getRenderFunc = GetRenderFunc<3>;
11384 break;
11385 default:
11386 return;
11387 }
11388
11389 while(renderer_ctx.renderer_control == 1)
11390 threaded_renderer_loop_impl();
11391
11392 renderer_ctx.renderer_control = 0; //loop is terminated.
11393 }
11394
fetchBackgroundOffset(int video_mode)11395 static void fetchBackgroundOffset(int video_mode) {
11396 //update gfxBG2X, gfxBG2Y, gfxBG3X, gfxBG3Y
11397 switch(video_mode) {
11398 case 0:
11399 break;
11400 case 1:
11401 fetchDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
11402 io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD],
11403 gfxBG2X, gfxBG2Y, gfxBG2Changed);
11404 break;
11405 case 2:
11406 fetchDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
11407 io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD],
11408 gfxBG2X, gfxBG2Y, gfxBG2Changed);
11409 fetchDrawRotScreen(io_registers[REG_BG3CNT], BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
11410 io_registers[REG_BG3PA], io_registers[REG_BG3PB], io_registers[REG_BG3PC], io_registers[REG_BG3PD],
11411 gfxBG3X, gfxBG3Y, gfxBG3Changed);
11412 break;
11413 case 3:
11414 fetchDrawRotScreen16Bit(gfxBG2X, gfxBG2Y, gfxBG2Changed);
11415 break;
11416 case 4:
11417 fetchDrawRotScreen256(gfxBG2X, gfxBG2Y, gfxBG2Changed);
11418 break;
11419 case 5:
11420 fetchDrawRotScreen16Bit160(gfxBG2X, gfxBG2Y, gfxBG2Changed);
11421 break;
11422 default:
11423 return;
11424 }
11425 }
11426
postRender()11427 static void postRender() {
11428
11429 int video_mode = R_DISPCNT_Video_Mode;
11430 bool draw_objwin = (graphics.layerEnable & 0x9000) == 0x9000;
11431 bool draw_sprites = R_DISPCNT_Screen_Display_OBJ;
11432
11433 #if DEBUG_RENDERER_NOSYNC
11434 if (threaded_renderer_contexts[threaded_renderer_idx].renderer_state) return;
11435 #else
11436 while(threaded_renderer_contexts[threaded_renderer_idx].renderer_state);
11437 #endif
11438
11439 INIT_RENDERER_CONTEXT(threaded_renderer_idx);
11440
11441 renderer_ctx.renderfunc_mode = renderfunc_mode;
11442 renderer_ctx.renderfunc_type = renderfunc_type;
11443 renderer_ctx.draw_objwin = draw_objwin;
11444 renderer_ctx.draw_sprites = draw_sprites;
11445 renderer_ctx.layers = graphics.layerEnable;
11446 renderer_ctx.mosaic = MOSAIC;
11447 renderer_ctx.bldmod = BLDMOD;
11448 renderer_ctx.vcount = io_registers[REG_VCOUNT];
11449
11450 renderer_ctx.io_registers[REG_DISPCNT] = io_registers[REG_DISPCNT];
11451 renderer_ctx.io_registers[REG_DISPSTAT] = io_registers[REG_DISPSTAT];
11452 renderer_ctx.io_registers[REG_VCOUNT] = io_registers[REG_VCOUNT];
11453
11454 renderer_ctx.io_registers[REG_BG0CNT] = io_registers[REG_BG0CNT];
11455 renderer_ctx.io_registers[REG_BG1CNT] = io_registers[REG_BG1CNT];
11456 renderer_ctx.io_registers[REG_BG2CNT] = io_registers[REG_BG2CNT];
11457 renderer_ctx.io_registers[REG_BG3CNT] = io_registers[REG_BG3CNT];
11458
11459 renderer_ctx.io_registers[REG_BG0HOFS] = io_registers[REG_BG0HOFS];
11460 renderer_ctx.io_registers[REG_BG1HOFS] = io_registers[REG_BG1HOFS];
11461 renderer_ctx.io_registers[REG_BG2HOFS] = io_registers[REG_BG2HOFS];
11462 renderer_ctx.io_registers[REG_BG3HOFS] = io_registers[REG_BG3HOFS];
11463 renderer_ctx.io_registers[REG_BG0VOFS] = io_registers[REG_BG0VOFS];
11464 renderer_ctx.io_registers[REG_BG1VOFS] = io_registers[REG_BG1VOFS];
11465 renderer_ctx.io_registers[REG_BG2VOFS] = io_registers[REG_BG2VOFS];
11466 renderer_ctx.io_registers[REG_BG3VOFS] = io_registers[REG_BG3VOFS];
11467
11468 renderer_ctx.io_registers[REG_BG2PA] = io_registers[REG_BG2PA];
11469 renderer_ctx.io_registers[REG_BG2PB] = io_registers[REG_BG2PB];
11470 renderer_ctx.io_registers[REG_BG2PC] = io_registers[REG_BG2PC];
11471 renderer_ctx.io_registers[REG_BG2PD] = io_registers[REG_BG2PD];
11472 renderer_ctx.io_registers[REG_BG3PA] = io_registers[REG_BG3PA];
11473 renderer_ctx.io_registers[REG_BG3PB] = io_registers[REG_BG3PB];
11474 renderer_ctx.io_registers[REG_BG3PC] = io_registers[REG_BG3PC];
11475 renderer_ctx.io_registers[REG_BG3PD] = io_registers[REG_BG3PD];
11476
11477 renderer_ctx.io_registers[REG_BG2X_L] = io_registers[REG_BG2X_L];
11478 renderer_ctx.io_registers[REG_BG2X_H] = io_registers[REG_BG2X_H];
11479 renderer_ctx.io_registers[REG_BG2Y_L] = io_registers[REG_BG2Y_L];
11480 renderer_ctx.io_registers[REG_BG2Y_H] = io_registers[REG_BG2Y_H];
11481 renderer_ctx.io_registers[REG_BG3X_L] = io_registers[REG_BG3X_L];
11482 renderer_ctx.io_registers[REG_BG3X_H] = io_registers[REG_BG3X_H];
11483 renderer_ctx.io_registers[REG_BG3Y_L] = io_registers[REG_BG3Y_L];
11484 renderer_ctx.io_registers[REG_BG3Y_H] = io_registers[REG_BG3Y_H];
11485
11486 renderer_ctx.io_registers[REG_WIN0H] = io_registers[REG_WIN0H];
11487 renderer_ctx.io_registers[REG_WIN1H] = io_registers[REG_WIN1H];
11488 renderer_ctx.io_registers[REG_WIN0V] = io_registers[REG_WIN0V];
11489 renderer_ctx.io_registers[REG_WIN1V] = io_registers[REG_WIN1V];
11490 renderer_ctx.io_registers[REG_WININ] = io_registers[REG_WININ];
11491 renderer_ctx.io_registers[REG_WINOUT] = io_registers[REG_WINOUT];
11492
11493 renderer_ctx.io_registers[REG_BLDCNT] = io_registers[REG_BLDCNT];
11494 renderer_ctx.io_registers[REG_BLDALPHA] = io_registers[REG_BLDALPHA];
11495 renderer_ctx.io_registers[REG_BLDY] = io_registers[REG_BLDY];
11496
11497 renderer_ctx.io_registers[REG_TM0D] = io_registers[REG_TM0D];
11498 renderer_ctx.io_registers[REG_TM1D] = io_registers[REG_TM1D];
11499 renderer_ctx.io_registers[REG_TM2D] = io_registers[REG_TM2D];
11500 renderer_ctx.io_registers[REG_TM3D] = io_registers[REG_TM3D];
11501
11502 renderer_ctx.io_registers[REG_TM0CNT] = io_registers[REG_TM0CNT];
11503 renderer_ctx.io_registers[REG_TM1CNT] = io_registers[REG_TM1CNT];
11504 renderer_ctx.io_registers[REG_TM2CNT] = io_registers[REG_TM2CNT];
11505 renderer_ctx.io_registers[REG_TM3CNT] = io_registers[REG_TM3CNT];
11506
11507 renderer_ctx.io_registers[REG_P1] = io_registers[REG_P1];
11508 renderer_ctx.io_registers[REG_P1CNT] = io_registers[REG_P1CNT];
11509 renderer_ctx.io_registers[REG_RCNT] = io_registers[REG_RCNT];
11510 renderer_ctx.io_registers[REG_IE] = io_registers[REG_IE];
11511 renderer_ctx.io_registers[REG_IF] = io_registers[REG_IF];
11512 renderer_ctx.io_registers[REG_IME] = io_registers[REG_IME];
11513 renderer_ctx.io_registers[REG_HALTCNT] = io_registers[REG_HALTCNT];
11514
11515 renderer_ctx.bg2c = gfxBG2Changed;
11516 renderer_ctx.bg2x = gfxBG2X;
11517 renderer_ctx.bg2y = gfxBG2Y;
11518 renderer_ctx.bg2x_l = BG2X_L;
11519 renderer_ctx.bg2x_h = BG2X_H;
11520 renderer_ctx.bg2y_l = BG2Y_L;
11521 renderer_ctx.bg2y_h = BG2Y_H;
11522
11523 if(video_mode == 2) {
11524 renderer_ctx.bg3c = gfxBG3Changed;
11525 renderer_ctx.bg3x = gfxBG3X;
11526 renderer_ctx.bg3y = gfxBG3Y;
11527 renderer_ctx.bg3x_l = BG3X_L;
11528 renderer_ctx.bg3x_h = BG3X_H;
11529 renderer_ctx.bg3y_l = BG3Y_L;
11530 renderer_ctx.bg3y_h = BG3Y_H;
11531 }
11532
11533 for(int u = 0; u < 2; ++u) {
11534 if(renderer_ctx.gfxinwin_ver[u] < threaded_gfxinwin_ver[u]) {
11535 renderer_ctx.gfxinwin_ver[u] = threaded_gfxinwin_ver[u];
11536 #if HAVE_NEON
11537 neon_memcpy(renderer_ctx.gfxInWin[u], gfxInWin[u], sizeof(gfxInWin) / 2);
11538 #else
11539 memcpy(renderer_ctx.gfxInWin[u], gfxInWin[u], sizeof(gfxInWin) / 2);
11540 #endif
11541 }
11542 }
11543
11544 fetchBackgroundOffset(video_mode);
11545
11546 gfxBG2Changed = 0;
11547 if(video_mode == 2) gfxBG3Changed = 0;
11548
11549 //buffer is ready.
11550 renderer_ctx.renderer_state = 1;
11551
11552 //notify screen is done.
11553 if(renderer_ctx.vcount == 159) threaded_renderer_ready = 1;
11554
11555 threaded_renderer_idx = (threaded_renderer_idx + 1) % THREADED_RENDERER_COUNT;
11556 }
11557
11558 #endif
11559
11560 #define CPUUpdateRender() { \
11561 renderfunc_mode = R_DISPCNT_Video_Mode; \
11562 if((!fxOn && !windowOn && !R_DISPCNT_OBJ_Window_Display)) \
11563 renderfunc_type = 0; \
11564 else if(fxOn && !windowOn && !R_DISPCNT_OBJ_Window_Display) \
11565 renderfunc_type = 1; \
11566 else \
11567 renderfunc_type = 2; \
11568 }
11569
11570 template<int renderer_idx>
GetRenderFunc(int mode,int type)11571 renderfunc_t GetRenderFunc(int mode, int type) {
11572 switch((mode << 4) | type) {
11573 case 0x00: return mode0RenderLine<renderer_idx>;
11574 case 0x01: return mode0RenderLineNoWindow<renderer_idx>;
11575 case 0x02: return mode0RenderLineAll<renderer_idx>;
11576 case 0x10: return mode1RenderLine<renderer_idx>;
11577 case 0x11: return mode1RenderLineNoWindow<renderer_idx>;
11578 case 0x12: return mode1RenderLineAll<renderer_idx>;
11579 case 0x20: return mode2RenderLine<renderer_idx>;
11580 case 0x21: return mode2RenderLineNoWindow<renderer_idx>;
11581 case 0x22: return mode2RenderLineAll<renderer_idx>;
11582 case 0x30: return mode3RenderLine<renderer_idx>;
11583 case 0x31: return mode3RenderLineNoWindow<renderer_idx>;
11584 case 0x32: return mode3RenderLineAll<renderer_idx>;
11585 case 0x40: return mode4RenderLine<renderer_idx>;
11586 case 0x41: return mode4RenderLineNoWindow<renderer_idx>;
11587 case 0x42: return mode4RenderLineAll<renderer_idx>;
11588 case 0x50: return mode5RenderLine<renderer_idx>;
11589 case 0x51: return mode5RenderLineNoWindow<renderer_idx>;
11590 case 0x52: return mode5RenderLineAll<renderer_idx>;
11591 default: return NULL;
11592 }
11593 }
11594
CPUReadState(const uint8_t * data,unsigned size)11595 bool CPUReadState(const uint8_t* data, unsigned size)
11596 {
11597 // Don't really care about version.
11598 int version = utilReadIntMem(data);
11599 if (version != SAVE_GAME_VERSION)
11600 return false;
11601
11602 char romname[16];
11603 utilReadMem(romname, data, 16);
11604 if (memcmp(&rom[0xa0], romname, 16) != 0)
11605 return false;
11606
11607 // Don't care about use bios ...
11608 utilReadIntMem(data);
11609
11610 utilReadMem(&bus.reg[0], data, sizeof(bus.reg));
11611
11612 utilReadDataMem(data, saveGameStruct);
11613
11614 stopState = utilReadIntMem(data) ? true : false;
11615
11616 IRQTicks = utilReadIntMem(data);
11617 if (IRQTicks > 0)
11618 intState = true;
11619 else
11620 {
11621 intState = false;
11622 IRQTicks = 0;
11623 }
11624
11625 utilReadMem(internalRAM, data, 0x8000);
11626 utilReadMem(paletteRAM, data, 0x400);
11627 utilReadMem(workRAM, data, 0x40000);
11628 utilReadMem(vram, data, 0x20000);
11629 utilReadMem(oam, data, 0x400);
11630 utilReadMem(pix, data, 4 * PIX_BUFFER_SCREEN_WIDTH * 160);
11631 utilReadMem(ioMem, data, 0x400);
11632
11633 eepromReadGameMem(data, version);
11634 flashReadGameMem(data, version);
11635 soundReadGameMem(data, version);
11636 rtcReadGameMem(data);
11637
11638 //// Copypasta stuff ...
11639 // set pointers!
11640 graphics.layerEnable = io_registers[REG_DISPCNT];
11641
11642 CPUUpdateRender();
11643
11644 #if !THREADED_RENDERER
11645 memset(line[Layer_BG0], -1, 240 * sizeof(u32));
11646 memset(line[Layer_BG1], -1, 240 * sizeof(u32));
11647 memset(line[Layer_BG2], -1, 240 * sizeof(u32));
11648 memset(line[Layer_BG3], -1, 240 * sizeof(u32));
11649 #endif
11650
11651 CPUUpdateWindow0();
11652 CPUUpdateWindow1();
11653 gbaSaveType = 0;
11654 switch(saveType) {
11655 case 0:
11656 cpuSaveGameFunc = flashSaveDecide;
11657 break;
11658 case 1:
11659 cpuSaveGameFunc = sramWrite;
11660 gbaSaveType = 1;
11661 break;
11662 case 2:
11663 cpuSaveGameFunc = flashWrite;
11664 gbaSaveType = 2;
11665 break;
11666 case 3:
11667 break;
11668 case 5:
11669 gbaSaveType = 5;
11670 break;
11671 default:
11672 break;
11673 }
11674 if(eepromInUse)
11675 gbaSaveType = 3;
11676
11677 if(armState) {
11678 ARM_PREFETCH;
11679 } else {
11680 THUMB_PREFETCH;
11681 }
11682
11683 CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
11684
11685 return true;
11686 }
11687
11688
11689 #define CPUSwap(a, b) \
11690 a ^= b; \
11691 b ^= a; \
11692 a ^= b;
11693
CPUSwitchMode(int mode,bool saveState,bool breakLoop)11694 static void CPUSwitchMode(int mode, bool saveState, bool breakLoop)
11695 {
11696 CPU_UPDATE_CPSR();
11697
11698 switch(armMode) {
11699 case 0x10:
11700 case 0x1F:
11701 bus.reg[R13_USR].I = bus.reg[13].I;
11702 bus.reg[R14_USR].I = bus.reg[14].I;
11703 bus.reg[17].I = bus.reg[16].I;
11704 break;
11705 case 0x11:
11706 CPUSwap(bus.reg[R8_FIQ].I, bus.reg[8].I);
11707 CPUSwap(bus.reg[R9_FIQ].I, bus.reg[9].I);
11708 CPUSwap(bus.reg[R10_FIQ].I, bus.reg[10].I);
11709 CPUSwap(bus.reg[R11_FIQ].I, bus.reg[11].I);
11710 CPUSwap(bus.reg[R12_FIQ].I, bus.reg[12].I);
11711 bus.reg[R13_FIQ].I = bus.reg[13].I;
11712 bus.reg[R14_FIQ].I = bus.reg[14].I;
11713 bus.reg[SPSR_FIQ].I = bus.reg[17].I;
11714 break;
11715 case 0x12:
11716 bus.reg[R13_IRQ].I = bus.reg[13].I;
11717 bus.reg[R14_IRQ].I = bus.reg[14].I;
11718 bus.reg[SPSR_IRQ].I = bus.reg[17].I;
11719 break;
11720 case 0x13:
11721 bus.reg[R13_SVC].I = bus.reg[13].I;
11722 bus.reg[R14_SVC].I = bus.reg[14].I;
11723 bus.reg[SPSR_SVC].I = bus.reg[17].I;
11724 break;
11725 case 0x17:
11726 bus.reg[R13_ABT].I = bus.reg[13].I;
11727 bus.reg[R14_ABT].I = bus.reg[14].I;
11728 bus.reg[SPSR_ABT].I = bus.reg[17].I;
11729 break;
11730 case 0x1b:
11731 bus.reg[R13_UND].I = bus.reg[13].I;
11732 bus.reg[R14_UND].I = bus.reg[14].I;
11733 bus.reg[SPSR_UND].I = bus.reg[17].I;
11734 break;
11735 }
11736
11737 uint32_t CPSR = bus.reg[16].I;
11738 uint32_t SPSR = bus.reg[17].I;
11739
11740 switch(mode) {
11741 case 0x10:
11742 case 0x1F:
11743 bus.reg[13].I = bus.reg[R13_USR].I;
11744 bus.reg[14].I = bus.reg[R14_USR].I;
11745 bus.reg[16].I = SPSR;
11746 break;
11747 case 0x11:
11748 CPUSwap(bus.reg[8].I, bus.reg[R8_FIQ].I);
11749 CPUSwap(bus.reg[9].I, bus.reg[R9_FIQ].I);
11750 CPUSwap(bus.reg[10].I, bus.reg[R10_FIQ].I);
11751 CPUSwap(bus.reg[11].I, bus.reg[R11_FIQ].I);
11752 CPUSwap(bus.reg[12].I, bus.reg[R12_FIQ].I);
11753 bus.reg[13].I = bus.reg[R13_FIQ].I;
11754 bus.reg[14].I = bus.reg[R14_FIQ].I;
11755 if(saveState)
11756 bus.reg[17].I = CPSR; else
11757 bus.reg[17].I = bus.reg[SPSR_FIQ].I;
11758 break;
11759 case 0x12:
11760 bus.reg[13].I = bus.reg[R13_IRQ].I;
11761 bus.reg[14].I = bus.reg[R14_IRQ].I;
11762 bus.reg[16].I = SPSR;
11763 if(saveState)
11764 bus.reg[17].I = CPSR;
11765 else
11766 bus.reg[17].I = bus.reg[SPSR_IRQ].I;
11767 break;
11768 case 0x13:
11769 bus.reg[13].I = bus.reg[R13_SVC].I;
11770 bus.reg[14].I = bus.reg[R14_SVC].I;
11771 bus.reg[16].I = SPSR;
11772 if(saveState)
11773 bus.reg[17].I = CPSR;
11774 else
11775 bus.reg[17].I = bus.reg[SPSR_SVC].I;
11776 break;
11777 case 0x17:
11778 bus.reg[13].I = bus.reg[R13_ABT].I;
11779 bus.reg[14].I = bus.reg[R14_ABT].I;
11780 bus.reg[16].I = SPSR;
11781 if(saveState)
11782 bus.reg[17].I = CPSR;
11783 else
11784 bus.reg[17].I = bus.reg[SPSR_ABT].I;
11785 break;
11786 case 0x1b:
11787 bus.reg[13].I = bus.reg[R13_UND].I;
11788 bus.reg[14].I = bus.reg[R14_UND].I;
11789 bus.reg[16].I = SPSR;
11790 if(saveState)
11791 bus.reg[17].I = CPSR;
11792 else
11793 bus.reg[17].I = bus.reg[SPSR_UND].I;
11794 break;
11795 default:
11796 break;
11797 }
11798 armMode = mode;
11799 CPUUpdateFlags(breakLoop);
11800 CPU_UPDATE_CPSR();
11801 }
11802
11803
11804
doDMA(uint32_t & s,uint32_t & d,uint32_t si,uint32_t di,uint32_t c,int transfer32)11805 void doDMA(uint32_t &s, uint32_t &d, uint32_t si, uint32_t di, uint32_t c, int transfer32)
11806 {
11807 int sm = s >> 24;
11808 int dm = d >> 24;
11809 int sw = 0;
11810 int dw = 0;
11811 int sc = c;
11812
11813 cpuDmaRunning = true;
11814 cpuDmaPC = bus.reg[15].I;
11815 cpuDmaCount = c;
11816
11817 // This is done to get the correct waitstates.
11818 int32_t sm_gt_15_mask = ((sm>15) | -(sm>15)) >> 31;
11819 int32_t dm_gt_15_mask = ((dm>15) | -(dm>15)) >> 31;
11820 sm = ((((15) & sm_gt_15_mask) | ((((sm) & ~(sm_gt_15_mask))))));
11821 dm = ((((15) & dm_gt_15_mask) | ((((dm) & ~(dm_gt_15_mask))))));
11822
11823 //if ((sm>=0x05) && (sm<=0x07) || (dm>=0x05) && (dm <=0x07))
11824 // blank = (((io_registers[REG_DISPSTAT] | ((io_registers[REG_DISPSTAT] >> 1)&1))==1) ? true : false);
11825
11826 if(transfer32)
11827 {
11828 s &= 0xFFFFFFFC;
11829 if(s < 0x02000000 && (bus.reg[15].I >> 24))
11830 {
11831 while(c != 0)
11832 {
11833 CPUWriteMemory(d, 0);
11834 d += di;
11835 c--;
11836 };
11837 }
11838 else
11839 {
11840 while(c != 0)
11841 {
11842 cpuDmaLast = CPUReadMemory(s);
11843 CPUWriteMemory(d, CPUReadMemory(s));
11844 d += di;
11845 s += si;
11846 c--;
11847 };
11848 }
11849 }
11850 else
11851 {
11852 s &= 0xFFFFFFFE;
11853 si = (int)si >> 1;
11854 di = (int)di >> 1;
11855 if(s < 0x02000000 && (bus.reg[15].I >> 24))
11856 {
11857 while(c != 0)
11858 {
11859 CPUWriteHalfWord(d, 0);
11860 d += di;
11861 c--;
11862 };
11863 }
11864 else
11865 {
11866 while(c != 0)
11867 {
11868 cpuDmaLast = CPUReadHalfWord(s);
11869 CPUWriteHalfWord(d, cpuDmaLast);
11870 cpuDmaLast |= cpuDmaLast << 16;
11871 d += di;
11872 s += si;
11873 c--;
11874 };
11875 }
11876 }
11877
11878 cpuDmaCount = 0;
11879 cpuDmaRunning = false;
11880
11881 if(transfer32)
11882 {
11883 sw = 1+memoryWaitSeq32[sm & 15];
11884 dw = 1+memoryWaitSeq32[dm & 15];
11885 cpuDmaTicksToUpdate += (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] + memoryWaitSeq32[dm & 15];
11886 }
11887 else
11888 {
11889 sw = 1+memoryWaitSeq[sm & 15];
11890 dw = 1+memoryWaitSeq[dm & 15];
11891 cpuDmaTicksToUpdate += (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] + memoryWaitSeq[dm & 15];
11892 }
11893 }
11894
11895
CPUCheckDMA(int reason,int dmamask)11896 void CPUCheckDMA(int reason, int dmamask)
11897 {
11898 uint32_t arrayval[] = {4, (uint32_t)-4, 0, 4};
11899 // DMA 0
11900 if((DM0CNT_H & 0x8000) && (dmamask & 1))
11901 {
11902 if(((DM0CNT_H >> 12) & 3) == reason)
11903 {
11904 uint32_t sourceIncrement, destIncrement;
11905 uint32_t condition1 = ((DM0CNT_H >> 7) & 3);
11906 uint32_t condition2 = ((DM0CNT_H >> 5) & 3);
11907 sourceIncrement = arrayval[condition1];
11908 destIncrement = arrayval[condition2];
11909 doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement,
11910 DM0CNT_L ? DM0CNT_L : 0x4000,
11911 DM0CNT_H & 0x0400);
11912
11913 if(DM0CNT_H & 0x4000)
11914 {
11915 io_registers[REG_IF] |= 0x0100;
11916 UPDATE_REG(0x202, io_registers[REG_IF]);
11917 cpuNextEvent = cpuTotalTicks;
11918 }
11919
11920 if(((DM0CNT_H >> 5) & 3) == 3) {
11921 dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
11922 }
11923
11924 if(!(DM0CNT_H & 0x0200) || (reason == 0)) {
11925 DM0CNT_H &= 0x7FFF;
11926 UPDATE_REG(0xBA, DM0CNT_H);
11927 }
11928 }
11929 }
11930
11931 // DMA 1
11932 if((DM1CNT_H & 0x8000) && (dmamask & 2)) {
11933 if(((DM1CNT_H >> 12) & 3) == reason) {
11934 uint32_t sourceIncrement, destIncrement;
11935 uint32_t condition1 = ((DM1CNT_H >> 7) & 3);
11936 uint32_t condition2 = ((DM1CNT_H >> 5) & 3);
11937 sourceIncrement = arrayval[condition1];
11938 destIncrement = arrayval[condition2];
11939 uint32_t di_value, c_value, transfer_value;
11940 if(reason == 3)
11941 {
11942 di_value = 0;
11943 c_value = 4;
11944 transfer_value = 0x0400;
11945 }
11946 else
11947 {
11948 di_value = destIncrement;
11949 c_value = DM1CNT_L ? DM1CNT_L : 0x4000;
11950 transfer_value = DM1CNT_H & 0x0400;
11951 }
11952 doDMA(dma1Source, dma1Dest, sourceIncrement, di_value, c_value, transfer_value);
11953
11954 if(DM1CNT_H & 0x4000) {
11955 io_registers[REG_IF] |= 0x0200;
11956 UPDATE_REG(0x202, io_registers[REG_IF]);
11957 cpuNextEvent = cpuTotalTicks;
11958 }
11959
11960 if(((DM1CNT_H >> 5) & 3) == 3) {
11961 dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
11962 }
11963
11964 if(!(DM1CNT_H & 0x0200) || (reason == 0)) {
11965 DM1CNT_H &= 0x7FFF;
11966 UPDATE_REG(0xC6, DM1CNT_H);
11967 }
11968 }
11969 }
11970
11971 // DMA 2
11972 if((DM2CNT_H & 0x8000) && (dmamask & 4)) {
11973 if(((DM2CNT_H >> 12) & 3) == reason) {
11974 uint32_t sourceIncrement, destIncrement;
11975 uint32_t condition1 = ((DM2CNT_H >> 7) & 3);
11976 uint32_t condition2 = ((DM2CNT_H >> 5) & 3);
11977 sourceIncrement = arrayval[condition1];
11978 destIncrement = arrayval[condition2];
11979 uint32_t di_value, c_value, transfer_value;
11980 if(reason == 3)
11981 {
11982 di_value = 0;
11983 c_value = 4;
11984 transfer_value = 0x0400;
11985 }
11986 else
11987 {
11988 di_value = destIncrement;
11989 c_value = DM2CNT_L ? DM2CNT_L : 0x4000;
11990 transfer_value = DM2CNT_H & 0x0400;
11991 }
11992 doDMA(dma2Source, dma2Dest, sourceIncrement, di_value, c_value, transfer_value);
11993
11994 if(DM2CNT_H & 0x4000) {
11995 io_registers[REG_IF] |= 0x0400;
11996 UPDATE_REG(0x202, io_registers[REG_IF]);
11997 cpuNextEvent = cpuTotalTicks;
11998 }
11999
12000 if(((DM2CNT_H >> 5) & 3) == 3) {
12001 dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
12002 }
12003
12004 if(!(DM2CNT_H & 0x0200) || (reason == 0)) {
12005 DM2CNT_H &= 0x7FFF;
12006 UPDATE_REG(0xD2, DM2CNT_H);
12007 }
12008 }
12009 }
12010
12011 // DMA 3
12012 if((DM3CNT_H & 0x8000) && (dmamask & 8))
12013 {
12014 if(((DM3CNT_H >> 12) & 3) == reason)
12015 {
12016 uint32_t sourceIncrement, destIncrement;
12017 uint32_t condition1 = ((DM3CNT_H >> 7) & 3);
12018 uint32_t condition2 = ((DM3CNT_H >> 5) & 3);
12019 sourceIncrement = arrayval[condition1];
12020 destIncrement = arrayval[condition2];
12021 doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement,
12022 DM3CNT_L ? DM3CNT_L : 0x10000,
12023 DM3CNT_H & 0x0400);
12024 if(DM3CNT_H & 0x4000) {
12025 io_registers[REG_IF] |= 0x0800;
12026 UPDATE_REG(0x202, io_registers[REG_IF]);
12027 cpuNextEvent = cpuTotalTicks;
12028 }
12029
12030 if(((DM3CNT_H >> 5) & 3) == 3) {
12031 dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
12032 }
12033
12034 if(!(DM3CNT_H & 0x0200) || (reason == 0)) {
12035 DM3CNT_H &= 0x7FFF;
12036 UPDATE_REG(0xDE, DM3CNT_H);
12037 }
12038 }
12039 }
12040 }
12041
12042 static uint16_t *address_lut[0x300];
12043
CPUUpdateRegister(uint32_t address,uint16_t value)12044 void CPUUpdateRegister(uint32_t address, uint16_t value)
12045 {
12046 switch(address)
12047 {
12048 case 0x00: /* DISPCNT */
12049 {
12050 if((value & 7) > 5) // display modes above 0-5 are prohibited
12051 io_registers[REG_DISPCNT] = (value & 7);
12052
12053 bool change = (0 != ((io_registers[REG_DISPCNT] ^ value) & 0x80));
12054 bool changeBG = (0 != ((io_registers[REG_DISPCNT] ^ value) & 0x0F00));
12055 uint16_t changeBGon = ((~io_registers[REG_DISPCNT]) & value) & 0x0F00; // these layers are being activated
12056
12057 io_registers[REG_DISPCNT] = (value & 0xFFF7); // bit 3 can only be accessed by the BIOS to enable GBC mode
12058 UPDATE_REG(0x00, io_registers[REG_DISPCNT]);
12059
12060 graphics.layerEnable = value;
12061
12062 if(changeBGon)
12063 {
12064 graphics.layerEnableDelay = 4;
12065 graphics.layerEnable &= ~changeBGon;
12066 }
12067
12068 windowOn = (graphics.layerEnable & 0x6000) ? true : false;
12069 if(change && !((value & 0x80)))
12070 {
12071 if(!(io_registers[REG_DISPSTAT] & 1))
12072 {
12073 graphics.lcdTicks = 1008;
12074 io_registers[REG_DISPSTAT] &= 0xFFFC;
12075 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12076 CPUCompareVCOUNT();
12077 }
12078 }
12079
12080 CPUUpdateRender();
12081
12082 // we only care about changes in BG0-BG3
12083 if(changeBG)
12084 {
12085 #if THREADED_RENDERER
12086 ++threaded_background_ver;
12087 #else
12088 if(!R_DISPCNT_Screen_Display_BG0)
12089 memset(line[Layer_BG0], -1, 240 * sizeof(u32));
12090 if(!R_DISPCNT_Screen_Display_BG1)
12091 memset(line[Layer_BG1], -1, 240 * sizeof(u32));
12092 if(!R_DISPCNT_Screen_Display_BG2)
12093 memset(line[Layer_BG2], -1, 240 * sizeof(u32));
12094 if(!R_DISPCNT_Screen_Display_BG3)
12095 memset(line[Layer_BG3], -1, 240 * sizeof(u32));
12096 #endif
12097 }
12098 break;
12099 }
12100 case 0x04: /* DISPSTAT */
12101 io_registers[REG_DISPSTAT] = (value & 0xFF38) | (io_registers[REG_DISPSTAT] & 7);
12102 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12103 break;
12104 case 0x06:
12105 // not writable
12106 break;
12107 case 0x08: /* BG0CNT */
12108 case 0x0A: /* BG1CNT */
12109 *address_lut[address] = (value & 0xDFCF);
12110 UPDATE_REG(address, *address_lut[address]);
12111 break;
12112 case 0x0C: /* BG2CNT */
12113 case 0x0E: /* BG3CNT */
12114 *address_lut[address] = (value & 0xFFCF);
12115 UPDATE_REG(address, *address_lut[address]);
12116 break;
12117 case 0x10: /* BG0HOFS */
12118 case 0x12: /* BG0VOFS */
12119 case 0x14: /* BG1HOFS */
12120 case 0x16: /* BG1VOFS */
12121 case 0x18: /* BG2HOFS */
12122 case 0x1A: /* BG2VOFS */
12123 case 0x1C: /* BG3HOFS */
12124 case 0x1E: /* BG3VOFS */
12125 *address_lut[address] = value & 511;
12126 UPDATE_REG(address, *address_lut[address]);
12127 break;
12128 case 0x20: /* BG2PA */
12129 case 0x22: /* BG2PB */
12130 case 0x24: /* BG2PC */
12131 case 0x26: /* BG2PD */
12132 *address_lut[address] = value;
12133 UPDATE_REG(address, *address_lut[address]);
12134 break;
12135 case 0x28:
12136 BG2X_L = value;
12137 UPDATE_REG(0x28, BG2X_L);
12138 gfxBG2Changed |= 1;
12139 break;
12140 case 0x2A:
12141 BG2X_H = (value & 0xFFF);
12142 UPDATE_REG(0x2A, BG2X_H);
12143 gfxBG2Changed |= 1;
12144 break;
12145 case 0x2C:
12146 BG2Y_L = value;
12147 UPDATE_REG(0x2C, BG2Y_L);
12148 gfxBG2Changed |= 2;
12149 break;
12150 case 0x2E:
12151 BG2Y_H = value & 0xFFF;
12152 UPDATE_REG(0x2E, BG2Y_H);
12153 gfxBG2Changed |= 2;
12154 break;
12155 case 0x30: /* BG3PA */
12156 case 0x32: /* BG3PB */
12157 case 0x34: /* BG3PC */
12158 case 0x36: /* BG3PD */
12159 *address_lut[address] = value;
12160 UPDATE_REG(address, *address_lut[address]);
12161 break;
12162 case 0x38:
12163 BG3X_L = value;
12164 UPDATE_REG(0x38, BG3X_L);
12165 gfxBG3Changed |= 1;
12166 break;
12167 case 0x3A:
12168 BG3X_H = value & 0xFFF;
12169 UPDATE_REG(0x3A, BG3X_H);
12170 gfxBG3Changed |= 1;
12171 break;
12172 case 0x3C:
12173 BG3Y_L = value;
12174 UPDATE_REG(0x3C, BG3Y_L);
12175 gfxBG3Changed |= 2;
12176 break;
12177 case 0x3E:
12178 BG3Y_H = value & 0xFFF;
12179 UPDATE_REG(0x3E, BG3Y_H);
12180 gfxBG3Changed |= 2;
12181 break;
12182 case 0x40:
12183 io_registers[REG_WIN0H] = value;
12184 UPDATE_REG(0x40, io_registers[REG_WIN0H]);
12185 CPUUpdateWindow0();
12186 break;
12187 case 0x42:
12188 io_registers[REG_WIN1H] = value;
12189 UPDATE_REG(0x42, io_registers[REG_WIN1H]);
12190 CPUUpdateWindow1();
12191 break;
12192 case 0x44:
12193 case 0x46:
12194 *address_lut[address] = value;
12195 UPDATE_REG(address, *address_lut[address]);
12196 break;
12197 case 0x48: /* WININ */
12198 case 0x4A: /* WINOUT */
12199 *address_lut[address] = value & 0x3F3F;
12200 UPDATE_REG(address, *address_lut[address]);
12201 break;
12202 case 0x4C:
12203 MOSAIC = value;
12204 UPDATE_REG(0x4C, MOSAIC);
12205 break;
12206 case 0x50:
12207 BLDMOD = value & 0x3FFF;
12208 UPDATE_REG(0x50, BLDMOD);
12209 fxOn = ((BLDMOD>>6)&3) != 0;
12210 CPUUpdateRender();
12211 break;
12212 case 0x52:
12213 COLEV = value & 0x1F1F;
12214 UPDATE_REG(0x52, COLEV);
12215 break;
12216 case 0x54:
12217 COLY = value & 0x1F;
12218 UPDATE_REG(0x54, COLY);
12219 break;
12220 case 0x60:
12221 case 0x62:
12222 case 0x64:
12223 case 0x68:
12224 case 0x6c:
12225 case 0x70:
12226 case 0x72:
12227 case 0x74:
12228 case 0x78:
12229 case 0x7c:
12230 case 0x80:
12231 case 0x84:
12232 soundEvent_u8(table[(int32_t)(address & 0xFF) - 0x60], (uint32_t)(address & 0xFF), (uint8_t)(value & 0xFF));
12233 soundEvent_u8(table[(int32_t)((address & 0xFF) + 1) - 0x60], (uint32_t)((address & 0xFF) + 1), (uint8_t)(value >> 8));
12234 break;
12235 case 0x82:
12236 case 0x88:
12237 case 0xa0:
12238 case 0xa2:
12239 case 0xa4:
12240 case 0xa6:
12241 case 0x90:
12242 case 0x92:
12243 case 0x94:
12244 case 0x96:
12245 case 0x98:
12246 case 0x9a:
12247 case 0x9c:
12248 case 0x9e:
12249 soundEvent_u16(address&0xFF, value);
12250 break;
12251 case 0xB0:
12252 DM0SAD_L = value;
12253 UPDATE_REG(0xB0, DM0SAD_L);
12254 break;
12255 case 0xB2:
12256 DM0SAD_H = value & 0x07FF;
12257 UPDATE_REG(0xB2, DM0SAD_H);
12258 break;
12259 case 0xB4:
12260 DM0DAD_L = value;
12261 UPDATE_REG(0xB4, DM0DAD_L);
12262 break;
12263 case 0xB6:
12264 DM0DAD_H = value & 0x07FF;
12265 UPDATE_REG(0xB6, DM0DAD_H);
12266 break;
12267 case 0xB8:
12268 DM0CNT_L = value & 0x3FFF;
12269 UPDATE_REG(0xB8, 0);
12270 break;
12271 case 0xBA:
12272 {
12273 bool start = ((DM0CNT_H ^ value) & 0x8000) ? true : false;
12274 value &= 0xF7E0;
12275
12276 DM0CNT_H = value;
12277 UPDATE_REG(0xBA, DM0CNT_H);
12278
12279 if(start && (value & 0x8000))
12280 {
12281 dma0Source = DM0SAD_L | (DM0SAD_H << 16);
12282 dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
12283 CPUCheckDMA(0, 1);
12284 }
12285 }
12286 break;
12287 case 0xBC:
12288 DM1SAD_L = value;
12289 UPDATE_REG(0xBC, DM1SAD_L);
12290 break;
12291 case 0xBE:
12292 DM1SAD_H = value & 0x0FFF;
12293 UPDATE_REG(0xBE, DM1SAD_H);
12294 break;
12295 case 0xC0:
12296 DM1DAD_L = value;
12297 UPDATE_REG(0xC0, DM1DAD_L);
12298 break;
12299 case 0xC2:
12300 DM1DAD_H = value & 0x07FF;
12301 UPDATE_REG(0xC2, DM1DAD_H);
12302 break;
12303 case 0xC4:
12304 DM1CNT_L = value & 0x3FFF;
12305 UPDATE_REG(0xC4, 0);
12306 break;
12307 case 0xC6:
12308 {
12309 bool start = ((DM1CNT_H ^ value) & 0x8000) ? true : false;
12310 value &= 0xF7E0;
12311
12312 DM1CNT_H = value;
12313 UPDATE_REG(0xC6, DM1CNT_H);
12314
12315 if(start && (value & 0x8000))
12316 {
12317 dma1Source = DM1SAD_L | (DM1SAD_H << 16);
12318 dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
12319 CPUCheckDMA(0, 2);
12320 }
12321 }
12322 break;
12323 case 0xC8:
12324 DM2SAD_L = value;
12325 UPDATE_REG(0xC8, DM2SAD_L);
12326 break;
12327 case 0xCA:
12328 DM2SAD_H = value & 0x0FFF;
12329 UPDATE_REG(0xCA, DM2SAD_H);
12330 break;
12331 case 0xCC:
12332 DM2DAD_L = value;
12333 UPDATE_REG(0xCC, DM2DAD_L);
12334 break;
12335 case 0xCE:
12336 DM2DAD_H = value & 0x07FF;
12337 UPDATE_REG(0xCE, DM2DAD_H);
12338 break;
12339 case 0xD0:
12340 DM2CNT_L = value & 0x3FFF;
12341 UPDATE_REG(0xD0, 0);
12342 break;
12343 case 0xD2:
12344 {
12345 bool start = ((DM2CNT_H ^ value) & 0x8000) ? true : false;
12346
12347 value &= 0xF7E0;
12348
12349 DM2CNT_H = value;
12350 UPDATE_REG(0xD2, DM2CNT_H);
12351
12352 if(start && (value & 0x8000)) {
12353 dma2Source = DM2SAD_L | (DM2SAD_H << 16);
12354 dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
12355
12356 CPUCheckDMA(0, 4);
12357 }
12358 }
12359 break;
12360 case 0xD4:
12361 DM3SAD_L = value;
12362 UPDATE_REG(0xD4, DM3SAD_L);
12363 break;
12364 case 0xD6:
12365 DM3SAD_H = value & 0x0FFF;
12366 UPDATE_REG(0xD6, DM3SAD_H);
12367 break;
12368 case 0xD8:
12369 DM3DAD_L = value;
12370 UPDATE_REG(0xD8, DM3DAD_L);
12371 break;
12372 case 0xDA:
12373 DM3DAD_H = value & 0x0FFF;
12374 UPDATE_REG(0xDA, DM3DAD_H);
12375 break;
12376 case 0xDC:
12377 DM3CNT_L = value;
12378 UPDATE_REG(0xDC, 0);
12379 break;
12380 case 0xDE:
12381 {
12382 bool start = ((DM3CNT_H ^ value) & 0x8000) ? true : false;
12383
12384 value &= 0xFFE0;
12385
12386 DM3CNT_H = value;
12387 UPDATE_REG(0xDE, DM3CNT_H);
12388
12389 if(start && (value & 0x8000)) {
12390 dma3Source = DM3SAD_L | (DM3SAD_H << 16);
12391 dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
12392 CPUCheckDMA(0,8);
12393 }
12394 }
12395 break;
12396 case 0x100:
12397 timer0Reload = value;
12398 break;
12399 case 0x102:
12400 timer0Value = value;
12401 timerOnOffDelay|=1;
12402 cpuNextEvent = cpuTotalTicks;
12403 break;
12404 case 0x104:
12405 timer1Reload = value;
12406 break;
12407 case 0x106:
12408 timer1Value = value;
12409 timerOnOffDelay|=2;
12410 cpuNextEvent = cpuTotalTicks;
12411 break;
12412 case 0x108:
12413 timer2Reload = value;
12414 break;
12415 case 0x10A:
12416 timer2Value = value;
12417 timerOnOffDelay|=4;
12418 cpuNextEvent = cpuTotalTicks;
12419 break;
12420 case 0x10C:
12421 timer3Reload = value;
12422 break;
12423 case 0x10E:
12424 timer3Value = value;
12425 timerOnOffDelay|=8;
12426 cpuNextEvent = cpuTotalTicks;
12427 break;
12428 case 0x130:
12429 io_registers[REG_P1] |= (value & 0x3FF);
12430 UPDATE_REG(0x130, io_registers[REG_P1]);
12431 break;
12432 case 0x132:
12433 UPDATE_REG(0x132, value & 0xC3FF);
12434 break;
12435 case 0x200:
12436 io_registers[REG_IE] = value & 0x3FFF;
12437 UPDATE_REG(0x200, io_registers[REG_IE]);
12438 if ((io_registers[REG_IME] & 1) && (io_registers[REG_IF] & io_registers[REG_IE]) && armIrqEnable)
12439 cpuNextEvent = cpuTotalTicks;
12440 break;
12441 case 0x202:
12442 io_registers[REG_IF] ^= (value & io_registers[REG_IF]);
12443 UPDATE_REG(0x202, io_registers[REG_IF]);
12444 break;
12445 case 0x204:
12446 memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3];
12447
12448 #if USE_TWEAK_SPEEDHACK
12449 memoryWait[0x08] = memoryWait[0x09] = 3;
12450 memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 1;
12451 memoryWait[0x0a] = memoryWait[0x0b] = 3;
12452 memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 1;
12453 memoryWait[0x0c] = memoryWait[0x0d] = 3;
12454 memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 1;
12455 #else
12456 memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 3];
12457 memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = gamepakWaitState0[(value >> 4) & 1];
12458 memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 3];
12459 memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = gamepakWaitState1[(value >> 7) & 1];
12460 memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 3];
12461 memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = gamepakWaitState2[(value >> 10) & 1];
12462 #endif
12463
12464 memoryWait32[8] = memoryWait[8] + memoryWaitSeq[8] + 1;
12465 memoryWaitSeq32[8] = (memoryWaitSeq[8] << 1) + 1;
12466 memoryWait32[9] = memoryWait[9] + memoryWaitSeq[9] + 1;
12467 memoryWaitSeq32[9] = (memoryWaitSeq[9] << 1) + 1;
12468 memoryWait32[10] = memoryWait[10] + memoryWaitSeq[10] + 1;
12469 memoryWaitSeq32[10] = (memoryWaitSeq[10] << 1) + 1;
12470 memoryWait32[11] = memoryWait[11] + memoryWaitSeq[11] + 1;
12471 memoryWaitSeq32[11] = (memoryWaitSeq[11] << 1) + 1;
12472 memoryWait32[12] = memoryWait[12] + memoryWaitSeq[12] + 1;
12473 memoryWaitSeq32[12] = (memoryWaitSeq[12] << 1) + 1;
12474 memoryWait32[13] = memoryWait[13] + memoryWaitSeq[13] + 1;
12475 memoryWaitSeq32[13] = (memoryWaitSeq[13] << 1) + 1;
12476 memoryWait32[14] = memoryWait[14] + memoryWaitSeq[14] + 1;
12477 memoryWaitSeq32[14] = (memoryWaitSeq[14] << 1) + 1;
12478
12479 if((value & 0x4000) == 0x4000)
12480 bus.busPrefetchEnable = true;
12481 else
12482 bus.busPrefetchEnable = false;
12483
12484 bus.busPrefetch = false;
12485 bus.busPrefetchCount = 0;
12486
12487 UPDATE_REG(0x204, value & 0x7FFF);
12488 break;
12489 case 0x208:
12490 io_registers[REG_IME] = value & 1;
12491 UPDATE_REG(0x208, io_registers[REG_IME]);
12492 if ((io_registers[REG_IME] & 1) && (io_registers[REG_IF] & io_registers[REG_IE]) && armIrqEnable)
12493 cpuNextEvent = cpuTotalTicks;
12494 break;
12495 case 0x300:
12496 if(value != 0)
12497 value &= 0xFFFE;
12498 UPDATE_REG(0x300, value);
12499 break;
12500 default:
12501 UPDATE_REG(address&0x3FE, value);
12502 break;
12503 }
12504 }
12505
CPUInit(const char * biosFileName,bool useBiosFile)12506 void CPUInit(const char *biosFileName, bool useBiosFile)
12507 {
12508 #ifdef MSB_FIRST
12509 if(!cpuBiosSwapped)
12510 {
12511 for(unsigned int i = 0; i < sizeof(myROM)/4; i++)
12512 {
12513 WRITE32LE(&myROM[i], myROM[i]);
12514 }
12515 cpuBiosSwapped = true;
12516 }
12517 #endif
12518 gbaSaveType = 0;
12519 eepromInUse = 0;
12520 saveType = 0;
12521 useBios = false;
12522
12523 #ifdef HAVE_HLE_BIOS
12524 if(useBiosFile)
12525 {
12526 int size = 0x4000;
12527 if(utilLoad(biosFileName, CPUIsGBABios, bios, size))
12528 {
12529 if(size == 0x4000)
12530 useBios = true;
12531 }
12532 }
12533 #endif
12534
12535 #ifdef HAVE_HLE_BIOS
12536 if(!useBios)
12537 #endif
12538 memcpy(bios, myROM, sizeof(myROM));
12539
12540 int i = 0;
12541
12542 biosProtected[0] = 0x00;
12543 biosProtected[1] = 0xf0;
12544 biosProtected[2] = 0x29;
12545 biosProtected[3] = 0xe1;
12546
12547 for(i = 0; i < 256; i++)
12548 {
12549 int count = 0;
12550 int j;
12551 for(j = 0; j < 8; j++)
12552 if(i & (1 << j))
12553 count++;
12554 cpuBitsSet[i] = count;
12555
12556 for(j = 0; j < 8; j++)
12557 if(i & (1 << j))
12558 break;
12559 }
12560
12561 for(i = 0; i < 0x400; i++)
12562 ioReadable[i] = true;
12563 for(i = 0x10; i < 0x48; i++)
12564 ioReadable[i] = false;
12565 for(i = 0x4c; i < 0x50; i++)
12566 ioReadable[i] = false;
12567 for(i = 0x54; i < 0x60; i++)
12568 ioReadable[i] = false;
12569 for(i = 0x8c; i < 0x90; i++)
12570 ioReadable[i] = false;
12571 for(i = 0xa0; i < 0xb8; i++)
12572 ioReadable[i] = false;
12573 for(i = 0xbc; i < 0xc4; i++)
12574 ioReadable[i] = false;
12575 for(i = 0xc8; i < 0xd0; i++)
12576 ioReadable[i] = false;
12577 for(i = 0xd4; i < 0xdc; i++)
12578 ioReadable[i] = false;
12579 for(i = 0xe0; i < 0x100; i++)
12580 ioReadable[i] = false;
12581 for(i = 0x110; i < 0x120; i++)
12582 ioReadable[i] = false;
12583 for(i = 0x12c; i < 0x130; i++)
12584 ioReadable[i] = false;
12585 for(i = 0x138; i < 0x140; i++)
12586 ioReadable[i] = false;
12587 for(i = 0x144; i < 0x150; i++)
12588 ioReadable[i] = false;
12589 for(i = 0x15c; i < 0x200; i++)
12590 ioReadable[i] = false;
12591 for(i = 0x20c; i < 0x300; i++)
12592 ioReadable[i] = false;
12593 for(i = 0x304; i < 0x400; i++)
12594 ioReadable[i] = false;
12595
12596 if(romSize < 0x1fe2000) {
12597 *((uint16_t *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA
12598 *((uint16_t *)&rom[0x1fe209e]) = 0x4770; // BX LR
12599 }
12600
12601 graphics.layerEnable = 0xff00;
12602 graphics.layerEnableDelay = 1;
12603 io_registers[REG_DISPCNT] = 0x0080;
12604 io_registers[REG_DISPSTAT] = 0;
12605 graphics.lcdTicks = (useBios && !skipBios) ? 1008 : 208;
12606
12607 /* address lut for use in CPUUpdateRegister */
12608 address_lut[0x08] = &io_registers[REG_BG0CNT];
12609 address_lut[0x0A] = &io_registers[REG_BG1CNT];
12610 address_lut[0x0C] = &io_registers[REG_BG2CNT];
12611 address_lut[0x0E] = &io_registers[REG_BG3CNT];
12612 address_lut[0x10] = &io_registers[REG_BG0HOFS];
12613 address_lut[0x12] = &io_registers[REG_BG0VOFS];
12614 address_lut[0x14] = &io_registers[REG_BG1HOFS];
12615 address_lut[0x16] = &io_registers[REG_BG1VOFS];
12616 address_lut[0x18] = &io_registers[REG_BG2HOFS];
12617 address_lut[0x1A] = &io_registers[REG_BG2VOFS];
12618 address_lut[0x1C] = &io_registers[REG_BG3HOFS];
12619 address_lut[0x1E] = &io_registers[REG_BG3VOFS];
12620 address_lut[0x20] = &io_registers[REG_BG2PA];
12621 address_lut[0x22] = &io_registers[REG_BG2PB];
12622 address_lut[0x24] = &io_registers[REG_BG2PC];
12623 address_lut[0x26] = &io_registers[REG_BG2PD];
12624 address_lut[0x48] = &io_registers[REG_WININ];
12625 address_lut[0x4A] = &io_registers[REG_WINOUT];
12626 address_lut[0x30] = &io_registers[REG_BG3PA];
12627 address_lut[0x32] = &io_registers[REG_BG3PB];
12628 address_lut[0x34] = &io_registers[REG_BG3PC];
12629 address_lut[0x36] = &io_registers[REG_BG3PD];
12630 address_lut[0x40] = &io_registers[REG_WIN0H];
12631 address_lut[0x42] = &io_registers[REG_WIN1H];
12632 address_lut[0x44] = &io_registers[REG_WIN0V];
12633 address_lut[0x46] = &io_registers[REG_WIN1V];
12634 }
12635
CPUReset(void)12636 void CPUReset (void)
12637 {
12638 if(gbaSaveType == 0)
12639 {
12640 if(eepromInUse)
12641 gbaSaveType = 3;
12642 else
12643 switch(saveType)
12644 {
12645 case 1:
12646 gbaSaveType = 1;
12647 break;
12648 case 2:
12649 gbaSaveType = 2;
12650 break;
12651 }
12652 }
12653 rtcReset();
12654 #if USE_MOTION_SENSOR
12655 hardware_reset();
12656 #endif
12657 memset(&bus.reg[0], 0, sizeof(bus.reg)); // clean registers
12658 memset(oam, 0, 0x400); // clean OAM
12659 memset(paletteRAM, 0, 0x400); // clean palette
12660 memset(pix, 0, 4 * 160 * 240); // clean picture
12661 memset(vram, 0, 0x20000); // clean vram
12662 memset(ioMem, 0, 0x400); // clean io memory
12663
12664 io_registers[REG_DISPCNT] = 0x0080;
12665 io_registers[REG_DISPSTAT] = 0x0000;
12666 io_registers[REG_VCOUNT] = (useBios && !skipBios) ? 0 :0x007E;
12667 io_registers[REG_BG0CNT] = 0x0000;
12668 io_registers[REG_BG1CNT] = 0x0000;
12669 io_registers[REG_BG2CNT] = 0x0000;
12670 io_registers[REG_BG3CNT] = 0x0000;
12671 io_registers[REG_BG0HOFS] = 0x0000;
12672 io_registers[REG_BG0VOFS] = 0x0000;
12673 io_registers[REG_BG1HOFS] = 0x0000;
12674 io_registers[REG_BG1VOFS] = 0x0000;
12675 io_registers[REG_BG2HOFS] = 0x0000;
12676 io_registers[REG_BG2VOFS] = 0x0000;
12677 io_registers[REG_BG3HOFS] = 0x0000;
12678 io_registers[REG_BG3VOFS] = 0x0000;
12679 io_registers[REG_BG2PA] = 0x0100;
12680 io_registers[REG_BG2PB] = 0x0000;
12681 io_registers[REG_BG2PC] = 0x0000;
12682 io_registers[REG_BG2PD] = 0x0100;
12683 BG2X_L = 0x0000;
12684 BG2X_H = 0x0000;
12685 BG2Y_L = 0x0000;
12686 BG2Y_H = 0x0000;
12687 io_registers[REG_BG3PA] = 0x0100;
12688 io_registers[REG_BG3PB] = 0x0000;
12689 io_registers[REG_BG3PC] = 0x0000;
12690 io_registers[REG_BG3PD] = 0x0100;
12691 BG3X_L = 0x0000;
12692 BG3X_H = 0x0000;
12693 BG3Y_L = 0x0000;
12694 BG3Y_H = 0x0000;
12695 io_registers[REG_WIN0H] = 0x0000;
12696 io_registers[REG_WIN1H] = 0x0000;
12697 io_registers[REG_WIN0V] = 0x0000;
12698 io_registers[REG_WIN1V] = 0x0000;
12699 io_registers[REG_WININ] = 0x0000;
12700 io_registers[REG_WINOUT] = 0x0000;
12701 MOSAIC = 0x0000;
12702 BLDMOD = 0x0000;
12703 COLEV = 0x0000;
12704 COLY = 0x0000;
12705 DM0SAD_L = 0x0000;
12706 DM0SAD_H = 0x0000;
12707 DM0DAD_L = 0x0000;
12708 DM0DAD_H = 0x0000;
12709 DM0CNT_L = 0x0000;
12710 DM0CNT_H = 0x0000;
12711 DM1SAD_L = 0x0000;
12712 DM1SAD_H = 0x0000;
12713 DM1DAD_L = 0x0000;
12714 DM1DAD_H = 0x0000;
12715 DM1CNT_L = 0x0000;
12716 DM1CNT_H = 0x0000;
12717 DM2SAD_L = 0x0000;
12718 DM2SAD_H = 0x0000;
12719 DM2DAD_L = 0x0000;
12720 DM2DAD_H = 0x0000;
12721 DM2CNT_L = 0x0000;
12722 DM2CNT_H = 0x0000;
12723 DM3SAD_L = 0x0000;
12724 DM3SAD_H = 0x0000;
12725 DM3DAD_L = 0x0000;
12726 DM3DAD_H = 0x0000;
12727 DM3CNT_L = 0x0000;
12728 DM3CNT_H = 0x0000;
12729 io_registers[REG_TM0D] = 0x0000;
12730 io_registers[REG_TM0CNT] = 0x0000;
12731 io_registers[REG_TM1D] = 0x0000;
12732 io_registers[REG_TM1CNT] = 0x0000;
12733 io_registers[REG_TM2D] = 0x0000;
12734 io_registers[REG_TM2CNT] = 0x0000;
12735 io_registers[REG_TM3D] = 0x0000;
12736 io_registers[REG_TM3CNT] = 0x0000;
12737 io_registers[REG_P1] = 0x03FF;
12738 io_registers[REG_IE] = 0x0000;
12739 io_registers[REG_IF] = 0x0000;
12740 io_registers[REG_IME] = 0x0000;
12741
12742 armMode = 0x1F;
12743
12744 if(cpuIsMultiBoot) {
12745 bus.reg[13].I = 0x03007F00;
12746 bus.reg[15].I = 0x02000000;
12747 bus.reg[16].I = 0x00000000;
12748 bus.reg[R13_IRQ].I = 0x03007FA0;
12749 bus.reg[R13_SVC].I = 0x03007FE0;
12750 armIrqEnable = true;
12751 } else {
12752 #ifdef HAVE_HLE_BIOS
12753 if(useBios && !skipBios)
12754 {
12755 bus.reg[15].I = 0x00000000;
12756 armMode = 0x13;
12757 armIrqEnable = false;
12758 }
12759 else
12760 {
12761 #endif
12762 bus.reg[13].I = 0x03007F00;
12763 bus.reg[15].I = 0x08000000;
12764 bus.reg[16].I = 0x00000000;
12765 bus.reg[R13_IRQ].I = 0x03007FA0;
12766 bus.reg[R13_SVC].I = 0x03007FE0;
12767 armIrqEnable = true;
12768 #ifdef HAVE_HLE_BIOS
12769 }
12770 #endif
12771 }
12772
12773 armState = true;
12774 C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
12775 UPDATE_REG(0x00, io_registers[REG_DISPCNT]);
12776 UPDATE_REG(0x06, io_registers[REG_VCOUNT]);
12777 UPDATE_REG(0x20, io_registers[REG_BG2PA]);
12778 UPDATE_REG(0x26, io_registers[REG_BG2PD]);
12779 UPDATE_REG(0x30, io_registers[REG_BG3PA]);
12780 UPDATE_REG(0x36, io_registers[REG_BG3PD]);
12781 UPDATE_REG(0x130, io_registers[REG_P1]);
12782 UPDATE_REG(0x88, 0x200);
12783
12784 // disable FIQ
12785 bus.reg[16].I |= 0x40;
12786
12787 CPU_UPDATE_CPSR();
12788
12789 bus.armNextPC = bus.reg[15].I;
12790 bus.reg[15].I += 4;
12791
12792 // reset internal state
12793 holdState = false;
12794
12795 biosProtected[0] = 0x00;
12796 biosProtected[1] = 0xf0;
12797 biosProtected[2] = 0x29;
12798 biosProtected[3] = 0xe1;
12799
12800 graphics.lcdTicks = (useBios && !skipBios) ? 1008 : 208;
12801 timer0On = false;
12802 timer0Ticks = 0;
12803 timer0Reload = 0;
12804 timer0ClockReload = 0;
12805 timer1On = false;
12806 timer1Ticks = 0;
12807 timer1Reload = 0;
12808 timer1ClockReload = 0;
12809 timer2On = false;
12810 timer2Ticks = 0;
12811 timer2Reload = 0;
12812 timer2ClockReload = 0;
12813 timer3On = false;
12814 timer3Ticks = 0;
12815 timer3Reload = 0;
12816 timer3ClockReload = 0;
12817 dma0Source = 0;
12818 dma0Dest = 0;
12819 dma1Source = 0;
12820 dma1Dest = 0;
12821 dma2Source = 0;
12822 dma2Dest = 0;
12823 dma3Source = 0;
12824 dma3Dest = 0;
12825 cpuSaveGameFunc = flashSaveDecide;
12826 fxOn = false;
12827 windowOn = false;
12828 saveType = 0;
12829 graphics.layerEnable = io_registers[REG_DISPCNT];
12830
12831 #if !THREADED_RENDERER
12832 memset(line[Layer_BG0], -1, 240 * sizeof(u32));
12833 memset(line[Layer_BG1], -1, 240 * sizeof(u32));
12834 memset(line[Layer_BG2], -1, 240 * sizeof(u32));
12835 memset(line[Layer_BG3], -1, 240 * sizeof(u32));
12836 #endif
12837
12838 for(int i = 0; i < 256; i++) {
12839 map[i].address = 0;
12840 map[i].mask = 0;
12841 }
12842
12843 map[0].address = bios;
12844 map[0].mask = 0x3FFF;
12845 map[2].address = workRAM;
12846 map[2].mask = 0x3FFFF;
12847 map[3].address = internalRAM;
12848 map[3].mask = 0x7FFF;
12849 map[4].address = ioMem;
12850 map[4].mask = 0x3FF;
12851 map[5].address = paletteRAM;
12852 map[5].mask = 0x3FF;
12853 map[6].address = vram;
12854 map[6].mask = 0x1FFFF;
12855 map[7].address = oam;
12856 map[7].mask = 0x3FF;
12857 map[8].address = rom;
12858 map[8].mask = 0x1FFFFFF;
12859 map[9].address = rom;
12860 map[9].mask = 0x1FFFFFF;
12861 map[10].address = rom;
12862 map[10].mask = 0x1FFFFFF;
12863 map[12].address = rom;
12864 map[12].mask = 0x1FFFFFF;
12865 map[14].address = flashSaveMemory;
12866 map[14].mask = 0xFFFF;
12867
12868 eepromReset();
12869 flashReset();
12870
12871 soundReset();
12872
12873 CPUUpdateWindow0();
12874 CPUUpdateWindow1();
12875
12876 // make sure registers are correctly initialized if not using BIOS
12877 if(cpuIsMultiBoot)
12878 BIOS_RegisterRamReset(0xfe);
12879 else if(!useBios && !cpuIsMultiBoot)
12880 BIOS_RegisterRamReset(0xff);
12881
12882 switch(cpuSaveType) {
12883 case 0: // automatic
12884 cpuSramEnabled = true;
12885 cpuFlashEnabled = true;
12886 cpuEEPROMEnabled = true;
12887 saveType = gbaSaveType = 0;
12888 break;
12889 case 1: // EEPROM
12890 cpuSramEnabled = false;
12891 cpuFlashEnabled = false;
12892 cpuEEPROMEnabled = true;
12893 saveType = gbaSaveType = 3;
12894 // EEPROM usage is automatically detected
12895 break;
12896 case 2: // SRAM
12897 cpuSramEnabled = true;
12898 cpuFlashEnabled = false;
12899 cpuEEPROMEnabled = false;
12900 cpuSaveGameFunc = sramDelayedWrite; // to insure we detect the write
12901 saveType = gbaSaveType = 1;
12902 break;
12903 case 3: // FLASH
12904 cpuSramEnabled = false;
12905 cpuFlashEnabled = true;
12906 cpuEEPROMEnabled = false;
12907 cpuSaveGameFunc = flashDelayedWrite; // to insure we detect the write
12908 saveType = gbaSaveType = 2;
12909 break;
12910 case 4: // EEPROM+Sensor
12911 cpuSramEnabled = false;
12912 cpuFlashEnabled = false;
12913 cpuEEPROMEnabled = true;
12914 // EEPROM usage is automatically detected
12915 saveType = gbaSaveType = 3;
12916 break;
12917 case 5: // NONE
12918 cpuSramEnabled = false;
12919 cpuFlashEnabled = false;
12920 cpuEEPROMEnabled = false;
12921 // no save at all
12922 saveType = gbaSaveType = 5;
12923 break;
12924 }
12925
12926 ARM_PREFETCH;
12927
12928 #ifdef USE_SWITICKS
12929 SWITicks = 0;
12930 #endif
12931
12932 cpuDmaLast = 0;
12933 cpuDmaRunning = false;
12934 }
12935
CPUInterrupt(void)12936 static void CPUInterrupt(void)
12937 {
12938 uint32_t PC = bus.reg[15].I;
12939 bool savedState = armState;
12940
12941 if(armMode != 0x12 )
12942 CPUSwitchMode(0x12, true, false);
12943
12944 bus.reg[14].I = PC;
12945 if(!savedState)
12946 bus.reg[14].I += 2;
12947 bus.reg[15].I = 0x18;
12948 armState = true;
12949 armIrqEnable = false;
12950
12951 bus.armNextPC = bus.reg[15].I;
12952 bus.reg[15].I += 4;
12953 ARM_PREFETCH;
12954
12955 // if(!holdState)
12956 biosProtected[0] = 0x02;
12957 biosProtected[1] = 0xc0;
12958 biosProtected[2] = 0x5e;
12959 biosProtected[3] = 0xe5;
12960 }
12961
UpdateJoypad(void)12962 void UpdateJoypad(void)
12963 {
12964 /* update joystick information */
12965 io_registers[REG_P1] = 0x03FF ^ (joy & 0x3FF);
12966 #if USE_MOTION_SENSOR
12967 if(hardware.sensor) {
12968 systemUpdateMotionSensor();
12969 hardware.tilt_x = (systemGetAccelX() >> 21) + 0x3A0;
12970 hardware.tilt_y = (systemGetAccelY() >> 21) + 0x3A0;
12971 }
12972 #endif
12973 UPDATE_REG(0x130, io_registers[REG_P1]);
12974 io_registers[REG_P1CNT] = READ16LE(((uint16_t *)&ioMem[0x132]));
12975
12976 // this seems wrong, but there are cases where the game
12977 // can enter the stop state without requesting an IRQ from
12978 // the joypad.
12979 if((io_registers[REG_P1CNT] & 0x4000) || stopState) {
12980 uint16_t p1 = (0x3FF ^ io_registers[REG_P1CNT]) & 0x3FF;
12981 if(io_registers[REG_P1CNT] & 0x8000) {
12982 if(p1 == (io_registers[REG_P1CNT] & 0x3FF)) {
12983 io_registers[REG_IF] |= 0x1000;
12984 UPDATE_REG(0x202, io_registers[REG_IF]);
12985 }
12986 } else {
12987 if(p1 & io_registers[REG_P1CNT]) {
12988 io_registers[REG_IF] |= 0x1000;
12989 UPDATE_REG(0x202, io_registers[REG_IF]);
12990 }
12991 }
12992 }
12993 }
12994
CPULoop(void)12995 void CPULoop (void)
12996 {
12997 bool framedone;
12998 int timerOverflow = 0;
12999 int ticks = 300000;
13000
13001 bus.busPrefetchCount = 0;
13002 // variable used by the CPU core
13003 cpuTotalTicks = 0;
13004
13005 cpuNextEvent = CPUUpdateTicks();
13006 if(cpuNextEvent > ticks)
13007 cpuNextEvent = ticks;
13008
13009 framedone = false;
13010
13011 do
13012 {
13013 if(!holdState)
13014 {
13015 if(armState)
13016 {
13017 if (!armExecute())
13018 return;
13019 }
13020 else
13021 {
13022 if (!thumbExecute())
13023 return;
13024 }
13025 clockTicks = 0;
13026 }
13027 else
13028 clockTicks = CPUUpdateTicks();
13029
13030 cpuTotalTicks += clockTicks;
13031
13032 if(cpuTotalTicks >= cpuNextEvent) {
13033 int remainingTicks = cpuTotalTicks - cpuNextEvent;
13034
13035 #ifdef USE_SWITICKS
13036 if (SWITicks) {
13037 SWITicks-=clockTicks;
13038 if (SWITicks<0)
13039 SWITicks = 0;
13040 }
13041 #endif
13042
13043 clockTicks = cpuNextEvent;
13044 cpuTotalTicks = 0;
13045
13046 updateLoop:
13047
13048 if (IRQTicks) {
13049 IRQTicks -= clockTicks;
13050 if (IRQTicks<0)
13051 IRQTicks = 0;
13052 }
13053
13054 graphics.lcdTicks -= clockTicks;
13055
13056 if(graphics.lcdTicks <= 0)
13057 {
13058 if(io_registers[REG_DISPSTAT] & 1)
13059 { // V-BLANK
13060 // if in V-Blank mode, keep computing...
13061 if(io_registers[REG_DISPSTAT] & 2)
13062 {
13063 graphics.lcdTicks += 1008;
13064 R_VCOUNT += 1;
13065 UPDATE_REG(0x06, R_VCOUNT);
13066 io_registers[REG_DISPSTAT] &= 0xFFFD;
13067 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
13068 CPUCompareVCOUNT();
13069 }
13070 else
13071 {
13072 graphics.lcdTicks += 224;
13073 io_registers[REG_DISPSTAT] |= 2;
13074 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
13075 if(io_registers[REG_DISPSTAT] & 16)
13076 {
13077 io_registers[REG_IF] |= 2;
13078 UPDATE_REG(0x202, io_registers[REG_IF]);
13079 }
13080 }
13081
13082 if(R_VCOUNT >= 228)
13083 {
13084 //Reaching last line
13085 io_registers[REG_DISPSTAT] &= 0xFFFC;
13086 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
13087 R_VCOUNT = 0;
13088 UPDATE_REG(0x06, R_VCOUNT);
13089 CPUCompareVCOUNT();
13090 }
13091 }
13092 else if(io_registers[REG_DISPSTAT] & 2)
13093 {
13094 // if in H-Blank, leave it and move to drawing mode
13095 R_VCOUNT += 1;
13096 UPDATE_REG(0x06, R_VCOUNT);
13097
13098 graphics.lcdTicks += 1008;
13099 io_registers[REG_DISPSTAT] &= 0xFFFD;
13100
13101 if(R_VCOUNT == 160)
13102 {
13103 uint32_t ext = (joy >> 10);
13104 // If no (m) code is enabled, apply the cheats at each LCDline
13105 #if USE_CHEATS
13106 if(mastercode == 0)
13107 remainingTicks += cheatsCheckKeys(io_registers[REG_P1] ^ 0x3FF, ext);
13108 #endif
13109 io_registers[REG_DISPSTAT] |= 1;
13110 io_registers[REG_DISPSTAT] &= 0xFFFD;
13111 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
13112 if(io_registers[REG_DISPSTAT] & 0x0008)
13113 {
13114 io_registers[REG_IF] |= 1;
13115 UPDATE_REG(0x202, io_registers[REG_IF]);
13116 }
13117 CPUCheckDMA(1, 0x0f);
13118
13119 #if !THREADED_RENDERER
13120 systemDrawScreen();
13121 #endif
13122
13123 #if USE_FRAME_SKIP
13124 ++fs_count;
13125
13126 if(fs_type_b == 0) {
13127 fs_draw = true;
13128 } else {
13129 if(fs_type_a > 0) {
13130 fs_draw = (fs_count % (fs_type_b + 1));
13131 } else {
13132 fs_draw = ((fs_count % (fs_type_b + 1)) == 0);
13133 }
13134 }
13135 #endif
13136 framedone = true;
13137 }
13138
13139 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
13140 CPUCompareVCOUNT();
13141 }
13142 else
13143 {
13144 #if USE_FRAME_SKIP
13145 if(fs_draw) {
13146 #endif
13147 #if THREADED_RENDERER
13148 postRender();
13149 #else
13150 bool draw_objwin = (graphics.layerEnable & 0x9000) == 0x9000;
13151 bool draw_sprites = R_DISPCNT_Screen_Display_OBJ;
13152
13153 memset(RENDERER_LINE[Layer_OBJ], -1, 240 * sizeof(u32)); // erase all sprites
13154 if(draw_sprites) gfxDrawSprites<0>();
13155
13156 if(renderfunc_type == 2) {
13157 memset(RENDERER_LINE[Layer_WIN_OBJ], -1, 240 * sizeof(u32)); // erase all OBJ Win
13158 if(draw_objwin) gfxDrawOBJWin<0>();
13159 }
13160
13161 GetRenderFunc<0>(renderfunc_mode, renderfunc_type)();
13162 #endif
13163 #if USE_FRAME_SKIP
13164 }
13165 #endif
13166
13167 // entering H-Blank
13168 io_registers[REG_DISPSTAT] |= 2;
13169 UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
13170 graphics.lcdTicks += 224;
13171 CPUCheckDMA(2, 0x0f);
13172 if(io_registers[REG_DISPSTAT] & 16)
13173 {
13174 io_registers[REG_IF] |= 2;
13175 UPDATE_REG(0x202, io_registers[REG_IF]);
13176 }
13177 }
13178 }
13179
13180 // we shouldn't be doing sound in stop state, but we lose synchronization
13181 // if sound is disabled, so in stop state, soundTick will just produce
13182 // mute sound
13183 soundTicks -= clockTicks;
13184 if(!soundTicks)
13185 {
13186 process_sound_tick_fn();
13187 soundTicks += SOUND_CLOCK_TICKS;
13188 }
13189
13190 if(!stopState) {
13191 if(timer0On) {
13192 timer0Ticks -= clockTicks;
13193 if(timer0Ticks <= 0) {
13194 timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload;
13195 timerOverflow |= 1;
13196 soundTimerOverflow(0);
13197 if(io_registers[REG_TM0CNT] & 0x40) {
13198 io_registers[REG_IF] |= 0x08;
13199 UPDATE_REG(0x202, io_registers[REG_IF]);
13200 }
13201 }
13202 io_registers[REG_TM0D] = 0xFFFF - (timer0Ticks >> timer0ClockReload);
13203 UPDATE_REG(0x100, io_registers[REG_TM0D]);
13204 }
13205
13206 if(timer1On) {
13207 if(io_registers[REG_TM1CNT] & 4) {
13208 if(timerOverflow & 1) {
13209 io_registers[REG_TM1D]++;
13210 if(io_registers[REG_TM1D] == 0) {
13211 io_registers[REG_TM1D] += timer1Reload;
13212 timerOverflow |= 2;
13213 soundTimerOverflow(1);
13214 if(io_registers[REG_TM1CNT] & 0x40) {
13215 io_registers[REG_IF] |= 0x10;
13216 UPDATE_REG(0x202, io_registers[REG_IF]);
13217 }
13218 }
13219 UPDATE_REG(0x104, io_registers[REG_TM1D]);
13220 }
13221 } else {
13222 timer1Ticks -= clockTicks;
13223 if(timer1Ticks <= 0) {
13224 timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload;
13225 timerOverflow |= 2;
13226 soundTimerOverflow(1);
13227 if(io_registers[REG_TM1CNT] & 0x40) {
13228 io_registers[REG_IF] |= 0x10;
13229 UPDATE_REG(0x202, io_registers[REG_IF]);
13230 }
13231 }
13232 io_registers[REG_TM1D] = 0xFFFF - (timer1Ticks >> timer1ClockReload);
13233 UPDATE_REG(0x104, io_registers[REG_TM1D]);
13234 }
13235 }
13236
13237 if(timer2On) {
13238 if(io_registers[REG_TM2CNT] & 4) {
13239 if(timerOverflow & 2) {
13240 io_registers[REG_TM2D]++;
13241 if(io_registers[REG_TM2D] == 0) {
13242 io_registers[REG_TM2D] += timer2Reload;
13243 timerOverflow |= 4;
13244 if(io_registers[REG_TM2CNT] & 0x40) {
13245 io_registers[REG_IF] |= 0x20;
13246 UPDATE_REG(0x202, io_registers[REG_IF]);
13247 }
13248 }
13249 UPDATE_REG(0x108, io_registers[REG_TM2D]);
13250 }
13251 } else {
13252 timer2Ticks -= clockTicks;
13253 if(timer2Ticks <= 0) {
13254 timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload;
13255 timerOverflow |= 4;
13256 if(io_registers[REG_TM2CNT] & 0x40) {
13257 io_registers[REG_IF] |= 0x20;
13258 UPDATE_REG(0x202, io_registers[REG_IF]);
13259 }
13260 }
13261 io_registers[REG_TM2D] = 0xFFFF - (timer2Ticks >> timer2ClockReload);
13262 UPDATE_REG(0x108, io_registers[REG_TM2D]);
13263 }
13264 }
13265
13266 if(timer3On) {
13267 if(io_registers[REG_TM3CNT] & 4) {
13268 if(timerOverflow & 4) {
13269 io_registers[REG_TM3D]++;
13270 if(io_registers[REG_TM3D] == 0) {
13271 io_registers[REG_TM3D] += timer3Reload;
13272 if(io_registers[REG_TM3CNT] & 0x40) {
13273 io_registers[REG_IF] |= 0x40;
13274 UPDATE_REG(0x202, io_registers[REG_IF]);
13275 }
13276 }
13277 UPDATE_REG(0x10C, io_registers[REG_TM3D]);
13278 }
13279 } else {
13280 timer3Ticks -= clockTicks;
13281 if(timer3Ticks <= 0) {
13282 timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload;
13283 if(io_registers[REG_TM3CNT] & 0x40) {
13284 io_registers[REG_IF] |= 0x40;
13285 UPDATE_REG(0x202, io_registers[REG_IF]);
13286 }
13287 }
13288 io_registers[REG_TM3D] = 0xFFFF - (timer3Ticks >> timer3ClockReload);
13289 UPDATE_REG(0x10C, io_registers[REG_TM3D]);
13290 }
13291 }
13292 }
13293
13294 timerOverflow = 0;
13295 ticks -= clockTicks;
13296 cpuNextEvent = CPUUpdateTicks();
13297
13298 if(cpuDmaTicksToUpdate > 0)
13299 {
13300 if(cpuDmaTicksToUpdate > cpuNextEvent)
13301 clockTicks = cpuNextEvent;
13302 else
13303 clockTicks = cpuDmaTicksToUpdate;
13304 cpuDmaTicksToUpdate -= clockTicks;
13305 if(cpuDmaTicksToUpdate < 0)
13306 cpuDmaTicksToUpdate = 0;
13307 goto updateLoop;
13308 }
13309
13310 if(io_registers[REG_IF] && (io_registers[REG_IME] & 1) && armIrqEnable)
13311 {
13312 int res = io_registers[REG_IF] & io_registers[REG_IE];
13313 if(stopState)
13314 res &= 0x3080;
13315 if(res)
13316 {
13317 if (intState)
13318 {
13319 if (!IRQTicks)
13320 {
13321 CPUInterrupt();
13322 intState = false;
13323 holdState = false;
13324 stopState = false;
13325 }
13326 }
13327 else
13328 {
13329 if (!holdState)
13330 {
13331 intState = true;
13332 IRQTicks=7;
13333 if (cpuNextEvent> IRQTicks)
13334 cpuNextEvent = IRQTicks;
13335 }
13336 else
13337 {
13338 CPUInterrupt();
13339 holdState = false;
13340 stopState = false;
13341 }
13342 }
13343
13344 #ifdef USE_SWITICKS
13345 // Stops the SWI Ticks emulation if an IRQ is executed
13346 //(to avoid problems with nested IRQ/SWI)
13347 if (SWITicks)
13348 SWITicks = 0;
13349 #endif
13350 }
13351 }
13352
13353 if(remainingTicks > 0) {
13354 if(remainingTicks > cpuNextEvent)
13355 clockTicks = cpuNextEvent;
13356 else
13357 clockTicks = remainingTicks;
13358 remainingTicks -= clockTicks;
13359 if(remainingTicks < 0)
13360 remainingTicks = 0;
13361 goto updateLoop;
13362 }
13363
13364 if (timerOnOffDelay)
13365 {
13366 // Apply Timer
13367 if (timerOnOffDelay & 1)
13368 {
13369 timer0ClockReload = TIMER_TICKS[timer0Value & 3];
13370 if(!timer0On && (timer0Value & 0x80)) {
13371 // reload the counter
13372 io_registers[REG_TM0D] = timer0Reload;
13373 timer0Ticks = (0x10000 - io_registers[REG_TM0D]) << timer0ClockReload;
13374 UPDATE_REG(0x100, io_registers[REG_TM0D]);
13375 }
13376 timer0On = timer0Value & 0x80 ? true : false;
13377 io_registers[REG_TM0CNT] = timer0Value & 0xC7;
13378 UPDATE_REG(0x102, io_registers[REG_TM0CNT]);
13379 }
13380 if (timerOnOffDelay & 2)
13381 {
13382 timer1ClockReload = TIMER_TICKS[timer1Value & 3];
13383 if(!timer1On && (timer1Value & 0x80)) {
13384 // reload the counter
13385 io_registers[REG_TM1D] = timer1Reload;
13386 timer1Ticks = (0x10000 - io_registers[REG_TM1D]) << timer1ClockReload;
13387 UPDATE_REG(0x104, io_registers[REG_TM1D]);
13388 }
13389 timer1On = timer1Value & 0x80 ? true : false;
13390 io_registers[REG_TM1CNT] = timer1Value & 0xC7;
13391 UPDATE_REG(0x106, io_registers[REG_TM1CNT]);
13392 }
13393 if (timerOnOffDelay & 4)
13394 {
13395 timer2ClockReload = TIMER_TICKS[timer2Value & 3];
13396 if(!timer2On && (timer2Value & 0x80)) {
13397 // reload the counter
13398 io_registers[REG_TM2D] = timer2Reload;
13399 timer2Ticks = (0x10000 - io_registers[REG_TM2D]) << timer2ClockReload;
13400 UPDATE_REG(0x108, io_registers[REG_TM2D]);
13401 }
13402 timer2On = timer2Value & 0x80 ? true : false;
13403 io_registers[REG_TM2CNT] = timer2Value & 0xC7;
13404 UPDATE_REG(0x10A, io_registers[REG_TM2CNT]);
13405 }
13406 if (timerOnOffDelay & 8)
13407 {
13408 timer3ClockReload = TIMER_TICKS[timer3Value & 3];
13409 if(!timer3On && (timer3Value & 0x80)) {
13410 // reload the counter
13411 io_registers[REG_TM3D] = timer3Reload;
13412 timer3Ticks = (0x10000 - io_registers[REG_TM3D]) << timer3ClockReload;
13413 UPDATE_REG(0x10C, io_registers[REG_TM3D]);
13414 }
13415 timer3On = timer3Value & 0x80 ? true : false;
13416 io_registers[REG_TM3CNT] = timer3Value & 0xC7;
13417 UPDATE_REG(0x10E, io_registers[REG_TM3CNT]);
13418 }
13419 cpuNextEvent = CPUUpdateTicks();
13420 timerOnOffDelay = 0;
13421 // End of Apply Timer
13422 }
13423
13424 if(cpuNextEvent > ticks)
13425 cpuNextEvent = ticks;
13426
13427 if(ticks <= 0 || framedone)
13428 break;
13429 }
13430 } while(1);
13431 }
13432
13433 /* GBA CHEATS */
13434
13435 /**
13436 * Gameshark code types: (based on AR v1.0)
13437 *
13438 * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM
13439 * DEADFACE XXXXXXXX - changes decryption seeds // Not supported by VBA.
13440 * 0AAAAAAA 000000YY - 8-bit constant write
13441 * 1AAAAAAA 0000YYYY - 16-bit constant write
13442 * 2AAAAAAA YYYYYYYY - 32-bit constant write
13443 * 30XXAAAA YYYYYYYY - 32bit Group Write, 8/16/32bit Sub/Add (depending on the XX value).
13444 * 6AAAAAAA Z000YYYY - 16-bit ROM Patch (address >> 1). Z selects the Rom Patching register.
13445 * - AR v1/2 hardware only supports Z=0.
13446 * - AR v3 hardware should support Z=0,1,2 or 3.
13447 * 8A1AAAAA 000000YY - 8-bit button write
13448 * 8A2AAAAA 0000YYYY - 16-bit button write
13449 * 8A4AAAAA YYYYYYYY - 32-bit button write // BUGGY ! Only writes 00000000 on the AR v1.0.
13450 * 80F00000 0000YYYY - button slow motion
13451 * DAAAAAAA 00Z0YYYY - Z = 0 : if 16-bit value at address != YYYY skip next line
13452 * - Z = 1 : if 16-bit value at address == YYYY skip next line
13453 * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip next line
13454 * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip next line
13455 * E0CCYYYY ZAAAAAAA - Z = 0 : if 16-bit value at address != YYYY skip CC lines
13456 * - Z = 1 : if 16-bit value at address == YYYY skip CC lines
13457 * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip CC lines
13458 * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip CC lines
13459 * FAAAAAAA 0000YYYY - Master code function
13460 *
13461 *
13462 *
13463 * CodeBreaker codes types: (based on the CBA clone "Cheatcode S" v1.1)
13464 *
13465 * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI)
13466 * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16)
13467 * + 0x08000100))
13468 * 2AAAAAAA YYYY - 16-bit or
13469 * 3AAAAAAA YYYY - 8-bit constant write
13470 * 4AAAAAAA YYYY - Slide code
13471 * XXXXCCCC IIII (C is count and I is address increment, X is value incr.)
13472 * 5AAAAAAA CCCC - Super code (Write bytes to address, 2*CCCC is count)
13473 * BBBBBBBB BBBB
13474 * 6AAAAAAA YYYY - 16-bit and
13475 * 7AAAAAAA YYYY - if address contains 16-bit value enable next code
13476 * 8AAAAAAA YYYY - 16-bit constant write
13477 * 9AAAAAAA YYYY - change decryption (when first code only?)
13478 * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code
13479 * BAAAAAAA YYYY - if 16-bit value at address <= YYYY skip next code
13480 * CAAAAAAA YYYY - if 16-bit value at address >= YYYY skip next code
13481 * D00000X0 YYYY - if button keys ... enable next code (else skip next code)
13482 * EAAAAAAA YYYY - increase 16/32bit value stored in address
13483 * FAAAAAAA YYYY - if 16-bit value at address AND YYYY = 0 then skip next code
13484 **/
13485
13486 #define UNKNOWN_CODE -1
13487 #define INT_8_BIT_WRITE 0
13488 #define INT_16_BIT_WRITE 1
13489 #define INT_32_BIT_WRITE 2
13490 #define GSA_16_BIT_ROM_PATCH 3
13491 #define GSA_8_BIT_GS_WRITE 4
13492 #define GSA_16_BIT_GS_WRITE 5
13493 #define GSA_32_BIT_GS_WRITE 6
13494 #define CBA_IF_KEYS_PRESSED 7
13495 #define CBA_IF_TRUE 8
13496 #define CBA_SLIDE_CODE 9
13497 #define CBA_IF_FALSE 10
13498 #define CBA_AND 11
13499 #define GSA_8_BIT_GS_WRITE2 12
13500 #define GSA_16_BIT_GS_WRITE2 13
13501 #define GSA_32_BIT_GS_WRITE2 14
13502 #define GSA_16_BIT_ROM_PATCH2C 15
13503 #define GSA_8_BIT_SLIDE 16
13504 #define GSA_16_BIT_SLIDE 17
13505 #define GSA_32_BIT_SLIDE 18
13506 #define GSA_8_BIT_IF_TRUE 19
13507 #define GSA_32_BIT_IF_TRUE 20
13508 #define GSA_8_BIT_IF_FALSE 21
13509 #define GSA_32_BIT_IF_FALSE 22
13510 #define GSA_8_BIT_FILL 23
13511 #define GSA_16_BIT_FILL 24
13512 #define GSA_8_BIT_IF_TRUE2 25
13513 #define GSA_16_BIT_IF_TRUE2 26
13514 #define GSA_32_BIT_IF_TRUE2 27
13515 #define GSA_8_BIT_IF_FALSE2 28
13516 #define GSA_16_BIT_IF_FALSE2 29
13517 #define GSA_32_BIT_IF_FALSE2 30
13518 #define GSA_SLOWDOWN 31
13519 #define CBA_ADD 32
13520 #define CBA_OR 33
13521 #define CBA_LT 34
13522 #define CBA_GT 35
13523 #define CBA_SUPER 36
13524 #define GSA_8_BIT_POINTER 37
13525 #define GSA_16_BIT_POINTER 38
13526 #define GSA_32_BIT_POINTER 39
13527 #define GSA_8_BIT_ADD 40
13528 #define GSA_16_BIT_ADD 41
13529 #define GSA_32_BIT_ADD 42
13530 #define GSA_8_BIT_IF_LOWER_U 43
13531 #define GSA_16_BIT_IF_LOWER_U 44
13532 #define GSA_32_BIT_IF_LOWER_U 45
13533 #define GSA_8_BIT_IF_HIGHER_U 46
13534 #define GSA_16_BIT_IF_HIGHER_U 47
13535 #define GSA_32_BIT_IF_HIGHER_U 48
13536 #define GSA_8_BIT_IF_AND 49
13537 #define GSA_16_BIT_IF_AND 50
13538 #define GSA_32_BIT_IF_AND 51
13539 #define GSA_8_BIT_IF_LOWER_U2 52
13540 #define GSA_16_BIT_IF_LOWER_U2 53
13541 #define GSA_32_BIT_IF_LOWER_U2 54
13542 #define GSA_8_BIT_IF_HIGHER_U2 55
13543 #define GSA_16_BIT_IF_HIGHER_U2 56
13544 #define GSA_32_BIT_IF_HIGHER_U2 57
13545 #define GSA_8_BIT_IF_AND2 58
13546 #define GSA_16_BIT_IF_AND2 59
13547 #define GSA_32_BIT_IF_AND2 60
13548 #define GSA_ALWAYS 61
13549 #define GSA_ALWAYS2 62
13550 #define GSA_8_BIT_IF_LOWER_S 63
13551 #define GSA_16_BIT_IF_LOWER_S 64
13552 #define GSA_32_BIT_IF_LOWER_S 65
13553 #define GSA_8_BIT_IF_HIGHER_S 66
13554 #define GSA_16_BIT_IF_HIGHER_S 67
13555 #define GSA_32_BIT_IF_HIGHER_S 68
13556 #define GSA_8_BIT_IF_LOWER_S2 69
13557 #define GSA_16_BIT_IF_LOWER_S2 70
13558 #define GSA_32_BIT_IF_LOWER_S2 71
13559 #define GSA_8_BIT_IF_HIGHER_S2 72
13560 #define GSA_16_BIT_IF_HIGHER_S2 73
13561 #define GSA_32_BIT_IF_HIGHER_S2 74
13562 #define GSA_16_BIT_WRITE_IOREGS 75
13563 #define GSA_32_BIT_WRITE_IOREGS 76
13564 #define GSA_CODES_ON 77
13565 #define GSA_8_BIT_IF_TRUE3 78
13566 #define GSA_16_BIT_IF_TRUE3 79
13567 #define GSA_32_BIT_IF_TRUE3 80
13568 #define GSA_8_BIT_IF_FALSE3 81
13569 #define GSA_16_BIT_IF_FALSE3 82
13570 #define GSA_32_BIT_IF_FALSE3 83
13571 #define GSA_8_BIT_IF_LOWER_S3 84
13572 #define GSA_16_BIT_IF_LOWER_S3 85
13573 #define GSA_32_BIT_IF_LOWER_S3 86
13574 #define GSA_8_BIT_IF_HIGHER_S3 87
13575 #define GSA_16_BIT_IF_HIGHER_S3 88
13576 #define GSA_32_BIT_IF_HIGHER_S3 89
13577 #define GSA_8_BIT_IF_LOWER_U3 90
13578 #define GSA_16_BIT_IF_LOWER_U3 91
13579 #define GSA_32_BIT_IF_LOWER_U3 92
13580 #define GSA_8_BIT_IF_HIGHER_U3 93
13581 #define GSA_16_BIT_IF_HIGHER_U3 94
13582 #define GSA_32_BIT_IF_HIGHER_U3 95
13583 #define GSA_8_BIT_IF_AND3 96
13584 #define GSA_16_BIT_IF_AND3 97
13585 #define GSA_32_BIT_IF_AND3 98
13586 #define GSA_ALWAYS3 99
13587 #define GSA_16_BIT_ROM_PATCH2D 100
13588 #define GSA_16_BIT_ROM_PATCH2E 101
13589 #define GSA_16_BIT_ROM_PATCH2F 102
13590 #define GSA_GROUP_WRITE 103
13591 #define GSA_32_BIT_ADD2 104
13592 #define GSA_32_BIT_SUB2 105
13593 #define GSA_16_BIT_IF_LOWER_OR_EQ_U 106
13594 #define GSA_16_BIT_IF_HIGHER_OR_EQ_U 107
13595 #define GSA_16_BIT_MIF_TRUE 108
13596 #define GSA_16_BIT_MIF_FALSE 109
13597 #define GSA_16_BIT_MIF_LOWER_OR_EQ_U 110
13598 #define GSA_16_BIT_MIF_HIGHER_OR_EQ_U 111
13599 #define MASTER_CODE 112
13600 #define CHEATS_16_BIT_WRITE 114
13601 #define CHEATS_32_BIT_WRITE 115
13602
13603 CheatsData cheatsList[100];
13604 int cheatsNumber = 0;
13605 u32 rompatch2addr [4];
13606 u16 rompatch2val [4];
13607 u16 rompatch2oldval [4];
13608
13609 u8 cheatsCBASeedBuffer[0x30];
13610 u32 cheatsCBASeed[4];
13611 u32 cheatsCBATemporaryValue = 0;
13612 u16 cheatsCBATable[256];
13613 bool cheatsCBATableGenerated = false;
13614 u16 super = 0;
13615 extern u32 mastercode;
13616
13617 #if (0)
13618 extern GameStorage xStorage;
13619 #endif
13620
13621 u8 cheatsCBACurrentSeed[12] = {
13622 0x00, 0x00, 0x00, 0x00,
13623 0x00, 0x00, 0x00, 0x00,
13624 0x00, 0x00, 0x00, 0x00
13625 };
13626
13627 u32 seeds_v1[4];
13628 u32 seeds_v3[4];
13629
13630 u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2);
13631
13632 //seed tables for AR v1
13633 u8 v1_deadtable1[256] = {
13634 0x31, 0x1C, 0x23, 0xE5, 0x89, 0x8E, 0xA1, 0x37, 0x74, 0x6D, 0x67, 0xFC, 0x1F, 0xC0, 0xB1, 0x94,
13635 0x3B, 0x05, 0x56, 0x86, 0x00, 0x24, 0xF0, 0x17, 0x72, 0xA2, 0x3D, 0x1B, 0xE3, 0x17, 0xC5, 0x0B,
13636 0xB9, 0xE2, 0xBD, 0x58, 0x71, 0x1B, 0x2C, 0xFF, 0xE4, 0xC9, 0x4C, 0x5E, 0xC9, 0x55, 0x33, 0x45,
13637 0x7C, 0x3F, 0xB2, 0x51, 0xFE, 0x10, 0x7E, 0x75, 0x3C, 0x90, 0x8D, 0xDA, 0x94, 0x38, 0xC3, 0xE9,
13638 0x95, 0xEA, 0xCE, 0xA6, 0x06, 0xE0, 0x4F, 0x3F, 0x2A, 0xE3, 0x3A, 0xE4, 0x43, 0xBD, 0x7F, 0xDA,
13639 0x55, 0xF0, 0xEA, 0xCB, 0x2C, 0xA8, 0x47, 0x61, 0xA0, 0xEF, 0xCB, 0x13, 0x18, 0x20, 0xAF, 0x3E,
13640 0x4D, 0x9E, 0x1E, 0x77, 0x51, 0xC5, 0x51, 0x20, 0xCF, 0x21, 0xF9, 0x39, 0x94, 0xDE, 0xDD, 0x79,
13641 0x4E, 0x80, 0xC4, 0x9D, 0x94, 0xD5, 0x95, 0x01, 0x27, 0x27, 0xBD, 0x6D, 0x78, 0xB5, 0xD1, 0x31,
13642 0x6A, 0x65, 0x74, 0x74, 0x58, 0xB3, 0x7C, 0xC9, 0x5A, 0xED, 0x50, 0x03, 0xC4, 0xA2, 0x94, 0x4B,
13643 0xF0, 0x58, 0x09, 0x6F, 0x3E, 0x7D, 0xAE, 0x7D, 0x58, 0xA0, 0x2C, 0x91, 0xBB, 0xE1, 0x70, 0xEB,
13644 0x73, 0xA6, 0x9A, 0x44, 0x25, 0x90, 0x16, 0x62, 0x53, 0xAE, 0x08, 0xEB, 0xDC, 0xF0, 0xEE, 0x77,
13645 0xC2, 0xDE, 0x81, 0xE8, 0x30, 0x89, 0xDB, 0xFE, 0xBC, 0xC2, 0xDF, 0x26, 0xE9, 0x8B, 0xD6, 0x93,
13646 0xF0, 0xCB, 0x56, 0x90, 0xC0, 0x46, 0x68, 0x15, 0x43, 0xCB, 0xE9, 0x98, 0xE3, 0xAF, 0x31, 0x25,
13647 0x4D, 0x7B, 0xF3, 0xB1, 0x74, 0xE2, 0x64, 0xAC, 0xD9, 0xF6, 0xA0, 0xD5, 0x0B, 0x9B, 0x49, 0x52,
13648 0x69, 0x3B, 0x71, 0x00, 0x2F, 0xBB, 0xBA, 0x08, 0xB1, 0xAE, 0xBB, 0xB3, 0xE1, 0xC9, 0xA6, 0x7F,
13649 0x17, 0x97, 0x28, 0x72, 0x12, 0x6E, 0x91, 0xAE, 0x3A, 0xA2, 0x35, 0x46, 0x27, 0xF8, 0x12, 0x50
13650 };
13651 u8 v1_deadtable2[256] = {
13652 0xD8, 0x65, 0x04, 0xC2, 0x65, 0xD5, 0xB0, 0x0C, 0xDF, 0x9D, 0xF0, 0xC3, 0x9A, 0x17, 0xC9, 0xA6,
13653 0xE1, 0xAC, 0x0D, 0x14, 0x2F, 0x3C, 0x2C, 0x87, 0xA2, 0xBF, 0x4D, 0x5F, 0xAC, 0x2D, 0x9D, 0xE1,
13654 0x0C, 0x9C, 0xE7, 0x7F, 0xFC, 0xA8, 0x66, 0x59, 0xAC, 0x18, 0xD7, 0x05, 0xF0, 0xBF, 0xD1, 0x8B,
13655 0x35, 0x9F, 0x59, 0xB4, 0xBA, 0x55, 0xB2, 0x85, 0xFD, 0xB1, 0x72, 0x06, 0x73, 0xA4, 0xDB, 0x48,
13656 0x7B, 0x5F, 0x67, 0xA5, 0x95, 0xB9, 0xA5, 0x4A, 0xCF, 0xD1, 0x44, 0xF3, 0x81, 0xF5, 0x6D, 0xF6,
13657 0x3A, 0xC3, 0x57, 0x83, 0xFA, 0x8E, 0x15, 0x2A, 0xA2, 0x04, 0xB2, 0x9D, 0xA8, 0x0D, 0x7F, 0xB8,
13658 0x0F, 0xF6, 0xAC, 0xBE, 0x97, 0xCE, 0x16, 0xE6, 0x31, 0x10, 0x60, 0x16, 0xB5, 0x83, 0x45, 0xEE,
13659 0xD7, 0x5F, 0x2C, 0x08, 0x58, 0xB1, 0xFD, 0x7E, 0x79, 0x00, 0x34, 0xAD, 0xB5, 0x31, 0x34, 0x39,
13660 0xAF, 0xA8, 0xDD, 0x52, 0x6A, 0xB0, 0x60, 0x35, 0xB8, 0x1D, 0x52, 0xF5, 0xF5, 0x30, 0x00, 0x7B,
13661 0xF4, 0xBA, 0x03, 0xCB, 0x3A, 0x84, 0x14, 0x8A, 0x6A, 0xEF, 0x21, 0xBD, 0x01, 0xD8, 0xA0, 0xD4,
13662 0x43, 0xBE, 0x23, 0xE7, 0x76, 0x27, 0x2C, 0x3F, 0x4D, 0x3F, 0x43, 0x18, 0xA7, 0xC3, 0x47, 0xA5,
13663 0x7A, 0x1D, 0x02, 0x55, 0x09, 0xD1, 0xFF, 0x55, 0x5E, 0x17, 0xA0, 0x56, 0xF4, 0xC9, 0x6B, 0x90,
13664 0xB4, 0x80, 0xA5, 0x07, 0x22, 0xFB, 0x22, 0x0D, 0xD9, 0xC0, 0x5B, 0x08, 0x35, 0x05, 0xC1, 0x75,
13665 0x4F, 0xD0, 0x51, 0x2D, 0x2E, 0x5E, 0x69, 0xE7, 0x3B, 0xC2, 0xDA, 0xFF, 0xF6, 0xCE, 0x3E, 0x76,
13666 0xE8, 0x36, 0x8C, 0x39, 0xD8, 0xF3, 0xE9, 0xA6, 0x42, 0xE6, 0xC1, 0x4C, 0x05, 0xBE, 0x17, 0xF2,
13667 0x5C, 0x1B, 0x19, 0xDB, 0x0F, 0xF3, 0xF8, 0x49, 0xEB, 0x36, 0xF6, 0x40, 0x6F, 0xAD, 0xC1, 0x8C
13668 };
13669
13670 //seed tables for AR v3
13671 u8 v3_deadtable1[256] = {
13672 0xD0, 0xFF, 0xBA, 0xE5, 0xC1, 0xC7, 0xDB, 0x5B, 0x16, 0xE3, 0x6E, 0x26, 0x62, 0x31, 0x2E, 0x2A,
13673 0xD1, 0xBB, 0x4A, 0xE6, 0xAE, 0x2F, 0x0A, 0x90, 0x29, 0x90, 0xB6, 0x67, 0x58, 0x2A, 0xB4, 0x45,
13674 0x7B, 0xCB, 0xF0, 0x73, 0x84, 0x30, 0x81, 0xC2, 0xD7, 0xBE, 0x89, 0xD7, 0x4E, 0x73, 0x5C, 0xC7,
13675 0x80, 0x1B, 0xE5, 0xE4, 0x43, 0xC7, 0x46, 0xD6, 0x6F, 0x7B, 0xBF, 0xED, 0xE5, 0x27, 0xD1, 0xB5,
13676 0xD0, 0xD8, 0xA3, 0xCB, 0x2B, 0x30, 0xA4, 0xF0, 0x84, 0x14, 0x72, 0x5C, 0xFF, 0xA4, 0xFB, 0x54,
13677 0x9D, 0x70, 0xE2, 0xFF, 0xBE, 0xE8, 0x24, 0x76, 0xE5, 0x15, 0xFB, 0x1A, 0xBC, 0x87, 0x02, 0x2A,
13678 0x58, 0x8F, 0x9A, 0x95, 0xBD, 0xAE, 0x8D, 0x0C, 0xA5, 0x4C, 0xF2, 0x5C, 0x7D, 0xAD, 0x51, 0xFB,
13679 0xB1, 0x22, 0x07, 0xE0, 0x29, 0x7C, 0xEB, 0x98, 0x14, 0xC6, 0x31, 0x97, 0xE4, 0x34, 0x8F, 0xCC,
13680 0x99, 0x56, 0x9F, 0x78, 0x43, 0x91, 0x85, 0x3F, 0xC2, 0xD0, 0xD1, 0x80, 0xD1, 0x77, 0xA7, 0xE2,
13681 0x43, 0x99, 0x1D, 0x2F, 0x8B, 0x6A, 0xE4, 0x66, 0x82, 0xF7, 0x2B, 0x0B, 0x65, 0x14, 0xC0, 0xC2,
13682 0x1D, 0x96, 0x78, 0x1C, 0xC4, 0xC3, 0xD2, 0xB1, 0x64, 0x07, 0xD7, 0x6F, 0x02, 0xE9, 0x44, 0x31,
13683 0xDB, 0x3C, 0xEB, 0x93, 0xED, 0x9A, 0x57, 0x05, 0xB9, 0x0E, 0xAF, 0x1F, 0x48, 0x11, 0xDC, 0x35,
13684 0x6C, 0xB8, 0xEE, 0x2A, 0x48, 0x2B, 0xBC, 0x89, 0x12, 0x59, 0xCB, 0xD1, 0x18, 0xEA, 0x72, 0x11,
13685 0x01, 0x75, 0x3B, 0xB5, 0x56, 0xF4, 0x8B, 0xA0, 0x41, 0x75, 0x86, 0x7B, 0x94, 0x12, 0x2D, 0x4C,
13686 0x0C, 0x22, 0xC9, 0x4A, 0xD8, 0xB1, 0x8D, 0xF0, 0x55, 0x2E, 0x77, 0x50, 0x1C, 0x64, 0x77, 0xAA,
13687 0x3E, 0xAC, 0xD3, 0x3D, 0xCE, 0x60, 0xCA, 0x5D, 0xA0, 0x92, 0x78, 0xC6, 0x51, 0xFE, 0xF9, 0x30
13688 };
13689 u8 v3_deadtable2[256] = {
13690 0xAA, 0xAF, 0xF0, 0x72, 0x90, 0xF7, 0x71, 0x27, 0x06, 0x11, 0xEB, 0x9C, 0x37, 0x12, 0x72, 0xAA,
13691 0x65, 0xBC, 0x0D, 0x4A, 0x76, 0xF6, 0x5C, 0xAA, 0xB0, 0x7A, 0x7D, 0x81, 0xC1, 0xCE, 0x2F, 0x9F,
13692 0x02, 0x75, 0x38, 0xC8, 0xFC, 0x66, 0x05, 0xC2, 0x2C, 0xBD, 0x91, 0xAD, 0x03, 0xB1, 0x88, 0x93,
13693 0x31, 0xC6, 0xAB, 0x40, 0x23, 0x43, 0x76, 0x54, 0xCA, 0xE7, 0x00, 0x96, 0x9F, 0xD8, 0x24, 0x8B,
13694 0xE4, 0xDC, 0xDE, 0x48, 0x2C, 0xCB, 0xF7, 0x84, 0x1D, 0x45, 0xE5, 0xF1, 0x75, 0xA0, 0xED, 0xCD,
13695 0x4B, 0x24, 0x8A, 0xB3, 0x98, 0x7B, 0x12, 0xB8, 0xF5, 0x63, 0x97, 0xB3, 0xA6, 0xA6, 0x0B, 0xDC,
13696 0xD8, 0x4C, 0xA8, 0x99, 0x27, 0x0F, 0x8F, 0x94, 0x63, 0x0F, 0xB0, 0x11, 0x94, 0xC7, 0xE9, 0x7F,
13697 0x3B, 0x40, 0x72, 0x4C, 0xDB, 0x84, 0x78, 0xFE, 0xB8, 0x56, 0x08, 0x80, 0xDF, 0x20, 0x2F, 0xB9,
13698 0x66, 0x2D, 0x60, 0x63, 0xF5, 0x18, 0x15, 0x1B, 0x86, 0x85, 0xB9, 0xB4, 0x68, 0x0E, 0xC6, 0xD1,
13699 0x8A, 0x81, 0x2B, 0xB3, 0xF6, 0x48, 0xF0, 0x4F, 0x9C, 0x28, 0x1C, 0xA4, 0x51, 0x2F, 0xD7, 0x4B,
13700 0x17, 0xE7, 0xCC, 0x50, 0x9F, 0xD0, 0xD1, 0x40, 0x0C, 0x0D, 0xCA, 0x83, 0xFA, 0x5E, 0xCA, 0xEC,
13701 0xBF, 0x4E, 0x7C, 0x8F, 0xF0, 0xAE, 0xC2, 0xD3, 0x28, 0x41, 0x9B, 0xC8, 0x04, 0xB9, 0x4A, 0xBA,
13702 0x72, 0xE2, 0xB5, 0x06, 0x2C, 0x1E, 0x0B, 0x2C, 0x7F, 0x11, 0xA9, 0x26, 0x51, 0x9D, 0x3F, 0xF8,
13703 0x62, 0x11, 0x2E, 0x89, 0xD2, 0x9D, 0x35, 0xB1, 0xE4, 0x0A, 0x4D, 0x93, 0x01, 0xA7, 0xD1, 0x2D,
13704 0x00, 0x87, 0xE2, 0x2D, 0xA4, 0xE9, 0x0A, 0x06, 0x66, 0xF8, 0x1F, 0x44, 0x75, 0xB5, 0x6B, 0x1C,
13705 0xFC, 0x31, 0x09, 0x48, 0xA3, 0xFF, 0x92, 0x12, 0x58, 0xE9, 0xFA, 0xAE, 0x4F, 0xE2, 0xB4, 0xCC
13706 };
13707
13708 #define debuggerReadMemory(addr) \
13709 READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
13710
13711 #define debuggerReadHalfWord(addr) \
13712 READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
13713
13714 #define debuggerReadByte(addr) \
13715 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
13716
13717 #define debuggerWriteMemory(addr, value) \
13718 WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
13719
13720 #define debuggerWriteHalfWord(addr, value) \
13721 WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
13722
13723 #define debuggerWriteByte(addr, value) \
13724 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
13725
13726
13727 #define CHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9'))
13728
13729 #define CHEAT_PATCH_ROM_16BIT(a,v) \
13730 WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v);
13731
13732 #define CHEAT_PATCH_ROM_32BIT(a,v) \
13733 WRITE32LE(((u32 *)&rom[(a) & 0x1ffffff]), v);
13734
isMultilineWithData(int i)13735 static bool isMultilineWithData(int i)
13736 {
13737 // we consider it a multiline code if it has more than one line of data
13738 // otherwise, it can still be considered a single code
13739 // (Only CBA codes can be true multilines !!!)
13740 if(i < cheatsNumber && i >= 0)
13741 switch(cheatsList[i].size) {
13742 case INT_8_BIT_WRITE:
13743 case INT_16_BIT_WRITE:
13744 case INT_32_BIT_WRITE:
13745 case GSA_16_BIT_ROM_PATCH:
13746 case GSA_8_BIT_GS_WRITE:
13747 case GSA_16_BIT_GS_WRITE:
13748 case GSA_32_BIT_GS_WRITE:
13749 case CBA_AND:
13750 case CBA_IF_KEYS_PRESSED:
13751 case CBA_IF_TRUE:
13752 case CBA_IF_FALSE:
13753 case GSA_8_BIT_IF_TRUE:
13754 case GSA_32_BIT_IF_TRUE:
13755 case GSA_8_BIT_IF_FALSE:
13756 case GSA_32_BIT_IF_FALSE:
13757 case GSA_8_BIT_FILL:
13758 case GSA_16_BIT_FILL:
13759 case GSA_8_BIT_IF_TRUE2:
13760 case GSA_16_BIT_IF_TRUE2:
13761 case GSA_32_BIT_IF_TRUE2:
13762 case GSA_8_BIT_IF_FALSE2:
13763 case GSA_16_BIT_IF_FALSE2:
13764 case GSA_32_BIT_IF_FALSE2:
13765 case GSA_SLOWDOWN:
13766 case CBA_ADD:
13767 case CBA_OR:
13768 case CBA_LT:
13769 case CBA_GT:
13770 case GSA_8_BIT_POINTER:
13771 case GSA_16_BIT_POINTER:
13772 case GSA_32_BIT_POINTER:
13773 case GSA_8_BIT_ADD:
13774 case GSA_16_BIT_ADD:
13775 case GSA_32_BIT_ADD:
13776 case GSA_8_BIT_IF_LOWER_U:
13777 case GSA_16_BIT_IF_LOWER_U:
13778 case GSA_32_BIT_IF_LOWER_U:
13779 case GSA_8_BIT_IF_HIGHER_U:
13780 case GSA_16_BIT_IF_HIGHER_U:
13781 case GSA_32_BIT_IF_HIGHER_U:
13782 case GSA_8_BIT_IF_AND:
13783 case GSA_16_BIT_IF_AND:
13784 case GSA_32_BIT_IF_AND:
13785 case GSA_8_BIT_IF_LOWER_U2:
13786 case GSA_16_BIT_IF_LOWER_U2:
13787 case GSA_32_BIT_IF_LOWER_U2:
13788 case GSA_8_BIT_IF_HIGHER_U2:
13789 case GSA_16_BIT_IF_HIGHER_U2:
13790 case GSA_32_BIT_IF_HIGHER_U2:
13791 case GSA_8_BIT_IF_AND2:
13792 case GSA_16_BIT_IF_AND2:
13793 case GSA_32_BIT_IF_AND2:
13794 case GSA_ALWAYS:
13795 case GSA_ALWAYS2:
13796 case GSA_8_BIT_IF_LOWER_S:
13797 case GSA_16_BIT_IF_LOWER_S:
13798 case GSA_32_BIT_IF_LOWER_S:
13799 case GSA_8_BIT_IF_HIGHER_S:
13800 case GSA_16_BIT_IF_HIGHER_S:
13801 case GSA_32_BIT_IF_HIGHER_S:
13802 case GSA_8_BIT_IF_LOWER_S2:
13803 case GSA_16_BIT_IF_LOWER_S2:
13804 case GSA_32_BIT_IF_LOWER_S2:
13805 case GSA_8_BIT_IF_HIGHER_S2:
13806 case GSA_16_BIT_IF_HIGHER_S2:
13807 case GSA_32_BIT_IF_HIGHER_S2:
13808 case GSA_16_BIT_WRITE_IOREGS:
13809 case GSA_32_BIT_WRITE_IOREGS:
13810 case GSA_CODES_ON:
13811 case GSA_8_BIT_IF_TRUE3:
13812 case GSA_16_BIT_IF_TRUE3:
13813 case GSA_32_BIT_IF_TRUE3:
13814 case GSA_8_BIT_IF_FALSE3:
13815 case GSA_16_BIT_IF_FALSE3:
13816 case GSA_32_BIT_IF_FALSE3:
13817 case GSA_8_BIT_IF_LOWER_S3:
13818 case GSA_16_BIT_IF_LOWER_S3:
13819 case GSA_32_BIT_IF_LOWER_S3:
13820 case GSA_8_BIT_IF_HIGHER_S3:
13821 case GSA_16_BIT_IF_HIGHER_S3:
13822 case GSA_32_BIT_IF_HIGHER_S3:
13823 case GSA_8_BIT_IF_LOWER_U3:
13824 case GSA_16_BIT_IF_LOWER_U3:
13825 case GSA_32_BIT_IF_LOWER_U3:
13826 case GSA_8_BIT_IF_HIGHER_U3:
13827 case GSA_16_BIT_IF_HIGHER_U3:
13828 case GSA_32_BIT_IF_HIGHER_U3:
13829 case GSA_8_BIT_IF_AND3:
13830 case GSA_16_BIT_IF_AND3:
13831 case GSA_32_BIT_IF_AND3:
13832 case GSA_ALWAYS3:
13833 case GSA_8_BIT_GS_WRITE2:
13834 case GSA_16_BIT_GS_WRITE2:
13835 case GSA_32_BIT_GS_WRITE2:
13836 case GSA_16_BIT_ROM_PATCH2C:
13837 case GSA_16_BIT_ROM_PATCH2D:
13838 case GSA_16_BIT_ROM_PATCH2E:
13839 case GSA_16_BIT_ROM_PATCH2F:
13840 case GSA_8_BIT_SLIDE:
13841 case GSA_16_BIT_SLIDE:
13842 case GSA_32_BIT_SLIDE:
13843 case GSA_GROUP_WRITE:
13844 case GSA_32_BIT_ADD2:
13845 case GSA_32_BIT_SUB2:
13846 case GSA_16_BIT_IF_LOWER_OR_EQ_U:
13847 case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
13848 case GSA_16_BIT_MIF_TRUE:
13849 case GSA_16_BIT_MIF_FALSE:
13850 case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
13851 case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
13852 case MASTER_CODE:
13853 case CHEATS_16_BIT_WRITE:
13854 case CHEATS_32_BIT_WRITE:
13855 return false;
13856 // the codes below have two lines of data
13857 case CBA_SLIDE_CODE:
13858 case CBA_SUPER:
13859 return true;
13860 }
13861 return false;
13862 }
13863
getCodeLength(int num)13864 static int getCodeLength(int num)
13865 {
13866 if(num >= cheatsNumber || num < 0)
13867 return 1;
13868
13869 // this is for all the codes that are true multiline
13870 switch(cheatsList[num].size) {
13871 case INT_8_BIT_WRITE:
13872 case INT_16_BIT_WRITE:
13873 case INT_32_BIT_WRITE:
13874 case GSA_16_BIT_ROM_PATCH:
13875 case GSA_8_BIT_GS_WRITE:
13876 case GSA_16_BIT_GS_WRITE:
13877 case GSA_32_BIT_GS_WRITE:
13878 case CBA_AND:
13879 case GSA_8_BIT_FILL:
13880 case GSA_16_BIT_FILL:
13881 case GSA_SLOWDOWN:
13882 case CBA_ADD:
13883 case CBA_OR:
13884 case GSA_8_BIT_POINTER:
13885 case GSA_16_BIT_POINTER:
13886 case GSA_32_BIT_POINTER:
13887 case GSA_8_BIT_ADD:
13888 case GSA_16_BIT_ADD:
13889 case GSA_32_BIT_ADD:
13890 case GSA_CODES_ON:
13891 case GSA_8_BIT_IF_TRUE3:
13892 case GSA_16_BIT_IF_TRUE3:
13893 case GSA_32_BIT_IF_TRUE3:
13894 case GSA_8_BIT_IF_FALSE3:
13895 case GSA_16_BIT_IF_FALSE3:
13896 case GSA_32_BIT_IF_FALSE3:
13897 case GSA_8_BIT_IF_LOWER_S3:
13898 case GSA_16_BIT_IF_LOWER_S3:
13899 case GSA_32_BIT_IF_LOWER_S3:
13900 case GSA_8_BIT_IF_HIGHER_S3:
13901 case GSA_16_BIT_IF_HIGHER_S3:
13902 case GSA_32_BIT_IF_HIGHER_S3:
13903 case GSA_8_BIT_IF_LOWER_U3:
13904 case GSA_16_BIT_IF_LOWER_U3:
13905 case GSA_32_BIT_IF_LOWER_U3:
13906 case GSA_8_BIT_IF_HIGHER_U3:
13907 case GSA_16_BIT_IF_HIGHER_U3:
13908 case GSA_32_BIT_IF_HIGHER_U3:
13909 case GSA_8_BIT_IF_AND3:
13910 case GSA_16_BIT_IF_AND3:
13911 case GSA_32_BIT_IF_AND3:
13912 case GSA_8_BIT_IF_LOWER_U:
13913 case GSA_16_BIT_IF_LOWER_U:
13914 case GSA_32_BIT_IF_LOWER_U:
13915 case GSA_8_BIT_IF_HIGHER_U:
13916 case GSA_16_BIT_IF_HIGHER_U:
13917 case GSA_32_BIT_IF_HIGHER_U:
13918 case GSA_8_BIT_IF_AND:
13919 case GSA_16_BIT_IF_AND:
13920 case GSA_32_BIT_IF_AND:
13921 case GSA_ALWAYS:
13922 case GSA_8_BIT_IF_LOWER_S:
13923 case GSA_16_BIT_IF_LOWER_S:
13924 case GSA_32_BIT_IF_LOWER_S:
13925 case GSA_8_BIT_IF_HIGHER_S:
13926 case GSA_16_BIT_IF_HIGHER_S:
13927 case GSA_32_BIT_IF_HIGHER_S:
13928 case GSA_16_BIT_WRITE_IOREGS:
13929 case GSA_32_BIT_WRITE_IOREGS:
13930 case GSA_8_BIT_GS_WRITE2:
13931 case GSA_16_BIT_GS_WRITE2:
13932 case GSA_32_BIT_GS_WRITE2:
13933 case GSA_16_BIT_ROM_PATCH2C:
13934 case GSA_16_BIT_ROM_PATCH2D:
13935 case GSA_16_BIT_ROM_PATCH2E:
13936 case GSA_16_BIT_ROM_PATCH2F:
13937 case GSA_8_BIT_SLIDE:
13938 case GSA_16_BIT_SLIDE:
13939 case GSA_32_BIT_SLIDE:
13940 case GSA_8_BIT_IF_TRUE:
13941 case GSA_32_BIT_IF_TRUE:
13942 case GSA_8_BIT_IF_FALSE:
13943 case GSA_32_BIT_IF_FALSE:
13944 case CBA_LT:
13945 case CBA_GT:
13946 case CBA_IF_TRUE:
13947 case CBA_IF_FALSE:
13948 case GSA_8_BIT_IF_TRUE2:
13949 case GSA_16_BIT_IF_TRUE2:
13950 case GSA_32_BIT_IF_TRUE2:
13951 case GSA_8_BIT_IF_FALSE2:
13952 case GSA_16_BIT_IF_FALSE2:
13953 case GSA_32_BIT_IF_FALSE2:
13954 case GSA_8_BIT_IF_LOWER_U2:
13955 case GSA_16_BIT_IF_LOWER_U2:
13956 case GSA_32_BIT_IF_LOWER_U2:
13957 case GSA_8_BIT_IF_HIGHER_U2:
13958 case GSA_16_BIT_IF_HIGHER_U2:
13959 case GSA_32_BIT_IF_HIGHER_U2:
13960 case GSA_8_BIT_IF_AND2:
13961 case GSA_16_BIT_IF_AND2:
13962 case GSA_32_BIT_IF_AND2:
13963 case GSA_ALWAYS2:
13964 case GSA_8_BIT_IF_LOWER_S2:
13965 case GSA_16_BIT_IF_LOWER_S2:
13966 case GSA_32_BIT_IF_LOWER_S2:
13967 case GSA_8_BIT_IF_HIGHER_S2:
13968 case GSA_16_BIT_IF_HIGHER_S2:
13969 case GSA_32_BIT_IF_HIGHER_S2:
13970 case GSA_GROUP_WRITE:
13971 case GSA_32_BIT_ADD2:
13972 case GSA_32_BIT_SUB2:
13973 case GSA_16_BIT_IF_LOWER_OR_EQ_U:
13974 case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
13975 case GSA_16_BIT_MIF_TRUE:
13976 case GSA_16_BIT_MIF_FALSE:
13977 case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
13978 case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
13979 case MASTER_CODE:
13980 case CHEATS_16_BIT_WRITE:
13981 case CHEATS_32_BIT_WRITE:
13982 case UNKNOWN_CODE:
13983 return 1;
13984 case CBA_IF_KEYS_PRESSED:
13985 case CBA_SLIDE_CODE:
13986 return 2;
13987 case CBA_SUPER:
13988 return ((((cheatsList[num].value-1) & 0xFFFF)/3) + 1);
13989 }
13990 return 1;
13991 }
13992
cheatsCheckKeys(u32 keys,u32 extended)13993 int cheatsCheckKeys(u32 keys, u32 extended)
13994 {
13995 bool onoff = true;
13996 int ticks = 0;
13997 int i;
13998 mastercode = 0;
13999
14000 for (i = 0; i<4; i++)
14001 if (rompatch2addr [i] != 0) {
14002 CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2oldval [i]);
14003 rompatch2addr [i] = 0;
14004 }
14005
14006 for (i = 0; i < cheatsNumber; i++) {
14007 if(!cheatsList[i].enabled) {
14008 // make sure we skip other lines in this code
14009 i += getCodeLength(i)-1;
14010 continue;
14011 }
14012 switch(cheatsList[i].size) {
14013 case GSA_CODES_ON:
14014 onoff = true;
14015 break;
14016 case GSA_SLOWDOWN:
14017 // check if button was pressed and released, if so toggle our state
14018 if((cheatsList[i].status & 4) && !(extended & 4))
14019 cheatsList[i].status ^= 1;
14020 if(extended & 4)
14021 cheatsList[i].status |= 4;
14022 else
14023 cheatsList[i].status &= ~4;
14024
14025 if(cheatsList[i].status & 1)
14026 ticks += ((cheatsList[i].value & 0xFFFF) * 7);
14027 break;
14028 case GSA_8_BIT_SLIDE:
14029 i++;
14030 if(i < cheatsNumber) {
14031 u32 addr = cheatsList[i-1].value;
14032 u8 value = cheatsList[i].rawaddress;
14033 int vinc = (cheatsList[i].value >> 24) & 255;
14034 int count = (cheatsList[i].value >> 16) & 255;
14035 int ainc = (cheatsList[i].value & 0xffff);
14036 while(count > 0) {
14037 CPUWriteByte(addr, value);
14038 value += vinc;
14039 addr += ainc;
14040 count--;
14041 }
14042 }
14043 break;
14044 case GSA_16_BIT_SLIDE:
14045 i++;
14046 if(i < cheatsNumber) {
14047 u32 addr = cheatsList[i-1].value;
14048 u16 value = cheatsList[i].rawaddress;
14049 int vinc = (cheatsList[i].value >> 24) & 255;
14050 int count = (cheatsList[i].value >> 16) & 255;
14051 int ainc = (cheatsList[i].value & 0xffff)*2;
14052 while(count > 0) {
14053 CPUWriteHalfWord(addr, value);
14054 value += vinc;
14055 addr += ainc;
14056 count--;
14057 }
14058 }
14059 break;
14060 case GSA_32_BIT_SLIDE:
14061 i++;
14062 if(i < cheatsNumber) {
14063 u32 addr = cheatsList[i-1].value;
14064 u32 value = cheatsList[i].rawaddress;
14065 int vinc = (cheatsList[i].value >> 24) & 255;
14066 int count = (cheatsList[i].value >> 16) & 255;
14067 int ainc = (cheatsList[i].value & 0xffff)*4;
14068 while(count > 0) {
14069 CPUWriteMemory(addr, value);
14070 value += vinc;
14071 addr += ainc;
14072 count--;
14073 }
14074 }
14075 break;
14076 case GSA_8_BIT_GS_WRITE2:
14077 i++;
14078 if(i < cheatsNumber) {
14079 if(extended & 4) {
14080 CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address);
14081 }
14082 }
14083 break;
14084 case GSA_16_BIT_GS_WRITE2:
14085 i++;
14086 if(i < cheatsNumber) {
14087 if(extended & 4) {
14088 CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address);
14089 }
14090 }
14091 break;
14092 case GSA_32_BIT_GS_WRITE2:
14093 i++;
14094 if(i < cheatsNumber) {
14095 if(extended & 4) {
14096 CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address);
14097 }
14098 }
14099 break;
14100 case GSA_16_BIT_ROM_PATCH:
14101 if((cheatsList[i].status & 1) == 0) {
14102 if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
14103 cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address);
14104 cheatsList[i].status |= 1;
14105 CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
14106 }
14107 }
14108 break;
14109 case GSA_16_BIT_ROM_PATCH2C:
14110 i++;
14111 if(i < cheatsNumber) {
14112 rompatch2addr [0] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
14113 rompatch2oldval [0] = CPUReadHalfWord(rompatch2addr [0]);
14114 rompatch2val [0] = cheatsList[i].rawaddress & 0xFFFF;
14115 }
14116 break;
14117 case GSA_16_BIT_ROM_PATCH2D:
14118 i++;
14119 if(i < cheatsNumber) {
14120 rompatch2addr [1] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
14121 rompatch2oldval [1] = CPUReadHalfWord(rompatch2addr [1]);
14122 rompatch2val [1] = cheatsList[i].rawaddress & 0xFFFF;
14123 }
14124 break;
14125 case GSA_16_BIT_ROM_PATCH2E:
14126 i++;
14127 if(i < cheatsNumber) {
14128 rompatch2addr [2] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
14129 rompatch2oldval [2] = CPUReadHalfWord(rompatch2addr [2]);
14130 rompatch2val [2] = cheatsList[i].rawaddress & 0xFFFF;
14131 }
14132 break;
14133 case GSA_16_BIT_ROM_PATCH2F:
14134 i++;
14135 if(i < cheatsNumber) {
14136 rompatch2addr [3] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
14137 rompatch2oldval [3] = CPUReadHalfWord(rompatch2addr [3]);
14138 rompatch2val [3] = cheatsList[i].rawaddress & 0xFFFF;
14139 }
14140 break;
14141 case MASTER_CODE:
14142 mastercode = cheatsList[i].address;
14143 break;
14144 }
14145 if (onoff) {
14146 switch(cheatsList[i].size) {
14147 case INT_8_BIT_WRITE:
14148 CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
14149 break;
14150 case INT_16_BIT_WRITE:
14151 CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
14152 break;
14153 case INT_32_BIT_WRITE:
14154 CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
14155 break;
14156 case GSA_8_BIT_GS_WRITE:
14157 if(extended & 4) {
14158 CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
14159 }
14160 break;
14161 case GSA_16_BIT_GS_WRITE:
14162 if(extended & 4) {
14163 CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
14164 }
14165 break;
14166 case GSA_32_BIT_GS_WRITE:
14167 if(extended & 4) {
14168 CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
14169 }
14170 break;
14171 case CBA_IF_KEYS_PRESSED:
14172 {
14173 u16 value = cheatsList[i].value;
14174 u32 addr = cheatsList[i].address;
14175 if((addr & 0xF0) == 0x20) {
14176 if((keys & value) == 0) {
14177 i++;
14178 }
14179 } else if((addr & 0xF0) == 0x10) {
14180 if((keys & value) == value) {
14181 i++;
14182 }
14183 } else if((addr & 0xF0) == 0x00) {
14184 if(((~keys) & 0x3FF) == value) {
14185 i++;
14186 }
14187 }
14188 }
14189 break;
14190 case CBA_IF_TRUE:
14191 if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
14192 i++;
14193 }
14194 break;
14195 case CBA_SLIDE_CODE:
14196 {
14197 u32 address = cheatsList[i].address;
14198 u16 value = cheatsList[i].value;
14199 i++;
14200 if(i < cheatsNumber) {
14201 int count = ((cheatsList[i].address - 1) & 0xFFFF);
14202 u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF;
14203 int inc = cheatsList[i].value;
14204 for(int x = 0; x <= count ; x++) {
14205 CPUWriteHalfWord(address, value);
14206 address += inc;
14207 value += vinc;
14208 }
14209 }
14210 }
14211 break;
14212 case CBA_IF_FALSE:
14213 if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value){
14214 i++;
14215 }
14216 break;
14217 case CBA_AND:
14218 CPUWriteHalfWord(cheatsList[i].address,
14219 CPUReadHalfWord(cheatsList[i].address) &
14220 cheatsList[i].value);
14221 break;
14222 case GSA_8_BIT_IF_TRUE:
14223 if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
14224 i++;
14225 }
14226 break;
14227 case GSA_32_BIT_IF_TRUE:
14228 if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
14229 i++;
14230 }
14231 break;
14232 case GSA_8_BIT_IF_FALSE:
14233 if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
14234 i++;
14235 }
14236 break;
14237 case GSA_32_BIT_IF_FALSE:
14238 if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
14239 i++;
14240 }
14241 break;
14242 case GSA_8_BIT_FILL:
14243 {
14244 u32 addr = cheatsList[i].address;
14245 u8 v = cheatsList[i].value & 0xff;
14246 u32 end = addr + (cheatsList[i].value >> 8);
14247 do {
14248 CPUWriteByte(addr, v);
14249 addr++;
14250 } while (addr <= end);
14251 }
14252 break;
14253 case GSA_16_BIT_FILL:
14254 {
14255 u32 addr = cheatsList[i].address;
14256 u16 v = cheatsList[i].value & 0xffff;
14257 u32 end = addr + ((cheatsList[i].value >> 16) << 1);
14258 do {
14259 CPUWriteHalfWord(addr, v);
14260 addr+=2;
14261 } while (addr <= end);
14262 }
14263 break;
14264 case GSA_8_BIT_IF_TRUE2:
14265 if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
14266 i+=2;
14267 }
14268 break;
14269 case GSA_16_BIT_IF_TRUE2:
14270 if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
14271 i+=2;
14272 }
14273 break;
14274 case GSA_32_BIT_IF_TRUE2:
14275 if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
14276 i+=2;
14277 }
14278 break;
14279 case GSA_8_BIT_IF_FALSE2:
14280 if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
14281 i+=2;
14282 }
14283 break;
14284 case GSA_16_BIT_IF_FALSE2:
14285 if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
14286 i+=2;
14287 }
14288 break;
14289 case GSA_32_BIT_IF_FALSE2:
14290 if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
14291 i+=2;
14292 }
14293 break;
14294 case CBA_ADD:
14295 if ((cheatsList[i].address & 1) == 0) {
14296 CPUWriteHalfWord(cheatsList[i].address,
14297 CPUReadHalfWord(cheatsList[i].address) +
14298 cheatsList[i].value);
14299 } else {
14300 CPUWriteMemory(cheatsList[i].address & 0x0FFFFFFE,
14301 CPUReadMemory(cheatsList[i].address & 0x0FFFFFFE) +
14302 cheatsList[i].value);
14303 }
14304 break;
14305 case CBA_OR:
14306 CPUWriteHalfWord(cheatsList[i].address,
14307 CPUReadHalfWord(cheatsList[i].address) |
14308 cheatsList[i].value);
14309 break;
14310 case CBA_GT:
14311 if (!(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value)){
14312 i++;
14313 }
14314 break;
14315 case CBA_LT:
14316 if (!(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value)){
14317 i++;
14318 }
14319 break;
14320 case CBA_SUPER:
14321 {
14322 int count = 2*((cheatsList[i].value -1) & 0xFFFF)+1;
14323 u32 address = cheatsList[i].address;
14324 for(int x = 0; x <= count; x++) {
14325 u8 b;
14326 int res = x % 6;
14327 if (res==0)
14328 i++;
14329 if(res < 4)
14330 b = (cheatsList[i].address >> (24-8*res)) & 0xFF;
14331 else
14332 b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0xFF;
14333 CPUWriteByte(address, b);
14334 address++;
14335 }
14336 }
14337 break;
14338 case GSA_8_BIT_POINTER :
14339 if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
14340 ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
14341 {
14342 CPUWriteByte(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFFFF00) >> 8),
14343 cheatsList[i].value & 0xFF);
14344 }
14345 break;
14346 case GSA_16_BIT_POINTER :
14347 if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
14348 ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
14349 {
14350 CPUWriteHalfWord(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFF0000) >> 15),
14351 cheatsList[i].value & 0xFFFF);
14352 }
14353 break;
14354 case GSA_32_BIT_POINTER :
14355 if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) ||
14356 ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)))
14357 {
14358 CPUWriteMemory(CPUReadMemory(cheatsList[i].address),
14359 cheatsList[i].value);
14360 }
14361 break;
14362 case GSA_8_BIT_ADD :
14363 CPUWriteByte(cheatsList[i].address,
14364 (cheatsList[i].value & 0xFF) + (CPUReadMemory(cheatsList[i].address) & 0xFF));
14365 break;
14366 case GSA_16_BIT_ADD :
14367 CPUWriteHalfWord(cheatsList[i].address,
14368 (cheatsList[i].value & 0xFFFF) + (CPUReadMemory(cheatsList[i].address) & 0xFFFF));
14369 break;
14370 case GSA_32_BIT_ADD :
14371 CPUWriteMemory(cheatsList[i].address ,
14372 cheatsList[i].value + (CPUReadMemory(cheatsList[i].address) & 0xFFFFFFFF));
14373 break;
14374 case GSA_8_BIT_IF_LOWER_U:
14375 if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
14376 i++;
14377 }
14378 break;
14379 case GSA_16_BIT_IF_LOWER_U:
14380 if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
14381 i++;
14382 }
14383 break;
14384 case GSA_32_BIT_IF_LOWER_U:
14385 if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
14386 i++;
14387 }
14388 break;
14389 case GSA_8_BIT_IF_HIGHER_U:
14390 if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
14391 i++;
14392 }
14393 break;
14394 case GSA_16_BIT_IF_HIGHER_U:
14395 if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
14396 i++;
14397 }
14398 break;
14399 case GSA_32_BIT_IF_HIGHER_U:
14400 if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
14401 i++;
14402 }
14403 break;
14404 case GSA_8_BIT_IF_AND:
14405 if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
14406 i++;
14407 }
14408 break;
14409 case GSA_16_BIT_IF_AND:
14410 if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
14411 i++;
14412 }
14413 break;
14414 case GSA_32_BIT_IF_AND:
14415 if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
14416 i++;
14417 }
14418 break;
14419 case GSA_8_BIT_IF_LOWER_U2:
14420 if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
14421 i+=2;
14422 }
14423 break;
14424 case GSA_16_BIT_IF_LOWER_U2:
14425 if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
14426 i+=2;
14427 }
14428 break;
14429 case GSA_32_BIT_IF_LOWER_U2:
14430 if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
14431 i+=2;
14432 }
14433 break;
14434 case GSA_8_BIT_IF_HIGHER_U2:
14435 if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
14436 i+=2;
14437 }
14438 break;
14439 case GSA_16_BIT_IF_HIGHER_U2:
14440 if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
14441 i+=2;
14442 }
14443 break;
14444 case GSA_32_BIT_IF_HIGHER_U2:
14445 if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
14446 i+=2;
14447 }
14448 break;
14449 case GSA_8_BIT_IF_AND2:
14450 if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
14451 i+=2;
14452 }
14453 break;
14454 case GSA_16_BIT_IF_AND2:
14455 if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
14456 i+=2;
14457 }
14458 break;
14459 case GSA_32_BIT_IF_AND2:
14460 if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
14461 i+=2;
14462 }
14463 break;
14464 case GSA_ALWAYS:
14465 i++;
14466 break;
14467 case GSA_ALWAYS2:
14468 i+=2;
14469 break;
14470 case GSA_8_BIT_IF_LOWER_S:
14471 if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
14472 i++;
14473 }
14474 break;
14475 case GSA_16_BIT_IF_LOWER_S:
14476 if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
14477 i++;
14478 }
14479 break;
14480 case GSA_32_BIT_IF_LOWER_S:
14481 if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
14482 i++;
14483 }
14484 break;
14485 case GSA_8_BIT_IF_HIGHER_S:
14486 if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
14487 i++;
14488 }
14489 break;
14490 case GSA_16_BIT_IF_HIGHER_S:
14491 if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
14492 i++;
14493 }
14494 break;
14495 case GSA_32_BIT_IF_HIGHER_S:
14496 if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
14497 i++;
14498 }
14499 break;
14500 case GSA_8_BIT_IF_LOWER_S2:
14501 if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
14502 i+=2;
14503 }
14504 break;
14505 case GSA_16_BIT_IF_LOWER_S2:
14506 if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
14507 i+=2;
14508 }
14509 break;
14510 case GSA_32_BIT_IF_LOWER_S2:
14511 if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
14512 i+=2;
14513 }
14514 break;
14515 case GSA_8_BIT_IF_HIGHER_S2:
14516 if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
14517 i+=2;
14518 }
14519 break;
14520 case GSA_16_BIT_IF_HIGHER_S2:
14521 if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
14522 i+=2;
14523 }
14524 break;
14525 case GSA_32_BIT_IF_HIGHER_S2:
14526 if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
14527 i+=2;
14528 }
14529 break;
14530 case GSA_16_BIT_WRITE_IOREGS:
14531 if ((cheatsList[i].address <= 0x3FF) && (cheatsList[i].address != 0x6) &&
14532 (cheatsList[i].address != 0x130))
14533 ioMem[cheatsList[i].address & 0x3FE]=cheatsList[i].value & 0xFFFF;
14534 break;
14535 case GSA_32_BIT_WRITE_IOREGS:
14536 if (cheatsList[i].address<=0x3FF)
14537 {
14538 if (((cheatsList[i].address & 0x3FC) != 0x6) && ((cheatsList[i].address & 0x3FC) != 0x130))
14539 ioMem[cheatsList[i].address & 0x3FC]= (cheatsList[i].value & 0xFFFF);
14540 if ((((cheatsList[i].address & 0x3FC)+2) != 0x6) && ((cheatsList[i].address & 0x3FC) +2) != 0x130)
14541 ioMem[(cheatsList[i].address & 0x3FC) + 2 ]= ((cheatsList[i].value>>16 ) & 0xFFFF);
14542 }
14543 break;
14544 case GSA_8_BIT_IF_TRUE3:
14545 if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
14546 onoff=false;
14547 }
14548 break;
14549 case GSA_16_BIT_IF_TRUE3:
14550 if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
14551 onoff=false;
14552 }
14553 break;
14554 case GSA_32_BIT_IF_TRUE3:
14555 if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
14556 onoff=false;
14557 }
14558 break;
14559 case GSA_8_BIT_IF_FALSE3:
14560 if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
14561 onoff=false;
14562 }
14563 break;
14564 case GSA_16_BIT_IF_FALSE3:
14565 if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
14566 onoff=false;
14567 }
14568 break;
14569 case GSA_32_BIT_IF_FALSE3:
14570 if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
14571 onoff=false;
14572 }
14573 break;
14574 case GSA_8_BIT_IF_LOWER_S3:
14575 if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
14576 onoff=false;
14577 }
14578 break;
14579 case GSA_16_BIT_IF_LOWER_S3:
14580 if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
14581 onoff=false;
14582 }
14583 break;
14584 case GSA_32_BIT_IF_LOWER_S3:
14585 if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
14586 onoff=false;
14587 }
14588 break;
14589 case GSA_8_BIT_IF_HIGHER_S3:
14590 if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
14591 onoff=false;
14592 }
14593 break;
14594 case GSA_16_BIT_IF_HIGHER_S3:
14595 if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
14596 onoff=false;
14597 }
14598 break;
14599 case GSA_32_BIT_IF_HIGHER_S3:
14600 if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
14601 onoff=false;
14602 }
14603 break;
14604 case GSA_8_BIT_IF_LOWER_U3:
14605 if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
14606 onoff=false;
14607 }
14608 break;
14609 case GSA_16_BIT_IF_LOWER_U3:
14610 if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
14611 onoff=false;
14612 }
14613 break;
14614 case GSA_32_BIT_IF_LOWER_U3:
14615 if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
14616 onoff=false;
14617 }
14618 break;
14619 case GSA_8_BIT_IF_HIGHER_U3:
14620 if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
14621 onoff=false;
14622 }
14623 break;
14624 case GSA_16_BIT_IF_HIGHER_U3:
14625 if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
14626 onoff=false;
14627 }
14628 break;
14629 case GSA_32_BIT_IF_HIGHER_U3:
14630 if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
14631 onoff=false;
14632 }
14633 break;
14634 case GSA_8_BIT_IF_AND3:
14635 if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
14636 onoff=false;
14637 }
14638 break;
14639 case GSA_16_BIT_IF_AND3:
14640 if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
14641 onoff=false;
14642 }
14643 break;
14644 case GSA_32_BIT_IF_AND3:
14645 if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
14646 onoff=false;
14647 }
14648 break;
14649 case GSA_ALWAYS3:
14650 if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
14651 onoff=false;
14652 }
14653 break;
14654 case GSA_GROUP_WRITE:
14655 {
14656 int count = ((cheatsList[i].address) & 0xFFFE) +1;
14657 u32 value = cheatsList[i].value;
14658 if (count==0)
14659 i++;
14660 else
14661 for (int x = 1; x <= count; x++) {
14662 if ((x % 2) ==0){
14663 if (x<count)
14664 i++;
14665 CPUWriteMemory(cheatsList[i].rawaddress, value);
14666 }
14667 else
14668 CPUWriteMemory(cheatsList[i].value, value);
14669 }
14670 }
14671 break;
14672 case GSA_32_BIT_ADD2:
14673 CPUWriteMemory(cheatsList[i].value ,
14674 (CPUReadMemory(cheatsList[i].value) + cheatsList[i+1].rawaddress) & 0xFFFFFFFF);
14675 i++;
14676 break;
14677 case GSA_32_BIT_SUB2:
14678 CPUWriteMemory(cheatsList[i].value ,
14679 (CPUReadMemory(cheatsList[i].value) - cheatsList[i+1].rawaddress) & 0xFFFFFFFF);
14680 i++;
14681 break;
14682 case GSA_16_BIT_IF_LOWER_OR_EQ_U:
14683 if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) {
14684 i++;
14685 }
14686 break;
14687 case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
14688 if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
14689 i++;
14690 }
14691 break;
14692 case GSA_16_BIT_MIF_TRUE:
14693 if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
14694 i+=((cheatsList[i].rawaddress >> 0x10) & 0xFF);
14695 }
14696 break;
14697 case GSA_16_BIT_MIF_FALSE:
14698 if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
14699 i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
14700 }
14701 break;
14702 case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
14703 if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) {
14704 i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
14705 }
14706 break;
14707 case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
14708 if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
14709 i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
14710 }
14711 break;
14712 case CHEATS_16_BIT_WRITE:
14713 if ((cheatsList[i].address>>24)>=0x08) {
14714 CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
14715 } else {
14716 CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
14717 }
14718 break;
14719 case CHEATS_32_BIT_WRITE:
14720 if ((cheatsList[i].address>>24)>=0x08) {
14721 CHEAT_PATCH_ROM_32BIT(cheatsList[i].address, cheatsList[i].value);
14722 } else {
14723 CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
14724 }
14725 break;
14726 }
14727 }
14728 }
14729 for (i = 0; i<4; i++)
14730 if (rompatch2addr [i] != 0)
14731 CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2val [i]);
14732 return ticks;
14733 }
14734
cheatsAdd(const char * codeStr,const char * desc,u32 rawaddress,u32 address,u32 value,int code,int size)14735 void cheatsAdd(const char *codeStr,
14736 const char *desc,
14737 u32 rawaddress,
14738 u32 address,
14739 u32 value,
14740 int code,
14741 int size)
14742 {
14743 if(cheatsNumber < 100) {
14744 int x = cheatsNumber;
14745 cheatsList[x].code = code;
14746 cheatsList[x].size = size;
14747 cheatsList[x].rawaddress = rawaddress;
14748 cheatsList[x].address = address;
14749 cheatsList[x].value = value;
14750 strcpy(cheatsList[x].codestring, codeStr);
14751 strcpy(cheatsList[x].desc, desc);
14752 cheatsList[x].enabled = true;
14753 cheatsList[x].status = 0;
14754
14755 // we only store the old value for this simple codes. ROM patching
14756 // is taken care when it actually patches the ROM
14757 switch(cheatsList[x].size) {
14758 case INT_8_BIT_WRITE:
14759 cheatsList[x].oldValue = CPUReadByte(address);
14760 break;
14761 case INT_16_BIT_WRITE:
14762 cheatsList[x].oldValue = CPUReadHalfWord(address);
14763 break;
14764 case INT_32_BIT_WRITE:
14765 cheatsList[x].oldValue = CPUReadMemory(address);
14766 break;
14767 case CHEATS_16_BIT_WRITE:
14768 cheatsList[x].oldValue = CPUReadHalfWord(address);
14769 break;
14770 case CHEATS_32_BIT_WRITE:
14771 cheatsList[x].oldValue = CPUReadMemory(address);
14772 break;
14773 }
14774 cheatsNumber++;
14775 }
14776 }
14777
cheatsDelete(int number,bool restore)14778 void cheatsDelete(int number, bool restore)
14779 {
14780 if(number < cheatsNumber && number >= 0) {
14781 int x = number;
14782
14783 if(restore) {
14784 switch(cheatsList[x].size) {
14785 case INT_8_BIT_WRITE:
14786 CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue);
14787 break;
14788 case INT_16_BIT_WRITE:
14789 CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue);
14790 break;
14791 case INT_32_BIT_WRITE:
14792 CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
14793 break;
14794 case CHEATS_16_BIT_WRITE:
14795 if ((cheatsList[x].address>>24)>=0x08) {
14796 CHEAT_PATCH_ROM_16BIT(cheatsList[x].address, cheatsList[x].oldValue);
14797 } else {
14798 CPUWriteHalfWord(cheatsList[x].address, cheatsList[x].oldValue);
14799 }
14800 break;
14801 case CHEATS_32_BIT_WRITE:
14802 if ((cheatsList[x].address>>24)>=0x08) {
14803 CHEAT_PATCH_ROM_32BIT(cheatsList[x].address, cheatsList[x].oldValue);
14804 } else {
14805 CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
14806 }
14807 case GSA_16_BIT_ROM_PATCH:
14808 if(cheatsList[x].status & 1) {
14809 cheatsList[x].status &= ~1;
14810 CHEAT_PATCH_ROM_16BIT(cheatsList[x].address,
14811 cheatsList[x].oldValue);
14812 }
14813 break;
14814 case GSA_16_BIT_ROM_PATCH2C:
14815 case GSA_16_BIT_ROM_PATCH2D:
14816 case GSA_16_BIT_ROM_PATCH2E:
14817 case GSA_16_BIT_ROM_PATCH2F:
14818 if(cheatsList[x].status & 1) {
14819 cheatsList[x].status &= ~1;
14820 }
14821 break;
14822 case MASTER_CODE:
14823 mastercode=0;
14824 break;
14825 }
14826 }
14827 if((x+1) < cheatsNumber) {
14828 memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)*
14829 (cheatsNumber-x-1));
14830 }
14831 cheatsNumber--;
14832 }
14833 }
14834
cheatsDeleteAll(bool restore)14835 void cheatsDeleteAll(bool restore)
14836 {
14837 for(int i = cheatsNumber-1; i >= 0; i--) {
14838 cheatsDelete(i, restore);
14839 }
14840 }
14841
cheatsEnable(int i)14842 void cheatsEnable(int i)
14843 {
14844 if(i >= 0 && i < cheatsNumber) {
14845 cheatsList[i].enabled = true;
14846 mastercode = 0;
14847 }
14848 }
14849
cheatsDisable(int i)14850 void cheatsDisable(int i)
14851 {
14852 if(i >= 0 && i < cheatsNumber) {
14853 switch(cheatsList[i].size) {
14854 case GSA_16_BIT_ROM_PATCH:
14855 if(cheatsList[i].status & 1) {
14856 cheatsList[i].status &= ~1;
14857 CHEAT_PATCH_ROM_16BIT(cheatsList[i].address,
14858 cheatsList[i].oldValue);
14859 }
14860 break;
14861 case GSA_16_BIT_ROM_PATCH2C:
14862 case GSA_16_BIT_ROM_PATCH2D:
14863 case GSA_16_BIT_ROM_PATCH2E:
14864 case GSA_16_BIT_ROM_PATCH2F:
14865 if(cheatsList[i].status & 1) {
14866 cheatsList[i].status &= ~1;
14867 }
14868 break;
14869 case MASTER_CODE:
14870 mastercode=0;
14871 break;
14872 }
14873 cheatsList[i].enabled = false;
14874 }
14875 }
14876
cheatsVerifyCheatCode(const char * code,const char * desc)14877 bool cheatsVerifyCheatCode(const char *code, const char *desc)
14878 {
14879 size_t len = strlen(code);
14880 if(len != 11 && len != 13 && len != 17) {
14881 systemMessage("Invalid cheat code '%s': wrong length", code);
14882 return false;
14883 }
14884
14885 if(code[8] != ':') {
14886 systemMessage("Invalid cheat code '%s': no colon", code);
14887 return false;
14888 }
14889
14890 size_t i;
14891 for(i = 0; i < 8; i++) {
14892 if(!CHEAT_IS_HEX(code[i])) {
14893 // wrong cheat
14894 systemMessage("Invalid cheat code '%s': first part is not hex", code);
14895 return false;
14896 }
14897 }
14898 for(i = 9; i < len; i++) {
14899 if(!CHEAT_IS_HEX(code[i])) {
14900 // wrong cheat
14901 systemMessage("Invalid cheat code '%s' second part is not hex", code);
14902 return false;
14903 }
14904 }
14905
14906 u32 address = 0;
14907 u32 value = 0;
14908
14909 char buffer[10];
14910 strncpy(buffer, code, 8);
14911 buffer[8] = 0;
14912 sscanf(buffer, "%x", &address);
14913
14914 switch(address >> 24) {
14915 case 0x02:
14916 case 0x03:
14917 case 0x04:
14918 case 0x05:
14919 case 0x06:
14920 case 0x07:
14921 case 0x08:
14922 case 0x09:
14923 case 0x0A:
14924 case 0x0B:
14925 case 0x0C:
14926 case 0x0D:
14927 break;
14928 default:
14929 systemMessage("Invalid cheat code address: %08x",
14930 address);
14931 return false;
14932 }
14933
14934 strncpy(buffer, &code[9], 8);
14935 sscanf(buffer, "%x", &value);
14936 int type = 0;
14937 if(len == 13)
14938 type = 114;
14939 if(len == 17)
14940 type = 115;
14941 cheatsAdd(code, desc, address, address, value, type, type);
14942 return true;
14943 }
14944
cheatsAddCheatCode(const char * code,const char * desc)14945 void cheatsAddCheatCode(const char *code, const char *desc)
14946 {
14947 cheatsVerifyCheatCode(code, desc);
14948 }
14949
cheatsGSAGetDeadface(bool v3)14950 u16 cheatsGSAGetDeadface(bool v3)
14951 {
14952 for(int i = cheatsNumber-1; i >= 0; i--)
14953 if ((cheatsList[i].address == 0xDEADFACE) && (cheatsList[i].code == (v3 ? 257 : 256)))
14954 return cheatsList[i].value & 0xFFFF;
14955 return 0;
14956 }
14957
cheatsGSAChangeEncryption(u16 value,bool v3)14958 void cheatsGSAChangeEncryption(u16 value, bool v3) {
14959 int i;
14960 u8 *deadtable1, *deadtable2;
14961
14962 if (v3) {
14963 deadtable1 = (u8*)(&v3_deadtable1);
14964 deadtable2 = (u8*)(&v3_deadtable2);
14965 for (i = 0; i < 4; i++)
14966 seeds_v3[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
14967 }
14968 else {
14969 deadtable1 = (u8*)(&v1_deadtable1);
14970 deadtable2 = (u8*)(&v1_deadtable2);
14971 for (i = 0; i < 4; i++){
14972 seeds_v1[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
14973 }
14974 }
14975 }
14976
seed_gen(u8 upper,u8 seed,u8 * deadtable1,u8 * deadtable2)14977 u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2) {
14978 int i;
14979 u32 newseed = 0;
14980
14981 for (i = 0; i < 4; i++)
14982 newseed = ((newseed << 8) | ((deadtable1[(i + upper) & 0xFF] + deadtable2[seed]) & 0xFF));
14983
14984 return newseed;
14985 }
14986
cheatsDecryptGSACode(u32 & address,u32 & value,bool v3)14987 void cheatsDecryptGSACode(u32& address, u32& value, bool v3)
14988 {
14989 u32 rollingseed = 0xC6EF3720;
14990 u32 *seeds = v3 ? seeds_v3 : seeds_v1;
14991
14992 int bitsleft = 32;
14993 while (bitsleft > 0) {
14994 value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^
14995 ((address >> 5) + seeds[3]));
14996 address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^
14997 ((value >> 5) + seeds[1]));
14998 rollingseed -= 0x9E3779B9;
14999 bitsleft--;
15000 }
15001 }
15002
cheatsAddGSACode(const char * code,const char * desc,bool v3)15003 void cheatsAddGSACode(const char *code, const char *desc, bool v3)
15004 {
15005 if(strlen(code) != 16) {
15006 // wrong cheat
15007 systemMessage("Invalid GSA code. Format is XXXXXXXXYYYYYYYY");
15008 return;
15009 }
15010
15011 int i;
15012 for(i = 0; i < 16; i++) {
15013 if(!CHEAT_IS_HEX(code[i])) {
15014 // wrong cheat
15015 systemMessage("Invalid GSA code. Format is XXXXXXXXYYYYYYYY");
15016 return;
15017 }
15018 }
15019
15020 char buffer[10];
15021 strncpy(buffer, code, 8);
15022 buffer[8] = 0;
15023 u32 address;
15024 sscanf(buffer, "%x", &address);
15025 strncpy(buffer, &code[8], 8);
15026 buffer[8] = 0;
15027 u32 value;
15028 sscanf(buffer, "%x", &value);
15029 cheatsGSAChangeEncryption(cheatsGSAGetDeadface (v3), v3);
15030 cheatsDecryptGSACode(address, value, v3);
15031
15032 if(value == 0x1DC0DE) {
15033 u32 gamecode = READ32LE(((u32 *)&rom[0xac]));
15034 if(gamecode != address) {
15035 char buffer[5];
15036 *((u32 *)buffer) = address;
15037 buffer[4] = 0;
15038 char buffer2[5];
15039 *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac]));
15040 buffer2[4] = 0;
15041 systemMessage("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly.",
15042 buffer, buffer2);
15043 }
15044 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, v3 ? 257 : 256,
15045 UNKNOWN_CODE);
15046 return;
15047 }
15048 if(isMultilineWithData(cheatsNumber-1)) {
15049 cheatsAdd(code, desc, address, address, value, v3 ? 257 : 256, UNKNOWN_CODE);
15050 return;
15051 }
15052 if(v3) {
15053 int type = ((address >> 25) & 127) | ((address >> 17) & 0x80);
15054 u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF);
15055 u16 mcode = (address>>24 & 0xFF);
15056
15057 if ((mcode & 0xFE) == 0xC4)
15058 {
15059 cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | (0x08000000),
15060 value, 257, MASTER_CODE);
15061 mastercode = (address & 0x1FFFFFF) | (0x08000000);
15062 }
15063 else
15064 switch(type) {
15065 case 0x00:
15066 if(address == 0) {
15067 type = (value >> 25) & 127;
15068 addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF);
15069 switch(type) {
15070 case 0x04:
15071 cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN);
15072 break;
15073 case 0x08:
15074 cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_GS_WRITE2);
15075 break;
15076 case 0x09:
15077 cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_GS_WRITE2);
15078 break;
15079 case 0x0a:
15080 cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_GS_WRITE2);
15081 break;
15082 case 0x0c:
15083 cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2C);
15084 break;
15085 case 0x0d:
15086 cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2D);
15087 break;
15088 case 0x0e:
15089 cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2E);
15090 break;
15091 case 0x0f:
15092 cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2F);
15093 break;
15094 case 0x20:
15095 cheatsAdd(code, desc, address, 0, addr, 257, GSA_CODES_ON);
15096 break;
15097 case 0x40:
15098 cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_SLIDE);
15099 break;
15100 case 0x41:
15101 cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_SLIDE);
15102 break;
15103 case 0x42:
15104 cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_SLIDE);
15105 break;
15106 default:
15107 cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
15108 break;
15109 }
15110 } else
15111 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_FILL);
15112 break;
15113 case 0x01:
15114 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_FILL);
15115 break;
15116 case 0x02:
15117 cheatsAdd(code, desc, address, addr, value, 257, INT_32_BIT_WRITE);
15118 break;
15119 case 0x04:
15120 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE);
15121 break;
15122 case 0x05:
15123 cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_TRUE);
15124 break;
15125 case 0x06:
15126 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE);
15127 break;
15128 case 0x07:
15129 cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS);
15130 break;
15131 case 0x08:
15132 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE);
15133 break;
15134 case 0x09:
15135 cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_FALSE);
15136 break;
15137 case 0x0a:
15138 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE);
15139 break;
15140 case 0xc:
15141 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S);
15142 break;
15143 case 0xd:
15144 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S);
15145 break;
15146 case 0xe:
15147 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S);
15148 break;
15149 case 0x10:
15150 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S);
15151 break;
15152 case 0x11:
15153 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S);
15154 break;
15155 case 0x12:
15156 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S);
15157 break;
15158 case 0x14:
15159 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U);
15160 break;
15161 case 0x15:
15162 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U);
15163 break;
15164 case 0x16:
15165 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U);
15166 break;
15167 case 0x18:
15168 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U);
15169 break;
15170 case 0x19:
15171 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U);
15172 break;
15173 case 0x1A:
15174 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U);
15175 break;
15176 case 0x1C:
15177 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND);
15178 break;
15179 case 0x1D:
15180 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND);
15181 break;
15182 case 0x1E:
15183 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND);
15184 break;
15185 case 0x20:
15186 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_POINTER);
15187 break;
15188 case 0x21:
15189 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_POINTER);
15190 break;
15191 case 0x22:
15192 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_POINTER);
15193 break;
15194 case 0x24:
15195 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE2);
15196 break;
15197 case 0x25:
15198 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE2);
15199 break;
15200 case 0x26:
15201 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE2);
15202 break;
15203 case 0x27:
15204 cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS2);
15205 break;
15206 case 0x28:
15207 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE2);
15208 break;
15209 case 0x29:
15210 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE2);
15211 break;
15212 case 0x2a:
15213 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE2);
15214 break;
15215 case 0x2c:
15216 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S2);
15217 break;
15218 case 0x2d:
15219 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S2);
15220 break;
15221 case 0x2e:
15222 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S2);
15223 break;
15224 case 0x30:
15225 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S2);
15226 break;
15227 case 0x31:
15228 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S2);
15229 break;
15230 case 0x32:
15231 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S2);
15232 break;
15233 case 0x34:
15234 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U2);
15235 break;
15236 case 0x35:
15237 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U2);
15238 break;
15239 case 0x36:
15240 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U2);
15241 break;
15242 case 0x38:
15243 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U2);
15244 break;
15245 case 0x39:
15246 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U2);
15247 break;
15248 case 0x3A:
15249 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U2);
15250 break;
15251 case 0x3C:
15252 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND2);
15253 break;
15254 case 0x3D:
15255 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND2);
15256 break;
15257 case 0x3E:
15258 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND2);
15259 break;
15260 case 0x40:
15261 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_ADD);
15262 break;
15263 case 0x41:
15264 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_ADD);
15265 break;
15266 case 0x42:
15267 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_ADD);
15268 break;
15269 case 0x44:
15270 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE3);
15271 break;
15272 case 0x45:
15273 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE3);
15274 break;
15275 case 0x46:
15276 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE3);
15277 break;
15278 case 0x47:
15279 cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS3);
15280 break;
15281 case 0x48:
15282 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE3);
15283 break;
15284 case 0x49:
15285 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE3);
15286 break;
15287 case 0x4a:
15288 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE3);
15289 break;
15290 case 0x4c:
15291 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S3);
15292 break;
15293 case 0x4d:
15294 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S3);
15295 break;
15296 case 0x4e:
15297 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S3);
15298 break;
15299 case 0x50:
15300 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S3);
15301 break;
15302 case 0x51:
15303 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S3);
15304 break;
15305 case 0x52:
15306 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S3);
15307 break;
15308 case 0x54:
15309 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U3);
15310 break;
15311 case 0x55:
15312 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U3);
15313 break;
15314 case 0x56:
15315 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U3);
15316 break;
15317 case 0x58:
15318 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U3);
15319 break;
15320 case 0x59:
15321 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U3);
15322 break;
15323 case 0x5a:
15324 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U3);
15325 break;
15326 case 0x5c:
15327 cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND3);
15328 break;
15329 case 0x5d:
15330 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND3);
15331 break;
15332 case 0x5e:
15333 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND3);
15334 break;
15335 case 0x63:
15336 cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_WRITE_IOREGS);
15337 break;
15338 case 0xE3:
15339 cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_WRITE_IOREGS);
15340 break;
15341 default:
15342 cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
15343 break;
15344 }
15345 } else {
15346 int type = (address >> 28) & 15;
15347 switch(type) {
15348 case 0:
15349 case 1:
15350 case 2:
15351 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, type);
15352 break;
15353 case 3:
15354 switch ((address >> 0x10) & 0xFF){
15355 case 0x00:
15356 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_GROUP_WRITE);
15357 break;
15358 case 0x10:
15359 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFF, 256, GSA_32_BIT_ADD );
15360 break;
15361 case 0x20:
15362 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFF)+1), 256, GSA_32_BIT_ADD );
15363 break;
15364 case 0x30:
15365 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, GSA_32_BIT_ADD );
15366 break;
15367 case 0x40:
15368 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFFFF)+1), 256, GSA_32_BIT_ADD );
15369 break;
15370 case 0x50:
15371 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_ADD2);
15372 break;
15373 case 0x60:
15374 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_SUB2);
15375 break;
15376 default:
15377 // unsupported code
15378 cheatsAdd(code, desc, address, address, value, 256,
15379 UNKNOWN_CODE);
15380 break;
15381 }
15382 break;
15383 case 6:
15384 address <<= 1;
15385 type = (value >> 24) & 0xFF;
15386 if(type == 0x00) {
15387 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
15388 GSA_16_BIT_ROM_PATCH);
15389 break;
15390 }
15391 // unsupported code
15392 cheatsAdd(code, desc, address, address, value, 256,
15393 UNKNOWN_CODE);
15394 break;
15395 case 8:
15396 switch((address >> 20) & 15) {
15397 case 1:
15398 cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
15399 GSA_8_BIT_GS_WRITE);
15400 break;
15401 case 2:
15402 cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
15403 GSA_16_BIT_GS_WRITE);
15404 break;
15405 case 4:
15406 // This code is buggy : the value is always set to 0 !
15407 cheatsAdd(code, desc, address, address & 0x0F0FFFFF, 0, 256,
15408 GSA_32_BIT_GS_WRITE);
15409 break;
15410 case 15:
15411 cheatsAdd(code, desc, address, 0, value & 0xFFFF, 256, GSA_SLOWDOWN);
15412 break;
15413 default:
15414 // unsupported code
15415 cheatsAdd(code, desc, address, address, value, 256,
15416 UNKNOWN_CODE);
15417 break;
15418 }
15419 break;
15420 case 0x0d:
15421 if(address != 0xDEADFACE) {
15422 switch((value >> 20) & 0xF) {
15423 case 0:
15424 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
15425 CBA_IF_TRUE);
15426 break;
15427 case 1:
15428 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
15429 CBA_IF_FALSE);
15430 break;
15431 case 2:
15432 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
15433 GSA_16_BIT_IF_LOWER_OR_EQ_U);
15434 break;
15435 case 3:
15436 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
15437 GSA_16_BIT_IF_HIGHER_OR_EQ_U);
15438 break;
15439 default:
15440 // unsupported code
15441 cheatsAdd(code, desc, address, address, value, 256,
15442 UNKNOWN_CODE);
15443 break;
15444 }
15445 } else
15446 cheatsAdd(code, desc, address, address, value, 256,
15447 UNKNOWN_CODE);
15448 break;
15449 case 0x0e:
15450 switch((value >> 28) & 0xF) {
15451 case 0:
15452 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
15453 GSA_16_BIT_MIF_TRUE);
15454 break;
15455 case 1:
15456 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
15457 GSA_16_BIT_MIF_FALSE);
15458 break;
15459 case 2:
15460 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
15461 GSA_16_BIT_MIF_LOWER_OR_EQ_U);
15462 break;
15463 case 3:
15464 cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
15465 GSA_16_BIT_MIF_HIGHER_OR_EQ_U);
15466 break;
15467 default:
15468 // unsupported code
15469 cheatsAdd(code, desc, address, address, value, 256,
15470 UNKNOWN_CODE);
15471 break;
15472 }
15473 break;
15474 case 0x0f:
15475 cheatsAdd(code, desc, address, (address & 0xFFFFFFF), value, 256, MASTER_CODE);
15476 mastercode = (address & 0xFFFFFFF);
15477 break;
15478 default:
15479 // unsupported code
15480 cheatsAdd(code, desc, address, address, value, 256,
15481 UNKNOWN_CODE);
15482 break;
15483 }
15484 }
15485 }
15486
cheatsImportGSACodeFile(const char * name,int game,bool v3)15487 bool cheatsImportGSACodeFile(const char *name, int game, bool v3)
15488 {
15489 FILE *f = fopen(name, "rb");
15490 if(!f)
15491 return false;
15492
15493 int games = 0;
15494 int len = 0;
15495 fseek(f, 0x1e, SEEK_CUR);
15496 fread(&games, 1, 4, f);
15497 bool found = false;
15498 int g = 0;
15499 while(games > 0) {
15500 if(g == game) {
15501 found = true;
15502 break;
15503 }
15504 fread(&len, 1, 4, f);
15505 fseek(f,len,SEEK_CUR);
15506 int codes = 0;
15507 fread(&codes, 1, 4, f);
15508 while(codes > 0) {
15509 fread(&len, 1, 4, f);
15510 fseek(f, len, SEEK_CUR);
15511 fseek(f, 8, SEEK_CUR);
15512 fread(&len, 1, 4, f);
15513 fseek(f, len*12, SEEK_CUR);
15514 codes--;
15515 }
15516 games--;
15517 g++;
15518 }
15519 if(found) {
15520 char desc[256];
15521 char code[17];
15522 fread(&len, 1, 4, f);
15523 fseek(f, len, SEEK_CUR);
15524 int codes = 0;
15525 fread(&codes, 1, 4, f);
15526 while(codes > 0) {
15527 fread(&len, 1, 4, f);
15528 fread(desc, 1, len, f);
15529 desc[len] =0;
15530 desc[31] = 0;
15531 fread(&len, 1, 4, f);
15532 fseek(f, len, SEEK_CUR);
15533 fseek(f, 4, SEEK_CUR);
15534 fread(&len, 1, 4, f);
15535 while(len) {
15536 fseek(f, 4, SEEK_CUR);
15537 fread(code, 1, 8, f);
15538 fseek(f, 4, SEEK_CUR);
15539 fread(&code[8], 1, 8, f);
15540 code[16] = 0;
15541 cheatsAddGSACode(code, desc, v3);
15542 len -= 2;
15543 }
15544 codes--;
15545 }
15546 }
15547 fclose(f);
15548 return false;
15549 }
15550
cheatsCBAReverseArray(u8 * array,u8 * dest)15551 void cheatsCBAReverseArray(u8 *array, u8 *dest)
15552 {
15553 dest[0] = array[3];
15554 dest[1] = array[2];
15555 dest[2] = array[1];
15556 dest[3] = array[0];
15557 dest[4] = array[5];
15558 dest[5] = array[4];
15559 }
15560
chatsCBAScramble(u8 * array,int count,u8 b)15561 void chatsCBAScramble(u8 *array, int count, u8 b)
15562 {
15563 u8 *x = array + (count >> 3);
15564 u8 *y = array + (b >> 3);
15565 u32 z = *x & (1 << (count & 7));
15566 u32 x0 = (*x & (~(1 << (count & 7))));
15567 if (z != 0)
15568 z = 1;
15569 if ((*y & (1 << (b & 7))) != 0)
15570 x0 |= (1 << (count & 7));
15571 *x = x0;
15572 u32 temp = *y & (~(1 << (b & 7)));
15573 if (z != 0)
15574 temp |= (1 << (b & 7));
15575 *y = temp;
15576 }
15577
cheatsCBAGetValue(u8 * array)15578 u32 cheatsCBAGetValue(u8 *array)
15579 {
15580 return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24;
15581 }
15582
cheatsCBAGetData(u8 * array)15583 u16 cheatsCBAGetData(u8 *array)
15584 {
15585 return array[4] | array[5]<<8;
15586 }
15587
cheatsCBAArrayToValue(u8 * array,u8 * dest)15588 void cheatsCBAArrayToValue(u8 *array, u8 *dest)
15589 {
15590 dest[0] = array[3];
15591 dest[1] = array[2];
15592 dest[2] = array[1];
15593 dest[3] = array[0];
15594 dest[4] = array[5];
15595 dest[5] = array[4];
15596 }
15597
cheatsCBAParseSeedCode(u32 address,u32 value,u32 * array)15598 void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array)
15599 {
15600 array[0] = 1;
15601 array[1] = value & 0xFF;
15602 array[2] = (address >> 0x10) & 0xFF;
15603 array[3] = (value >> 8) & 0xFF;
15604 array[4] = (address >> 0x18) & 0x0F;
15605 array[5] = address & 0xFFFF;
15606 array[6] = address;
15607 array[7] = value;
15608 }
15609
cheatsCBAEncWorker()15610 u32 cheatsCBAEncWorker()
15611 {
15612 u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039;
15613 u32 y = (x * 0x41c64e6d) + 0x3039;
15614 u32 z = x >> 0x10;
15615 x = ((y >> 0x10) & 0x7fff) << 0x0f;
15616 z = (z << 0x1e) | x;
15617 x = (y * 0x41c64e6d) + 0x3039;
15618 cheatsCBATemporaryValue = x;
15619 return z | ((x >> 0x10) & 0x7fff);
15620 }
15621
15622 #define ROR(v, s) \
15623 (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
15624
cheatsCBACalcIndex(u32 x,u32 y)15625 u32 cheatsCBACalcIndex(u32 x, u32 y)
15626 {
15627 if(y != 0) {
15628 if(y == 1)
15629 x = 0;
15630 else if(x == y)
15631 x = 0;
15632 if(y < 1)
15633 return x;
15634 else if(x < y)
15635 return x;
15636 u32 x0 = 1;
15637
15638 while(y < 0x10000000) {
15639 if(y < x) {
15640 y = y << 4;
15641 x0 = x0 << 4;
15642 } else break;
15643 }
15644
15645 while(y < 0x80000000) {
15646 if(y < x) {
15647 y = y << 1;
15648 x0 = x0 << 1;
15649 } else break;
15650 }
15651
15652 loop:
15653 u32 z = 0;
15654 if(x >= y)
15655 x -= y;
15656 if(x >= (y >> 1)) {
15657 x -= (y >> 1);
15658 z |= ROR(x0, 1);
15659 }
15660 if(x >= (y >> 2)) {
15661 x -= (y >> 2);
15662 z |= ROR(x0, 2);
15663 }
15664 if(x >= (y >> 3)) {
15665 x -= (y >> 3);
15666 z |= ROR(x0, 3);
15667 }
15668
15669 u32 temp = x0;
15670
15671 if(x != 0) {
15672 x0 = x0 >> 4;
15673 if(x0 != 0) {
15674 y = y >> 4;
15675 goto loop;
15676 }
15677 }
15678
15679 z = z & 0xe0000000;
15680
15681 if(z != 0) {
15682 if((temp & 7) == 0)
15683 return x;
15684 } else
15685 return x;
15686
15687 if((z & ROR(temp, 3)) != 0)
15688 x += y >> 3;
15689 if((z & ROR(temp, 2)) != 0)
15690 x += y >> 2;
15691 if((z & ROR(temp, 1)) != 0)
15692 x += y >> 1;
15693 return x;
15694 } else {
15695 }
15696 // should not happen in the current code
15697 return 0;
15698 }
15699
cheatsCBAUpdateSeedBuffer(u32 a,u8 * buffer,int count)15700 void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count)
15701 {
15702 int i;
15703 for(i = 0; i < count; i++)
15704 buffer[i] = i;
15705 for(i = 0; (u32)i < a; i++) {
15706 u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
15707 u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
15708 u32 t = buffer[a];
15709 buffer[a] = buffer[b];
15710 buffer[b] = t;
15711 }
15712 }
15713
cheatsCBAChangeEncryption(u32 * seed)15714 void cheatsCBAChangeEncryption(u32 *seed)
15715 {
15716 int i;
15717
15718 cheatsCBATemporaryValue = (seed[1] ^ 0x1111);
15719 cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30);
15720 cheatsCBATemporaryValue = 0x4efad1c3;
15721
15722 for(i = 0; (u32)i < seed[4]; i++) {
15723 cheatsCBATemporaryValue = cheatsCBAEncWorker();
15724 }
15725 cheatsCBASeed[2] = cheatsCBAEncWorker();
15726 cheatsCBASeed[3] = cheatsCBAEncWorker();
15727
15728 cheatsCBATemporaryValue = seed[3] ^ 0xf254;
15729
15730 for(i = 0; (u32)i < seed[3]; i++) {
15731 cheatsCBATemporaryValue = cheatsCBAEncWorker();
15732 }
15733
15734 cheatsCBASeed[0] = cheatsCBAEncWorker();
15735 cheatsCBASeed[1] = cheatsCBAEncWorker();
15736
15737 *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6];
15738 *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7];
15739 *((u32 *)&cheatsCBACurrentSeed[8]) = 0;
15740 }
15741
cheatsCBAGenValue(u32 x,u32 y,u32 z)15742 u16 cheatsCBAGenValue(u32 x, u32 y, u32 z)
15743 {
15744 y <<= 0x10;
15745 z <<= 0x10;
15746 x <<= 0x18;
15747 u32 x0 = (int)y >> 0x10;
15748 z = (int)z >> 0x10;
15749 x = (int)x >> 0x10;
15750 for(int i = 0; i < 8; i++) {
15751 u32 temp = z ^ x;
15752 if ((int)temp >= 0) {
15753 temp = z << 0x11;
15754 }
15755 else {
15756 temp = z << 0x01;
15757 temp ^= x0;
15758 temp = temp << 0x10;
15759 }
15760 z = (int)temp >> 0x10;
15761 temp = x << 0x11;
15762 x = (int)temp >> 0x10;
15763 }
15764 return z & 0xffff;
15765 }
15766
cheatsCBAGenTable()15767 void cheatsCBAGenTable() {
15768 for (int i = 0; i < 0x100; i++) {
15769 cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0);
15770 }
15771 cheatsCBATableGenerated = true;
15772 }
15773
cheatsCBACalcCRC(u8 * rom,int count)15774 u16 cheatsCBACalcCRC(u8 *rom, int count)
15775 {
15776 u32 crc = 0xffffffff;
15777
15778 if (count & 3) {
15779 // 0x08000EAE
15780 } else {
15781 count = (count >> 2) - 1;
15782 if(count != -1) {
15783 while(count != -1) {
15784 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
15785 ^ *rom++]) << 0x10) >> 0x10;
15786 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
15787 ^ *rom++]) << 0x10) >> 0x10;
15788 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
15789 ^ *rom++]) << 0x10) >> 0x10;
15790 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
15791 ^ *rom++]) << 0x10) >> 0x10;
15792 count--;
15793 }
15794 }
15795 }
15796 return crc & 0xffff;
15797 }
15798
cheatsCBADecrypt(u8 * decrypt)15799 void cheatsCBADecrypt(u8 *decrypt)
15800 {
15801 u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
15802 u8 *array = &buffer[1];
15803
15804 cheatsCBAReverseArray(decrypt, array);
15805
15806 for(int count = 0x2f; count >= 0; count--) {
15807 chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]);
15808 }
15809 cheatsCBAArrayToValue(array, decrypt);
15810 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^
15811 cheatsCBASeed[0];
15812 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^
15813 cheatsCBASeed[1]) & 0xffff;
15814
15815 cheatsCBAReverseArray(decrypt, array);
15816
15817 u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed);
15818 for(int i = 0; i <= 4; i++) {
15819 array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ;
15820 }
15821
15822 array[5] = (cs >> 8) ^ array[5];
15823
15824 for(int j = 5; j >=0; j--) {
15825 array[j] = (cs ^ array[j-1]) ^ array[j];
15826 }
15827
15828 cheatsCBAArrayToValue(array, decrypt);
15829
15830 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt)
15831 ^ cheatsCBASeed[2];
15832 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt)
15833 ^ cheatsCBASeed[3]) & 0xffff;
15834 }
15835
cheatsCBAGetCount()15836 int cheatsCBAGetCount()
15837 {
15838 int count = 0;
15839 for(int i = 0; i < cheatsNumber; i++) {
15840 if(cheatsList[i].code == 512)
15841 count++;
15842 }
15843 return count;
15844 }
15845
cheatsCBAShouldDecrypt()15846 bool cheatsCBAShouldDecrypt()
15847 {
15848 for(int i = 0; i < cheatsNumber; i++) {
15849 if(cheatsList[i].code == 512) {
15850 return (cheatsList[i].codestring[0] == '9');
15851 }
15852 }
15853 return false;
15854 }
15855
cheatsAddCBACode(const char * code,const char * desc)15856 void cheatsAddCBACode(const char *code, const char *desc)
15857 {
15858 if(strlen(code) != 13) {
15859 // wrong cheat
15860 systemMessage("Invalid CBA code. Format is XXXXXXXX YYYY.");
15861 return;
15862 }
15863
15864 int i;
15865 for(i = 0; i < 8; i++) {
15866 if(!CHEAT_IS_HEX(code[i])) {
15867 // wrong cheat
15868 systemMessage("Invalid CBA code. Format is XXXXXXXX YYYY.");
15869 return;
15870 }
15871 }
15872
15873 if(code[8] != ' ') {
15874 systemMessage("Invalid CBA code. Format is XXXXXXXX YYYY.");
15875 return;
15876 }
15877
15878 for(i = 9; i < 13; i++) {
15879 if(!CHEAT_IS_HEX(code[i])) {
15880 // wrong cheat
15881 systemMessage("Invalid CBA code. Format is XXXXXXXX YYYY.");
15882 return;
15883 }
15884 }
15885
15886 char buffer[10];
15887 strncpy(buffer, code, 8);
15888 buffer[8] = 0;
15889 u32 address;
15890 sscanf(buffer, "%x", &address);
15891 strncpy(buffer, &code[9], 4);
15892 buffer[4] = 0;
15893 u32 value;
15894 sscanf(buffer, "%x", &value);
15895
15896 u8 array[8] = {
15897 (u8)(address & 255),
15898 (u8)((address >> 8) & 255),
15899 (u8)((address >> 16) & 255),
15900 (u8)((address >> 24) & 255),
15901 (u8)(value & 255),
15902 (u8)((value >> 8) & 255),
15903 0,
15904 0
15905 };
15906
15907 if(cheatsCBAGetCount() == 0 &&
15908 (address >> 28) == 9) {
15909 u32 seed[8];
15910 cheatsCBAParseSeedCode(address, value, seed);
15911 cheatsCBAChangeEncryption(seed);
15912 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE);
15913 } else {
15914 if(cheatsCBAShouldDecrypt())
15915 cheatsCBADecrypt(array);
15916
15917 address = READ32LE(((u32 *)array));
15918 value = READ16LE(((u16 *)&array[4]));
15919
15920 int type = (address >> 28) & 15;
15921
15922 if(isMultilineWithData(cheatsNumber-1) || (super>0)) {
15923 cheatsAdd(code, desc, address, address, value, 512, UNKNOWN_CODE);
15924 if (super>0)
15925 super-= 1;
15926 return;
15927 }
15928
15929 switch(type) {
15930 case 0x00:
15931 {
15932 if(!cheatsCBATableGenerated)
15933 cheatsCBAGenTable();
15934 u32 crc = cheatsCBACalcCRC(rom, 0x10000);
15935 if(crc != address) {
15936 systemMessage("Warning: Codes seem to be for a different game.\nCodes may not work correctly.");
15937 }
15938 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
15939 UNKNOWN_CODE);
15940 }
15941 break;
15942 case 0x01:
15943 cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | 0x08000000, value, 512, MASTER_CODE);
15944 mastercode = (address & 0x1FFFFFF) | 0x08000000;
15945 break;
15946 case 0x02:
15947 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15948 CBA_OR);
15949 break;
15950 case 0x03:
15951 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
15952 INT_8_BIT_WRITE);
15953 break;
15954 case 0x04:
15955 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15956 CBA_SLIDE_CODE);
15957 break;
15958 case 0x05:
15959 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15960 CBA_SUPER);
15961 super = getCodeLength(cheatsNumber-1);
15962 break;
15963 case 0x06:
15964 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15965 CBA_AND);
15966 break;
15967 case 0x07:
15968 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15969 CBA_IF_TRUE);
15970 break;
15971 case 0x08:
15972 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15973 INT_16_BIT_WRITE);
15974 break;
15975 case 0x0a:
15976 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15977 CBA_IF_FALSE);
15978 break;
15979 case 0x0b:
15980 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15981 CBA_GT);
15982 break;
15983 case 0x0c:
15984 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15985 CBA_LT);
15986 break;
15987 case 0x0d:
15988 if ((address & 0xF0)<0x30)
15989 cheatsAdd(code, desc, address, address & 0xF0, value, 512,
15990 CBA_IF_KEYS_PRESSED);
15991 break;
15992 case 0x0e:
15993 cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0x8000 ? value | 0xFFFF0000 : value, 512,
15994 CBA_ADD);
15995 break;
15996 case 0x0f:
15997 cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
15998 GSA_16_BIT_IF_AND);
15999 break;
16000 default:
16001 // unsupported code
16002 cheatsAdd(code, desc, address, address & 0xFFFFFFFF, value, 512,
16003 UNKNOWN_CODE);
16004 break;
16005 }
16006 }
16007 }
16008
16009 #if (0)
Xbox_cheatsSaveGame(HANDLE file)16010 void Xbox_cheatsSaveGame(HANDLE file)
16011 {
16012 xStorage.WriteStream(file,(char *)cheatsNumber, sizeof(int));
16013 xStorage.WriteStream(file,(char *)cheatsList, sizeof(cheatsList));
16014
16015 }
16016 #endif
16017
cheatsSaveCheatList(const char * file)16018 void cheatsSaveCheatList(const char *file)
16019 {
16020 if(cheatsNumber == 0)
16021 return;
16022 FILE *f = fopen(file, "wb");
16023 if(f == NULL)
16024 return;
16025 int version = 1;
16026 fwrite(&version, 1, sizeof(version), f);
16027 int type = 1;
16028 fwrite(&type, 1, sizeof(type), f);
16029 fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f);
16030 fwrite(cheatsList, 1, sizeof(cheatsList), f);
16031 fclose(f);
16032 }
16033
cheatsLoadCheatList(const char * file)16034 bool cheatsLoadCheatList(const char *file)
16035 {
16036
16037 int count = 0;
16038
16039 FILE *f = fopen(file, "rb");
16040
16041 if(f == NULL)
16042 return false;
16043
16044 int version = 0;
16045
16046 if(fread(&version, 1, sizeof(version), f) != sizeof(version)) {
16047 fclose(f);
16048 return false;
16049 }
16050
16051 if(version != 1) {
16052 systemMessage("Unsupported cheat list version %d", version);
16053 fclose(f);
16054 return false;
16055 }
16056
16057 int type = 0;
16058 if(fread(&type, 1, sizeof(type), f) != sizeof(type)) {
16059 fclose(f);
16060 return false;
16061 }
16062
16063
16064 if((type != 0) && (type != 1)) {
16065 systemMessage("Unsupported cheat list type %d", type);
16066 fclose(f);
16067 return false;
16068 }
16069
16070 if(fread(&count, 1, sizeof(count), f) != sizeof(count)) {
16071 fclose(f);
16072 return false;
16073 }
16074 if (type == 1)
16075 {
16076 if(fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) {
16077 fclose(f);
16078 return false;
16079 }
16080 }
16081 else if (type == 0)
16082 {
16083 for(int i = 0; i < count; i++) {
16084 fread(&cheatsList[i].code, 1, sizeof(int),f);
16085 fread(&cheatsList[i].size, 1, sizeof(int),f);
16086 fread(&cheatsList[i].status, 1, sizeof(int),f);
16087 fread(&cheatsList[i].enabled, 1, sizeof(int),f);
16088 cheatsList[i].enabled = cheatsList[i].enabled ? true : false;
16089 fread(&cheatsList[i].address, 1, sizeof(u32),f);
16090 cheatsList[i].rawaddress = cheatsList[i].address;
16091 fread(&cheatsList[i].value, 1, sizeof(u32),f);
16092 fread(&cheatsList[i].oldValue, 1, sizeof(u32),f);
16093 fread(&cheatsList[i].codestring, 1, 20*sizeof(char),f);
16094 if(fread(&cheatsList[i].desc, 1, 32*sizeof(char),f) != 32*sizeof(char)) {
16095 fclose(f);
16096 return false;
16097 }
16098 }
16099 }
16100
16101 bool firstCodeBreaker = true;
16102
16103 for(int i = 0; i < count; i++) {
16104 cheatsList[i].status = 0; // remove old status as it is not used
16105 if(!cheatsList[i].codestring[0]) {
16106 switch(cheatsList[i].size) {
16107 case 0:
16108 sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
16109 cheatsList[i].value);
16110 break;
16111 case 1:
16112 sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
16113 cheatsList[i].value);
16114 break;
16115 case 2:
16116 sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
16117 cheatsList[i].value);
16118 break;
16119 }
16120 }
16121
16122 if(cheatsList[i].code == 512 && firstCodeBreaker) {
16123 firstCodeBreaker = false;
16124 char buffer[10];
16125 strncpy(buffer, cheatsList[i].codestring, 8);
16126 buffer[8] = 0;
16127 u32 address;
16128 sscanf(buffer, "%x", &address);
16129 if((address >> 28) == 9) {
16130 strncpy(buffer, &cheatsList[i].codestring[9], 4);
16131 buffer[4] = 0;
16132 u32 value;
16133 sscanf(buffer, "%x", &value);
16134
16135 u32 seed[8];
16136 cheatsCBAParseSeedCode(address, value, seed);
16137 cheatsCBAChangeEncryption(seed);
16138 }
16139 }
16140 }
16141 cheatsNumber = count;
16142 fclose(f);
16143 return true;
16144 }
16145
16146 extern int cpuNextEvent;
16147
16148 extern void debuggerBreakOnWrite(u32 , u32, u32, int, int);
16149
16150 #ifdef BKPT_SUPPORT
cheatsGetType(u32 address)16151 static u8 cheatsGetType(u32 address)
16152 {
16153 switch(address >> 24) {
16154 case 2:
16155 return freezeWorkRAM[address & 0x3FFFF];
16156 case 3:
16157 return freezeInternalRAM[address & 0x7FFF];
16158 case 5:
16159 return freezePRAM[address & 0x3FC];
16160 case 6:
16161 if (address > 0x06010000)
16162 return freezeVRAM[address & 0x17FFF];
16163 else
16164 return freezeVRAM[address & 0x1FFFF];
16165 case 7:
16166 return freezeOAM[address & 0x3FC];
16167 }
16168 return 0;
16169 }
16170 #endif
16171
cheatsWriteMemory(u32 address,u32 value)16172 void cheatsWriteMemory(u32 address, u32 value)
16173 {
16174 #ifdef BKPT_SUPPORT
16175 #ifdef SDL
16176 if(cheatsNumber == 0) {
16177 int type = cheatsGetType(address);
16178 u32 oldValue = debuggerReadMemory(address);
16179 if(type == 1 || (type == 2 && oldValue != value)) {
16180 debuggerBreakOnWrite(address, oldValue, value, 2, type);
16181 cpuNextEvent = 0;
16182 }
16183 debuggerWriteMemory(address, value);
16184 }
16185 #endif
16186 #endif
16187 }
16188
cheatsWriteHalfWord(u32 address,u16 value)16189 void cheatsWriteHalfWord(u32 address, u16 value)
16190 {
16191 #ifdef BKPT_SUPPORT
16192 #ifdef SDL
16193 if(cheatsNumber == 0) {
16194 int type = cheatsGetType(address);
16195 u16 oldValue = debuggerReadHalfWord(address);
16196 if(type == 1 || (type == 2 && oldValue != value)) {
16197 debuggerBreakOnWrite(address, oldValue, value, 1, type);
16198 cpuNextEvent = 0;
16199 }
16200 debuggerWriteHalfWord(address, value);
16201 }
16202 #endif
16203 #endif
16204 }
16205
16206 #if defined BKPT_SUPPORT && defined SDL
cheatsWriteByte(u32 address,u8 value)16207 void cheatsWriteByte(u32 address, u8 value)
16208 #else
16209 void cheatsWriteByte(u32, u8)
16210 #endif
16211 {
16212 #ifdef BKPT_SUPPORT
16213 #ifdef SDL
16214 if(cheatsNumber == 0) {
16215 int type = cheatsGetType(address);
16216 u8 oldValue = debuggerReadByte(address);
16217 if(type == 1 || (type == 2 && oldValue != value)) {
16218 debuggerBreakOnWrite(address, oldValue, value, 0, type);
16219 cpuNextEvent = 0;
16220 }
16221 debuggerWriteByte(address, value);
16222 }
16223 #endif
16224 #endif
16225 }
16226