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 &currentX, 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 &currentX, 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