1 /***********************************************************************************
2   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3 
4   (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5                              Jerremy Koot (jkoot@snes9x.com)
6 
7   (c) Copyright 2002 - 2004  Matthew Kendora
8 
9   (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10 
11   (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12 
13   (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14 
15   (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16                              Kris Bleakley (codeviolation@hotmail.com)
17 
18   (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19                              Nach (n-a-c-h@users.sourceforge.net),
20                              zones (kasumitokoduck@yahoo.com)
21 
22   (c) Copyright 2006 - 2007  nitsuja
23 
24   (c) Copyright 2009 - 2010  BearOso,
25                              OV2
26 
27 
28   BS-X C emulator code
29   (c) Copyright 2005 - 2006  Dreamer Nom,
30                              zones
31 
32   C4 x86 assembler and some C emulation code
33   (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
34                              Nach,
35                              zsKnight (zsknight@zsnes.com)
36 
37   C4 C++ code
38   (c) Copyright 2003 - 2006  Brad Jorsch,
39                              Nach
40 
41   DSP-1 emulator code
42   (c) Copyright 1998 - 2006  _Demo_,
43                              Andreas Naive (andreasnaive@gmail.com),
44                              Gary Henderson,
45                              Ivar (ivar@snes9x.com),
46                              John Weidman,
47                              Kris Bleakley,
48                              Matthew Kendora,
49                              Nach,
50                              neviksti (neviksti@hotmail.com)
51 
52   DSP-2 emulator code
53   (c) Copyright 2003         John Weidman,
54                              Kris Bleakley,
55                              Lord Nightmare (lord_nightmare@users.sourceforge.net),
56                              Matthew Kendora,
57                              neviksti
58 
59   DSP-3 emulator code
60   (c) Copyright 2003 - 2006  John Weidman,
61                              Kris Bleakley,
62                              Lancer,
63                              z80 gaiden
64 
65   DSP-4 emulator code
66   (c) Copyright 2004 - 2006  Dreamer Nom,
67                              John Weidman,
68                              Kris Bleakley,
69                              Nach,
70                              z80 gaiden
71 
72   OBC1 emulator code
73   (c) Copyright 2001 - 2004  zsKnight,
74                              pagefault (pagefault@zsnes.com),
75                              Kris Bleakley
76                              Ported from x86 assembler to C by sanmaiwashi
77 
78   SPC7110 and RTC C++ emulator code used in 1.39-1.51
79   (c) Copyright 2002         Matthew Kendora with research by
80                              zsKnight,
81                              John Weidman,
82                              Dark Force
83 
84   SPC7110 and RTC C++ emulator code used in 1.52+
85   (c) Copyright 2009         byuu,
86                              neviksti
87 
88   S-DD1 C emulator code
89   (c) Copyright 2003         Brad Jorsch with research by
90                              Andreas Naive,
91                              John Weidman
92 
93   S-RTC C emulator code
94   (c) Copyright 2001 - 2006  byuu,
95                              John Weidman
96 
97   ST010 C++ emulator code
98   (c) Copyright 2003         Feather,
99                              John Weidman,
100                              Kris Bleakley,
101                              Matthew Kendora
102 
103   Super FX x86 assembler emulator code
104   (c) Copyright 1998 - 2003  _Demo_,
105                              pagefault,
106                              zsKnight
107 
108   Super FX C emulator code
109   (c) Copyright 1997 - 1999  Ivar,
110                              Gary Henderson,
111                              John Weidman
112 
113   Sound emulator code used in 1.5-1.51
114   (c) Copyright 1998 - 2003  Brad Martin
115   (c) Copyright 1998 - 2006  Charles Bilyue'
116 
117   Sound emulator code used in 1.52+
118   (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
119 
120   SH assembler code partly based on x86 assembler code
121   (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
122 
123   2xSaI filter
124   (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
125 
126   HQ2x, HQ3x, HQ4x filters
127   (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
128 
129   NTSC filter
130   (c) Copyright 2006 - 2007  Shay Green
131 
132   GTK+ GUI code
133   (c) Copyright 2004 - 2010  BearOso
134 
135   Win32 GUI code
136   (c) Copyright 2003 - 2006  blip,
137                              funkyass,
138                              Matthew Kendora,
139                              Nach,
140                              nitsuja
141   (c) Copyright 2009 - 2010  OV2
142 
143   Mac OS GUI code
144   (c) Copyright 1998 - 2001  John Stiles
145   (c) Copyright 2001 - 2010  zones
146 
147   (c) Copyright 2010 - 2016 Daniel De Matteis. (UNDER NO CIRCUMSTANCE
148   WILL COMMERCIAL RIGHTS EVER BE APPROPRIATED TO ANY PARTY)
149 
150   Specific ports contains the works of other authors. See headers in
151   individual files.
152 
153 
154   Snes9x homepage: http://www.snes9x.com/
155 
156   Permission to use, copy, modify and/or distribute Snes9x in both binary
157   and source form, for non-commercial purposes, is hereby granted without
158   fee, providing that this license information and copyright notice appear
159   with all copies and any derived work.
160 
161   This software is provided 'as-is', without any express or implied
162   warranty. In no event shall the authors be held liable for any damages
163   arising from the use of this software or it's derivatives.
164 
165   Snes9x is freeware for PERSONAL USE only. Commercial users should
166   seek permission of the copyright holders first. Commercial use includes,
167   but is not limited to, charging money for Snes9x or software derived from
168   Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
169   using Snes9x as a promotion for your commercial product.
170 
171   The copyright holders request that bug fixes and improvements to the code
172   should be forwarded to them so everyone can benefit from the modifications
173   in future versions.
174 
175   Super NES and Super Nintendo Entertainment System are trademarks of
176   Nintendo Co., Limited and its subsidiary companies.
177  ***********************************************************************************/
178 
179 #include <stdlib.h>
180 #include <string.h>
181 #include "snes9x.h"
182 #include "memmap.h"
183 #include "getset.h"
184 
185 static uint8	SA1OpenBus;
186 
S9xSA1Init(void)187 void S9xSA1Init (void)
188 {
189 	SA1.IRQActive = FALSE;
190 	SA1.WaitingForInterrupt = FALSE;
191 	SA1.Flags = 0;
192 	memset(&Memory.FillRAM[0x2200], 0, 0x200);
193 	Memory.FillRAM[0x2200] = 0x20;
194 	Memory.FillRAM[0x2220] = 0x00;
195 	Memory.FillRAM[0x2221] = 0x01;
196 	Memory.FillRAM[0x2222] = 0x02;
197 	Memory.FillRAM[0x2223] = 0x03;
198 	Memory.FillRAM[0x2228] = 0xff;
199 	SA1.op1 = 0;
200 	SA1.op2 = 0;
201 	SA1.arithmetic_op = 0;
202 	SA1.sum = 0;
203 	SA1.overflow = FALSE;
204 	SA1.S9xOpcodes = NULL;
205 	SA1.PCBase = NULL;
206 }
207 
S9xSA1SetPCBase(uint32 address)208 static void S9xSA1SetPCBase (uint32 address)
209 {
210 	uint8	*GetAddress;
211 
212 	SA1Registers.PBPC = address & 0xffffff;
213 	SA1.ShiftedPB = address & 0xff0000;
214 
215 	GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT];
216 
217 	if (GetAddress >= (uint8 *) MAP_LAST)
218 	{
219 		SA1.PCBase = GetAddress;
220 		return;
221 	}
222 
223 	switch ((intptr_t) GetAddress)
224 	{
225 		case MAP_LOROM_SRAM:
226 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
227 				SA1.PCBase = NULL;
228 			else
229 				SA1.PCBase = (Memory.SRAM + ((((address & 0xff0000) >> 1) | (address & 0x7fff)) & Memory.SRAMMask)) - (address & 0xffff);
230 			return;
231 
232 		case MAP_HIROM_SRAM:
233 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
234 				SA1.PCBase = NULL;
235 			else
236 				SA1.PCBase = (Memory.SRAM + (((address & 0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address & 0xffff);
237 			return;
238 
239 		case MAP_BWRAM:
240 			SA1.PCBase = SA1.BWRAM - 0x6000 - (address & 0x8000);
241 			return;
242 
243 		case MAP_SA1RAM:
244 			SA1.PCBase = Memory.SRAM;
245 			return;
246 
247 		default:
248 			SA1.PCBase = NULL;
249 			return;
250 	}
251 }
252 
S9xSA1UnpackStatus(void)253 static INLINE void S9xSA1UnpackStatus (void)
254 {
255 	SA1._Zero = (SA1Registers.PL & Zero) == 0;
256 	SA1._Negative = (SA1Registers.PL & Negative);
257 	SA1._Carry = (SA1Registers.PL & Carry);
258 	SA1._Overflow = (SA1Registers.PL & Overflow) >> 6;
259 }
260 
S9xSA1FixCycles(void)261 static INLINE void S9xSA1FixCycles (void)
262 {
263 	if (SA1CheckEmulation())
264 	{
265 		SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
266 		SA1.S9xOpLengths = S9xOpLengthsM1X1;
267 	}
268 	else
269 	if (SA1CheckMemory())
270 	{
271 		if (SA1CheckIndex())
272 		{
273 			SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
274 			SA1.S9xOpLengths = S9xOpLengthsM1X1;
275 		}
276 		else
277 		{
278 			SA1.S9xOpcodes = S9xSA1OpcodesM1X0;
279 			SA1.S9xOpLengths = S9xOpLengthsM1X0;
280 		}
281 	}
282 	else
283 	{
284 		if (SA1CheckIndex())
285 		{
286 			SA1.S9xOpcodes = S9xSA1OpcodesM0X1;
287 			SA1.S9xOpLengths = S9xOpLengthsM0X1;
288 		}
289 		else
290 		{
291 			SA1.S9xOpcodes = S9xSA1OpcodesM0X0;
292 			SA1.S9xOpLengths = S9xOpLengthsM0X0;
293 		}
294 	}
295 }
296 
S9xSA1Reset(void)297 static void S9xSA1Reset (void)
298 {
299 	SA1Registers.PBPC = 0;
300 	SA1Registers.PB = 0;
301 	SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8);
302 	SA1Registers.D.W = 0;
303 	SA1Registers.DB = 0;
304 	SA1Registers.SH = 1;
305 	SA1Registers.SL = 0xFF;
306 	SA1Registers.XH = 0;
307 	SA1Registers.YH = 0;
308 	SA1Registers.P.W = 0;
309 
310 	SA1.ShiftedPB = 0;
311 	SA1.ShiftedDB = 0;
312 	SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
313 	SA1ClearFlags(Decimal);
314 
315 	SA1.WaitingForInterrupt = FALSE;
316 	SA1.PCBase = NULL;
317 	S9xSA1SetPCBase(SA1Registers.PBPC);
318 	SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
319 	SA1.S9xOpLengths = S9xOpLengthsM1X1;
320 
321 	S9xSA1UnpackStatus();
322 	S9xSA1FixCycles();
323 	SA1.BWRAM = Memory.SRAM;
324 	Memory.FillRAM[0x2225] = 0;
325 }
326 
S9xSA1SetBWRAMMemMap(uint8 val)327 static void S9xSA1SetBWRAMMemMap (uint8 val)
328 {
329 	int c;
330 	if (val & 0x80)
331 	{
332 		for ( c = 0; c < 0x400; c += 16)
333 		{
334 			SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) MAP_BWRAM_BITMAP2;
335 			SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) MAP_BWRAM_BITMAP2;
336 			SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) MAP_BWRAM_BITMAP2;
337 			SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) MAP_BWRAM_BITMAP2;
338 		}
339 
340 		SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4;
341 	}
342 	else
343 	{
344 		for ( c = 0; c < 0x400; c += 16)
345 		{
346 			SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) MAP_BWRAM;
347 			SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) MAP_BWRAM;
348 			SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) MAP_BWRAM;
349 			SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) MAP_BWRAM;
350 		}
351 
352 		SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000;
353 	}
354 }
355 
S9xSA1PostLoadState(void)356 void S9xSA1PostLoadState (void)
357 {
358 	SA1.ShiftedPB = (uint32) SA1Registers.PB << 16;
359 	SA1.ShiftedDB = (uint32) SA1Registers.DB << 16;
360 
361 	S9xSA1SetPCBase(SA1Registers.PBPC);
362 	S9xSA1UnpackStatus();
363 	S9xSA1FixCycles();
364 	SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4;
365 	Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000;
366 	S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]);
367 }
368 
S9xSetSA1MemMap(uint32 which1,uint8 map)369 static void S9xSetSA1MemMap (uint32 which1, uint8 map)
370 {
371 	unsigned c, i;
372 	unsigned start  = which1 * 0x100 + 0xc00;
373 	unsigned start2 = which1 * 0x200;
374 
375 	if (which1 >= 2)
376 		start2 += 0x400;
377 
378 	for (c = 0; c < 0x100; c += 16)
379 	{
380 		uint8	*block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)];
381 		for (i = c; i < c + 16; i++)
382 			Memory.Map[start  + i] = SA1.Map[start  + i] = block;
383 	}
384 
385 	for (c = 0; c < 0x200; c += 16)
386 	{
387 		int32 offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000;
388 		uint8 *block = &Memory.ROM[offset];
389 
390 		for (i = c + 8; i < c + 16; i++)
391 			Memory.Map[start2 + i] = SA1.Map[start2 + i] = block;
392 	}
393 }
394 
S9xSA1GetByte(uint32 address)395 static uint8 S9xSA1GetByte (uint32 address)
396 {
397 	uint8	*GetAddress;
398 
399 	GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT];
400 
401 	if (GetAddress >= (uint8 *) MAP_LAST)
402 		return (*(GetAddress + (address & 0xffff)));
403 
404 	switch ((intptr_t) GetAddress)
405 	{
406 		case MAP_PPU:
407 			return (S9xGetSA1(address & 0xffff));
408 
409 		case MAP_LOROM_SRAM:
410 		case MAP_SA1RAM:
411 			return (*(Memory.SRAM + (address & 0xffff)));
412 
413 		case MAP_BWRAM:
414 			return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000)));
415 
416 		case MAP_BWRAM_BITMAP:
417 			address -= 0x600000;
418 			if (SA1.VirtualBitmapFormat == 2)
419 				return ((Memory.SRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) &  3);
420 			else
421 				return ((Memory.SRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15);
422 
423 		case MAP_BWRAM_BITMAP2:
424 			address = (address & 0xffff) - 0x6000;
425 			if (SA1.VirtualBitmapFormat == 2)
426 				return ((SA1.BWRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) &  3);
427 			else
428 				return ((SA1.BWRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15);
429 
430 		default:
431 			return (SA1OpenBus);
432 	}
433 }
434 
S9xSA1GetWord(uint32 address,uint32 w)435 static uint16 S9xSA1GetWord (uint32 address, uint32 w)
436 {
437 	PC_t	a;
438 
439 	SA1OpenBus = S9xSA1GetByte(address);
440 
441 	switch (w)
442 	{
443 		case WRAP_PAGE:
444 			a.xPBPC = address;
445 			a.B.xPCl++;
446 			return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8));
447 
448 		case WRAP_BANK:
449 			a.xPBPC = address;
450 			a.W.xPC++;
451 			return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8));
452 
453 		case WRAP_NONE:
454 		default:
455 			return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8));
456 	}
457 }
458 
S9xSA1ReadVariableLengthData(bool8 inc,bool8 no_shift)459 static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift)
460 {
461 	uint32 addr, data;
462 	uint8 shift, s;
463 
464 	addr  = Memory.FillRAM[0x2259] | (Memory.FillRAM[0x225a] << 8) | (Memory.FillRAM[0x225b] << 16);
465 	shift = Memory.FillRAM[0x2258] & 15;
466 
467 	if (no_shift)
468 		shift = 0;
469 	else
470 	if (shift == 0)
471 		shift = 16;
472 
473 	s = shift + SA1.variable_bit_pos;
474 
475 	if (s >= 16)
476 	{
477 		addr += (s >> 4) << 1;
478 		s &= 15;
479 	}
480 
481 	data = S9xSA1GetWord(addr, WRAP_NONE) | (S9xSA1GetWord(addr + 2, WRAP_NONE) << 16);
482 
483 	data >>= s;
484 	Memory.FillRAM[0x230c] = (uint8) data;
485 	Memory.FillRAM[0x230d] = (uint8) (data >> 8);
486 
487 	if (inc)
488 	{
489 		SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15;
490 		Memory.FillRAM[0x2259] = (uint8) addr;
491 		Memory.FillRAM[0x225a] = (uint8) (addr >> 8);
492 		Memory.FillRAM[0x225b] = (uint8) (addr >> 16);
493 	}
494 }
495 
S9xGetSA1(uint32 address)496 uint8 S9xGetSA1 (uint32 address)
497 {
498 	switch (address)
499 	{
500 		case 0x2300:
501 			return ((uint8) ((Memory.FillRAM[0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE))));
502 
503 		case 0x2301:
504 			return ((Memory.FillRAM[0x2200] & 0xf) | (Memory.FillRAM[0x2301] & 0xf0));
505 
506 		case 0x2306:
507 			return ((uint8)  SA1.sum);
508 
509 		case 0x2307:
510 			return ((uint8) (SA1.sum >>  8));
511 
512 		case 0x2308:
513 			return ((uint8) (SA1.sum >> 16));
514 
515 		case 0x2309:
516 			return ((uint8) (SA1.sum >> 24));
517 
518 		case 0x230a:
519 			return ((uint8) (SA1.sum >> 32));
520 
521 		case 0x230c:
522 			return (Memory.FillRAM[0x230c]);
523 
524 		case 0x230d:
525 		{
526 			uint8	byte = Memory.FillRAM[0x230d];
527 
528 			if (Memory.FillRAM[0x2258] & 0x80)
529 				S9xSA1ReadVariableLengthData(TRUE, FALSE);
530 
531 			return (byte);
532 		}
533 
534 		default:
535 			/*printf("R: %04x\n", address);*/
536 			break;
537 	}
538 
539 	return (Memory.FillRAM[address]);
540 }
541 
S9xSA1CharConv2(void)542 static void S9xSA1CharConv2 (void)
543 {
544 	uint32 dest, offset;
545 	uint8 *p, *q;
546 	int depth, bytes_per_char, l, b;
547 
548 	dest           = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8);
549 	offset         = (SA1.in_char_dma & 7) ? 0 : 1;
550 	depth          = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2;
551 	bytes_per_char = 8 * depth;
552 	p             = &Memory.FillRAM[0x3000] + (dest & 0x7ff) + offset * bytes_per_char;
553 	q             = &Memory.ROM[MAX_ROM_SIZE - 0x10000] + offset * 64;
554 
555 	switch (depth)
556 	{
557 		case 2:
558 			for ( l = 0; l < 8; l++, q += 8)
559 			{
560 				for ( b = 0; b < 8; b++)
561 				{
562 					uint8	r = *(q + b);
563 					*(p +  0) = (*(p +  0) << 1) | (r & 1);
564 					*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
565 				}
566 
567 				p += 2;
568 			}
569 
570 			break;
571 
572 		case 4:
573 			for ( l = 0; l < 8; l++, q += 8)
574 			{
575 				for ( b = 0; b < 8; b++)
576 				{
577 					uint8	r = *(q + b);
578 					*(p +  0) = (*(p +  0) << 1) | (r & 1);
579 					*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
580 					*(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1);
581 					*(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1);
582 				}
583 
584 				p += 2;
585 			}
586 
587 			break;
588 
589 		case 8:
590 			for ( l = 0; l < 8; l++, q += 8)
591 			{
592 				for ( b = 0; b < 8; b++)
593 				{
594 					uint8	r = *(q + b);
595 					*(p +  0) = (*(p +  0) << 1) | (r & 1);
596 					*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
597 					*(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1);
598 					*(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1);
599 					*(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1);
600 					*(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1);
601 					*(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1);
602 					*(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1);
603 				}
604 
605 				p += 2;
606 			}
607 
608 			break;
609 	}
610 }
611 
S9xSA1DMA(void)612 static void S9xSA1DMA (void)
613 {
614 	uint32 src, dst, len;
615 	uint8	*s, *d;
616 
617 	src = Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16);
618 	dst = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16);
619 	len = Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8);
620 
621 	switch (Memory.FillRAM[0x2230] & 3)
622 	{
623 		case 0: /* ROM*/
624 			s = SA1.Map[((src & 0xffffff) >> MEMMAP_SHIFT)];
625 			if (s >= (uint8 *) MAP_LAST)
626 				s += (src & 0xffff);
627 			else
628 				s = Memory.ROM + (src & 0xffff);
629 			break;
630 
631 		case 1: /* BW-RAM*/
632 			src &= Memory.SRAMMask;
633 			len &= Memory.SRAMMask;
634 			s = Memory.SRAM + src;
635 			break;
636 
637 		default:
638 		case 2:
639 			src &= 0x3ff;
640 			len &= 0x3ff;
641 			s = &Memory.FillRAM[0x3000] + src;
642 			break;
643 	}
644 
645 	if (Memory.FillRAM[0x2230] & 4)
646 	{
647 		dst &= Memory.SRAMMask;
648 		len &= Memory.SRAMMask;
649 		d = Memory.SRAM + dst;
650 	}
651 	else
652 	{
653 		dst &= 0x3ff;
654 		len &= 0x3ff;
655 		d = &Memory.FillRAM[0x3000] + dst;
656 	}
657 
658 	memmove(d, s, len);
659 	Memory.FillRAM[0x2301] |= 0x20;
660 
661 	if (Memory.FillRAM[0x220a] & 0x20)
662 	{
663 		SA1.Flags |= IRQ_FLAG;
664 		SA1.IRQActive |= DMA_IRQ_SOURCE;
665 	}
666 }
667 
S9xSetSA1(uint8 byte,uint32 address)668 void S9xSetSA1 (uint8 byte, uint32 address)
669 {
670 	switch (address)
671 	{
672 		case 0x2200:
673 			if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20))
674 				S9xSA1Reset();
675 
676 			if (byte & 0x80)
677 			{
678 				Memory.FillRAM[0x2301] |= 0x80;
679 				if (Memory.FillRAM[0x220a] & 0x80)
680 				{
681 					SA1.Flags |= IRQ_FLAG;
682 					SA1.IRQActive |= SNES_IRQ_SOURCE;
683 				}
684 			}
685 
686 			if (byte & 0x10)
687 			{
688 				Memory.FillRAM[0x2301] |= 0x10;
689 				if (Memory.FillRAM[0x220a] & 0x10)
690 				{
691 					SA1.Flags |= NMI_FLAG;
692 				}
693 			}
694 
695 			break;
696 
697 		case 0x2201:
698 			if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
699 			{
700 				S9X_SET_IRQ(SA1_IRQ_SOURCE);
701 			}
702 
703 			if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
704 			{
705 				S9X_SET_IRQ(SA1_DMA_IRQ_SOURCE);
706 			}
707 
708 			break;
709 
710 		case 0x2202:
711 			if (byte & 0x80)
712 			{
713 				Memory.FillRAM[0x2300] &= ~0x80;
714 				S9X_CLEAR_IRQ(SA1_IRQ_SOURCE);
715 			}
716 
717 			if (byte & 0x20)
718 			{
719 				Memory.FillRAM[0x2300] &= ~0x20;
720 				S9X_CLEAR_IRQ(SA1_DMA_IRQ_SOURCE);
721 			}
722 
723 			break;
724 
725 		case 0x2203:
726 			/*printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8));*/
727 		case 0x2204:
728 			/*printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]);*/
729 		case 0x2205:
730 			/*printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8));*/
731 		case 0x2206:
732 			/*printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]);*/
733 		case 0x2207:
734 			/*printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8));*/
735 		case 0x2208:
736 			/*printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]);*/
737 			break;
738 		case 0x2209:
739 			Memory.FillRAM[0x2209] = byte;
740 
741 			if (byte & 0x80)
742 				Memory.FillRAM[0x2300] |= 0x80;
743 
744 			if (byte & Memory.FillRAM[0x2201] & 0x80)
745 			{
746 				S9X_SET_IRQ(SA1_IRQ_SOURCE);
747 			}
748 
749 			break;
750 
751 		case 0x220a:
752 			if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80))
753 			{
754 				SA1.Flags |= IRQ_FLAG;
755 				SA1.IRQActive |= SNES_IRQ_SOURCE;
756 			}
757 
758 			if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40))
759 			{
760 				SA1.Flags |= IRQ_FLAG;
761 				SA1.IRQActive |= TIMER_IRQ_SOURCE;
762 			}
763 
764 			if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20))
765 			{
766 				SA1.Flags |= IRQ_FLAG;
767 				SA1.IRQActive |= DMA_IRQ_SOURCE;
768 			}
769 
770 			if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10))
771 			{
772 				SA1.Flags |= NMI_FLAG;
773 			}
774 
775 			break;
776 
777 		case 0x220b:
778 			if (byte & 0x80)
779 			{
780 				SA1.IRQActive &= ~SNES_IRQ_SOURCE;
781 				Memory.FillRAM[0x2301] &= ~0x80;
782 			}
783 
784 			if (byte & 0x40)
785 			{
786 				SA1.IRQActive &= ~TIMER_IRQ_SOURCE;
787 				Memory.FillRAM[0x2301] &= ~0x40;
788 			}
789 
790 			if (byte & 0x20)
791 			{
792 				SA1.IRQActive &= ~DMA_IRQ_SOURCE;
793 				Memory.FillRAM[0x2301] &= ~0x20;
794 			}
795 
796 			if (byte & 0x10)
797 				Memory.FillRAM[0x2301] &= ~0x10;
798 
799 			if (!SA1.IRQActive)
800 				SA1.Flags &= ~IRQ_FLAG;
801 
802 			break;
803 
804 		case 0x220c:
805 			/*printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8));*/
806 		case 0x220d:
807 			/*printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]);*/
808 		case 0x220e:
809 			/*printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8));*/
810 		case 0x220f:
811 			/*printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]);*/
812 		case 0x2210:
813 		case 0x2211:
814 			/*printf("Timer reset\n");*/
815 		case 0x2212:
816 			/*printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8));*/
817 		case 0x2213:
818 			/*printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]);*/
819 		case 0x2214:
820 			/*printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8));*/
821 		case 0x2215:
822 			/*printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]);*/
823 			break;
824 		case 0x2220:
825 		case 0x2221:
826 		case 0x2222:
827 		case 0x2223:
828 			/*printf("MMC: %02x\n", byte);*/
829 			S9xSetSA1MemMap(address - 0x2220, byte);
830 			break;
831 
832 		case 0x2224:
833 			/*printf("BWRAM image SNES %02x -> 0x6000\n", byte);*/
834 			Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000;
835 			break;
836 
837 		case 0x2225:
838 			/*printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]);*/
839 			if (byte != Memory.FillRAM[0x2225])
840 				S9xSA1SetBWRAMMemMap(byte);
841 			break;
842 
843 		case 0x2226:
844 			/*printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled");*/
845 		case 0x2227:
846 			/*printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled");*/
847 		case 0x2228:
848 			/*printf("BW-RAM write protect area %02x\n", byte);*/
849 		case 0x2229:
850 			/*printf("I-RAM SNES write protect area %02x\n", byte);*/
851 		case 0x222a:
852 			/*printf("I-RAM SA1 write protect area %02x\n", byte);*/
853 		case 0x2230:
854 			break;
855 		case 0x2231:
856 			if (byte & 0x80)
857 				SA1.in_char_dma = FALSE;
858 			break;
859 
860 		case 0x2232:
861 		case 0x2233:
862 		case 0x2234:
863 			Memory.FillRAM[address] = byte;
864 			break;
865 
866 		case 0x2235:
867 			Memory.FillRAM[0x2235] = byte;
868 			break;
869 
870 		case 0x2236:
871 			Memory.FillRAM[0x2236] = byte;
872 
873 			if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) /* Normal DMA to I-RAM*/
874 				S9xSA1DMA();
875 			else
876 			if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0)
877 			{
878 				Memory.FillRAM[0x2300] |= 0x20;
879 				if (Memory.FillRAM[0x2201] & 0x20)
880 				{
881 					S9X_SET_IRQ(SA1_DMA_IRQ_SOURCE);
882 				}
883 				SA1.in_char_dma = TRUE;
884 			}
885 
886 			break;
887 
888 		case 0x2237:
889 			Memory.FillRAM[0x2237] = byte;
890 
891 			if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) /* Normal DMA to BW-RAM*/
892 				S9xSA1DMA();
893 			break;
894 
895 		case 0x2238:
896 		case 0x2239:
897 			Memory.FillRAM[address] = byte;
898 			break;
899 
900 		case 0x223f:
901 			/*printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4);*/
902 			SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4;
903 			break;
904 
905 		case 0x2240:
906 		case 0x2241:
907 		case 0x2242:
908 		case 0x2243:
909 		case 0x2244:
910 		case 0x2245:
911 		case 0x2246:
912 		case 0x2247:
913 		case 0x2248:
914 		case 0x2249:
915 		case 0x224a:
916 		case 0x224b:
917 		case 0x224c:
918 		case 0x224d:
919 		case 0x224e:
920 			Memory.FillRAM[address] = byte;
921 			break;
922 
923 		case 0x224f:
924 			Memory.FillRAM[0x224f] = byte;
925 
926 			if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) /* Char conversion 2 DMA enabled*/
927 			{
928 				memcpy(&Memory.ROM[MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16);
929 				SA1.in_char_dma = (SA1.in_char_dma + 1) & 7;
930 				if ((SA1.in_char_dma & 3) == 0)
931 					S9xSA1CharConv2();
932 			}
933 
934 			break;
935 
936 		case 0x2250:
937 			if (byte & 2)
938 				SA1.sum = 0;
939 			SA1.arithmetic_op = byte & 3;
940 			break;
941 
942 		case 0x2251:
943 			SA1.op1 = (SA1.op1 & 0xff00) | byte;
944 			break;
945 
946 		case 0x2252:
947 			SA1.op1 = (SA1.op1 & 0xff) | (byte << 8);
948 			break;
949 
950 		case 0x2253:
951 			SA1.op2 = (SA1.op2 & 0xff00) | byte;
952 			break;
953 
954 		case 0x2254:
955 			SA1.op2 = (SA1.op2 & 0xff) | (byte << 8);
956 
957 			switch (SA1.arithmetic_op)
958 			{
959 				case 0:	/* multiply*/
960 					SA1.sum = SA1.op1 * SA1.op2;
961 					break;
962 
963 				case 1: /* divide*/
964 					if (SA1.op2 == 0)
965 						SA1.sum = SA1.op1 << 16;
966 					else
967 						SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16);
968 					break;
969 
970 				case 2: /* cumulative sum*/
971 				default:
972 					SA1.sum += SA1.op1 * SA1.op2;
973 					if (SA1.sum & ((int64) 0xffffff << 32))
974 						SA1.overflow = TRUE;
975 					break;
976 			}
977 
978 			break;
979 
980 		case 0x2258: /* Variable bit-field length/auto inc/start.*/
981 			Memory.FillRAM[0x2258] = byte;
982 			S9xSA1ReadVariableLengthData(TRUE, FALSE);
983 			return;
984 
985 		case 0x2259: /* Variable bit-field start address*/
986 		case 0x225a:
987 		case 0x225b:
988 			Memory.FillRAM[address] = byte;
989 			/* XXX: ???*/
990 			SA1.variable_bit_pos = 0;
991 			S9xSA1ReadVariableLengthData(FALSE, TRUE);
992 			return;
993 
994 		default:
995 			/*printf("W: %02x->%04x\n", byte, address);*/
996 			break;
997 	}
998 
999 	if (address >= 0x2200 && address <= 0x22ff)
1000 		Memory.FillRAM[address] = byte;
1001 }
1002 
1003 
1004 
S9xSA1SetByte(uint8 byte,uint32 address)1005 static void S9xSA1SetByte (uint8 byte, uint32 address)
1006 {
1007 	uint8 *SetAddress;
1008 
1009 	SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT];
1010 
1011 	if (SetAddress >= (uint8 *) MAP_LAST)
1012 	{
1013 		*(SetAddress + (address & 0xffff)) = byte;
1014 		return;
1015 	}
1016 
1017 	switch ((intptr_t) SetAddress)
1018 	{
1019 		case MAP_PPU:
1020 			S9xSetSA1(byte, address & 0xffff);
1021 			return;
1022 
1023 		case MAP_LOROM_SRAM:
1024 		case MAP_SA1RAM:
1025 			*(Memory.SRAM + (address & 0xffff)) = byte;
1026 			return;
1027 
1028 		case MAP_BWRAM:
1029 			*(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte;
1030 			return;
1031 
1032 		case MAP_BWRAM_BITMAP:
1033 			address -= 0x600000;
1034 			if (SA1.VirtualBitmapFormat == 2)
1035 			{
1036 				uint8	*ptr = &Memory.SRAM[(address >> 2) & 0xffff];
1037 				*ptr &= ~(3  << ((address & 3) << 1));
1038 				*ptr |= (byte &  3) << ((address & 3) << 1);
1039 			}
1040 			else
1041 			{
1042 				uint8	*ptr = &Memory.SRAM[(address >> 1) & 0xffff];
1043 				*ptr &= ~(15 << ((address & 1) << 2));
1044 				*ptr |= (byte & 15) << ((address & 1) << 2);
1045 			}
1046 
1047 			return;
1048 
1049 		case MAP_BWRAM_BITMAP2:
1050 			address = (address & 0xffff) - 0x6000;
1051 			if (SA1.VirtualBitmapFormat == 2)
1052 			{
1053 				uint8	*ptr = &SA1.BWRAM[(address >> 2) & 0xffff];
1054 				*ptr &= ~(3  << ((address & 3) << 1));
1055 				*ptr |= (byte &  3) << ((address & 3) << 1);
1056 			}
1057 			else
1058 			{
1059 				uint8	*ptr = &SA1.BWRAM[(address >> 1) & 0xffff];
1060 				*ptr &= ~(15 << ((address & 1) << 2));
1061 				*ptr |= (byte & 15) << ((address & 1) << 2);
1062 			}
1063 
1064 			return;
1065 
1066 		default:
1067 			return;
1068 	}
1069 }
1070 
S9xSA1SetWord_Write0(uint16 Word,uint32 address,uint32 w)1071 static void S9xSA1SetWord_Write0(uint16 Word, uint32 address, uint32 w)
1072 {
1073 	PC_t	a;
1074 
1075 	S9xSA1SetByte((uint8) Word, address);
1076 
1077 	switch (w)
1078 	{
1079 		case WRAP_PAGE:
1080 			a.xPBPC = address;
1081 			a.B.xPCl++;
1082 			S9xSA1SetByte(Word >> 8, a.xPBPC);
1083 			break;
1084 
1085 		case WRAP_BANK:
1086 			a.xPBPC = address;
1087 			a.W.xPC++;
1088 			S9xSA1SetByte(Word >> 8, a.xPBPC);
1089 			break;
1090 
1091 		case WRAP_NONE:
1092 		default:
1093 			S9xSA1SetByte(Word >> 8, address + 1);
1094 			break;
1095 	}
1096 }
1097 
S9xSA1SetWord_Write1(uint16 Word,uint32 address,uint32 w)1098 static void S9xSA1SetWord_Write1(uint16 Word, uint32 address, uint32 w)
1099 {
1100 	PC_t	a;
1101 
1102 	switch (w)
1103 	{
1104 		case WRAP_PAGE:
1105 			a.xPBPC = address;
1106 			a.B.xPCl++;
1107 			S9xSA1SetByte(Word >> 8, a.xPBPC);
1108 			break;
1109 
1110 		case WRAP_BANK:
1111 			a.xPBPC = address;
1112 			a.W.xPC++;
1113 			S9xSA1SetByte(Word >> 8, a.xPBPC);
1114 			break;
1115 
1116 		case WRAP_NONE:
1117 		default:
1118 			S9xSA1SetByte(Word >> 8, address + 1);
1119 			break;
1120 	}
1121 
1122 	S9xSA1SetByte((uint8) Word, address);
1123 }
1124 
1125 #define CPU						SA1
1126 #define ICPU						SA1
1127 #define Registers					SA1Registers
1128 #define OpenBus						SA1OpenBus
1129 #define S9xGetByte					S9xSA1GetByte
1130 #define S9xGetWord					S9xSA1GetWord
1131 #define S9xSetByte					S9xSA1SetByte
1132 #define S9xSetWord_Write0				S9xSA1SetWord_Write0
1133 #define S9xSetWord_Write1				S9xSA1SetWord_Write1
1134 #define S9xSetPCBase					S9xSA1SetPCBase
1135 #define S9xOpcodesM1X1					S9xSA1OpcodesM1X1
1136 #define S9xOpcodesM1X0					S9xSA1OpcodesM1X0
1137 #define S9xOpcodesM0X1					S9xSA1OpcodesM0X1
1138 #define S9xOpcodesM0X0					S9xSA1OpcodesM0X0
1139 #define S9xOpcodesE1					S9xSA1OpcodesE1
1140 #define S9xOpcodesSlow					S9xSA1OpcodesSlow
1141 #define S9xOpcode_IRQ					S9xSA1Opcode_IRQ
1142 #define S9xOpcode_NMI					S9xSA1Opcode_NMI
1143 #undef S9xUnpackStatus
1144 #define S9xUnpackStatus					S9xSA1UnpackStatus
1145 #undef S9xPackStatus
1146 #define S9xPackStatus					S9xSA1PackStatus
1147 #define S9xFixCycles					S9xSA1FixCycles
1148 #define Immediate8					SA1Immediate8
1149 #define Immediate16					SA1Immediate16
1150 #define Relative					SA1Relative
1151 #define RelativeLong					SA1RelativeLong
1152 #define Absolute					SA1Absolute
1153 #define AbsoluteLong					SA1AbsoluteLong
1154 #define AbsoluteIndirect				SA1AbsoluteIndirect
1155 #define AbsoluteIndirectLong				SA1AbsoluteIndirectLong
1156 #define AbsoluteIndexedIndirect				SA1AbsoluteIndexedIndirect
1157 #define Direct						SA1Direct
1158 #define DirectIndirectIndexed				SA1DirectIndirectIndexed
1159 #define DirectIndirectIndexedLong			SA1DirectIndirectIndexedLong
1160 #define DirectIndexedIndirect				SA1DirectIndexedIndirect
1161 #define DirectIndexedX					SA1DirectIndexedX
1162 #define DirectIndexedY					SA1DirectIndexedY
1163 #define AbsoluteIndexedX				SA1AbsoluteIndexedX
1164 #define AbsoluteIndexedY				SA1AbsoluteIndexedY
1165 #define AbsoluteLongIndexedX				SA1AbsoluteLongIndexedX
1166 #define DirectIndirect					SA1DirectIndirect
1167 #define DirectIndirectLong				SA1DirectIndirectLong
1168 #define StackRelative					SA1StackRelative
1169 #define StackRelativeIndirectIndexed			SA1StackRelativeIndirectIndexed
1170 
1171 #define SA1_OPCODES
1172 
1173 #include "cpuops_.h"
1174 
S9xSA1MainLoop(void)1175 void S9xSA1MainLoop (void)
1176 {
1177 	int i;
1178 	bool8 sa1_quit;
1179 
1180 	if (SA1.Flags & NMI_FLAG)
1181 	{
1182 		if (Memory.FillRAM[0x2200] & 0x10)
1183 		{
1184 			SA1.Flags &= ~NMI_FLAG;
1185 			Memory.FillRAM[0x2301] |= 0x10;
1186 
1187 			if (SA1.WaitingForInterrupt)
1188 			{
1189 				SA1.WaitingForInterrupt = FALSE;
1190 				SA1Registers.PCw++;
1191 			}
1192 
1193 			S9xSA1Opcode_NMI();
1194 		}
1195 	}
1196 
1197 	if (SA1.Flags & IRQ_FLAG)
1198 	{
1199 		if (SA1.IRQActive)
1200 		{
1201 			if (SA1.WaitingForInterrupt)
1202 			{
1203 				SA1.WaitingForInterrupt = FALSE;
1204 				SA1Registers.PCw++;
1205 			}
1206 
1207 			if (!SA1CheckFlag(IRQ))
1208 				S9xSA1Opcode_IRQ();
1209 		}
1210 		else
1211 			SA1.Flags &= ~IRQ_FLAG;
1212 	}
1213 
1214 	sa1_quit = Memory.FillRAM[0x2200] & 0x60;
1215 
1216 	for ( i = 0; i < 3 && !sa1_quit; i++)
1217 	{
1218 		register uint8			Op;
1219 		register struct SOpcodes	*Opcodes;
1220 
1221 		if (SA1.PCBase)
1222 		{
1223 			SA1OpenBus = Op = SA1.PCBase[Registers.PCw];
1224 			Opcodes = SA1.S9xOpcodes;
1225 		}
1226 		else
1227 		{
1228 			Op = S9xSA1GetByte(Registers.PBPC);
1229 			Opcodes = S9xOpcodesSlow;
1230 		}
1231 
1232 		if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
1233 		{
1234 			uint32	oldPC = SA1Registers.PBPC;
1235 			S9xSA1SetPCBase(SA1Registers.PBPC);
1236 			SA1Registers.PBPC = oldPC;
1237 			Opcodes = S9xSA1OpcodesSlow;
1238 		}
1239 
1240 		Registers.PCw++;
1241 		(*Opcodes[Op].S9xOpcode)();
1242 	}
1243 }
1244