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