Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.
| ... | ... |
@@ -1,186 +1,15 @@ |
| 1 |
-/*********************************************************************************** |
|
| 1 |
+/*****************************************************************************\ |
|
| 2 | 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 |
- |
|
| 21 |
- (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) |
|
| 22 |
- |
|
| 23 |
- (c) Copyright 2006 - 2007 nitsuja |
|
| 24 |
- |
|
| 25 |
- (c) Copyright 2009 - 2011 BearOso, |
|
| 26 |
- OV2 |
|
| 27 |
- |
|
| 28 |
- |
|
| 29 |
- BS-X C emulator code |
|
| 30 |
- (c) Copyright 2005 - 2006 Dreamer Nom, |
|
| 31 |
- zones |
|
| 32 |
- |
|
| 33 |
- C4 x86 assembler and some C emulation code |
|
| 34 |
- (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), |
|
| 35 |
- Nach, |
|
| 36 |
- zsKnight (zsknight@zsnes.com) |
|
| 37 |
- |
|
| 38 |
- C4 C++ code |
|
| 39 |
- (c) Copyright 2003 - 2006 Brad Jorsch, |
|
| 40 |
- Nach |
|
| 41 |
- |
|
| 42 |
- DSP-1 emulator code |
|
| 43 |
- (c) Copyright 1998 - 2006 _Demo_, |
|
| 44 |
- Andreas Naive (andreasnaive@gmail.com), |
|
| 45 |
- Gary Henderson, |
|
| 46 |
- Ivar (ivar@snes9x.com), |
|
| 47 |
- John Weidman, |
|
| 48 |
- Kris Bleakley, |
|
| 49 |
- Matthew Kendora, |
|
| 50 |
- Nach, |
|
| 51 |
- neviksti (neviksti@hotmail.com) |
|
| 52 |
- |
|
| 53 |
- DSP-2 emulator code |
|
| 54 |
- (c) Copyright 2003 John Weidman, |
|
| 55 |
- Kris Bleakley, |
|
| 56 |
- Lord Nightmare (lord_nightmare@users.sourceforge.net), |
|
| 57 |
- Matthew Kendora, |
|
| 58 |
- neviksti |
|
| 59 |
- |
|
| 60 |
- DSP-3 emulator code |
|
| 61 |
- (c) Copyright 2003 - 2006 John Weidman, |
|
| 62 |
- Kris Bleakley, |
|
| 63 |
- Lancer, |
|
| 64 |
- z80 gaiden |
|
| 65 |
- |
|
| 66 |
- DSP-4 emulator code |
|
| 67 |
- (c) Copyright 2004 - 2006 Dreamer Nom, |
|
| 68 |
- John Weidman, |
|
| 69 |
- Kris Bleakley, |
|
| 70 |
- Nach, |
|
| 71 |
- z80 gaiden |
|
| 72 |
- |
|
| 73 |
- OBC1 emulator code |
|
| 74 |
- (c) Copyright 2001 - 2004 zsKnight, |
|
| 75 |
- pagefault (pagefault@zsnes.com), |
|
| 76 |
- Kris Bleakley |
|
| 77 |
- Ported from x86 assembler to C by sanmaiwashi |
|
| 78 |
- |
|
| 79 |
- SPC7110 and RTC C++ emulator code used in 1.39-1.51 |
|
| 80 |
- (c) Copyright 2002 Matthew Kendora with research by |
|
| 81 |
- zsKnight, |
|
| 82 |
- John Weidman, |
|
| 83 |
- Dark Force |
|
| 84 |
- |
|
| 85 |
- SPC7110 and RTC C++ emulator code used in 1.52+ |
|
| 86 |
- (c) Copyright 2009 byuu, |
|
| 87 |
- neviksti |
|
| 88 |
- |
|
| 89 |
- S-DD1 C emulator code |
|
| 90 |
- (c) Copyright 2003 Brad Jorsch with research by |
|
| 91 |
- Andreas Naive, |
|
| 92 |
- John Weidman |
|
| 93 |
- |
|
| 94 |
- S-RTC C emulator code |
|
| 95 |
- (c) Copyright 2001 - 2006 byuu, |
|
| 96 |
- John Weidman |
|
| 97 |
- |
|
| 98 |
- ST010 C++ emulator code |
|
| 99 |
- (c) Copyright 2003 Feather, |
|
| 100 |
- John Weidman, |
|
| 101 |
- Kris Bleakley, |
|
| 102 |
- Matthew Kendora |
|
| 103 |
- |
|
| 104 |
- Super FX x86 assembler emulator code |
|
| 105 |
- (c) Copyright 1998 - 2003 _Demo_, |
|
| 106 |
- pagefault, |
|
| 107 |
- zsKnight |
|
| 108 |
- |
|
| 109 |
- Super FX C emulator code |
|
| 110 |
- (c) Copyright 1997 - 1999 Ivar, |
|
| 111 |
- Gary Henderson, |
|
| 112 |
- John Weidman |
|
| 113 |
- |
|
| 114 |
- Sound emulator code used in 1.5-1.51 |
|
| 115 |
- (c) Copyright 1998 - 2003 Brad Martin |
|
| 116 |
- (c) Copyright 1998 - 2006 Charles Bilyue' |
|
| 117 |
- |
|
| 118 |
- Sound emulator code used in 1.52+ |
|
| 119 |
- (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) |
|
| 120 |
- |
|
| 121 |
- SH assembler code partly based on x86 assembler code |
|
| 122 |
- (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) |
|
| 123 |
- |
|
| 124 |
- 2xSaI filter |
|
| 125 |
- (c) Copyright 1999 - 2001 Derek Liauw Kie Fa |
|
| 126 |
- |
|
| 127 |
- HQ2x, HQ3x, HQ4x filters |
|
| 128 |
- (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) |
|
| 129 |
- |
|
| 130 |
- NTSC filter |
|
| 131 |
- (c) Copyright 2006 - 2007 Shay Green |
|
| 132 |
- |
|
| 133 |
- GTK+ GUI code |
|
| 134 |
- (c) Copyright 2004 - 2011 BearOso |
|
| 135 |
- |
|
| 136 |
- Win32 GUI code |
|
| 137 |
- (c) Copyright 2003 - 2006 blip, |
|
| 138 |
- funkyass, |
|
| 139 |
- Matthew Kendora, |
|
| 140 |
- Nach, |
|
| 141 |
- nitsuja |
|
| 142 |
- (c) Copyright 2009 - 2011 OV2 |
|
| 143 |
- |
|
| 144 |
- Mac OS GUI code |
|
| 145 |
- (c) Copyright 1998 - 2001 John Stiles |
|
| 146 |
- (c) Copyright 2001 - 2011 zones |
|
| 147 |
- |
|
| 148 |
- |
|
| 149 |
- Specific ports contains the works of other authors. See headers in |
|
| 150 |
- individual files. |
|
| 151 |
- |
|
| 152 |
- |
|
| 153 |
- Snes9x homepage: http://www.snes9x.com/ |
|
| 154 |
- |
|
| 155 |
- Permission to use, copy, modify and/or distribute Snes9x in both binary |
|
| 156 |
- and source form, for non-commercial purposes, is hereby granted without |
|
| 157 |
- fee, providing that this license information and copyright notice appear |
|
| 158 |
- with all copies and any derived work. |
|
| 159 |
- |
|
| 160 |
- This software is provided 'as-is', without any express or implied |
|
| 161 |
- warranty. In no event shall the authors be held liable for any damages |
|
| 162 |
- arising from the use of this software or it's derivatives. |
|
| 163 |
- |
|
| 164 |
- Snes9x is freeware for PERSONAL USE only. Commercial users should |
|
| 165 |
- seek permission of the copyright holders first. Commercial use includes, |
|
| 166 |
- but is not limited to, charging money for Snes9x or software derived from |
|
| 167 |
- Snes9x, including Snes9x or derivatives in commercial game bundles, and/or |
|
| 168 |
- using Snes9x as a promotion for your commercial product. |
|
| 169 |
- |
|
| 170 |
- The copyright holders request that bug fixes and improvements to the code |
|
| 171 |
- should be forwarded to them so everyone can benefit from the modifications |
|
| 172 |
- in future versions. |
|
| 173 |
- |
|
| 174 |
- Super NES and Super Nintendo Entertainment System are trademarks of |
|
| 175 |
- Nintendo Co., Limited and its subsidiary companies. |
|
| 176 |
- ***********************************************************************************/ |
|
| 3 |
+ This file is licensed under the Snes9x License. |
|
| 4 |
+ For further information, consult the LICENSE file in the root directory. |
|
| 5 |
+\*****************************************************************************/ |
|
| 177 | 6 |
|
| 178 | 7 |
#include "snes9x.h" |
| 179 | 8 |
#include "memmap.h" |
| 180 | 9 |
#include "dma.h" |
| 181 | 10 |
#include "apu/apu.h" |
| 182 | 11 |
|
| 183 |
-static inline void ADD_CYCLES(int32_t n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += n; S9xCheckInterrupts(); }
|
|
| 12 |
+static inline void ADD_CYCLES(int32_t n) { CPU.Cycles += n; }
|
|
| 184 | 13 |
|
| 185 | 14 |
extern uint8_t *HDMAMemPointers[8]; |
| 186 | 15 |
extern int HDMA_ModeByteCounts[8]; |
| ... | ... |
@@ -365,7 +194,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 365 | 194 |
if (!UPDATE_COUNTERS()) |
| 366 | 195 |
return false; |
| 367 | 196 |
--count; |
| 368 |
- |
|
| 197 |
+ // Fall through |
|
| 369 | 198 |
case 1: |
| 370 | 199 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 371 | 200 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -402,7 +231,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 402 | 231 |
b = 1; |
| 403 | 232 |
break; |
| 404 | 233 |
} |
| 405 |
- |
|
| 234 |
+ // Fall through |
|
| 406 | 235 |
case 1: |
| 407 | 236 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 408 | 237 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| ... | ... |
@@ -413,7 +242,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 413 | 242 |
b = 2; |
| 414 | 243 |
break; |
| 415 | 244 |
} |
| 416 |
- |
|
| 245 |
+ // Fall through |
|
| 417 | 246 |
case 2: |
| 418 | 247 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 419 | 248 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -424,7 +253,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 424 | 253 |
b = 3; |
| 425 | 254 |
break; |
| 426 | 255 |
} |
| 427 |
- |
|
| 256 |
+ // Fall through |
|
| 428 | 257 |
case 3: |
| 429 | 258 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 430 | 259 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -454,7 +283,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 454 | 283 |
b = 1; |
| 455 | 284 |
break; |
| 456 | 285 |
} |
| 457 |
- |
|
| 286 |
+ // Fall through |
|
| 458 | 287 |
case 1: |
| 459 | 288 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 460 | 289 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -465,7 +294,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 465 | 294 |
b = 2; |
| 466 | 295 |
break; |
| 467 | 296 |
} |
| 468 |
- |
|
| 297 |
+ // Fall through |
|
| 469 | 298 |
case 2: |
| 470 | 299 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 471 | 300 |
S9xSetPPU(Work, 0x2102 + d->BAddress); |
| ... | ... |
@@ -476,7 +305,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 476 | 305 |
b = 3; |
| 477 | 306 |
break; |
| 478 | 307 |
} |
| 479 |
- |
|
| 308 |
+ // Fall through |
|
| 480 | 309 |
case 3: |
| 481 | 310 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 482 | 311 |
S9xSetPPU(Work, 0x2103 + d->BAddress); |
| ... | ... |
@@ -618,10 +447,10 @@ bool S9xDoDMA(uint8_t Channel) |
| 618 | 447 |
if (!UPDATE_COUNTERS()) |
| 619 | 448 |
return false; |
| 620 | 449 |
--count; |
| 621 |
- |
|
| 450 |
+ // Fall through |
|
| 622 | 451 |
case 1: |
| 623 |
- Work = *(base + p); |
|
| 624 |
- REGISTER_2119_linear(Work); |
|
| 452 |
+ OpenBus = *(base + p); |
|
| 453 |
+ REGISTER_2119_linear(OpenBus); |
|
| 625 | 454 |
if (!UPDATE_COUNTERS()) |
| 626 | 455 |
return false; |
| 627 | 456 |
--count; |
| ... | ... |
@@ -651,7 +480,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 651 | 480 |
if (!UPDATE_COUNTERS()) |
| 652 | 481 |
return false; |
| 653 | 482 |
--count; |
| 654 |
- |
|
| 483 |
+ // Fall through |
|
| 655 | 484 |
case 1: |
| 656 | 485 |
Work = *(base + p); |
| 657 | 486 |
REGISTER_2119_tile(Work); |
| ... | ... |
@@ -686,7 +515,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 686 | 515 |
if (!UPDATE_COUNTERS()) |
| 687 | 516 |
return false; |
| 688 | 517 |
--count; |
| 689 |
- |
|
| 518 |
+ // Fall through |
|
| 690 | 519 |
case 1: |
| 691 | 520 |
Work = *(base + p); |
| 692 | 521 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -724,7 +553,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 724 | 553 |
b = 1; |
| 725 | 554 |
break; |
| 726 | 555 |
} |
| 727 |
- |
|
| 556 |
+ // Fall through |
|
| 728 | 557 |
case 1: |
| 729 | 558 |
Work = *(base + p); |
| 730 | 559 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| ... | ... |
@@ -735,7 +564,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 735 | 564 |
b = 2; |
| 736 | 565 |
break; |
| 737 | 566 |
} |
| 738 |
- |
|
| 567 |
+ // Fall through |
|
| 739 | 568 |
case 2: |
| 740 | 569 |
Work = *(base + p); |
| 741 | 570 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -746,7 +575,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 746 | 575 |
b = 3; |
| 747 | 576 |
break; |
| 748 | 577 |
} |
| 749 |
- |
|
| 578 |
+ // Fall through |
|
| 750 | 579 |
case 3: |
| 751 | 580 |
Work = *(base + p); |
| 752 | 581 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -776,7 +605,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 776 | 605 |
b = 1; |
| 777 | 606 |
break; |
| 778 | 607 |
} |
| 779 |
- |
|
| 608 |
+ // Fall through |
|
| 780 | 609 |
case 1: |
| 781 | 610 |
Work = *(base + p); |
| 782 | 611 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| ... | ... |
@@ -787,7 +616,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 787 | 616 |
b = 2; |
| 788 | 617 |
break; |
| 789 | 618 |
} |
| 790 |
- |
|
| 619 |
+ // Fall through |
|
| 791 | 620 |
case 2: |
| 792 | 621 |
Work = *(base + p); |
| 793 | 622 |
S9xSetPPU(Work, 0x2102 + d->BAddress); |
| ... | ... |
@@ -798,7 +627,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 798 | 627 |
b = 3; |
| 799 | 628 |
break; |
| 800 | 629 |
} |
| 801 |
- |
|
| 630 |
+ // Fall through |
|
| 802 | 631 |
case 3: |
| 803 | 632 |
Work = *(base + p); |
| 804 | 633 |
S9xSetPPU(Work, 0x2103 + d->BAddress); |
| ... | ... |
@@ -1066,12 +895,8 @@ bool S9xDoDMA(uint8_t Channel) |
| 1066 | 895 |
} |
| 1067 | 896 |
} |
| 1068 | 897 |
|
| 1069 |
- if (CPU.NMILine && (Timings.NMITriggerPos != 0xffff)) |
|
| 1070 |
- {
|
|
| 898 |
+ if (CPU.NMIPending && Timings.NMITriggerPos != 0xffff) |
|
| 1071 | 899 |
Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay; |
| 1072 |
- if (Timings.NMITriggerPos >= Timings.H_Max) |
|
| 1073 |
- Timings.NMITriggerPos -= Timings.H_Max; |
|
| 1074 |
- } |
|
| 1075 | 900 |
|
| 1076 | 901 |
CPU.InDMA = CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = false; |
| 1077 | 902 |
CPU.CurrentDMAorHDMAChannel = -1; |
| ... | ... |
@@ -1176,9 +1001,10 @@ void S9xStartHDMA() |
| 1176 | 1001 |
|
| 1177 | 1002 |
uint8_t S9xDoHDMA(uint8_t byte) |
| 1178 | 1003 |
{
|
| 1179 |
- SDMA *p = &DMA[0]; |
|
| 1004 |
+ SDMA *p; |
|
| 1180 | 1005 |
|
| 1181 |
- int d = 0; |
|
| 1006 |
+ int d; |
|
| 1007 |
+ uint8_t mask; |
|
| 1182 | 1008 |
|
| 1183 | 1009 |
CPU.InHDMA = CPU.InDMAorHDMA = true; |
| 1184 | 1010 |
CPU.HDMARanInDMA = CPU.InDMA ? byte : 0; |
| ... | ... |
@@ -1188,7 +1014,7 @@ uint8_t S9xDoHDMA(uint8_t byte) |
| 1188 | 1014 |
// XXX: Not quite right... |
| 1189 | 1015 |
ADD_CYCLES(Timings.DMACPUSync); |
| 1190 | 1016 |
|
| 1191 |
- for (uint8_t mask = 1; mask; mask <<= 1, ++p, ++d) |
|
| 1017 |
+ for (mask = 1, p = &DMA[0], d = 0; mask; mask <<= 1, ++p, ++d) |
|
| 1192 | 1018 |
{
|
| 1193 | 1019 |
if (byte & mask) |
| 1194 | 1020 |
{
|
| ... | ... |
@@ -1374,7 +1200,10 @@ uint8_t S9xDoHDMA(uint8_t byte) |
| 1374 | 1200 |
case 1: |
| 1375 | 1201 |
S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress); |
| 1376 | 1202 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1377 |
- S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); |
|
| 1203 |
+ // XXX: All HDMA should read to MDR first. This one just |
|
| 1204 |
+ // happens to fix Speedy Gonzales. |
|
| 1205 |
+ OpenBus = *(HDMAMemPointers[d] + 1); |
|
| 1206 |
+ S9xSetPPU(OpenBus, 0x2101 + p->BAddress); |
|
| 1378 | 1207 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1379 | 1208 |
HDMAMemPointers[d] += 2; |
| 1380 | 1209 |
break; |
| ... | ... |
@@ -1484,7 +1313,16 @@ uint8_t S9xDoHDMA(uint8_t byte) |
| 1484 | 1313 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1485 | 1314 |
} |
| 1486 | 1315 |
} |
| 1316 |
+ } |
|
| 1317 |
+ } |
|
| 1318 |
+ } |
|
| 1487 | 1319 |
|
| 1320 |
+ for (mask = 1, p = &DMA[0], d = 0; mask; mask <<= 1, ++p, ++d) |
|
| 1321 |
+ {
|
|
| 1322 |
+ if (byte & mask) |
|
| 1323 |
+ {
|
|
| 1324 |
+ if (p->DoTransfer) |
|
| 1325 |
+ {
|
|
| 1488 | 1326 |
if (p->HDMAIndirectAddressing) |
| 1489 | 1327 |
p->DMACount_Or_HDMAIndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; |
| 1490 | 1328 |
else |
| ... | ... |
@@ -1500,7 +1338,6 @@ uint8_t S9xDoHDMA(uint8_t byte) |
| 1500 | 1338 |
byte &= ~mask; |
| 1501 | 1339 |
PPU.HDMAEnded |= mask; |
| 1502 | 1340 |
p->DoTransfer = false; |
| 1503 |
- continue; |
|
| 1504 | 1341 |
} |
| 1505 | 1342 |
} |
| 1506 | 1343 |
else |
| ... | ... |
@@ -209,8 +209,7 @@ static inline bool addCyclesInDMA(uint8_t dma_channel) |
| 209 | 209 |
|
| 210 | 210 |
bool S9xDoDMA(uint8_t Channel) |
| 211 | 211 |
{
|
| 212 |
- CPU.InDMA = true; |
|
| 213 |
- CPU.InDMAorHDMA = true; |
|
| 212 |
+ CPU.InDMA = CPU.InDMAorHDMA = true; |
|
| 214 | 213 |
CPU.CurrentDMAorHDMAChannel = Channel; |
| 215 | 214 |
|
| 216 | 215 |
SDMA *d = &DMA[Channel]; |
| ... | ... |
@@ -325,9 +324,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 325 | 324 |
p += inc; |
| 326 | 325 |
if (!addCyclesInDMA(Channel)) |
| 327 | 326 |
{
|
| 328 |
- CPU.InDMA = false; |
|
| 329 |
- CPU.InDMAorHDMA = false; |
|
| 330 |
- CPU.InWRAMDMAorHDMA = false; |
|
| 327 |
+ CPU.InDMA = CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = false; |
|
| 331 | 328 |
CPU.CurrentDMAorHDMAChannel = -1; |
| 332 | 329 |
return false; |
| 333 | 330 |
} |
| ... | ... |
@@ -836,9 +833,7 @@ bool S9xDoDMA(uint8_t Channel) |
| 836 | 833 |
d->AAddress += inc; |
| 837 | 834 |
if (!addCyclesInDMA(Channel)) |
| 838 | 835 |
{
|
| 839 |
- CPU.InDMA = false; |
|
| 840 |
- CPU.InDMAorHDMA = false; |
|
| 841 |
- CPU.InWRAMDMAorHDMA = false; |
|
| 836 |
+ CPU.InDMA = CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = false; |
|
| 842 | 837 |
CPU.CurrentDMAorHDMAChannel = -1; |
| 843 | 838 |
return false; |
| 844 | 839 |
} |
| ... | ... |
@@ -1148,8 +1143,7 @@ void S9xStartHDMA() |
| 1148 | 1143 |
|
| 1149 | 1144 |
PPU.HDMAEnded = 0; |
| 1150 | 1145 |
|
| 1151 |
- CPU.InHDMA = true; |
|
| 1152 |
- CPU.InDMAorHDMA = true; |
|
| 1146 |
+ CPU.InHDMA = CPU.InDMAorHDMA = true; |
|
| 1153 | 1147 |
int32_t tmpch = CPU.CurrentDMAorHDMAChannel; |
| 1154 | 1148 |
|
| 1155 | 1149 |
// XXX: Not quite right... |
| ... | ... |
@@ -1186,8 +1180,7 @@ uint8_t S9xDoHDMA(uint8_t byte) |
| 1186 | 1180 |
|
| 1187 | 1181 |
int d = 0; |
| 1188 | 1182 |
|
| 1189 |
- CPU.InHDMA = true; |
|
| 1190 |
- CPU.InDMAorHDMA = true; |
|
| 1183 |
+ CPU.InHDMA = CPU.InDMAorHDMA = true; |
|
| 1191 | 1184 |
CPU.HDMARanInDMA = CPU.InDMA ? byte : 0; |
| 1192 | 1185 |
bool temp = CPU.InWRAMDMAorHDMA; |
| 1193 | 1186 |
int32_t tmpch = CPU.CurrentDMAorHDMAChannel; |
| ... | ... |
@@ -179,26 +179,15 @@ |
| 179 | 179 |
#include "memmap.h" |
| 180 | 180 |
#include "dma.h" |
| 181 | 181 |
#include "apu/apu.h" |
| 182 |
-//#include "sdd1emu.h" |
|
| 183 |
-//#include "spc7110emu.h" |
|
| 184 |
-#ifdef DEBUGGER |
|
| 185 |
-#include "missing.h" |
|
| 186 |
-#endif |
|
| 187 | 182 |
|
| 188 |
-//#define ADD_CYCLES(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); }
|
|
| 189 | 183 |
static inline void ADD_CYCLES(int32_t n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += n; S9xCheckInterrupts(); }
|
| 190 | 184 |
|
| 191 |
-extern uint8_t *HDMAMemPointers[8]; |
|
| 192 |
-extern int HDMA_ModeByteCounts[8]; |
|
| 193 |
-//extern SPC7110 s7emu; |
|
| 185 |
+extern uint8_t *HDMAMemPointers[8]; |
|
| 186 |
+extern int HDMA_ModeByteCounts[8]; |
|
| 194 | 187 |
|
| 195 |
-static uint8_t sdd1_decode_buffer[0x10000]; |
|
| 188 |
+static uint8_t sdd1_decode_buffer[0x10000]; |
|
| 196 | 189 |
|
| 197 |
-//static inline bool addCyclesInDMA (uint8_t); |
|
| 198 |
-//static inline bool HDMAReadLineCount (int); |
|
| 199 |
- |
|
| 200 |
- |
|
| 201 |
-static inline bool addCyclesInDMA (uint8_t dma_channel) |
|
| 190 |
+static inline bool addCyclesInDMA(uint8_t dma_channel) |
|
| 202 | 191 |
{
|
| 203 | 192 |
// Add 8 cycles per byte, sync APU, and do HC related events. |
| 204 | 193 |
// If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. |
| ... | ... |
@@ -209,9 +198,6 @@ static inline bool addCyclesInDMA (uint8_t dma_channel) |
| 209 | 198 |
if (CPU.HDMARanInDMA & (1 << dma_channel)) |
| 210 | 199 |
{
|
| 211 | 200 |
CPU.HDMARanInDMA = 0; |
| 212 |
- #ifdef DEBUGGER |
|
| 213 |
- printf("HDMA and DMA use the same channel %d!\n", dma_channel);
|
|
| 214 |
- #endif |
|
| 215 | 201 |
// If HDMA triggers in the middle of DMA transfer and it uses the same channel, |
| 216 | 202 |
// it kills the DMA transfer immediately. $43x2 and $43x5 stop updating. |
| 217 | 203 |
return false; |
| ... | ... |
@@ -221,13 +207,13 @@ static inline bool addCyclesInDMA (uint8_t dma_channel) |
| 221 | 207 |
return true; |
| 222 | 208 |
} |
| 223 | 209 |
|
| 224 |
-bool S9xDoDMA (uint8_t Channel) |
|
| 210 |
+bool S9xDoDMA(uint8_t Channel) |
|
| 225 | 211 |
{
|
| 226 | 212 |
CPU.InDMA = true; |
| 227 |
- CPU.InDMAorHDMA = true; |
|
| 213 |
+ CPU.InDMAorHDMA = true; |
|
| 228 | 214 |
CPU.CurrentDMAorHDMAChannel = Channel; |
| 229 | 215 |
|
| 230 |
- SDMA *d = &DMA[Channel]; |
|
| 216 |
+ SDMA *d = &DMA[Channel]; |
|
| 231 | 217 |
|
| 232 | 218 |
// Check invalid DMA first |
| 233 | 219 |
if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer) |
| ... | ... |
@@ -242,9 +228,9 @@ bool S9xDoDMA (uint8_t Channel) |
| 242 | 228 |
// not being able to read and write itself at the same time |
| 243 | 229 |
// And no, PPU.WRAM should not be updated. |
| 244 | 230 |
|
| 245 |
- int32_t c = d->TransferBytes; |
|
| 231 |
+ int32_t c = d->DMACount_Or_HDMAIndirectAddress; |
|
| 246 | 232 |
// Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. |
| 247 |
- if (c == 0) |
|
| 233 |
+ if (!c) |
|
| 248 | 234 |
c = 0x10000; |
| 249 | 235 |
|
| 250 | 236 |
// 8 cycles per channel |
| ... | ... |
@@ -252,9 +238,9 @@ bool S9xDoDMA (uint8_t Channel) |
| 252 | 238 |
// 8 cycles per byte |
| 253 | 239 |
while (c) |
| 254 | 240 |
{
|
| 255 |
- d->TransferBytes--; |
|
| 256 |
- d->AAddress++; |
|
| 257 |
- c--; |
|
| 241 |
+ --d->DMACount_Or_HDMAIndirectAddress; |
|
| 242 |
+ ++d->AAddress; |
|
| 243 |
+ --c; |
|
| 258 | 244 |
if (!addCyclesInDMA(Channel)) |
| 259 | 245 |
{
|
| 260 | 246 |
CPU.InDMA = false; |
| ... | ... |
@@ -264,14 +250,6 @@ bool S9xDoDMA (uint8_t Channel) |
| 264 | 250 |
} |
| 265 | 251 |
} |
| 266 | 252 |
|
| 267 |
- #ifdef DEBUGGER |
|
| 268 |
- if (Settings.TraceDMA) |
|
| 269 |
- {
|
|
| 270 |
- sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank); |
|
| 271 |
- S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 272 |
- } |
|
| 273 |
- #endif |
|
| 274 |
- |
|
| 275 | 253 |
CPU.InDMA = false; |
| 276 | 254 |
CPU.InDMAorHDMA = false; |
| 277 | 255 |
CPU.CurrentDMAorHDMAChannel = -1; |
| ... | ... |
@@ -279,26 +257,18 @@ bool S9xDoDMA (uint8_t Channel) |
| 279 | 257 |
} |
| 280 | 258 |
|
| 281 | 259 |
// Prepare for accessing $2118-2119 |
| 282 |
- /*switch (d->BAddress) |
|
| 283 |
- {
|
|
| 284 |
- case 0x18: |
|
| 285 |
- case 0x19: |
|
| 286 |
- if (IPPU.RenderThisFrame) |
|
| 287 |
- FLUSH_REDRAW(); |
|
| 288 |
- break; |
|
| 289 |
- }*/ |
|
| 290 |
- |
|
| 291 |
- int32_t inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); |
|
| 292 |
- int32_t count = d->TransferBytes; |
|
| 260 |
+ |
|
| 261 |
+ int32_t inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); |
|
| 262 |
+ int32_t count = d->DMACount_Or_HDMAIndirectAddress; |
|
| 293 | 263 |
// Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. |
| 294 |
- if (count == 0) |
|
| 264 |
+ if (!count) |
|
| 295 | 265 |
count = 0x10000; |
| 296 | 266 |
|
| 297 | 267 |
// Prepare for custom chip DMA |
| 298 | 268 |
|
| 299 | 269 |
// S-DD1 |
| 300 | 270 |
|
| 301 |
- uint8_t *in_sdd1_dma = NULL; |
|
| 271 |
+ uint8_t *in_sdd1_dma = nullptr; |
|
| 302 | 272 |
|
| 303 | 273 |
if (Settings.SDD1) |
| 304 | 274 |
{
|
| ... | ... |
@@ -309,19 +279,9 @@ bool S9xDoDMA (uint8_t Channel) |
| 309 | 279 |
// Hacky support for pre-decompressed S-DD1 data |
| 310 | 280 |
inc = !d->AAddressDecrement ? 1 : -1; |
| 311 | 281 |
|
| 312 |
- uint8_t *in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress)); |
|
| 282 |
+ uint8_t *in_ptr = S9xGetBasePointer((d->ABank << 16) | d->AAddress); |
|
| 313 | 283 |
if (in_ptr) |
| 314 |
- {
|
|
| 315 | 284 |
in_ptr += d->AAddress; |
| 316 |
- //SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); |
|
| 317 |
- } |
|
| 318 |
- #ifdef DEBUGGER |
|
| 319 |
- else |
|
| 320 |
- {
|
|
| 321 |
- sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); |
|
| 322 |
- S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); |
|
| 323 |
- } |
|
| 324 |
- #endif |
|
| 325 | 285 |
|
| 326 | 286 |
in_sdd1_dma = sdd1_decode_buffer; |
| 327 | 287 |
} |
| ... | ... |
@@ -329,242 +289,50 @@ bool S9xDoDMA (uint8_t Channel) |
| 329 | 289 |
Memory.FillRAM[0x4801] = 0; |
| 330 | 290 |
} |
| 331 | 291 |
|
| 332 |
- // SPC7110 |
|
| 333 |
- |
|
| 334 |
- //uint8_t *spc7110_dma = NULL; |
|
| 335 |
- |
|
| 336 |
- /*if (Settings.SPC7110) |
|
| 337 |
- {
|
|
| 338 |
- if (d->AAddress == 0x4800 || d->ABank == 0x50) |
|
| 339 |
- {
|
|
| 340 |
- spc7110_dma = new uint8_t[d->TransferBytes]; |
|
| 341 |
- for (int i = 0; i < d->TransferBytes; i++) |
|
| 342 |
- spc7110_dma[i] = s7emu.decomp.read(); |
|
| 343 |
- |
|
| 344 |
- int32_t icount = s7emu.r4809 | (s7emu.r480a << 8); |
|
| 345 |
- icount -= d->TransferBytes; |
|
| 346 |
- s7emu.r4809 = icount & 0x00ff; |
|
| 347 |
- s7emu.r480a = (icount & 0xff00) >> 8; |
|
| 348 |
- |
|
| 349 |
- inc = 1; |
|
| 350 |
- d->AAddress -= count; |
|
| 351 |
- } |
|
| 352 |
- }*/ |
|
| 353 |
- |
|
| 354 |
- // SA-1 |
|
| 355 |
- |
|
| 356 |
- //bool in_sa1_dma = false; |
|
| 357 |
- |
|
| 358 |
- /*if (Settings.SA1) |
|
| 359 |
- {
|
|
| 360 |
- if (SA1.in_char_dma && d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40) |
|
| 361 |
- {
|
|
| 362 |
- // Perform packed bitmap to PPU character format conversion on the data |
|
| 363 |
- // before transmitting it to V-RAM via-DMA. |
|
| 364 |
- int32_t num_chars = 1 << ((Memory.FillRAM[0x2231] >> 2) & 7); |
|
| 365 |
- int32_t depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; |
|
| 366 |
- int32_t bytes_per_char = 8 * depth; |
|
| 367 |
- int32_t bytes_per_line = depth * num_chars; |
|
| 368 |
- int32_t char_line_bytes = bytes_per_char * num_chars; |
|
| 369 |
- uint32_t addr = (d->AAddress / char_line_bytes) * char_line_bytes; |
|
| 370 |
- |
|
| 371 |
- uint8_t *base = S9xGetBasePointer((d->ABank << 16) + addr); |
|
| 372 |
- if (!base) |
|
| 373 |
- {
|
|
| 374 |
- sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr); |
|
| 375 |
- S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); |
|
| 376 |
- base = Memory.ROM; |
|
| 377 |
- } |
|
| 378 |
- |
|
| 379 |
- base += addr; |
|
| 380 |
- |
|
| 381 |
- uint8_t *buffer = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; |
|
| 382 |
- uint8_t *p = buffer; |
|
| 383 |
- uint32_t inc_sa1 = char_line_bytes - (d->AAddress % char_line_bytes); |
|
| 384 |
- uint32_t char_count = inc_sa1 / bytes_per_char; |
|
| 385 |
- |
|
| 386 |
- in_sa1_dma = true; |
|
| 387 |
- |
|
| 388 |
- #if 0 |
|
| 389 |
- printf("SA-1 DMA: %08x,", base);
|
|
| 390 |
- printf("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n",
|
|
| 391 |
- depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); |
|
| 392 |
- #endif |
|
| 393 |
- |
|
| 394 |
- switch (depth) |
|
| 395 |
- {
|
|
| 396 |
- case 2: |
|
| 397 |
- for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) |
|
| 398 |
- {
|
|
| 399 |
- uint8_t *line = base + (num_chars - char_count) * 2; |
|
| 400 |
- for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 2) |
|
| 401 |
- {
|
|
| 402 |
- uint8_t *q = line; |
|
| 403 |
- for (int32_t l = 0; l < 8; l++, q += bytes_per_line) |
|
| 404 |
- {
|
|
| 405 |
- for (int32_t b = 0; b < 2; b++) |
|
| 406 |
- {
|
|
| 407 |
- uint8_t r = *(q + b); |
|
| 408 |
- *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); |
|
| 409 |
- *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); |
|
| 410 |
- *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); |
|
| 411 |
- *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); |
|
| 412 |
- *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); |
|
| 413 |
- *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); |
|
| 414 |
- *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); |
|
| 415 |
- *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); |
|
| 416 |
- } |
|
| 417 |
- |
|
| 418 |
- p += 2; |
|
| 419 |
- } |
|
| 420 |
- } |
|
| 421 |
- } |
|
| 422 |
- |
|
| 423 |
- break; |
|
| 424 |
- |
|
| 425 |
- case 4: |
|
| 426 |
- for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) |
|
| 427 |
- {
|
|
| 428 |
- uint8_t *line = base + (num_chars - char_count) * 4; |
|
| 429 |
- for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 4) |
|
| 430 |
- {
|
|
| 431 |
- uint8_t *q = line; |
|
| 432 |
- for (int32_t l = 0; l < 8; l++, q += bytes_per_line) |
|
| 433 |
- {
|
|
| 434 |
- for (int32_t b = 0; b < 4; b++) |
|
| 435 |
- {
|
|
| 436 |
- uint8_t r = *(q + b); |
|
| 437 |
- *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); |
|
| 438 |
- *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); |
|
| 439 |
- *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); |
|
| 440 |
- *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); |
|
| 441 |
- *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); |
|
| 442 |
- *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); |
|
| 443 |
- *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); |
|
| 444 |
- *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); |
|
| 445 |
- } |
|
| 446 |
- |
|
| 447 |
- p += 2; |
|
| 448 |
- } |
|
| 449 |
- |
|
| 450 |
- p += 32 - 16; |
|
| 451 |
- } |
|
| 452 |
- } |
|
| 453 |
- |
|
| 454 |
- break; |
|
| 455 |
- |
|
| 456 |
- case 8: |
|
| 457 |
- for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) |
|
| 458 |
- {
|
|
| 459 |
- uint8_t *line = base + (num_chars - char_count) * 8; |
|
| 460 |
- for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 8) |
|
| 461 |
- {
|
|
| 462 |
- uint8_t *q = line; |
|
| 463 |
- for (int32_t l = 0; l < 8; l++, q += bytes_per_line) |
|
| 464 |
- {
|
|
| 465 |
- for (int32_t b = 0; b < 8; b++) |
|
| 466 |
- {
|
|
| 467 |
- uint8_t r = *(q + b); |
|
| 468 |
- *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); |
|
| 469 |
- *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); |
|
| 470 |
- *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); |
|
| 471 |
- *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); |
|
| 472 |
- *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); |
|
| 473 |
- *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); |
|
| 474 |
- *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); |
|
| 475 |
- *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); |
|
| 476 |
- } |
|
| 477 |
- |
|
| 478 |
- p += 2; |
|
| 479 |
- } |
|
| 480 |
- |
|
| 481 |
- p += 64 - 16; |
|
| 482 |
- } |
|
| 483 |
- } |
|
| 484 |
- |
|
| 485 |
- break; |
|
| 486 |
- } |
|
| 487 |
- } |
|
| 488 |
- }*/ |
|
| 489 |
- |
|
| 490 |
-#ifdef DEBUGGER |
|
| 491 |
- if (Settings.TraceDMA) |
|
| 492 |
- {
|
|
| 493 |
- sprintf(String, "DMA[%d]: %s Mode:%d 0x%02X%04X->0x21%02X Bytes:%d (%s) V:%03d", |
|
| 494 |
- Channel, d->ReverseTransfer ? "PPU->CPU" : "CPU->PPU", d->TransferMode, d->ABank, d->AAddress, d->BAddress, |
|
| 495 |
- d->TransferBytes, d->AAddressFixed ? "fixed" : (d->AAddressDecrement ? "dec" : "inc"), CPU.V_Counter); |
|
| 496 |
- |
|
| 497 |
- if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a) |
|
| 498 |
- sprintf(String, "%s VRAM: %04X (%d,%d) %s", String, |
|
| 499 |
- PPU.VMA.Address, PPU.VMA.Increment, PPU.VMA.FullGraphicCount, PPU.VMA.High ? "word" : "byte"); |
|
| 500 |
- else |
|
| 501 |
- if (d->BAddress == 0x22 || d->BAddress == 0x3b) |
|
| 502 |
- sprintf(String, "%s CGRAM: %02X (%x)", String, PPU.CGADD, PPU.CGFLIP); |
|
| 503 |
- else |
|
| 504 |
- if (d->BAddress == 0x04 || d->BAddress == 0x38) |
|
| 505 |
- sprintf(String, "%s OBJADDR: %04X", String, PPU.OAMAddr); |
|
| 506 |
- |
|
| 507 |
- S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 508 |
- } |
|
| 509 |
-#endif |
|
| 510 |
- |
|
| 511 | 292 |
// Do Transfer |
| 512 | 293 |
|
| 513 |
- uint8_t Work; |
|
| 294 |
+ uint8_t Work; |
|
| 514 | 295 |
|
| 515 | 296 |
// 8 cycles per channel |
| 516 | 297 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 517 | 298 |
|
| 518 | 299 |
if (!d->ReverseTransfer) |
| 519 |
- {
|
|
| 300 |
+ {
|
|
| 520 | 301 |
// CPU -> PPU |
| 521 |
- int32_t b = 0; |
|
| 522 |
- uint16_t p = d->AAddress; |
|
| 523 |
- uint8_t *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); |
|
| 524 |
- bool inWRAM_DMA; |
|
| 302 |
+ int32_t b = 0; |
|
| 303 |
+ uint16_t p = d->AAddress; |
|
| 304 |
+ uint8_t *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); |
|
| 525 | 305 |
|
| 526 |
- int32_t rem = count; |
|
| 306 |
+ int32_t rem = count; |
|
| 527 | 307 |
// Transfer per block if d->AAdressFixed is false |
| 528 | 308 |
count = d->AAddressFixed ? rem : (d->AAddressDecrement ? ((p & MEMMAP_MASK) + 1) : (MEMMAP_BLOCK_SIZE - (p & MEMMAP_MASK))); |
| 529 | 309 |
|
| 530 | 310 |
// Settings for custom chip DMA |
| 531 |
- /*if (in_sa1_dma) |
|
| 532 |
- {
|
|
| 533 |
- base = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; |
|
| 534 |
- p = 0; |
|
| 535 |
- count = rem; |
|
| 536 |
- } |
|
| 537 |
- else*/ |
|
| 538 | 311 |
if (in_sdd1_dma) |
| 539 | 312 |
{
|
| 540 | 313 |
base = in_sdd1_dma; |
| 541 | 314 |
p = 0; |
| 542 | 315 |
count = rem; |
| 543 | 316 |
} |
| 544 |
- /*else |
|
| 545 |
- if (spc7110_dma) |
|
| 546 |
- {
|
|
| 547 |
- base = spc7110_dma; |
|
| 548 |
- p = 0; |
|
| 549 |
- count = rem; |
|
| 550 |
- }*/ |
|
| 551 | 317 |
|
| 552 |
- inWRAM_DMA = ((/*!in_sa1_dma && */!in_sdd1_dma/* && !spc7110_dma*/) && |
|
| 553 |
- (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); |
|
| 318 |
+ bool inWRAM_DMA = !in_sdd1_dma && (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000)); |
|
| 554 | 319 |
|
| 555 | 320 |
// 8 cycles per byte |
| 556 |
- #define UPDATE_COUNTERS \ |
|
| 557 |
- d->TransferBytes--; \ |
|
| 558 |
- d->AAddress += inc; \ |
|
| 559 |
- p += inc; \ |
|
| 560 |
- if (!addCyclesInDMA(Channel)) \ |
|
| 561 |
- { \
|
|
| 562 |
- CPU.InDMA = false; \ |
|
| 563 |
- CPU.InDMAorHDMA = false; \ |
|
| 564 |
- CPU.InWRAMDMAorHDMA = false; \ |
|
| 565 |
- CPU.CurrentDMAorHDMAChannel = -1; \ |
|
| 566 |
- return false; \ |
|
| 321 |
+ auto UPDATE_COUNTERS = [&]() -> bool |
|
| 322 |
+ {
|
|
| 323 |
+ --d->DMACount_Or_HDMAIndirectAddress; |
|
| 324 |
+ d->AAddress += inc; |
|
| 325 |
+ p += inc; |
|
| 326 |
+ if (!addCyclesInDMA(Channel)) |
|
| 327 |
+ {
|
|
| 328 |
+ CPU.InDMA = false; |
|
| 329 |
+ CPU.InDMAorHDMA = false; |
|
| 330 |
+ CPU.InWRAMDMAorHDMA = false; |
|
| 331 |
+ CPU.CurrentDMAorHDMAChannel = -1; |
|
| 332 |
+ return false; |
|
| 567 | 333 |
} |
| 334 |
+ return true; |
|
| 335 |
+ }; |
|
| 568 | 336 |
|
| 569 | 337 |
while (1) |
| 570 | 338 |
{
|
| ... | ... |
@@ -577,17 +345,17 @@ bool S9xDoDMA (uint8_t Channel) |
| 577 | 345 |
if (!base) |
| 578 | 346 |
{
|
| 579 | 347 |
// DMA SLOW PATH |
| 580 |
- if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) |
|
| 348 |
+ if (!d->TransferMode || d->TransferMode == 2 || d->TransferMode == 6) |
|
| 581 | 349 |
{
|
| 582 | 350 |
do |
| 583 | 351 |
{
|
| 584 | 352 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 585 | 353 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 586 |
- UPDATE_COUNTERS; |
|
| 354 |
+ if (!UPDATE_COUNTERS()) |
|
| 355 |
+ return false; |
|
| 587 | 356 |
} while (--count > 0); |
| 588 | 357 |
} |
| 589 |
- else |
|
| 590 |
- if (d->TransferMode == 1 || d->TransferMode == 5) |
|
| 358 |
+ else if (d->TransferMode == 1 || d->TransferMode == 5) |
|
| 591 | 359 |
{
|
| 592 | 360 |
// This is a variation on Duff's Device. It is legal C/C++. |
| 593 | 361 |
switch (b) |
| ... | ... |
@@ -597,14 +365,16 @@ bool S9xDoDMA (uint8_t Channel) |
| 597 | 365 |
{
|
| 598 | 366 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 599 | 367 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 600 |
- UPDATE_COUNTERS; |
|
| 601 |
- count--; |
|
| 368 |
+ if (!UPDATE_COUNTERS()) |
|
| 369 |
+ return false; |
|
| 370 |
+ --count; |
|
| 602 | 371 |
|
| 603 | 372 |
case 1: |
| 604 | 373 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 605 | 374 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 606 |
- UPDATE_COUNTERS; |
|
| 607 |
- count--; |
|
| 375 |
+ if (!UPDATE_COUNTERS()) |
|
| 376 |
+ return false; |
|
| 377 |
+ --count; |
|
| 608 | 378 |
} |
| 609 | 379 |
} |
| 610 | 380 |
|
| ... | ... |
@@ -612,14 +382,14 @@ bool S9xDoDMA (uint8_t Channel) |
| 612 | 382 |
{
|
| 613 | 383 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 614 | 384 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 615 |
- UPDATE_COUNTERS; |
|
| 385 |
+ if (!UPDATE_COUNTERS()) |
|
| 386 |
+ return false; |
|
| 616 | 387 |
b = 1; |
| 617 | 388 |
} |
| 618 | 389 |
else |
| 619 | 390 |
b = 0; |
| 620 | 391 |
} |
| 621 |
- else |
|
| 622 |
- if (d->TransferMode == 3 || d->TransferMode == 7) |
|
| 392 |
+ else if (d->TransferMode == 3 || d->TransferMode == 7) |
|
| 623 | 393 |
{
|
| 624 | 394 |
switch (b) |
| 625 | 395 |
{
|
| ... | ... |
@@ -628,7 +398,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 628 | 398 |
{
|
| 629 | 399 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 630 | 400 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 631 |
- UPDATE_COUNTERS; |
|
| 401 |
+ if (!UPDATE_COUNTERS()) |
|
| 402 |
+ return false; |
|
| 632 | 403 |
if (--count <= 0) |
| 633 | 404 |
{
|
| 634 | 405 |
b = 1; |
| ... | ... |
@@ -638,7 +409,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 638 | 409 |
case 1: |
| 639 | 410 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 640 | 411 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 641 |
- UPDATE_COUNTERS; |
|
| 412 |
+ if (!UPDATE_COUNTERS()) |
|
| 413 |
+ return false; |
|
| 642 | 414 |
if (--count <= 0) |
| 643 | 415 |
{
|
| 644 | 416 |
b = 2; |
| ... | ... |
@@ -648,7 +420,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 648 | 420 |
case 2: |
| 649 | 421 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 650 | 422 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 651 |
- UPDATE_COUNTERS; |
|
| 423 |
+ if (!UPDATE_COUNTERS()) |
|
| 424 |
+ return false; |
|
| 652 | 425 |
if (--count <= 0) |
| 653 | 426 |
{
|
| 654 | 427 |
b = 3; |
| ... | ... |
@@ -658,7 +431,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 658 | 431 |
case 3: |
| 659 | 432 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 660 | 433 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 661 |
- UPDATE_COUNTERS; |
|
| 434 |
+ if (!UPDATE_COUNTERS()) |
|
| 435 |
+ return false; |
|
| 662 | 436 |
if (--count <= 0) |
| 663 | 437 |
{
|
| 664 | 438 |
b = 0; |
| ... | ... |
@@ -667,8 +441,7 @@ bool S9xDoDMA (uint8_t Channel) |
| 667 | 441 |
} while (1); |
| 668 | 442 |
} |
| 669 | 443 |
} |
| 670 |
- else |
|
| 671 |
- if (d->TransferMode == 4) |
|
| 444 |
+ else if (d->TransferMode == 4) |
|
| 672 | 445 |
{
|
| 673 | 446 |
switch (b) |
| 674 | 447 |
{
|
| ... | ... |
@@ -677,7 +450,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 677 | 450 |
{
|
| 678 | 451 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 679 | 452 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 680 |
- UPDATE_COUNTERS; |
|
| 453 |
+ if (!UPDATE_COUNTERS()) |
|
| 454 |
+ return false; |
|
| 681 | 455 |
if (--count <= 0) |
| 682 | 456 |
{
|
| 683 | 457 |
b = 1; |
| ... | ... |
@@ -687,7 +461,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 687 | 461 |
case 1: |
| 688 | 462 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 689 | 463 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 690 |
- UPDATE_COUNTERS; |
|
| 464 |
+ if (!UPDATE_COUNTERS()) |
|
| 465 |
+ return false; |
|
| 691 | 466 |
if (--count <= 0) |
| 692 | 467 |
{
|
| 693 | 468 |
b = 2; |
| ... | ... |
@@ -697,7 +472,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 697 | 472 |
case 2: |
| 698 | 473 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 699 | 474 |
S9xSetPPU(Work, 0x2102 + d->BAddress); |
| 700 |
- UPDATE_COUNTERS; |
|
| 475 |
+ if (!UPDATE_COUNTERS()) |
|
| 476 |
+ return false; |
|
| 701 | 477 |
if (--count <= 0) |
| 702 | 478 |
{
|
| 703 | 479 |
b = 3; |
| ... | ... |
@@ -707,7 +483,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 707 | 483 |
case 3: |
| 708 | 484 |
Work = S9xGetByte((d->ABank << 16) + p); |
| 709 | 485 |
S9xSetPPU(Work, 0x2103 + d->BAddress); |
| 710 |
- UPDATE_COUNTERS; |
|
| 486 |
+ if (!UPDATE_COUNTERS()) |
|
| 487 |
+ return false; |
|
| 711 | 488 |
if (--count <= 0) |
| 712 | 489 |
{
|
| 713 | 490 |
b = 0; |
| ... | ... |
@@ -716,18 +493,11 @@ bool S9xDoDMA (uint8_t Channel) |
| 716 | 493 |
} while (1); |
| 717 | 494 |
} |
| 718 | 495 |
} |
| 719 |
- #ifdef DEBUGGER |
|
| 720 |
- else |
|
| 721 |
- {
|
|
| 722 |
- sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 723 |
- S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 724 |
- } |
|
| 725 |
- #endif |
|
| 726 | 496 |
} |
| 727 | 497 |
else |
| 728 | 498 |
{
|
| 729 | 499 |
// DMA FAST PATH |
| 730 |
- if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) |
|
| 500 |
+ if (!d->TransferMode || d->TransferMode == 2 || d->TransferMode == 6) |
|
| 731 | 501 |
{
|
| 732 | 502 |
switch (d->BAddress) |
| 733 | 503 |
{
|
| ... | ... |
@@ -736,7 +506,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 736 | 506 |
{
|
| 737 | 507 |
Work = *(base + p); |
| 738 | 508 |
REGISTER_2104(Work); |
| 739 |
- UPDATE_COUNTERS; |
|
| 509 |
+ if (!UPDATE_COUNTERS()) |
|
| 510 |
+ return false; |
|
| 740 | 511 |
} while (--count > 0); |
| 741 | 512 |
|
| 742 | 513 |
break; |
| ... | ... |
@@ -748,7 +519,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 748 | 519 |
{
|
| 749 | 520 |
Work = *(base + p); |
| 750 | 521 |
REGISTER_2118_linear(Work); |
| 751 |
- UPDATE_COUNTERS; |
|
| 522 |
+ if (!UPDATE_COUNTERS()) |
|
| 523 |
+ return false; |
|
| 752 | 524 |
} while (--count > 0); |
| 753 | 525 |
} |
| 754 | 526 |
else |
| ... | ... |
@@ -757,7 +529,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 757 | 529 |
{
|
| 758 | 530 |
Work = *(base + p); |
| 759 | 531 |
REGISTER_2118_tile(Work); |
| 760 |
- UPDATE_COUNTERS; |
|
| 532 |
+ if (!UPDATE_COUNTERS()) |
|
| 533 |
+ return false; |
|
| 761 | 534 |
} while (--count > 0); |
| 762 | 535 |
} |
| 763 | 536 |
|
| ... | ... |
@@ -770,7 +543,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 770 | 543 |
{
|
| 771 | 544 |
Work = *(base + p); |
| 772 | 545 |
REGISTER_2119_linear(Work); |
| 773 |
- UPDATE_COUNTERS; |
|
| 546 |
+ if (!UPDATE_COUNTERS()) |
|
| 547 |
+ return false; |
|
| 774 | 548 |
} while (--count > 0); |
| 775 | 549 |
} |
| 776 | 550 |
else |
| ... | ... |
@@ -779,7 +553,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 779 | 553 |
{
|
| 780 | 554 |
Work = *(base + p); |
| 781 | 555 |
REGISTER_2119_tile(Work); |
| 782 |
- UPDATE_COUNTERS; |
|
| 556 |
+ if (!UPDATE_COUNTERS()) |
|
| 557 |
+ return false; |
|
| 783 | 558 |
} while (--count > 0); |
| 784 | 559 |
} |
| 785 | 560 |
|
| ... | ... |
@@ -789,8 +564,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 789 | 564 |
do |
| 790 | 565 |
{
|
| 791 | 566 |
Work = *(base + p); |
| 792 |
- //REGISTER_2122(Work); |
|
| 793 |
- UPDATE_COUNTERS; |
|
| 567 |
+ if (!UPDATE_COUNTERS()) |
|
| 568 |
+ return false; |
|
| 794 | 569 |
} while (--count > 0); |
| 795 | 570 |
|
| 796 | 571 |
break; |
| ... | ... |
@@ -802,14 +577,16 @@ bool S9xDoDMA (uint8_t Channel) |
| 802 | 577 |
{
|
| 803 | 578 |
Work = *(base + p); |
| 804 | 579 |
REGISTER_2180(Work); |
| 805 |
- UPDATE_COUNTERS; |
|
| 580 |
+ if (!UPDATE_COUNTERS()) |
|
| 581 |
+ return false; |
|
| 806 | 582 |
} while (--count > 0); |
| 807 | 583 |
} |
| 808 | 584 |
else |
| 809 | 585 |
{
|
| 810 | 586 |
do |
| 811 | 587 |
{
|
| 812 |
- UPDATE_COUNTERS; |
|
| 588 |
+ if (!UPDATE_COUNTERS()) |
|
| 589 |
+ return false; |
|
| 813 | 590 |
} while (--count > 0); |
| 814 | 591 |
} |
| 815 | 592 |
|
| ... | ... |
@@ -820,14 +597,14 @@ bool S9xDoDMA (uint8_t Channel) |
| 820 | 597 |
{
|
| 821 | 598 |
Work = *(base + p); |
| 822 | 599 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 823 |
- UPDATE_COUNTERS; |
|
| 600 |
+ if (!UPDATE_COUNTERS()) |
|
| 601 |
+ return false; |
|
| 824 | 602 |
} while (--count > 0); |
| 825 | 603 |
|
| 826 | 604 |
break; |
| 827 | 605 |
} |
| 828 | 606 |
} |
| 829 |
- else |
|
| 830 |
- if (d->TransferMode == 1 || d->TransferMode == 5) |
|
| 607 |
+ else if (d->TransferMode == 1 || d->TransferMode == 5) |
|
| 831 | 608 |
{
|
| 832 | 609 |
if (d->BAddress == 0x18) |
| 833 | 610 |
{
|
| ... | ... |
@@ -841,14 +618,16 @@ bool S9xDoDMA (uint8_t Channel) |
| 841 | 618 |
{
|
| 842 | 619 |
Work = *(base + p); |
| 843 | 620 |
REGISTER_2118_linear(Work); |
| 844 |
- UPDATE_COUNTERS; |
|
| 845 |
- count--; |
|
| 621 |
+ if (!UPDATE_COUNTERS()) |
|
| 622 |
+ return false; |
|
| 623 |
+ --count; |
|
| 846 | 624 |
|
| 847 | 625 |
case 1: |
| 848 | 626 |
Work = *(base + p); |
| 849 | 627 |
REGISTER_2119_linear(Work); |
| 850 |
- UPDATE_COUNTERS; |
|
| 851 |
- count--; |
|
| 628 |
+ if (!UPDATE_COUNTERS()) |
|
| 629 |
+ return false; |
|
| 630 |
+ --count; |
|
| 852 | 631 |
} |
| 853 | 632 |
} |
| 854 | 633 |
|
| ... | ... |
@@ -856,7 +635,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 856 | 635 |
{
|
| 857 | 636 |
Work = *(base + p); |
| 858 | 637 |
REGISTER_2118_linear(Work); |
| 859 |
- UPDATE_COUNTERS; |
|
| 638 |
+ if (!UPDATE_COUNTERS()) |
|
| 639 |
+ return false; |
|
| 860 | 640 |
b = 1; |
| 861 | 641 |
} |
| 862 | 642 |
else |
| ... | ... |
@@ -871,14 +651,16 @@ bool S9xDoDMA (uint8_t Channel) |
| 871 | 651 |
{
|
| 872 | 652 |
Work = *(base + p); |
| 873 | 653 |
REGISTER_2118_tile(Work); |
| 874 |
- UPDATE_COUNTERS; |
|
| 875 |
- count--; |
|
| 654 |
+ if (!UPDATE_COUNTERS()) |
|
| 655 |
+ return false; |
|
| 656 |
+ --count; |
|
| 876 | 657 |
|
| 877 | 658 |
case 1: |
| 878 | 659 |
Work = *(base + p); |
| 879 | 660 |
REGISTER_2119_tile(Work); |
| 880 |
- UPDATE_COUNTERS; |
|
| 881 |
- count--; |
|
| 661 |
+ if (!UPDATE_COUNTERS()) |
|
| 662 |
+ return false; |
|
| 663 |
+ --count; |
|
| 882 | 664 |
} |
| 883 | 665 |
} |
| 884 | 666 |
|
| ... | ... |
@@ -886,7 +668,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 886 | 668 |
{
|
| 887 | 669 |
Work = *(base + p); |
| 888 | 670 |
REGISTER_2118_tile(Work); |
| 889 |
- UPDATE_COUNTERS; |
|
| 671 |
+ if (!UPDATE_COUNTERS()) |
|
| 672 |
+ return false; |
|
| 890 | 673 |
b = 1; |
| 891 | 674 |
} |
| 892 | 675 |
else |
| ... | ... |
@@ -903,14 +686,16 @@ bool S9xDoDMA (uint8_t Channel) |
| 903 | 686 |
{
|
| 904 | 687 |
Work = *(base + p); |
| 905 | 688 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 906 |
- UPDATE_COUNTERS; |
|
| 907 |
- count--; |
|
| 689 |
+ if (!UPDATE_COUNTERS()) |
|
| 690 |
+ return false; |
|
| 691 |
+ --count; |
|
| 908 | 692 |
|
| 909 | 693 |
case 1: |
| 910 | 694 |
Work = *(base + p); |
| 911 | 695 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 912 |
- UPDATE_COUNTERS; |
|
| 913 |
- count--; |
|
| 696 |
+ if (!UPDATE_COUNTERS()) |
|
| 697 |
+ return false; |
|
| 698 |
+ --count; |
|
| 914 | 699 |
} |
| 915 | 700 |
} |
| 916 | 701 |
|
| ... | ... |
@@ -918,15 +703,15 @@ bool S9xDoDMA (uint8_t Channel) |
| 918 | 703 |
{
|
| 919 | 704 |
Work = *(base + p); |
| 920 | 705 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 921 |
- UPDATE_COUNTERS; |
|
| 706 |
+ if (!UPDATE_COUNTERS()) |
|
| 707 |
+ return false; |
|
| 922 | 708 |
b = 1; |
| 923 | 709 |
} |
| 924 | 710 |
else |
| 925 | 711 |
b = 0; |
| 926 | 712 |
} |
| 927 | 713 |
} |
| 928 |
- else |
|
| 929 |
- if (d->TransferMode == 3 || d->TransferMode == 7) |
|
| 714 |
+ else if (d->TransferMode == 3 || d->TransferMode == 7) |
|
| 930 | 715 |
{
|
| 931 | 716 |
switch (b) |
| 932 | 717 |
{
|
| ... | ... |
@@ -935,7 +720,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 935 | 720 |
{
|
| 936 | 721 |
Work = *(base + p); |
| 937 | 722 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 938 |
- UPDATE_COUNTERS; |
|
| 723 |
+ if (!UPDATE_COUNTERS()) |
|
| 724 |
+ return false; |
|
| 939 | 725 |
if (--count <= 0) |
| 940 | 726 |
{
|
| 941 | 727 |
b = 1; |
| ... | ... |
@@ -945,7 +731,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 945 | 731 |
case 1: |
| 946 | 732 |
Work = *(base + p); |
| 947 | 733 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 948 |
- UPDATE_COUNTERS; |
|
| 734 |
+ if (!UPDATE_COUNTERS()) |
|
| 735 |
+ return false; |
|
| 949 | 736 |
if (--count <= 0) |
| 950 | 737 |
{
|
| 951 | 738 |
b = 2; |
| ... | ... |
@@ -955,7 +742,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 955 | 742 |
case 2: |
| 956 | 743 |
Work = *(base + p); |
| 957 | 744 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 958 |
- UPDATE_COUNTERS; |
|
| 745 |
+ if (!UPDATE_COUNTERS()) |
|
| 746 |
+ return false; |
|
| 959 | 747 |
if (--count <= 0) |
| 960 | 748 |
{
|
| 961 | 749 |
b = 3; |
| ... | ... |
@@ -965,7 +753,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 965 | 753 |
case 3: |
| 966 | 754 |
Work = *(base + p); |
| 967 | 755 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 968 |
- UPDATE_COUNTERS; |
|
| 756 |
+ if (!UPDATE_COUNTERS()) |
|
| 757 |
+ return false; |
|
| 969 | 758 |
if (--count <= 0) |
| 970 | 759 |
{
|
| 971 | 760 |
b = 0; |
| ... | ... |
@@ -974,8 +763,7 @@ bool S9xDoDMA (uint8_t Channel) |
| 974 | 763 |
} while (1); |
| 975 | 764 |
} |
| 976 | 765 |
} |
| 977 |
- else |
|
| 978 |
- if (d->TransferMode == 4) |
|
| 766 |
+ else if (d->TransferMode == 4) |
|
| 979 | 767 |
{
|
| 980 | 768 |
switch (b) |
| 981 | 769 |
{
|
| ... | ... |
@@ -984,7 +772,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 984 | 772 |
{
|
| 985 | 773 |
Work = *(base + p); |
| 986 | 774 |
S9xSetPPU(Work, 0x2100 + d->BAddress); |
| 987 |
- UPDATE_COUNTERS; |
|
| 775 |
+ if (!UPDATE_COUNTERS()) |
|
| 776 |
+ return false; |
|
| 988 | 777 |
if (--count <= 0) |
| 989 | 778 |
{
|
| 990 | 779 |
b = 1; |
| ... | ... |
@@ -994,7 +783,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 994 | 783 |
case 1: |
| 995 | 784 |
Work = *(base + p); |
| 996 | 785 |
S9xSetPPU(Work, 0x2101 + d->BAddress); |
| 997 |
- UPDATE_COUNTERS; |
|
| 786 |
+ if (!UPDATE_COUNTERS()) |
|
| 787 |
+ return false; |
|
| 998 | 788 |
if (--count <= 0) |
| 999 | 789 |
{
|
| 1000 | 790 |
b = 2; |
| ... | ... |
@@ -1004,7 +794,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 1004 | 794 |
case 2: |
| 1005 | 795 |
Work = *(base + p); |
| 1006 | 796 |
S9xSetPPU(Work, 0x2102 + d->BAddress); |
| 1007 |
- UPDATE_COUNTERS; |
|
| 797 |
+ if (!UPDATE_COUNTERS()) |
|
| 798 |
+ return false; |
|
| 1008 | 799 |
if (--count <= 0) |
| 1009 | 800 |
{
|
| 1010 | 801 |
b = 3; |
| ... | ... |
@@ -1014,7 +805,8 @@ bool S9xDoDMA (uint8_t Channel) |
| 1014 | 805 |
case 3: |
| 1015 | 806 |
Work = *(base + p); |
| 1016 | 807 |
S9xSetPPU(Work, 0x2103 + d->BAddress); |
| 1017 |
- UPDATE_COUNTERS; |
|
| 808 |
+ if (!UPDATE_COUNTERS()) |
|
| 809 |
+ return false; |
|
| 1018 | 810 |
if (--count <= 0) |
| 1019 | 811 |
{
|
| 1020 | 812 |
b = 0; |
| ... | ... |
@@ -1023,13 +815,6 @@ bool S9xDoDMA (uint8_t Channel) |
| 1023 | 815 |
} while (1); |
| 1024 | 816 |
} |
| 1025 | 817 |
} |
| 1026 |
- #ifdef DEBUGGER |
|
| 1027 |
- else |
|
| 1028 |
- {
|
|
| 1029 |
- sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 1030 |
- S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 1031 |
- } |
|
| 1032 |
- #endif |
|
| 1033 | 818 |
} |
| 1034 | 819 |
|
| 1035 | 820 |
if (rem <= 0) |
| ... | ... |
@@ -1037,28 +822,28 @@ bool S9xDoDMA (uint8_t Channel) |
| 1037 | 822 |
|
| 1038 | 823 |
base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); |
| 1039 | 824 |
count = MEMMAP_BLOCK_SIZE; |
| 1040 |
- inWRAM_DMA = ((/*!in_sa1_dma && */!in_sdd1_dma/* && !spc7110_dma*/) && |
|
| 1041 |
- (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); |
|
| 825 |
+ inWRAM_DMA = !in_sdd1_dma && (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000)); |
|
| 1042 | 826 |
} |
| 1043 |
- |
|
| 1044 |
- #undef UPDATE_COUNTERS |
|
| 1045 | 827 |
} |
| 1046 |
- else |
|
| 1047 |
- {
|
|
| 828 |
+ else |
|
| 829 |
+ {
|
|
| 1048 | 830 |
// PPU -> CPU |
| 1049 | 831 |
|
| 1050 | 832 |
// 8 cycles per byte |
| 1051 |
- #define UPDATE_COUNTERS \ |
|
| 1052 |
- d->TransferBytes--; \ |
|
| 1053 |
- d->AAddress += inc; \ |
|
| 1054 |
- if (!addCyclesInDMA(Channel)) \ |
|
| 1055 |
- { \
|
|
| 1056 |
- CPU.InDMA = false; \ |
|
| 1057 |
- CPU.InDMAorHDMA = false; \ |
|
| 1058 |
- CPU.InWRAMDMAorHDMA = false; \ |
|
| 1059 |
- CPU.CurrentDMAorHDMAChannel = -1; \ |
|
| 1060 |
- return false; \ |
|
| 833 |
+ auto UPDATE_COUNTERS = [&]() -> bool |
|
| 834 |
+ {
|
|
| 835 |
+ --d->DMACount_Or_HDMAIndirectAddress; |
|
| 836 |
+ d->AAddress += inc; |
|
| 837 |
+ if (!addCyclesInDMA(Channel)) |
|
| 838 |
+ {
|
|
| 839 |
+ CPU.InDMA = false; |
|
| 840 |
+ CPU.InDMAorHDMA = false; |
|
| 841 |
+ CPU.InWRAMDMAorHDMA = false; |
|
| 842 |
+ CPU.CurrentDMAorHDMAChannel = -1; |
|
| 843 |
+ return false; |
|
| 1061 | 844 |
} |
| 845 |
+ return true; |
|
| 846 |
+ }; |
|
| 1062 | 847 |
|
| 1063 | 848 |
if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40)) |
| 1064 | 849 |
{
|
| ... | ... |
@@ -1070,111 +855,117 @@ bool S9xDoDMA (uint8_t Channel) |
| 1070 | 855 |
case 0: |
| 1071 | 856 |
case 2: |
| 1072 | 857 |
case 6: |
| 1073 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 858 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1074 | 859 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1075 | 860 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1076 |
- UPDATE_COUNTERS; |
|
| 1077 |
- count--; |
|
| 861 |
+ if (!UPDATE_COUNTERS()) |
|
| 862 |
+ return false; |
|
| 863 |
+ --count; |
|
| 1078 | 864 |
|
| 1079 | 865 |
break; |
| 1080 | 866 |
|
| 1081 | 867 |
case 1: |
| 1082 | 868 |
case 5: |
| 1083 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 869 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1084 | 870 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1085 | 871 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1086 |
- UPDATE_COUNTERS; |
|
| 872 |
+ if (!UPDATE_COUNTERS()) |
|
| 873 |
+ return false; |
|
| 1087 | 874 |
if (!--count) |
| 1088 | 875 |
break; |
| 1089 | 876 |
|
| 1090 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 877 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1091 | 878 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1092 | 879 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1093 |
- UPDATE_COUNTERS; |
|
| 1094 |
- count--; |
|
| 880 |
+ if (!UPDATE_COUNTERS()) |
|
| 881 |
+ return false; |
|
| 882 |
+ --count; |
|
| 1095 | 883 |
|
| 1096 | 884 |
break; |
| 1097 | 885 |
|
| 1098 | 886 |
case 3: |
| 1099 | 887 |
case 7: |
| 1100 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 888 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1101 | 889 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1102 | 890 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1103 |
- UPDATE_COUNTERS; |
|
| 891 |
+ if (!UPDATE_COUNTERS()) |
|
| 892 |
+ return false; |
|
| 1104 | 893 |
if (!--count) |
| 1105 | 894 |
break; |
| 1106 | 895 |
|
| 1107 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 896 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1108 | 897 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1109 | 898 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1110 |
- UPDATE_COUNTERS; |
|
| 899 |
+ if (!UPDATE_COUNTERS()) |
|
| 900 |
+ return false; |
|
| 1111 | 901 |
if (!--count) |
| 1112 | 902 |
break; |
| 1113 | 903 |
|
| 1114 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 904 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1115 | 905 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1116 | 906 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1117 |
- UPDATE_COUNTERS; |
|
| 907 |
+ if (!UPDATE_COUNTERS()) |
|
| 908 |
+ return false; |
|
| 1118 | 909 |
if (!--count) |
| 1119 | 910 |
break; |
| 1120 | 911 |
|
| 1121 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 912 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1122 | 913 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1123 | 914 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1124 |
- UPDATE_COUNTERS; |
|
| 1125 |
- count--; |
|
| 915 |
+ if (!UPDATE_COUNTERS()) |
|
| 916 |
+ return false; |
|
| 917 |
+ --count; |
|
| 1126 | 918 |
|
| 1127 | 919 |
break; |
| 1128 | 920 |
|
| 1129 | 921 |
case 4: |
| 1130 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 922 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1131 | 923 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1132 | 924 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1133 |
- UPDATE_COUNTERS; |
|
| 925 |
+ if (!UPDATE_COUNTERS()) |
|
| 926 |
+ return false; |
|
| 1134 | 927 |
if (!--count) |
| 1135 | 928 |
break; |
| 1136 | 929 |
|
| 1137 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 930 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1138 | 931 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1139 | 932 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1140 |
- UPDATE_COUNTERS; |
|
| 933 |
+ if (!UPDATE_COUNTERS()) |
|
| 934 |
+ return false; |
|
| 1141 | 935 |
if (!--count) |
| 1142 | 936 |
break; |
| 1143 | 937 |
|
| 1144 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 938 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1145 | 939 |
Work = S9xGetPPU(0x2102 + d->BAddress); |
| 1146 | 940 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1147 |
- UPDATE_COUNTERS; |
|
| 941 |
+ if (!UPDATE_COUNTERS()) |
|
| 942 |
+ return false; |
|
| 1148 | 943 |
if (!--count) |
| 1149 | 944 |
break; |
| 1150 | 945 |
|
| 1151 |
- CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 946 |
+ CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000; |
|
| 1152 | 947 |
Work = S9xGetPPU(0x2103 + d->BAddress); |
| 1153 | 948 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1154 |
- UPDATE_COUNTERS; |
|
| 1155 |
- count--; |
|
| 949 |
+ if (!UPDATE_COUNTERS()) |
|
| 950 |
+ return false; |
|
| 951 |
+ --count; |
|
| 1156 | 952 |
|
| 1157 | 953 |
break; |
| 1158 | 954 |
|
| 1159 | 955 |
default: |
| 1160 |
- #ifdef DEBUGGER |
|
| 1161 |
- sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 1162 |
- S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 1163 |
- #endif |
|
| 1164 | 956 |
while (count) |
| 1165 | 957 |
{
|
| 1166 |
- UPDATE_COUNTERS; |
|
| 1167 |
- count--; |
|
| 958 |
+ if (!UPDATE_COUNTERS()) |
|
| 959 |
+ return false; |
|
| 960 |
+ --count; |
|
| 1168 | 961 |
} |
| 1169 |
- |
|
| 1170 |
- break; |
|
| 1171 | 962 |
} |
| 1172 | 963 |
} while (count); |
| 1173 | 964 |
} |
| 1174 | 965 |
else |
| 1175 | 966 |
{
|
| 1176 | 967 |
// REVERSE-DMA FASTER PATH |
| 1177 |
- CPU.InWRAMDMAorHDMA = (d->ABank == 0x7e || d->ABank == 0x7f); |
|
| 968 |
+ CPU.InWRAMDMAorHDMA = d->ABank == 0x7e || d->ABank == 0x7f; |
|
| 1178 | 969 |
do |
| 1179 | 970 |
{
|
| 1180 | 971 |
switch (d->TransferMode) |
| ... | ... |
@@ -1184,8 +975,9 @@ bool S9xDoDMA (uint8_t Channel) |
| 1184 | 975 |
case 6: |
| 1185 | 976 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1186 | 977 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1187 |
- UPDATE_COUNTERS; |
|
| 1188 |
- count--; |
|
| 978 |
+ if (!UPDATE_COUNTERS()) |
|
| 979 |
+ return false; |
|
| 980 |
+ --count; |
|
| 1189 | 981 |
|
| 1190 | 982 |
break; |
| 1191 | 983 |
|
| ... | ... |
@@ -1193,14 +985,16 @@ bool S9xDoDMA (uint8_t Channel) |
| 1193 | 985 |
case 5: |
| 1194 | 986 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1195 | 987 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1196 |
- UPDATE_COUNTERS; |
|
| 988 |
+ if (!UPDATE_COUNTERS()) |
|
| 989 |
+ return false; |
|
| 1197 | 990 |
if (!--count) |
| 1198 | 991 |
break; |
| 1199 | 992 |
|
| 1200 | 993 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1201 | 994 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1202 |
- UPDATE_COUNTERS; |
|
| 1203 |
- count--; |
|
| 995 |
+ if (!UPDATE_COUNTERS()) |
|
| 996 |
+ return false; |
|
| 997 |
+ --count; |
|
| 1204 | 998 |
|
| 1205 | 999 |
break; |
| 1206 | 1000 |
|
| ... | ... |
@@ -1208,67 +1002,70 @@ bool S9xDoDMA (uint8_t Channel) |
| 1208 | 1002 |
case 7: |
| 1209 | 1003 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1210 | 1004 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1211 |
- UPDATE_COUNTERS; |
|
| 1005 |
+ if (!UPDATE_COUNTERS()) |
|
| 1006 |
+ return false; |
|
| 1212 | 1007 |
if (!--count) |
| 1213 | 1008 |
break; |
| 1214 | 1009 |
|
| 1215 | 1010 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1216 | 1011 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1217 |
- UPDATE_COUNTERS; |
|
| 1012 |
+ if (!UPDATE_COUNTERS()) |
|
| 1013 |
+ return false; |
|
| 1218 | 1014 |
if (!--count) |
| 1219 | 1015 |
break; |
| 1220 | 1016 |
|
| 1221 | 1017 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1222 | 1018 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1223 |
- UPDATE_COUNTERS; |
|
| 1019 |
+ if (!UPDATE_COUNTERS()) |
|
| 1020 |
+ return false; |
|
| 1224 | 1021 |
if (!--count) |
| 1225 | 1022 |
break; |
| 1226 | 1023 |
|
| 1227 | 1024 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1228 | 1025 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1229 |
- UPDATE_COUNTERS; |
|
| 1230 |
- count--; |
|
| 1026 |
+ if (!UPDATE_COUNTERS()) |
|
| 1027 |
+ return false; |
|
| 1028 |
+ --count; |
|
| 1231 | 1029 |
|
| 1232 | 1030 |
break; |
| 1233 | 1031 |
|
| 1234 | 1032 |
case 4: |
| 1235 | 1033 |
Work = S9xGetPPU(0x2100 + d->BAddress); |
| 1236 | 1034 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1237 |
- UPDATE_COUNTERS; |
|
| 1035 |
+ if (!UPDATE_COUNTERS()) |
|
| 1036 |
+ return false; |
|
| 1238 | 1037 |
if (!--count) |
| 1239 | 1038 |
break; |
| 1240 | 1039 |
|
| 1241 | 1040 |
Work = S9xGetPPU(0x2101 + d->BAddress); |
| 1242 | 1041 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1243 |
- UPDATE_COUNTERS; |
|
| 1042 |
+ if (!UPDATE_COUNTERS()) |
|
| 1043 |
+ return false; |
|
| 1244 | 1044 |
if (!--count) |
| 1245 | 1045 |
break; |
| 1246 | 1046 |
|
| 1247 | 1047 |
Work = S9xGetPPU(0x2102 + d->BAddress); |
| 1248 | 1048 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1249 |
- UPDATE_COUNTERS; |
|
| 1049 |
+ if (!UPDATE_COUNTERS()) |
|
| 1050 |
+ return false; |
|
| 1250 | 1051 |
if (!--count) |
| 1251 | 1052 |
break; |
| 1252 | 1053 |
|
| 1253 | 1054 |
Work = S9xGetPPU(0x2103 + d->BAddress); |
| 1254 | 1055 |
S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
| 1255 |
- UPDATE_COUNTERS; |
|
| 1256 |
- count--; |
|
| 1056 |
+ if (!UPDATE_COUNTERS()) |
|
| 1057 |
+ return false; |
|
| 1058 |
+ --count; |
|
| 1257 | 1059 |
|
| 1258 | 1060 |
break; |
| 1259 | 1061 |
|
| 1260 | 1062 |
default: |
| 1261 |
- #ifdef DEBUGGER |
|
| 1262 |
- sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 1263 |
- S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 1264 |
- #endif |
|
| 1265 | 1063 |
while (count) |
| 1266 | 1064 |
{
|
| 1267 |
- UPDATE_COUNTERS; |
|
| 1268 |
- count--; |
|
| 1065 |
+ if (!UPDATE_COUNTERS()) |
|
| 1066 |
+ return false; |
|
| 1067 |
+ --count; |
|
| 1269 | 1068 |
} |
| 1270 |
- |
|
| 1271 |
- break; |
|
| 1272 | 1069 |
} |
| 1273 | 1070 |
} while (count); |
| 1274 | 1071 |
} |
| ... | ... |
@@ -1281,34 +1078,17 @@ bool S9xDoDMA (uint8_t Channel) |
| 1281 | 1078 |
Timings.NMITriggerPos -= Timings.H_Max; |
| 1282 | 1079 |
} |
| 1283 | 1080 |
|
| 1284 |
- // Release the memory used in SPC7110 DMA |
|
| 1285 |
- /*if (Settings.SPC7110) |
|
| 1286 |
- {
|
|
| 1287 |
- if (spc7110_dma) |
|
| 1288 |
- delete [] spc7110_dma; |
|
| 1289 |
- }*/ |
|
| 1290 |
- |
|
| 1291 |
-#if 0 |
|
| 1292 |
- // sanity check |
|
| 1293 |
- if (d->TransferBytes != 0) |
|
| 1294 |
- fprintf(stderr,"DMA[%d] TransferBytes not 0! $21%02x Reverse:%d %04x\n", Channel, d->BAddress, d->ReverseTransfer, d->TransferBytes); |
|
| 1295 |
-#endif |
|
| 1296 |
- |
|
| 1297 |
- CPU.InDMA = false; |
|
| 1298 |
- CPU.InDMAorHDMA = false; |
|
| 1299 |
- CPU.InWRAMDMAorHDMA = false; |
|
| 1081 |
+ CPU.InDMA = CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = false; |
|
| 1300 | 1082 |
CPU.CurrentDMAorHDMAChannel = -1; |
| 1301 | 1083 |
|
| 1302 | 1084 |
return true; |
| 1303 | 1085 |
} |
| 1304 | 1086 |
|
| 1305 |
-static inline bool HDMAReadLineCount (int d) |
|
| 1087 |
+static inline bool HDMAReadLineCount(int d) |
|
| 1306 | 1088 |
{
|
| 1307 | 1089 |
// CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. |
| 1308 | 1090 |
|
| 1309 |
- uint8_t line; |
|
| 1310 |
- |
|
| 1311 |
- line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1091 |
+ uint8_t line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1312 | 1092 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1313 | 1093 |
|
| 1314 | 1094 |
if (!line) |
| ... | ... |
@@ -1320,23 +1100,22 @@ static inline bool HDMAReadLineCount (int d) |
| 1320 | 1100 |
{
|
| 1321 | 1101 |
if (PPU.HDMA & (0xfe << d)) |
| 1322 | 1102 |
{
|
| 1323 |
- DMA[d].Address++; |
|
| 1103 |
+ ++DMA[d].Address; |
|
| 1324 | 1104 |
ADD_CYCLES(SLOW_ONE_CYCLE << 1); |
| 1325 | 1105 |
} |
| 1326 | 1106 |
else |
| 1327 | 1107 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1328 | 1108 |
|
| 1329 |
- DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1330 |
- DMA[d].Address++; |
|
| 1109 |
+ DMA[d].DMACount_Or_HDMAIndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1110 |
+ ++DMA[d].Address; |
|
| 1331 | 1111 |
} |
| 1332 | 1112 |
|
| 1333 |
- DMA[d].Address++; |
|
| 1334 |
- HDMAMemPointers[d] = NULL; |
|
| 1113 |
+ ++DMA[d].Address; |
|
| 1114 |
+ HDMAMemPointers[d] = nullptr; |
|
| 1335 | 1115 |
|
| 1336 | 1116 |
return false; |
| 1337 | 1117 |
} |
| 1338 |
- else |
|
| 1339 |
- if (line == 0x80) |
|
| 1118 |
+ else if (line == 0x80) |
|
| 1340 | 1119 |
{
|
| 1341 | 1120 |
DMA[d].Repeat = true; |
| 1342 | 1121 |
DMA[d].LineCount = 128; |
| ... | ... |
@@ -1347,15 +1126,15 @@ static inline bool HDMAReadLineCount (int d) |
| 1347 | 1126 |
DMA[d].LineCount = line & 0x7f; |
| 1348 | 1127 |
} |
| 1349 | 1128 |
|
| 1350 |
- DMA[d].Address++; |
|
| 1129 |
+ ++DMA[d].Address; |
|
| 1351 | 1130 |
DMA[d].DoTransfer = true; |
| 1352 | 1131 |
|
| 1353 | 1132 |
if (DMA[d].HDMAIndirectAddressing) |
| 1354 | 1133 |
{
|
| 1355 | 1134 |
ADD_CYCLES(SLOW_ONE_CYCLE << 1); |
| 1356 |
- DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1135 |
+ DMA[d].DMACount_Or_HDMAIndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1357 | 1136 |
DMA[d].Address += 2; |
| 1358 |
- HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress); |
|
| 1137 |
+ HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].DMACount_Or_HDMAIndirectAddress); |
|
| 1359 | 1138 |
} |
| 1360 | 1139 |
else |
| 1361 | 1140 |
HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address); |
| ... | ... |
@@ -1367,23 +1146,17 @@ void S9xStartHDMA() |
| 1367 | 1146 |
{
|
| 1368 | 1147 |
PPU.HDMA = Memory.FillRAM[0x420c]; |
| 1369 | 1148 |
|
| 1370 |
-#ifdef DEBUGGER |
|
| 1371 |
- missing.hdma_this_frame = PPU.HDMA; |
|
| 1372 |
-#endif |
|
| 1373 |
- |
|
| 1374 | 1149 |
PPU.HDMAEnded = 0; |
| 1375 | 1150 |
|
| 1376 |
- int32_t tmpch; |
|
| 1377 |
- |
|
| 1378 | 1151 |
CPU.InHDMA = true; |
| 1379 | 1152 |
CPU.InDMAorHDMA = true; |
| 1380 |
- tmpch = CPU.CurrentDMAorHDMAChannel; |
|
| 1153 |
+ int32_t tmpch = CPU.CurrentDMAorHDMAChannel; |
|
| 1381 | 1154 |
|
| 1382 | 1155 |
// XXX: Not quite right... |
| 1383 |
- if (PPU.HDMA != 0) |
|
| 1156 |
+ if (PPU.HDMA) |
|
| 1384 | 1157 |
ADD_CYCLES(Timings.DMACPUSync); |
| 1385 | 1158 |
|
| 1386 |
- for (uint8_t i = 0; i < 8; i++) |
|
| 1159 |
+ for (uint8_t i = 0; i < 8; ++i) |
|
| 1387 | 1160 |
{
|
| 1388 | 1161 |
if (PPU.HDMA & (1 << i)) |
| 1389 | 1162 |
{
|
| ... | ... |
@@ -1394,7 +1167,7 @@ void S9xStartHDMA() |
| 1394 | 1167 |
if (!HDMAReadLineCount(i)) |
| 1395 | 1168 |
{
|
| 1396 | 1169 |
PPU.HDMA &= ~(1 << i); |
| 1397 |
- PPU.HDMAEnded |= (1 << i); |
|
| 1170 |
+ PPU.HDMAEnded |= 1 << i; |
|
| 1398 | 1171 |
} |
| 1399 | 1172 |
} |
| 1400 | 1173 |
else |
| ... | ... |
@@ -1407,40 +1180,38 @@ void S9xStartHDMA() |
| 1407 | 1180 |
CPU.CurrentDMAorHDMAChannel = tmpch; |
| 1408 | 1181 |
} |
| 1409 | 1182 |
|
| 1410 |
-uint8_t S9xDoHDMA (uint8_t byte) |
|
| 1183 |
+uint8_t S9xDoHDMA(uint8_t byte) |
|
| 1411 | 1184 |
{
|
| 1412 |
- struct SDMA *p = &DMA[0]; |
|
| 1185 |
+ SDMA *p = &DMA[0]; |
|
| 1413 | 1186 |
|
| 1414 |
- uint32_t ShiftedIBank; |
|
| 1415 |
- uint16_t IAddr; |
|
| 1416 |
- bool temp; |
|
| 1417 |
- int32_t tmpch; |
|
| 1418 |
- int d = 0; |
|
| 1187 |
+ int d = 0; |
|
| 1419 | 1188 |
|
| 1420 | 1189 |
CPU.InHDMA = true; |
| 1421 | 1190 |
CPU.InDMAorHDMA = true; |
| 1422 | 1191 |
CPU.HDMARanInDMA = CPU.InDMA ? byte : 0; |
| 1423 |
- temp = CPU.InWRAMDMAorHDMA; |
|
| 1424 |
- tmpch = CPU.CurrentDMAorHDMAChannel; |
|
| 1192 |
+ bool temp = CPU.InWRAMDMAorHDMA; |
|
| 1193 |
+ int32_t tmpch = CPU.CurrentDMAorHDMAChannel; |
|
| 1425 | 1194 |
|
| 1426 | 1195 |
// XXX: Not quite right... |
| 1427 | 1196 |
ADD_CYCLES(Timings.DMACPUSync); |
| 1428 | 1197 |
|
| 1429 |
- for (uint8_t mask = 1; mask; mask <<= 1, p++, d++) |
|
| 1198 |
+ for (uint8_t mask = 1; mask; mask <<= 1, ++p, ++d) |
|
| 1430 | 1199 |
{
|
| 1431 | 1200 |
if (byte & mask) |
| 1432 | 1201 |
{
|
| 1433 | 1202 |
CPU.InWRAMDMAorHDMA = false; |
| 1434 | 1203 |
CPU.CurrentDMAorHDMAChannel = d; |
| 1435 | 1204 |
|
| 1205 |
+ uint32_t ShiftedIBank; |
|
| 1206 |
+ uint16_t IAddr; |
|
| 1436 | 1207 |
if (p->HDMAIndirectAddressing) |
| 1437 | 1208 |
{
|
| 1438 |
- ShiftedIBank = (p->IndirectBank << 16); |
|
| 1439 |
- IAddr = p->IndirectAddress; |
|
| 1209 |
+ ShiftedIBank = p->IndirectBank << 16; |
|
| 1210 |
+ IAddr = p->DMACount_Or_HDMAIndirectAddress; |
|
| 1440 | 1211 |
} |
| 1441 | 1212 |
else |
| 1442 | 1213 |
{
|
| 1443 |
- ShiftedIBank = (p->ABank << 16); |
|
| 1214 |
+ ShiftedIBank = p->ABank << 16; |
|
| 1444 | 1215 |
IAddr = p->Address; |
| 1445 | 1216 |
} |
| 1446 | 1217 |
|
| ... | ... |
@@ -1460,31 +1231,18 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1460 | 1231 |
} |
| 1461 | 1232 |
} |
| 1462 | 1233 |
|
| 1463 |
- #ifdef DEBUGGER |
|
| 1464 |
- if (Settings.TraceHDMA && p->DoTransfer) |
|
| 1465 |
- {
|
|
| 1466 |
- sprintf(String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X", |
|
| 1467 |
- p-DMA, p->ReverseTransfer? "read" : "write", |
|
| 1468 |
- p->TransferMode, ShiftedIBank+IAddr, p->BAddress, |
|
| 1469 |
- p->HDMAIndirectAddressing ? "ind" : "abs", |
|
| 1470 |
- p->LineCount, |
|
| 1471 |
- p->Repeat ? "yes" : "no ", (long) CPU.V_Counter, |
|
| 1472 |
- p->ABank, p->Address); |
|
| 1473 |
- S9xMessage(S9X_TRACE, S9X_HDMA_TRACE, String); |
|
| 1474 |
- } |
|
| 1475 |
- #endif |
|
| 1476 |
- |
|
| 1477 | 1234 |
if (!p->ReverseTransfer) |
| 1478 | 1235 |
{
|
| 1479 | 1236 |
if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE) |
| 1480 | 1237 |
{
|
| 1481 | 1238 |
// HDMA REALLY-SLOW PATH |
| 1482 |
- HDMAMemPointers[d] = NULL; |
|
| 1239 |
+ HDMAMemPointers[d] = nullptr; |
|
| 1483 | 1240 |
|
| 1484 |
- #define DOBYTE(Addr, RegOff) \ |
|
| 1485 |
- CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ |
|
| 1486 |
- (!(ShiftedIBank & 0x400000) && ((uint16_t) (Addr)) < 0x2000)); \ |
|
| 1487 |
- S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16_t) (Addr))), 0x2100 + p->BAddress + (RegOff)); |
|
| 1241 |
+ auto DOBYTE = [&](uint16_t Addr, uint16_t RegOff) |
|
| 1242 |
+ {
|
|
| 1243 |
+ CPU.InWRAMDMAorHDMA = ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || (!(ShiftedIBank & 0x400000) && Addr < 0x2000); |
|
| 1244 |
+ S9xSetPPU(S9xGetByte(ShiftedIBank + Addr), 0x2100 + p->BAddress + RegOff); |
|
| 1245 |
+ }; |
|
| 1488 | 1246 |
|
| 1489 | 1247 |
switch (p->TransferMode) |
| 1490 | 1248 |
{
|
| ... | ... |
@@ -1494,7 +1252,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1494 | 1252 |
break; |
| 1495 | 1253 |
|
| 1496 | 1254 |
case 5: |
| 1497 |
- DOBYTE(IAddr + 0, 0); |
|
| 1255 |
+ DOBYTE(IAddr, 0); |
|
| 1498 | 1256 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1499 | 1257 |
DOBYTE(IAddr + 1, 1); |
| 1500 | 1258 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1505,7 +1263,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1505 | 1263 |
break; |
| 1506 | 1264 |
|
| 1507 | 1265 |
case 1: |
| 1508 |
- DOBYTE(IAddr + 0, 0); |
|
| 1266 |
+ DOBYTE(IAddr, 0); |
|
| 1509 | 1267 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1510 | 1268 |
DOBYTE(IAddr + 1, 1); |
| 1511 | 1269 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1513,7 +1271,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1513 | 1271 |
|
| 1514 | 1272 |
case 2: |
| 1515 | 1273 |
case 6: |
| 1516 |
- DOBYTE(IAddr + 0, 0); |
|
| 1274 |
+ DOBYTE(IAddr, 0); |
|
| 1517 | 1275 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1518 | 1276 |
DOBYTE(IAddr + 1, 0); |
| 1519 | 1277 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1521,7 +1279,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1521 | 1279 |
|
| 1522 | 1280 |
case 3: |
| 1523 | 1281 |
case 7: |
| 1524 |
- DOBYTE(IAddr + 0, 0); |
|
| 1282 |
+ DOBYTE(IAddr, 0); |
|
| 1525 | 1283 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1526 | 1284 |
DOBYTE(IAddr + 1, 0); |
| 1527 | 1285 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1532,7 +1290,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1532 | 1290 |
break; |
| 1533 | 1291 |
|
| 1534 | 1292 |
case 4: |
| 1535 |
- DOBYTE(IAddr + 0, 0); |
|
| 1293 |
+ DOBYTE(IAddr, 0); |
|
| 1536 | 1294 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1537 | 1295 |
DOBYTE(IAddr + 1, 1); |
| 1538 | 1296 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1540,20 +1298,16 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1540 | 1298 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1541 | 1299 |
DOBYTE(IAddr + 3, 3); |
| 1542 | 1300 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1543 |
- break; |
|
| 1544 | 1301 |
} |
| 1545 |
- |
|
| 1546 |
- #undef DOBYTE |
|
| 1547 | 1302 |
} |
| 1548 | 1303 |
else |
| 1549 | 1304 |
{
|
| 1550 |
- CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || |
|
| 1551 |
- (!(ShiftedIBank & 0x400000) && IAddr < 0x2000)); |
|
| 1305 |
+ CPU.InWRAMDMAorHDMA = ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || (!(ShiftedIBank & 0x400000) && IAddr < 0x2000); |
|
| 1552 | 1306 |
|
| 1553 | 1307 |
if (!HDMAMemPointers[d]) |
| 1554 | 1308 |
{
|
| 1555 | 1309 |
// HDMA SLOW PATH |
| 1556 |
- uint32_t Addr = ShiftedIBank + IAddr; |
|
| 1310 |
+ uint32_t Addr = ShiftedIBank + IAddr; |
|
| 1557 | 1311 |
|
| 1558 | 1312 |
switch (p->TransferMode) |
| 1559 | 1313 |
{
|
| ... | ... |
@@ -1563,14 +1317,14 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1563 | 1317 |
break; |
| 1564 | 1318 |
|
| 1565 | 1319 |
case 5: |
| 1566 |
- S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1320 |
+ S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); |
|
| 1567 | 1321 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1568 | 1322 |
S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); |
| 1569 | 1323 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1570 | 1324 |
Addr += 2; |
| 1571 | 1325 |
/* fall through */ |
| 1572 | 1326 |
case 1: |
| 1573 |
- S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1327 |
+ S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); |
|
| 1574 | 1328 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1575 | 1329 |
S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); |
| 1576 | 1330 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1578,7 +1332,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1578 | 1332 |
|
| 1579 | 1333 |
case 2: |
| 1580 | 1334 |
case 6: |
| 1581 |
- S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1335 |
+ S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); |
|
| 1582 | 1336 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1583 | 1337 |
S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); |
| 1584 | 1338 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1586,7 +1340,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1586 | 1340 |
|
| 1587 | 1341 |
case 3: |
| 1588 | 1342 |
case 7: |
| 1589 |
- S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1343 |
+ S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); |
|
| 1590 | 1344 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1591 | 1345 |
S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); |
| 1592 | 1346 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1597,7 +1351,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1597 | 1351 |
break; |
| 1598 | 1352 |
|
| 1599 | 1353 |
case 4: |
| 1600 |
- S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1354 |
+ S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); |
|
| 1601 | 1355 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1602 | 1356 |
S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); |
| 1603 | 1357 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1605,7 +1359,6 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1605 | 1359 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1606 | 1360 |
S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); |
| 1607 | 1361 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1608 |
- break; |
|
| 1609 | 1362 |
} |
| 1610 | 1363 |
} |
| 1611 | 1364 |
else |
| ... | ... |
@@ -1619,14 +1372,14 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1619 | 1372 |
break; |
| 1620 | 1373 |
|
| 1621 | 1374 |
case 5: |
| 1622 |
- S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1375 |
+ S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress); |
|
| 1623 | 1376 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1624 | 1377 |
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); |
| 1625 | 1378 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1626 | 1379 |
HDMAMemPointers[d] += 2; |
| 1627 | 1380 |
/* fall through */ |
| 1628 | 1381 |
case 1: |
| 1629 |
- S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1382 |
+ S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress); |
|
| 1630 | 1383 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1631 | 1384 |
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); |
| 1632 | 1385 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1635,7 +1388,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1635 | 1388 |
|
| 1636 | 1389 |
case 2: |
| 1637 | 1390 |
case 6: |
| 1638 |
- S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1391 |
+ S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress); |
|
| 1639 | 1392 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1640 | 1393 |
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); |
| 1641 | 1394 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1644,7 +1397,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1644 | 1397 |
|
| 1645 | 1398 |
case 3: |
| 1646 | 1399 |
case 7: |
| 1647 |
- S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1400 |
+ S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress); |
|
| 1648 | 1401 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1649 | 1402 |
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); |
| 1650 | 1403 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1656,7 +1409,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1656 | 1409 |
break; |
| 1657 | 1410 |
|
| 1658 | 1411 |
case 4: |
| 1659 |
- S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1412 |
+ S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress); |
|
| 1660 | 1413 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1661 | 1414 |
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); |
| 1662 | 1415 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1665,7 +1418,6 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1665 | 1418 |
S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress); |
| 1666 | 1419 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1667 | 1420 |
HDMAMemPointers[d] += 4; |
| 1668 |
- break; |
|
| 1669 | 1421 |
} |
| 1670 | 1422 |
} |
| 1671 | 1423 |
} |
| ... | ... |
@@ -1675,12 +1427,13 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1675 | 1427 |
// REVERSE HDMA REALLY-SLOW PATH |
| 1676 | 1428 |
// anomie says: Since this is apparently never used |
| 1677 | 1429 |
// (otherwise we would have noticed before now), let's not bother with faster paths. |
| 1678 |
- HDMAMemPointers[d] = NULL; |
|
| 1430 |
+ HDMAMemPointers[d] = nullptr; |
|
| 1679 | 1431 |
|
| 1680 |
- #define DOBYTE(Addr, RegOff) \ |
|
| 1681 |
- CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ |
|
| 1682 |
- (!(ShiftedIBank & 0x400000) && ((uint16_t) (Addr)) < 0x2000)); \ |
|
| 1683 |
- S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + (RegOff)), ShiftedIBank + ((uint16_t) (Addr))); |
|
| 1432 |
+ auto DOBYTE = [&](uint16_t Addr, uint16_t RegOff) |
|
| 1433 |
+ {
|
|
| 1434 |
+ CPU.InWRAMDMAorHDMA = ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || (!(ShiftedIBank & 0x400000) && Addr < 0x2000); |
|
| 1435 |
+ S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + RegOff), ShiftedIBank + Addr); |
|
| 1436 |
+ }; |
|
| 1684 | 1437 |
|
| 1685 | 1438 |
switch (p->TransferMode) |
| 1686 | 1439 |
{
|
| ... | ... |
@@ -1690,7 +1443,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1690 | 1443 |
break; |
| 1691 | 1444 |
|
| 1692 | 1445 |
case 5: |
| 1693 |
- DOBYTE(IAddr + 0, 0); |
|
| 1446 |
+ DOBYTE(IAddr, 0); |
|
| 1694 | 1447 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1695 | 1448 |
DOBYTE(IAddr + 1, 1); |
| 1696 | 1449 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1701,7 +1454,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1701 | 1454 |
break; |
| 1702 | 1455 |
|
| 1703 | 1456 |
case 1: |
| 1704 |
- DOBYTE(IAddr + 0, 0); |
|
| 1457 |
+ DOBYTE(IAddr, 0); |
|
| 1705 | 1458 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1706 | 1459 |
DOBYTE(IAddr + 1, 1); |
| 1707 | 1460 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1709,7 +1462,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1709 | 1462 |
|
| 1710 | 1463 |
case 2: |
| 1711 | 1464 |
case 6: |
| 1712 |
- DOBYTE(IAddr + 0, 0); |
|
| 1465 |
+ DOBYTE(IAddr, 0); |
|
| 1713 | 1466 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1714 | 1467 |
DOBYTE(IAddr + 1, 0); |
| 1715 | 1468 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1717,7 +1470,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1717 | 1470 |
|
| 1718 | 1471 |
case 3: |
| 1719 | 1472 |
case 7: |
| 1720 |
- DOBYTE(IAddr + 0, 0); |
|
| 1473 |
+ DOBYTE(IAddr, 0); |
|
| 1721 | 1474 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1722 | 1475 |
DOBYTE(IAddr + 1, 0); |
| 1723 | 1476 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1728,7 +1481,7 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1728 | 1481 |
break; |
| 1729 | 1482 |
|
| 1730 | 1483 |
case 4: |
| 1731 |
- DOBYTE(IAddr + 0, 0); |
|
| 1484 |
+ DOBYTE(IAddr, 0); |
|
| 1732 | 1485 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1733 | 1486 |
DOBYTE(IAddr + 1, 1); |
| 1734 | 1487 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| ... | ... |
@@ -1736,14 +1489,11 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1736 | 1489 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1737 | 1490 |
DOBYTE(IAddr + 3, 3); |
| 1738 | 1491 |
ADD_CYCLES(SLOW_ONE_CYCLE); |
| 1739 |
- break; |
|
| 1740 | 1492 |
} |
| 1741 |
- |
|
| 1742 |
- #undef DOBYTE |
|
| 1743 | 1493 |
} |
| 1744 | 1494 |
|
| 1745 | 1495 |
if (p->HDMAIndirectAddressing) |
| 1746 |
- p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; |
|
| 1496 |
+ p->DMACount_Or_HDMAIndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; |
|
| 1747 | 1497 |
else |
| 1748 | 1498 |
p->Address += HDMA_ModeByteCounts[p->TransferMode]; |
| 1749 | 1499 |
} |
| ... | ... |
@@ -1775,12 +1525,9 @@ uint8_t S9xDoHDMA (uint8_t byte) |
| 1775 | 1525 |
|
| 1776 | 1526 |
void S9xResetDMA() |
| 1777 | 1527 |
{
|
| 1778 |
- for (int d = 0; d < 8; d++) |
|
| 1528 |
+ for (int d = 0; d < 8; ++d) |
|
| 1779 | 1529 |
{
|
| 1780 |
- DMA[d].ReverseTransfer = true; |
|
| 1781 |
- DMA[d].HDMAIndirectAddressing = true; |
|
| 1782 |
- DMA[d].AAddressFixed = true; |
|
| 1783 |
- DMA[d].AAddressDecrement = true; |
|
| 1530 |
+ DMA[d].ReverseTransfer = DMA[d].HDMAIndirectAddressing = DMA[d].AAddressFixed = DMA[d].AAddressDecrement = true; |
|
| 1784 | 1531 |
DMA[d].TransferMode = 7; |
| 1785 | 1532 |
DMA[d].BAddress = 0xff; |
| 1786 | 1533 |
DMA[d].AAddress = 0xffff; |
| ... | ... |
@@ -1792,6 +1539,6 @@ void S9xResetDMA() |
| 1792 | 1539 |
DMA[d].LineCount = 0x7f; |
| 1793 | 1540 |
DMA[d].UnknownByte = 0xff; |
| 1794 | 1541 |
DMA[d].DoTransfer = false; |
| 1795 |
- DMA[d].UnusedBit43x0 = 1; |
|
| 1542 |
+ DMA[d].UnusedBit43x0 = true; |
|
| 1796 | 1543 |
} |
| 1797 | 1544 |
} |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,1797 @@ |
| 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 |
+ |
|
| 21 |
+ (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) |
|
| 22 |
+ |
|
| 23 |
+ (c) Copyright 2006 - 2007 nitsuja |
|
| 24 |
+ |
|
| 25 |
+ (c) Copyright 2009 - 2011 BearOso, |
|
| 26 |
+ OV2 |
|
| 27 |
+ |
|
| 28 |
+ |
|
| 29 |
+ BS-X C emulator code |
|
| 30 |
+ (c) Copyright 2005 - 2006 Dreamer Nom, |
|
| 31 |
+ zones |
|
| 32 |
+ |
|
| 33 |
+ C4 x86 assembler and some C emulation code |
|
| 34 |
+ (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), |
|
| 35 |
+ Nach, |
|
| 36 |
+ zsKnight (zsknight@zsnes.com) |
|
| 37 |
+ |
|
| 38 |
+ C4 C++ code |
|
| 39 |
+ (c) Copyright 2003 - 2006 Brad Jorsch, |
|
| 40 |
+ Nach |
|
| 41 |
+ |
|
| 42 |
+ DSP-1 emulator code |
|
| 43 |
+ (c) Copyright 1998 - 2006 _Demo_, |
|
| 44 |
+ Andreas Naive (andreasnaive@gmail.com), |
|
| 45 |
+ Gary Henderson, |
|
| 46 |
+ Ivar (ivar@snes9x.com), |
|
| 47 |
+ John Weidman, |
|
| 48 |
+ Kris Bleakley, |
|
| 49 |
+ Matthew Kendora, |
|
| 50 |
+ Nach, |
|
| 51 |
+ neviksti (neviksti@hotmail.com) |
|
| 52 |
+ |
|
| 53 |
+ DSP-2 emulator code |
|
| 54 |
+ (c) Copyright 2003 John Weidman, |
|
| 55 |
+ Kris Bleakley, |
|
| 56 |
+ Lord Nightmare (lord_nightmare@users.sourceforge.net), |
|
| 57 |
+ Matthew Kendora, |
|
| 58 |
+ neviksti |
|
| 59 |
+ |
|
| 60 |
+ DSP-3 emulator code |
|
| 61 |
+ (c) Copyright 2003 - 2006 John Weidman, |
|
| 62 |
+ Kris Bleakley, |
|
| 63 |
+ Lancer, |
|
| 64 |
+ z80 gaiden |
|
| 65 |
+ |
|
| 66 |
+ DSP-4 emulator code |
|
| 67 |
+ (c) Copyright 2004 - 2006 Dreamer Nom, |
|
| 68 |
+ John Weidman, |
|
| 69 |
+ Kris Bleakley, |
|
| 70 |
+ Nach, |
|
| 71 |
+ z80 gaiden |
|
| 72 |
+ |
|
| 73 |
+ OBC1 emulator code |
|
| 74 |
+ (c) Copyright 2001 - 2004 zsKnight, |
|
| 75 |
+ pagefault (pagefault@zsnes.com), |
|
| 76 |
+ Kris Bleakley |
|
| 77 |
+ Ported from x86 assembler to C by sanmaiwashi |
|
| 78 |
+ |
|
| 79 |
+ SPC7110 and RTC C++ emulator code used in 1.39-1.51 |
|
| 80 |
+ (c) Copyright 2002 Matthew Kendora with research by |
|
| 81 |
+ zsKnight, |
|
| 82 |
+ John Weidman, |
|
| 83 |
+ Dark Force |
|
| 84 |
+ |
|
| 85 |
+ SPC7110 and RTC C++ emulator code used in 1.52+ |
|
| 86 |
+ (c) Copyright 2009 byuu, |
|
| 87 |
+ neviksti |
|
| 88 |
+ |
|
| 89 |
+ S-DD1 C emulator code |
|
| 90 |
+ (c) Copyright 2003 Brad Jorsch with research by |
|
| 91 |
+ Andreas Naive, |
|
| 92 |
+ John Weidman |
|
| 93 |
+ |
|
| 94 |
+ S-RTC C emulator code |
|
| 95 |
+ (c) Copyright 2001 - 2006 byuu, |
|
| 96 |
+ John Weidman |
|
| 97 |
+ |
|
| 98 |
+ ST010 C++ emulator code |
|
| 99 |
+ (c) Copyright 2003 Feather, |
|
| 100 |
+ John Weidman, |
|
| 101 |
+ Kris Bleakley, |
|
| 102 |
+ Matthew Kendora |
|
| 103 |
+ |
|
| 104 |
+ Super FX x86 assembler emulator code |
|
| 105 |
+ (c) Copyright 1998 - 2003 _Demo_, |
|
| 106 |
+ pagefault, |
|
| 107 |
+ zsKnight |
|
| 108 |
+ |
|
| 109 |
+ Super FX C emulator code |
|
| 110 |
+ (c) Copyright 1997 - 1999 Ivar, |
|
| 111 |
+ Gary Henderson, |
|
| 112 |
+ John Weidman |
|
| 113 |
+ |
|
| 114 |
+ Sound emulator code used in 1.5-1.51 |
|
| 115 |
+ (c) Copyright 1998 - 2003 Brad Martin |
|
| 116 |
+ (c) Copyright 1998 - 2006 Charles Bilyue' |
|
| 117 |
+ |
|
| 118 |
+ Sound emulator code used in 1.52+ |
|
| 119 |
+ (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) |
|
| 120 |
+ |
|
| 121 |
+ SH assembler code partly based on x86 assembler code |
|
| 122 |
+ (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) |
|
| 123 |
+ |
|
| 124 |
+ 2xSaI filter |
|
| 125 |
+ (c) Copyright 1999 - 2001 Derek Liauw Kie Fa |
|
| 126 |
+ |
|
| 127 |
+ HQ2x, HQ3x, HQ4x filters |
|
| 128 |
+ (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) |
|
| 129 |
+ |
|
| 130 |
+ NTSC filter |
|
| 131 |
+ (c) Copyright 2006 - 2007 Shay Green |
|
| 132 |
+ |
|
| 133 |
+ GTK+ GUI code |
|
| 134 |
+ (c) Copyright 2004 - 2011 BearOso |
|
| 135 |
+ |
|
| 136 |
+ Win32 GUI code |
|
| 137 |
+ (c) Copyright 2003 - 2006 blip, |
|
| 138 |
+ funkyass, |
|
| 139 |
+ Matthew Kendora, |
|
| 140 |
+ Nach, |
|
| 141 |
+ nitsuja |
|
| 142 |
+ (c) Copyright 2009 - 2011 OV2 |
|
| 143 |
+ |
|
| 144 |
+ Mac OS GUI code |
|
| 145 |
+ (c) Copyright 1998 - 2001 John Stiles |
|
| 146 |
+ (c) Copyright 2001 - 2011 zones |
|
| 147 |
+ |
|
| 148 |
+ |
|
| 149 |
+ Specific ports contains the works of other authors. See headers in |
|
| 150 |
+ individual files. |
|
| 151 |
+ |
|
| 152 |
+ |
|
| 153 |
+ Snes9x homepage: http://www.snes9x.com/ |
|
| 154 |
+ |
|
| 155 |
+ Permission to use, copy, modify and/or distribute Snes9x in both binary |
|
| 156 |
+ and source form, for non-commercial purposes, is hereby granted without |
|
| 157 |
+ fee, providing that this license information and copyright notice appear |
|
| 158 |
+ with all copies and any derived work. |
|
| 159 |
+ |
|
| 160 |
+ This software is provided 'as-is', without any express or implied |
|
| 161 |
+ warranty. In no event shall the authors be held liable for any damages |
|
| 162 |
+ arising from the use of this software or it's derivatives. |
|
| 163 |
+ |
|
| 164 |
+ Snes9x is freeware for PERSONAL USE only. Commercial users should |
|
| 165 |
+ seek permission of the copyright holders first. Commercial use includes, |
|
| 166 |
+ but is not limited to, charging money for Snes9x or software derived from |
|
| 167 |
+ Snes9x, including Snes9x or derivatives in commercial game bundles, and/or |
|
| 168 |
+ using Snes9x as a promotion for your commercial product. |
|
| 169 |
+ |
|
| 170 |
+ The copyright holders request that bug fixes and improvements to the code |
|
| 171 |
+ should be forwarded to them so everyone can benefit from the modifications |
|
| 172 |
+ in future versions. |
|
| 173 |
+ |
|
| 174 |
+ Super NES and Super Nintendo Entertainment System are trademarks of |
|
| 175 |
+ Nintendo Co., Limited and its subsidiary companies. |
|
| 176 |
+ ***********************************************************************************/ |
|
| 177 |
+ |
|
| 178 |
+#include "snes9x.h" |
|
| 179 |
+#include "memmap.h" |
|
| 180 |
+#include "dma.h" |
|
| 181 |
+#include "apu/apu.h" |
|
| 182 |
+//#include "sdd1emu.h" |
|
| 183 |
+//#include "spc7110emu.h" |
|
| 184 |
+#ifdef DEBUGGER |
|
| 185 |
+#include "missing.h" |
|
| 186 |
+#endif |
|
| 187 |
+ |
|
| 188 |
+//#define ADD_CYCLES(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); }
|
|
| 189 |
+static inline void ADD_CYCLES(int32_t n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += n; S9xCheckInterrupts(); }
|
|
| 190 |
+ |
|
| 191 |
+extern uint8_t *HDMAMemPointers[8]; |
|
| 192 |
+extern int HDMA_ModeByteCounts[8]; |
|
| 193 |
+//extern SPC7110 s7emu; |
|
| 194 |
+ |
|
| 195 |
+static uint8_t sdd1_decode_buffer[0x10000]; |
|
| 196 |
+ |
|
| 197 |
+//static inline bool addCyclesInDMA (uint8_t); |
|
| 198 |
+//static inline bool HDMAReadLineCount (int); |
|
| 199 |
+ |
|
| 200 |
+ |
|
| 201 |
+static inline bool addCyclesInDMA (uint8_t dma_channel) |
|
| 202 |
+{
|
|
| 203 |
+ // Add 8 cycles per byte, sync APU, and do HC related events. |
|
| 204 |
+ // If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. |
|
| 205 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 206 |
+ while (CPU.Cycles >= CPU.NextEvent) |
|
| 207 |
+ S9xDoHEventProcessing(); |
|
| 208 |
+ |
|
| 209 |
+ if (CPU.HDMARanInDMA & (1 << dma_channel)) |
|
| 210 |
+ {
|
|
| 211 |
+ CPU.HDMARanInDMA = 0; |
|
| 212 |
+ #ifdef DEBUGGER |
|
| 213 |
+ printf("HDMA and DMA use the same channel %d!\n", dma_channel);
|
|
| 214 |
+ #endif |
|
| 215 |
+ // If HDMA triggers in the middle of DMA transfer and it uses the same channel, |
|
| 216 |
+ // it kills the DMA transfer immediately. $43x2 and $43x5 stop updating. |
|
| 217 |
+ return false; |
|
| 218 |
+ } |
|
| 219 |
+ |
|
| 220 |
+ CPU.HDMARanInDMA = 0; |
|
| 221 |
+ return true; |
|
| 222 |
+} |
|
| 223 |
+ |
|
| 224 |
+bool S9xDoDMA (uint8_t Channel) |
|
| 225 |
+{
|
|
| 226 |
+ CPU.InDMA = true; |
|
| 227 |
+ CPU.InDMAorHDMA = true; |
|
| 228 |
+ CPU.CurrentDMAorHDMAChannel = Channel; |
|
| 229 |
+ |
|
| 230 |
+ SDMA *d = &DMA[Channel]; |
|
| 231 |
+ |
|
| 232 |
+ // Check invalid DMA first |
|
| 233 |
+ if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer) |
|
| 234 |
+ {
|
|
| 235 |
+ // Attempting a DMA from WRAM to $2180 will not work, WRAM will not be written. |
|
| 236 |
+ // Attempting a DMA from $2180 to WRAM will similarly not work, |
|
| 237 |
+ // the value written is (initially) the OpenBus value. |
|
| 238 |
+ // In either case, the address in $2181-3 is not incremented. |
|
| 239 |
+ |
|
| 240 |
+ // Does an invalid DMA actually take time? |
|
| 241 |
+ // I'd say yes, since 'invalid' is probably just the WRAM chip |
|
| 242 |
+ // not being able to read and write itself at the same time |
|
| 243 |
+ // And no, PPU.WRAM should not be updated. |
|
| 244 |
+ |
|
| 245 |
+ int32_t c = d->TransferBytes; |
|
| 246 |
+ // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. |
|
| 247 |
+ if (c == 0) |
|
| 248 |
+ c = 0x10000; |
|
| 249 |
+ |
|
| 250 |
+ // 8 cycles per channel |
|
| 251 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 252 |
+ // 8 cycles per byte |
|
| 253 |
+ while (c) |
|
| 254 |
+ {
|
|
| 255 |
+ d->TransferBytes--; |
|
| 256 |
+ d->AAddress++; |
|
| 257 |
+ c--; |
|
| 258 |
+ if (!addCyclesInDMA(Channel)) |
|
| 259 |
+ {
|
|
| 260 |
+ CPU.InDMA = false; |
|
| 261 |
+ CPU.InDMAorHDMA = false; |
|
| 262 |
+ CPU.CurrentDMAorHDMAChannel = -1; |
|
| 263 |
+ return false; |
|
| 264 |
+ } |
|
| 265 |
+ } |
|
| 266 |
+ |
|
| 267 |
+ #ifdef DEBUGGER |
|
| 268 |
+ if (Settings.TraceDMA) |
|
| 269 |
+ {
|
|
| 270 |
+ sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank); |
|
| 271 |
+ S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 272 |
+ } |
|
| 273 |
+ #endif |
|
| 274 |
+ |
|
| 275 |
+ CPU.InDMA = false; |
|
| 276 |
+ CPU.InDMAorHDMA = false; |
|
| 277 |
+ CPU.CurrentDMAorHDMAChannel = -1; |
|
| 278 |
+ return true; |
|
| 279 |
+ } |
|
| 280 |
+ |
|
| 281 |
+ // Prepare for accessing $2118-2119 |
|
| 282 |
+ /*switch (d->BAddress) |
|
| 283 |
+ {
|
|
| 284 |
+ case 0x18: |
|
| 285 |
+ case 0x19: |
|
| 286 |
+ if (IPPU.RenderThisFrame) |
|
| 287 |
+ FLUSH_REDRAW(); |
|
| 288 |
+ break; |
|
| 289 |
+ }*/ |
|
| 290 |
+ |
|
| 291 |
+ int32_t inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); |
|
| 292 |
+ int32_t count = d->TransferBytes; |
|
| 293 |
+ // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. |
|
| 294 |
+ if (count == 0) |
|
| 295 |
+ count = 0x10000; |
|
| 296 |
+ |
|
| 297 |
+ // Prepare for custom chip DMA |
|
| 298 |
+ |
|
| 299 |
+ // S-DD1 |
|
| 300 |
+ |
|
| 301 |
+ uint8_t *in_sdd1_dma = NULL; |
|
| 302 |
+ |
|
| 303 |
+ if (Settings.SDD1) |
|
| 304 |
+ {
|
|
| 305 |
+ if (d->AAddressFixed && Memory.FillRAM[0x4801] > 0) |
|
| 306 |
+ {
|
|
| 307 |
+ // XXX: Should probably verify that we're DMAing from ROM? |
|
| 308 |
+ // And somewhere we should make sure we're not running across a mapping boundary too. |
|
| 309 |
+ // Hacky support for pre-decompressed S-DD1 data |
|
| 310 |
+ inc = !d->AAddressDecrement ? 1 : -1; |
|
| 311 |
+ |
|
| 312 |
+ uint8_t *in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress)); |
|
| 313 |
+ if (in_ptr) |
|
| 314 |
+ {
|
|
| 315 |
+ in_ptr += d->AAddress; |
|
| 316 |
+ //SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); |
|
| 317 |
+ } |
|
| 318 |
+ #ifdef DEBUGGER |
|
| 319 |
+ else |
|
| 320 |
+ {
|
|
| 321 |
+ sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); |
|
| 322 |
+ S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); |
|
| 323 |
+ } |
|
| 324 |
+ #endif |
|
| 325 |
+ |
|
| 326 |
+ in_sdd1_dma = sdd1_decode_buffer; |
|
| 327 |
+ } |
|
| 328 |
+ |
|
| 329 |
+ Memory.FillRAM[0x4801] = 0; |
|
| 330 |
+ } |
|
| 331 |
+ |
|
| 332 |
+ // SPC7110 |
|
| 333 |
+ |
|
| 334 |
+ //uint8_t *spc7110_dma = NULL; |
|
| 335 |
+ |
|
| 336 |
+ /*if (Settings.SPC7110) |
|
| 337 |
+ {
|
|
| 338 |
+ if (d->AAddress == 0x4800 || d->ABank == 0x50) |
|
| 339 |
+ {
|
|
| 340 |
+ spc7110_dma = new uint8_t[d->TransferBytes]; |
|
| 341 |
+ for (int i = 0; i < d->TransferBytes; i++) |
|
| 342 |
+ spc7110_dma[i] = s7emu.decomp.read(); |
|
| 343 |
+ |
|
| 344 |
+ int32_t icount = s7emu.r4809 | (s7emu.r480a << 8); |
|
| 345 |
+ icount -= d->TransferBytes; |
|
| 346 |
+ s7emu.r4809 = icount & 0x00ff; |
|
| 347 |
+ s7emu.r480a = (icount & 0xff00) >> 8; |
|
| 348 |
+ |
|
| 349 |
+ inc = 1; |
|
| 350 |
+ d->AAddress -= count; |
|
| 351 |
+ } |
|
| 352 |
+ }*/ |
|
| 353 |
+ |
|
| 354 |
+ // SA-1 |
|
| 355 |
+ |
|
| 356 |
+ //bool in_sa1_dma = false; |
|
| 357 |
+ |
|
| 358 |
+ /*if (Settings.SA1) |
|
| 359 |
+ {
|
|
| 360 |
+ if (SA1.in_char_dma && d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40) |
|
| 361 |
+ {
|
|
| 362 |
+ // Perform packed bitmap to PPU character format conversion on the data |
|
| 363 |
+ // before transmitting it to V-RAM via-DMA. |
|
| 364 |
+ int32_t num_chars = 1 << ((Memory.FillRAM[0x2231] >> 2) & 7); |
|
| 365 |
+ int32_t depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; |
|
| 366 |
+ int32_t bytes_per_char = 8 * depth; |
|
| 367 |
+ int32_t bytes_per_line = depth * num_chars; |
|
| 368 |
+ int32_t char_line_bytes = bytes_per_char * num_chars; |
|
| 369 |
+ uint32_t addr = (d->AAddress / char_line_bytes) * char_line_bytes; |
|
| 370 |
+ |
|
| 371 |
+ uint8_t *base = S9xGetBasePointer((d->ABank << 16) + addr); |
|
| 372 |
+ if (!base) |
|
| 373 |
+ {
|
|
| 374 |
+ sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr); |
|
| 375 |
+ S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); |
|
| 376 |
+ base = Memory.ROM; |
|
| 377 |
+ } |
|
| 378 |
+ |
|
| 379 |
+ base += addr; |
|
| 380 |
+ |
|
| 381 |
+ uint8_t *buffer = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; |
|
| 382 |
+ uint8_t *p = buffer; |
|
| 383 |
+ uint32_t inc_sa1 = char_line_bytes - (d->AAddress % char_line_bytes); |
|
| 384 |
+ uint32_t char_count = inc_sa1 / bytes_per_char; |
|
| 385 |
+ |
|
| 386 |
+ in_sa1_dma = true; |
|
| 387 |
+ |
|
| 388 |
+ #if 0 |
|
| 389 |
+ printf("SA-1 DMA: %08x,", base);
|
|
| 390 |
+ printf("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n",
|
|
| 391 |
+ depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); |
|
| 392 |
+ #endif |
|
| 393 |
+ |
|
| 394 |
+ switch (depth) |
|
| 395 |
+ {
|
|
| 396 |
+ case 2: |
|
| 397 |
+ for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) |
|
| 398 |
+ {
|
|
| 399 |
+ uint8_t *line = base + (num_chars - char_count) * 2; |
|
| 400 |
+ for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 2) |
|
| 401 |
+ {
|
|
| 402 |
+ uint8_t *q = line; |
|
| 403 |
+ for (int32_t l = 0; l < 8; l++, q += bytes_per_line) |
|
| 404 |
+ {
|
|
| 405 |
+ for (int32_t b = 0; b < 2; b++) |
|
| 406 |
+ {
|
|
| 407 |
+ uint8_t r = *(q + b); |
|
| 408 |
+ *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); |
|
| 409 |
+ *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); |
|
| 410 |
+ *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); |
|
| 411 |
+ *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); |
|
| 412 |
+ *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); |
|
| 413 |
+ *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); |
|
| 414 |
+ *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); |
|
| 415 |
+ *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); |
|
| 416 |
+ } |
|
| 417 |
+ |
|
| 418 |
+ p += 2; |
|
| 419 |
+ } |
|
| 420 |
+ } |
|
| 421 |
+ } |
|
| 422 |
+ |
|
| 423 |
+ break; |
|
| 424 |
+ |
|
| 425 |
+ case 4: |
|
| 426 |
+ for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) |
|
| 427 |
+ {
|
|
| 428 |
+ uint8_t *line = base + (num_chars - char_count) * 4; |
|
| 429 |
+ for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 4) |
|
| 430 |
+ {
|
|
| 431 |
+ uint8_t *q = line; |
|
| 432 |
+ for (int32_t l = 0; l < 8; l++, q += bytes_per_line) |
|
| 433 |
+ {
|
|
| 434 |
+ for (int32_t b = 0; b < 4; b++) |
|
| 435 |
+ {
|
|
| 436 |
+ uint8_t r = *(q + b); |
|
| 437 |
+ *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); |
|
| 438 |
+ *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); |
|
| 439 |
+ *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); |
|
| 440 |
+ *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); |
|
| 441 |
+ *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); |
|
| 442 |
+ *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); |
|
| 443 |
+ *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); |
|
| 444 |
+ *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); |
|
| 445 |
+ } |
|
| 446 |
+ |
|
| 447 |
+ p += 2; |
|
| 448 |
+ } |
|
| 449 |
+ |
|
| 450 |
+ p += 32 - 16; |
|
| 451 |
+ } |
|
| 452 |
+ } |
|
| 453 |
+ |
|
| 454 |
+ break; |
|
| 455 |
+ |
|
| 456 |
+ case 8: |
|
| 457 |
+ for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) |
|
| 458 |
+ {
|
|
| 459 |
+ uint8_t *line = base + (num_chars - char_count) * 8; |
|
| 460 |
+ for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 8) |
|
| 461 |
+ {
|
|
| 462 |
+ uint8_t *q = line; |
|
| 463 |
+ for (int32_t l = 0; l < 8; l++, q += bytes_per_line) |
|
| 464 |
+ {
|
|
| 465 |
+ for (int32_t b = 0; b < 8; b++) |
|
| 466 |
+ {
|
|
| 467 |
+ uint8_t r = *(q + b); |
|
| 468 |
+ *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); |
|
| 469 |
+ *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); |
|
| 470 |
+ *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); |
|
| 471 |
+ *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); |
|
| 472 |
+ *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); |
|
| 473 |
+ *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); |
|
| 474 |
+ *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); |
|
| 475 |
+ *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); |
|
| 476 |
+ } |
|
| 477 |
+ |
|
| 478 |
+ p += 2; |
|
| 479 |
+ } |
|
| 480 |
+ |
|
| 481 |
+ p += 64 - 16; |
|
| 482 |
+ } |
|
| 483 |
+ } |
|
| 484 |
+ |
|
| 485 |
+ break; |
|
| 486 |
+ } |
|
| 487 |
+ } |
|
| 488 |
+ }*/ |
|
| 489 |
+ |
|
| 490 |
+#ifdef DEBUGGER |
|
| 491 |
+ if (Settings.TraceDMA) |
|
| 492 |
+ {
|
|
| 493 |
+ sprintf(String, "DMA[%d]: %s Mode:%d 0x%02X%04X->0x21%02X Bytes:%d (%s) V:%03d", |
|
| 494 |
+ Channel, d->ReverseTransfer ? "PPU->CPU" : "CPU->PPU", d->TransferMode, d->ABank, d->AAddress, d->BAddress, |
|
| 495 |
+ d->TransferBytes, d->AAddressFixed ? "fixed" : (d->AAddressDecrement ? "dec" : "inc"), CPU.V_Counter); |
|
| 496 |
+ |
|
| 497 |
+ if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a) |
|
| 498 |
+ sprintf(String, "%s VRAM: %04X (%d,%d) %s", String, |
|
| 499 |
+ PPU.VMA.Address, PPU.VMA.Increment, PPU.VMA.FullGraphicCount, PPU.VMA.High ? "word" : "byte"); |
|
| 500 |
+ else |
|
| 501 |
+ if (d->BAddress == 0x22 || d->BAddress == 0x3b) |
|
| 502 |
+ sprintf(String, "%s CGRAM: %02X (%x)", String, PPU.CGADD, PPU.CGFLIP); |
|
| 503 |
+ else |
|
| 504 |
+ if (d->BAddress == 0x04 || d->BAddress == 0x38) |
|
| 505 |
+ sprintf(String, "%s OBJADDR: %04X", String, PPU.OAMAddr); |
|
| 506 |
+ |
|
| 507 |
+ S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 508 |
+ } |
|
| 509 |
+#endif |
|
| 510 |
+ |
|
| 511 |
+ // Do Transfer |
|
| 512 |
+ |
|
| 513 |
+ uint8_t Work; |
|
| 514 |
+ |
|
| 515 |
+ // 8 cycles per channel |
|
| 516 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 517 |
+ |
|
| 518 |
+ if (!d->ReverseTransfer) |
|
| 519 |
+ {
|
|
| 520 |
+ // CPU -> PPU |
|
| 521 |
+ int32_t b = 0; |
|
| 522 |
+ uint16_t p = d->AAddress; |
|
| 523 |
+ uint8_t *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); |
|
| 524 |
+ bool inWRAM_DMA; |
|
| 525 |
+ |
|
| 526 |
+ int32_t rem = count; |
|
| 527 |
+ // Transfer per block if d->AAdressFixed is false |
|
| 528 |
+ count = d->AAddressFixed ? rem : (d->AAddressDecrement ? ((p & MEMMAP_MASK) + 1) : (MEMMAP_BLOCK_SIZE - (p & MEMMAP_MASK))); |
|
| 529 |
+ |
|
| 530 |
+ // Settings for custom chip DMA |
|
| 531 |
+ /*if (in_sa1_dma) |
|
| 532 |
+ {
|
|
| 533 |
+ base = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; |
|
| 534 |
+ p = 0; |
|
| 535 |
+ count = rem; |
|
| 536 |
+ } |
|
| 537 |
+ else*/ |
|
| 538 |
+ if (in_sdd1_dma) |
|
| 539 |
+ {
|
|
| 540 |
+ base = in_sdd1_dma; |
|
| 541 |
+ p = 0; |
|
| 542 |
+ count = rem; |
|
| 543 |
+ } |
|
| 544 |
+ /*else |
|
| 545 |
+ if (spc7110_dma) |
|
| 546 |
+ {
|
|
| 547 |
+ base = spc7110_dma; |
|
| 548 |
+ p = 0; |
|
| 549 |
+ count = rem; |
|
| 550 |
+ }*/ |
|
| 551 |
+ |
|
| 552 |
+ inWRAM_DMA = ((/*!in_sa1_dma && */!in_sdd1_dma/* && !spc7110_dma*/) && |
|
| 553 |
+ (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); |
|
| 554 |
+ |
|
| 555 |
+ // 8 cycles per byte |
|
| 556 |
+ #define UPDATE_COUNTERS \ |
|
| 557 |
+ d->TransferBytes--; \ |
|
| 558 |
+ d->AAddress += inc; \ |
|
| 559 |
+ p += inc; \ |
|
| 560 |
+ if (!addCyclesInDMA(Channel)) \ |
|
| 561 |
+ { \
|
|
| 562 |
+ CPU.InDMA = false; \ |
|
| 563 |
+ CPU.InDMAorHDMA = false; \ |
|
| 564 |
+ CPU.InWRAMDMAorHDMA = false; \ |
|
| 565 |
+ CPU.CurrentDMAorHDMAChannel = -1; \ |
|
| 566 |
+ return false; \ |
|
| 567 |
+ } |
|
| 568 |
+ |
|
| 569 |
+ while (1) |
|
| 570 |
+ {
|
|
| 571 |
+ if (count > rem) |
|
| 572 |
+ count = rem; |
|
| 573 |
+ rem -= count; |
|
| 574 |
+ |
|
| 575 |
+ CPU.InWRAMDMAorHDMA = inWRAM_DMA; |
|
| 576 |
+ |
|
| 577 |
+ if (!base) |
|
| 578 |
+ {
|
|
| 579 |
+ // DMA SLOW PATH |
|
| 580 |
+ if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) |
|
| 581 |
+ {
|
|
| 582 |
+ do |
|
| 583 |
+ {
|
|
| 584 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 585 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 586 |
+ UPDATE_COUNTERS; |
|
| 587 |
+ } while (--count > 0); |
|
| 588 |
+ } |
|
| 589 |
+ else |
|
| 590 |
+ if (d->TransferMode == 1 || d->TransferMode == 5) |
|
| 591 |
+ {
|
|
| 592 |
+ // This is a variation on Duff's Device. It is legal C/C++. |
|
| 593 |
+ switch (b) |
|
| 594 |
+ {
|
|
| 595 |
+ default: |
|
| 596 |
+ while (count > 1) |
|
| 597 |
+ {
|
|
| 598 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 599 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 600 |
+ UPDATE_COUNTERS; |
|
| 601 |
+ count--; |
|
| 602 |
+ |
|
| 603 |
+ case 1: |
|
| 604 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 605 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 606 |
+ UPDATE_COUNTERS; |
|
| 607 |
+ count--; |
|
| 608 |
+ } |
|
| 609 |
+ } |
|
| 610 |
+ |
|
| 611 |
+ if (count == 1) |
|
| 612 |
+ {
|
|
| 613 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 614 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 615 |
+ UPDATE_COUNTERS; |
|
| 616 |
+ b = 1; |
|
| 617 |
+ } |
|
| 618 |
+ else |
|
| 619 |
+ b = 0; |
|
| 620 |
+ } |
|
| 621 |
+ else |
|
| 622 |
+ if (d->TransferMode == 3 || d->TransferMode == 7) |
|
| 623 |
+ {
|
|
| 624 |
+ switch (b) |
|
| 625 |
+ {
|
|
| 626 |
+ default: |
|
| 627 |
+ do |
|
| 628 |
+ {
|
|
| 629 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 630 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 631 |
+ UPDATE_COUNTERS; |
|
| 632 |
+ if (--count <= 0) |
|
| 633 |
+ {
|
|
| 634 |
+ b = 1; |
|
| 635 |
+ break; |
|
| 636 |
+ } |
|
| 637 |
+ |
|
| 638 |
+ case 1: |
|
| 639 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 640 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 641 |
+ UPDATE_COUNTERS; |
|
| 642 |
+ if (--count <= 0) |
|
| 643 |
+ {
|
|
| 644 |
+ b = 2; |
|
| 645 |
+ break; |
|
| 646 |
+ } |
|
| 647 |
+ |
|
| 648 |
+ case 2: |
|
| 649 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 650 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 651 |
+ UPDATE_COUNTERS; |
|
| 652 |
+ if (--count <= 0) |
|
| 653 |
+ {
|
|
| 654 |
+ b = 3; |
|
| 655 |
+ break; |
|
| 656 |
+ } |
|
| 657 |
+ |
|
| 658 |
+ case 3: |
|
| 659 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 660 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 661 |
+ UPDATE_COUNTERS; |
|
| 662 |
+ if (--count <= 0) |
|
| 663 |
+ {
|
|
| 664 |
+ b = 0; |
|
| 665 |
+ break; |
|
| 666 |
+ } |
|
| 667 |
+ } while (1); |
|
| 668 |
+ } |
|
| 669 |
+ } |
|
| 670 |
+ else |
|
| 671 |
+ if (d->TransferMode == 4) |
|
| 672 |
+ {
|
|
| 673 |
+ switch (b) |
|
| 674 |
+ {
|
|
| 675 |
+ default: |
|
| 676 |
+ do |
|
| 677 |
+ {
|
|
| 678 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 679 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 680 |
+ UPDATE_COUNTERS; |
|
| 681 |
+ if (--count <= 0) |
|
| 682 |
+ {
|
|
| 683 |
+ b = 1; |
|
| 684 |
+ break; |
|
| 685 |
+ } |
|
| 686 |
+ |
|
| 687 |
+ case 1: |
|
| 688 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 689 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 690 |
+ UPDATE_COUNTERS; |
|
| 691 |
+ if (--count <= 0) |
|
| 692 |
+ {
|
|
| 693 |
+ b = 2; |
|
| 694 |
+ break; |
|
| 695 |
+ } |
|
| 696 |
+ |
|
| 697 |
+ case 2: |
|
| 698 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 699 |
+ S9xSetPPU(Work, 0x2102 + d->BAddress); |
|
| 700 |
+ UPDATE_COUNTERS; |
|
| 701 |
+ if (--count <= 0) |
|
| 702 |
+ {
|
|
| 703 |
+ b = 3; |
|
| 704 |
+ break; |
|
| 705 |
+ } |
|
| 706 |
+ |
|
| 707 |
+ case 3: |
|
| 708 |
+ Work = S9xGetByte((d->ABank << 16) + p); |
|
| 709 |
+ S9xSetPPU(Work, 0x2103 + d->BAddress); |
|
| 710 |
+ UPDATE_COUNTERS; |
|
| 711 |
+ if (--count <= 0) |
|
| 712 |
+ {
|
|
| 713 |
+ b = 0; |
|
| 714 |
+ break; |
|
| 715 |
+ } |
|
| 716 |
+ } while (1); |
|
| 717 |
+ } |
|
| 718 |
+ } |
|
| 719 |
+ #ifdef DEBUGGER |
|
| 720 |
+ else |
|
| 721 |
+ {
|
|
| 722 |
+ sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 723 |
+ S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 724 |
+ } |
|
| 725 |
+ #endif |
|
| 726 |
+ } |
|
| 727 |
+ else |
|
| 728 |
+ {
|
|
| 729 |
+ // DMA FAST PATH |
|
| 730 |
+ if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) |
|
| 731 |
+ {
|
|
| 732 |
+ switch (d->BAddress) |
|
| 733 |
+ {
|
|
| 734 |
+ case 0x04: // OAMDATA |
|
| 735 |
+ do |
|
| 736 |
+ {
|
|
| 737 |
+ Work = *(base + p); |
|
| 738 |
+ REGISTER_2104(Work); |
|
| 739 |
+ UPDATE_COUNTERS; |
|
| 740 |
+ } while (--count > 0); |
|
| 741 |
+ |
|
| 742 |
+ break; |
|
| 743 |
+ |
|
| 744 |
+ case 0x18: // VMDATAL |
|
| 745 |
+ if (!PPU.VMA.FullGraphicCount) |
|
| 746 |
+ {
|
|
| 747 |
+ do |
|
| 748 |
+ {
|
|
| 749 |
+ Work = *(base + p); |
|
| 750 |
+ REGISTER_2118_linear(Work); |
|
| 751 |
+ UPDATE_COUNTERS; |
|
| 752 |
+ } while (--count > 0); |
|
| 753 |
+ } |
|
| 754 |
+ else |
|
| 755 |
+ {
|
|
| 756 |
+ do |
|
| 757 |
+ {
|
|
| 758 |
+ Work = *(base + p); |
|
| 759 |
+ REGISTER_2118_tile(Work); |
|
| 760 |
+ UPDATE_COUNTERS; |
|
| 761 |
+ } while (--count > 0); |
|
| 762 |
+ } |
|
| 763 |
+ |
|
| 764 |
+ break; |
|
| 765 |
+ |
|
| 766 |
+ case 0x19: // VMDATAH |
|
| 767 |
+ if (!PPU.VMA.FullGraphicCount) |
|
| 768 |
+ {
|
|
| 769 |
+ do |
|
| 770 |
+ {
|
|
| 771 |
+ Work = *(base + p); |
|
| 772 |
+ REGISTER_2119_linear(Work); |
|
| 773 |
+ UPDATE_COUNTERS; |
|
| 774 |
+ } while (--count > 0); |
|
| 775 |
+ } |
|
| 776 |
+ else |
|
| 777 |
+ {
|
|
| 778 |
+ do |
|
| 779 |
+ {
|
|
| 780 |
+ Work = *(base + p); |
|
| 781 |
+ REGISTER_2119_tile(Work); |
|
| 782 |
+ UPDATE_COUNTERS; |
|
| 783 |
+ } while (--count > 0); |
|
| 784 |
+ } |
|
| 785 |
+ |
|
| 786 |
+ break; |
|
| 787 |
+ |
|
| 788 |
+ case 0x22: // CGDATA |
|
| 789 |
+ do |
|
| 790 |
+ {
|
|
| 791 |
+ Work = *(base + p); |
|
| 792 |
+ //REGISTER_2122(Work); |
|
| 793 |
+ UPDATE_COUNTERS; |
|
| 794 |
+ } while (--count > 0); |
|
| 795 |
+ |
|
| 796 |
+ break; |
|
| 797 |
+ |
|
| 798 |
+ case 0x80: // WMDATA |
|
| 799 |
+ if (!CPU.InWRAMDMAorHDMA) |
|
| 800 |
+ {
|
|
| 801 |
+ do |
|
| 802 |
+ {
|
|
| 803 |
+ Work = *(base + p); |
|
| 804 |
+ REGISTER_2180(Work); |
|
| 805 |
+ UPDATE_COUNTERS; |
|
| 806 |
+ } while (--count > 0); |
|
| 807 |
+ } |
|
| 808 |
+ else |
|
| 809 |
+ {
|
|
| 810 |
+ do |
|
| 811 |
+ {
|
|
| 812 |
+ UPDATE_COUNTERS; |
|
| 813 |
+ } while (--count > 0); |
|
| 814 |
+ } |
|
| 815 |
+ |
|
| 816 |
+ break; |
|
| 817 |
+ |
|
| 818 |
+ default: |
|
| 819 |
+ do |
|
| 820 |
+ {
|
|
| 821 |
+ Work = *(base + p); |
|
| 822 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 823 |
+ UPDATE_COUNTERS; |
|
| 824 |
+ } while (--count > 0); |
|
| 825 |
+ |
|
| 826 |
+ break; |
|
| 827 |
+ } |
|
| 828 |
+ } |
|
| 829 |
+ else |
|
| 830 |
+ if (d->TransferMode == 1 || d->TransferMode == 5) |
|
| 831 |
+ {
|
|
| 832 |
+ if (d->BAddress == 0x18) |
|
| 833 |
+ {
|
|
| 834 |
+ // VMDATAL |
|
| 835 |
+ if (!PPU.VMA.FullGraphicCount) |
|
| 836 |
+ {
|
|
| 837 |
+ switch (b) |
|
| 838 |
+ {
|
|
| 839 |
+ default: |
|
| 840 |
+ while (count > 1) |
|
| 841 |
+ {
|
|
| 842 |
+ Work = *(base + p); |
|
| 843 |
+ REGISTER_2118_linear(Work); |
|
| 844 |
+ UPDATE_COUNTERS; |
|
| 845 |
+ count--; |
|
| 846 |
+ |
|
| 847 |
+ case 1: |
|
| 848 |
+ Work = *(base + p); |
|
| 849 |
+ REGISTER_2119_linear(Work); |
|
| 850 |
+ UPDATE_COUNTERS; |
|
| 851 |
+ count--; |
|
| 852 |
+ } |
|
| 853 |
+ } |
|
| 854 |
+ |
|
| 855 |
+ if (count == 1) |
|
| 856 |
+ {
|
|
| 857 |
+ Work = *(base + p); |
|
| 858 |
+ REGISTER_2118_linear(Work); |
|
| 859 |
+ UPDATE_COUNTERS; |
|
| 860 |
+ b = 1; |
|
| 861 |
+ } |
|
| 862 |
+ else |
|
| 863 |
+ b = 0; |
|
| 864 |
+ } |
|
| 865 |
+ else |
|
| 866 |
+ {
|
|
| 867 |
+ switch (b) |
|
| 868 |
+ {
|
|
| 869 |
+ default: |
|
| 870 |
+ while (count > 1) |
|
| 871 |
+ {
|
|
| 872 |
+ Work = *(base + p); |
|
| 873 |
+ REGISTER_2118_tile(Work); |
|
| 874 |
+ UPDATE_COUNTERS; |
|
| 875 |
+ count--; |
|
| 876 |
+ |
|
| 877 |
+ case 1: |
|
| 878 |
+ Work = *(base + p); |
|
| 879 |
+ REGISTER_2119_tile(Work); |
|
| 880 |
+ UPDATE_COUNTERS; |
|
| 881 |
+ count--; |
|
| 882 |
+ } |
|
| 883 |
+ } |
|
| 884 |
+ |
|
| 885 |
+ if (count == 1) |
|
| 886 |
+ {
|
|
| 887 |
+ Work = *(base + p); |
|
| 888 |
+ REGISTER_2118_tile(Work); |
|
| 889 |
+ UPDATE_COUNTERS; |
|
| 890 |
+ b = 1; |
|
| 891 |
+ } |
|
| 892 |
+ else |
|
| 893 |
+ b = 0; |
|
| 894 |
+ } |
|
| 895 |
+ } |
|
| 896 |
+ else |
|
| 897 |
+ {
|
|
| 898 |
+ // DMA mode 1 general case |
|
| 899 |
+ switch (b) |
|
| 900 |
+ {
|
|
| 901 |
+ default: |
|
| 902 |
+ while (count > 1) |
|
| 903 |
+ {
|
|
| 904 |
+ Work = *(base + p); |
|
| 905 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 906 |
+ UPDATE_COUNTERS; |
|
| 907 |
+ count--; |
|
| 908 |
+ |
|
| 909 |
+ case 1: |
|
| 910 |
+ Work = *(base + p); |
|
| 911 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 912 |
+ UPDATE_COUNTERS; |
|
| 913 |
+ count--; |
|
| 914 |
+ } |
|
| 915 |
+ } |
|
| 916 |
+ |
|
| 917 |
+ if (count == 1) |
|
| 918 |
+ {
|
|
| 919 |
+ Work = *(base + p); |
|
| 920 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 921 |
+ UPDATE_COUNTERS; |
|
| 922 |
+ b = 1; |
|
| 923 |
+ } |
|
| 924 |
+ else |
|
| 925 |
+ b = 0; |
|
| 926 |
+ } |
|
| 927 |
+ } |
|
| 928 |
+ else |
|
| 929 |
+ if (d->TransferMode == 3 || d->TransferMode == 7) |
|
| 930 |
+ {
|
|
| 931 |
+ switch (b) |
|
| 932 |
+ {
|
|
| 933 |
+ default: |
|
| 934 |
+ do |
|
| 935 |
+ {
|
|
| 936 |
+ Work = *(base + p); |
|
| 937 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 938 |
+ UPDATE_COUNTERS; |
|
| 939 |
+ if (--count <= 0) |
|
| 940 |
+ {
|
|
| 941 |
+ b = 1; |
|
| 942 |
+ break; |
|
| 943 |
+ } |
|
| 944 |
+ |
|
| 945 |
+ case 1: |
|
| 946 |
+ Work = *(base + p); |
|
| 947 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 948 |
+ UPDATE_COUNTERS; |
|
| 949 |
+ if (--count <= 0) |
|
| 950 |
+ {
|
|
| 951 |
+ b = 2; |
|
| 952 |
+ break; |
|
| 953 |
+ } |
|
| 954 |
+ |
|
| 955 |
+ case 2: |
|
| 956 |
+ Work = *(base + p); |
|
| 957 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 958 |
+ UPDATE_COUNTERS; |
|
| 959 |
+ if (--count <= 0) |
|
| 960 |
+ {
|
|
| 961 |
+ b = 3; |
|
| 962 |
+ break; |
|
| 963 |
+ } |
|
| 964 |
+ |
|
| 965 |
+ case 3: |
|
| 966 |
+ Work = *(base + p); |
|
| 967 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 968 |
+ UPDATE_COUNTERS; |
|
| 969 |
+ if (--count <= 0) |
|
| 970 |
+ {
|
|
| 971 |
+ b = 0; |
|
| 972 |
+ break; |
|
| 973 |
+ } |
|
| 974 |
+ } while (1); |
|
| 975 |
+ } |
|
| 976 |
+ } |
|
| 977 |
+ else |
|
| 978 |
+ if (d->TransferMode == 4) |
|
| 979 |
+ {
|
|
| 980 |
+ switch (b) |
|
| 981 |
+ {
|
|
| 982 |
+ default: |
|
| 983 |
+ do |
|
| 984 |
+ {
|
|
| 985 |
+ Work = *(base + p); |
|
| 986 |
+ S9xSetPPU(Work, 0x2100 + d->BAddress); |
|
| 987 |
+ UPDATE_COUNTERS; |
|
| 988 |
+ if (--count <= 0) |
|
| 989 |
+ {
|
|
| 990 |
+ b = 1; |
|
| 991 |
+ break; |
|
| 992 |
+ } |
|
| 993 |
+ |
|
| 994 |
+ case 1: |
|
| 995 |
+ Work = *(base + p); |
|
| 996 |
+ S9xSetPPU(Work, 0x2101 + d->BAddress); |
|
| 997 |
+ UPDATE_COUNTERS; |
|
| 998 |
+ if (--count <= 0) |
|
| 999 |
+ {
|
|
| 1000 |
+ b = 2; |
|
| 1001 |
+ break; |
|
| 1002 |
+ } |
|
| 1003 |
+ |
|
| 1004 |
+ case 2: |
|
| 1005 |
+ Work = *(base + p); |
|
| 1006 |
+ S9xSetPPU(Work, 0x2102 + d->BAddress); |
|
| 1007 |
+ UPDATE_COUNTERS; |
|
| 1008 |
+ if (--count <= 0) |
|
| 1009 |
+ {
|
|
| 1010 |
+ b = 3; |
|
| 1011 |
+ break; |
|
| 1012 |
+ } |
|
| 1013 |
+ |
|
| 1014 |
+ case 3: |
|
| 1015 |
+ Work = *(base + p); |
|
| 1016 |
+ S9xSetPPU(Work, 0x2103 + d->BAddress); |
|
| 1017 |
+ UPDATE_COUNTERS; |
|
| 1018 |
+ if (--count <= 0) |
|
| 1019 |
+ {
|
|
| 1020 |
+ b = 0; |
|
| 1021 |
+ break; |
|
| 1022 |
+ } |
|
| 1023 |
+ } while (1); |
|
| 1024 |
+ } |
|
| 1025 |
+ } |
|
| 1026 |
+ #ifdef DEBUGGER |
|
| 1027 |
+ else |
|
| 1028 |
+ {
|
|
| 1029 |
+ sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 1030 |
+ S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 1031 |
+ } |
|
| 1032 |
+ #endif |
|
| 1033 |
+ } |
|
| 1034 |
+ |
|
| 1035 |
+ if (rem <= 0) |
|
| 1036 |
+ break; |
|
| 1037 |
+ |
|
| 1038 |
+ base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); |
|
| 1039 |
+ count = MEMMAP_BLOCK_SIZE; |
|
| 1040 |
+ inWRAM_DMA = ((/*!in_sa1_dma && */!in_sdd1_dma/* && !spc7110_dma*/) && |
|
| 1041 |
+ (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); |
|
| 1042 |
+ } |
|
| 1043 |
+ |
|
| 1044 |
+ #undef UPDATE_COUNTERS |
|
| 1045 |
+ } |
|
| 1046 |
+ else |
|
| 1047 |
+ {
|
|
| 1048 |
+ // PPU -> CPU |
|
| 1049 |
+ |
|
| 1050 |
+ // 8 cycles per byte |
|
| 1051 |
+ #define UPDATE_COUNTERS \ |
|
| 1052 |
+ d->TransferBytes--; \ |
|
| 1053 |
+ d->AAddress += inc; \ |
|
| 1054 |
+ if (!addCyclesInDMA(Channel)) \ |
|
| 1055 |
+ { \
|
|
| 1056 |
+ CPU.InDMA = false; \ |
|
| 1057 |
+ CPU.InDMAorHDMA = false; \ |
|
| 1058 |
+ CPU.InWRAMDMAorHDMA = false; \ |
|
| 1059 |
+ CPU.CurrentDMAorHDMAChannel = -1; \ |
|
| 1060 |
+ return false; \ |
|
| 1061 |
+ } |
|
| 1062 |
+ |
|
| 1063 |
+ if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40)) |
|
| 1064 |
+ {
|
|
| 1065 |
+ // REVERSE-DMA REALLY-SLOW PATH |
|
| 1066 |
+ do |
|
| 1067 |
+ {
|
|
| 1068 |
+ switch (d->TransferMode) |
|
| 1069 |
+ {
|
|
| 1070 |
+ case 0: |
|
| 1071 |
+ case 2: |
|
| 1072 |
+ case 6: |
|
| 1073 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1074 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1075 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1076 |
+ UPDATE_COUNTERS; |
|
| 1077 |
+ count--; |
|
| 1078 |
+ |
|
| 1079 |
+ break; |
|
| 1080 |
+ |
|
| 1081 |
+ case 1: |
|
| 1082 |
+ case 5: |
|
| 1083 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1084 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1085 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1086 |
+ UPDATE_COUNTERS; |
|
| 1087 |
+ if (!--count) |
|
| 1088 |
+ break; |
|
| 1089 |
+ |
|
| 1090 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1091 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1092 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1093 |
+ UPDATE_COUNTERS; |
|
| 1094 |
+ count--; |
|
| 1095 |
+ |
|
| 1096 |
+ break; |
|
| 1097 |
+ |
|
| 1098 |
+ case 3: |
|
| 1099 |
+ case 7: |
|
| 1100 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1101 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1102 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1103 |
+ UPDATE_COUNTERS; |
|
| 1104 |
+ if (!--count) |
|
| 1105 |
+ break; |
|
| 1106 |
+ |
|
| 1107 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1108 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1109 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1110 |
+ UPDATE_COUNTERS; |
|
| 1111 |
+ if (!--count) |
|
| 1112 |
+ break; |
|
| 1113 |
+ |
|
| 1114 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1115 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1116 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1117 |
+ UPDATE_COUNTERS; |
|
| 1118 |
+ if (!--count) |
|
| 1119 |
+ break; |
|
| 1120 |
+ |
|
| 1121 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1122 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1123 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1124 |
+ UPDATE_COUNTERS; |
|
| 1125 |
+ count--; |
|
| 1126 |
+ |
|
| 1127 |
+ break; |
|
| 1128 |
+ |
|
| 1129 |
+ case 4: |
|
| 1130 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1131 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1132 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1133 |
+ UPDATE_COUNTERS; |
|
| 1134 |
+ if (!--count) |
|
| 1135 |
+ break; |
|
| 1136 |
+ |
|
| 1137 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1138 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1139 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1140 |
+ UPDATE_COUNTERS; |
|
| 1141 |
+ if (!--count) |
|
| 1142 |
+ break; |
|
| 1143 |
+ |
|
| 1144 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1145 |
+ Work = S9xGetPPU(0x2102 + d->BAddress); |
|
| 1146 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1147 |
+ UPDATE_COUNTERS; |
|
| 1148 |
+ if (!--count) |
|
| 1149 |
+ break; |
|
| 1150 |
+ |
|
| 1151 |
+ CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); |
|
| 1152 |
+ Work = S9xGetPPU(0x2103 + d->BAddress); |
|
| 1153 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1154 |
+ UPDATE_COUNTERS; |
|
| 1155 |
+ count--; |
|
| 1156 |
+ |
|
| 1157 |
+ break; |
|
| 1158 |
+ |
|
| 1159 |
+ default: |
|
| 1160 |
+ #ifdef DEBUGGER |
|
| 1161 |
+ sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 1162 |
+ S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 1163 |
+ #endif |
|
| 1164 |
+ while (count) |
|
| 1165 |
+ {
|
|
| 1166 |
+ UPDATE_COUNTERS; |
|
| 1167 |
+ count--; |
|
| 1168 |
+ } |
|
| 1169 |
+ |
|
| 1170 |
+ break; |
|
| 1171 |
+ } |
|
| 1172 |
+ } while (count); |
|
| 1173 |
+ } |
|
| 1174 |
+ else |
|
| 1175 |
+ {
|
|
| 1176 |
+ // REVERSE-DMA FASTER PATH |
|
| 1177 |
+ CPU.InWRAMDMAorHDMA = (d->ABank == 0x7e || d->ABank == 0x7f); |
|
| 1178 |
+ do |
|
| 1179 |
+ {
|
|
| 1180 |
+ switch (d->TransferMode) |
|
| 1181 |
+ {
|
|
| 1182 |
+ case 0: |
|
| 1183 |
+ case 2: |
|
| 1184 |
+ case 6: |
|
| 1185 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1186 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1187 |
+ UPDATE_COUNTERS; |
|
| 1188 |
+ count--; |
|
| 1189 |
+ |
|
| 1190 |
+ break; |
|
| 1191 |
+ |
|
| 1192 |
+ case 1: |
|
| 1193 |
+ case 5: |
|
| 1194 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1195 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1196 |
+ UPDATE_COUNTERS; |
|
| 1197 |
+ if (!--count) |
|
| 1198 |
+ break; |
|
| 1199 |
+ |
|
| 1200 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1201 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1202 |
+ UPDATE_COUNTERS; |
|
| 1203 |
+ count--; |
|
| 1204 |
+ |
|
| 1205 |
+ break; |
|
| 1206 |
+ |
|
| 1207 |
+ case 3: |
|
| 1208 |
+ case 7: |
|
| 1209 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1210 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1211 |
+ UPDATE_COUNTERS; |
|
| 1212 |
+ if (!--count) |
|
| 1213 |
+ break; |
|
| 1214 |
+ |
|
| 1215 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1216 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1217 |
+ UPDATE_COUNTERS; |
|
| 1218 |
+ if (!--count) |
|
| 1219 |
+ break; |
|
| 1220 |
+ |
|
| 1221 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1222 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1223 |
+ UPDATE_COUNTERS; |
|
| 1224 |
+ if (!--count) |
|
| 1225 |
+ break; |
|
| 1226 |
+ |
|
| 1227 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1228 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1229 |
+ UPDATE_COUNTERS; |
|
| 1230 |
+ count--; |
|
| 1231 |
+ |
|
| 1232 |
+ break; |
|
| 1233 |
+ |
|
| 1234 |
+ case 4: |
|
| 1235 |
+ Work = S9xGetPPU(0x2100 + d->BAddress); |
|
| 1236 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1237 |
+ UPDATE_COUNTERS; |
|
| 1238 |
+ if (!--count) |
|
| 1239 |
+ break; |
|
| 1240 |
+ |
|
| 1241 |
+ Work = S9xGetPPU(0x2101 + d->BAddress); |
|
| 1242 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1243 |
+ UPDATE_COUNTERS; |
|
| 1244 |
+ if (!--count) |
|
| 1245 |
+ break; |
|
| 1246 |
+ |
|
| 1247 |
+ Work = S9xGetPPU(0x2102 + d->BAddress); |
|
| 1248 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1249 |
+ UPDATE_COUNTERS; |
|
| 1250 |
+ if (!--count) |
|
| 1251 |
+ break; |
|
| 1252 |
+ |
|
| 1253 |
+ Work = S9xGetPPU(0x2103 + d->BAddress); |
|
| 1254 |
+ S9xSetByte(Work, (d->ABank << 16) + d->AAddress); |
|
| 1255 |
+ UPDATE_COUNTERS; |
|
| 1256 |
+ count--; |
|
| 1257 |
+ |
|
| 1258 |
+ break; |
|
| 1259 |
+ |
|
| 1260 |
+ default: |
|
| 1261 |
+ #ifdef DEBUGGER |
|
| 1262 |
+ sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); |
|
| 1263 |
+ S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); |
|
| 1264 |
+ #endif |
|
| 1265 |
+ while (count) |
|
| 1266 |
+ {
|
|
| 1267 |
+ UPDATE_COUNTERS; |
|
| 1268 |
+ count--; |
|
| 1269 |
+ } |
|
| 1270 |
+ |
|
| 1271 |
+ break; |
|
| 1272 |
+ } |
|
| 1273 |
+ } while (count); |
|
| 1274 |
+ } |
|
| 1275 |
+ } |
|
| 1276 |
+ |
|
| 1277 |
+ if (CPU.NMILine && (Timings.NMITriggerPos != 0xffff)) |
|
| 1278 |
+ {
|
|
| 1279 |
+ Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay; |
|
| 1280 |
+ if (Timings.NMITriggerPos >= Timings.H_Max) |
|
| 1281 |
+ Timings.NMITriggerPos -= Timings.H_Max; |
|
| 1282 |
+ } |
|
| 1283 |
+ |
|
| 1284 |
+ // Release the memory used in SPC7110 DMA |
|
| 1285 |
+ /*if (Settings.SPC7110) |
|
| 1286 |
+ {
|
|
| 1287 |
+ if (spc7110_dma) |
|
| 1288 |
+ delete [] spc7110_dma; |
|
| 1289 |
+ }*/ |
|
| 1290 |
+ |
|
| 1291 |
+#if 0 |
|
| 1292 |
+ // sanity check |
|
| 1293 |
+ if (d->TransferBytes != 0) |
|
| 1294 |
+ fprintf(stderr,"DMA[%d] TransferBytes not 0! $21%02x Reverse:%d %04x\n", Channel, d->BAddress, d->ReverseTransfer, d->TransferBytes); |
|
| 1295 |
+#endif |
|
| 1296 |
+ |
|
| 1297 |
+ CPU.InDMA = false; |
|
| 1298 |
+ CPU.InDMAorHDMA = false; |
|
| 1299 |
+ CPU.InWRAMDMAorHDMA = false; |
|
| 1300 |
+ CPU.CurrentDMAorHDMAChannel = -1; |
|
| 1301 |
+ |
|
| 1302 |
+ return true; |
|
| 1303 |
+} |
|
| 1304 |
+ |
|
| 1305 |
+static inline bool HDMAReadLineCount (int d) |
|
| 1306 |
+{
|
|
| 1307 |
+ // CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. |
|
| 1308 |
+ |
|
| 1309 |
+ uint8_t line; |
|
| 1310 |
+ |
|
| 1311 |
+ line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1312 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1313 |
+ |
|
| 1314 |
+ if (!line) |
|
| 1315 |
+ {
|
|
| 1316 |
+ DMA[d].Repeat = false; |
|
| 1317 |
+ DMA[d].LineCount = 128; |
|
| 1318 |
+ |
|
| 1319 |
+ if (DMA[d].HDMAIndirectAddressing) |
|
| 1320 |
+ {
|
|
| 1321 |
+ if (PPU.HDMA & (0xfe << d)) |
|
| 1322 |
+ {
|
|
| 1323 |
+ DMA[d].Address++; |
|
| 1324 |
+ ADD_CYCLES(SLOW_ONE_CYCLE << 1); |
|
| 1325 |
+ } |
|
| 1326 |
+ else |
|
| 1327 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1328 |
+ |
|
| 1329 |
+ DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1330 |
+ DMA[d].Address++; |
|
| 1331 |
+ } |
|
| 1332 |
+ |
|
| 1333 |
+ DMA[d].Address++; |
|
| 1334 |
+ HDMAMemPointers[d] = NULL; |
|
| 1335 |
+ |
|
| 1336 |
+ return false; |
|
| 1337 |
+ } |
|
| 1338 |
+ else |
|
| 1339 |
+ if (line == 0x80) |
|
| 1340 |
+ {
|
|
| 1341 |
+ DMA[d].Repeat = true; |
|
| 1342 |
+ DMA[d].LineCount = 128; |
|
| 1343 |
+ } |
|
| 1344 |
+ else |
|
| 1345 |
+ {
|
|
| 1346 |
+ DMA[d].Repeat = !(line & 0x80); |
|
| 1347 |
+ DMA[d].LineCount = line & 0x7f; |
|
| 1348 |
+ } |
|
| 1349 |
+ |
|
| 1350 |
+ DMA[d].Address++; |
|
| 1351 |
+ DMA[d].DoTransfer = true; |
|
| 1352 |
+ |
|
| 1353 |
+ if (DMA[d].HDMAIndirectAddressing) |
|
| 1354 |
+ {
|
|
| 1355 |
+ ADD_CYCLES(SLOW_ONE_CYCLE << 1); |
|
| 1356 |
+ DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1357 |
+ DMA[d].Address += 2; |
|
| 1358 |
+ HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress); |
|
| 1359 |
+ } |
|
| 1360 |
+ else |
|
| 1361 |
+ HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address); |
|
| 1362 |
+ |
|
| 1363 |
+ return true; |
|
| 1364 |
+} |
|
| 1365 |
+ |
|
| 1366 |
+void S9xStartHDMA() |
|
| 1367 |
+{
|
|
| 1368 |
+ PPU.HDMA = Memory.FillRAM[0x420c]; |
|
| 1369 |
+ |
|
| 1370 |
+#ifdef DEBUGGER |
|
| 1371 |
+ missing.hdma_this_frame = PPU.HDMA; |
|
| 1372 |
+#endif |
|
| 1373 |
+ |
|
| 1374 |
+ PPU.HDMAEnded = 0; |
|
| 1375 |
+ |
|
| 1376 |
+ int32_t tmpch; |
|
| 1377 |
+ |
|
| 1378 |
+ CPU.InHDMA = true; |
|
| 1379 |
+ CPU.InDMAorHDMA = true; |
|
| 1380 |
+ tmpch = CPU.CurrentDMAorHDMAChannel; |
|
| 1381 |
+ |
|
| 1382 |
+ // XXX: Not quite right... |
|
| 1383 |
+ if (PPU.HDMA != 0) |
|
| 1384 |
+ ADD_CYCLES(Timings.DMACPUSync); |
|
| 1385 |
+ |
|
| 1386 |
+ for (uint8_t i = 0; i < 8; i++) |
|
| 1387 |
+ {
|
|
| 1388 |
+ if (PPU.HDMA & (1 << i)) |
|
| 1389 |
+ {
|
|
| 1390 |
+ CPU.CurrentDMAorHDMAChannel = i; |
|
| 1391 |
+ |
|
| 1392 |
+ DMA[i].Address = DMA[i].AAddress; |
|
| 1393 |
+ |
|
| 1394 |
+ if (!HDMAReadLineCount(i)) |
|
| 1395 |
+ {
|
|
| 1396 |
+ PPU.HDMA &= ~(1 << i); |
|
| 1397 |
+ PPU.HDMAEnded |= (1 << i); |
|
| 1398 |
+ } |
|
| 1399 |
+ } |
|
| 1400 |
+ else |
|
| 1401 |
+ DMA[i].DoTransfer = false; |
|
| 1402 |
+ } |
|
| 1403 |
+ |
|
| 1404 |
+ CPU.InHDMA = false; |
|
| 1405 |
+ CPU.InDMAorHDMA = CPU.InDMA; |
|
| 1406 |
+ CPU.HDMARanInDMA = CPU.InDMA ? PPU.HDMA : 0; |
|
| 1407 |
+ CPU.CurrentDMAorHDMAChannel = tmpch; |
|
| 1408 |
+} |
|
| 1409 |
+ |
|
| 1410 |
+uint8_t S9xDoHDMA (uint8_t byte) |
|
| 1411 |
+{
|
|
| 1412 |
+ struct SDMA *p = &DMA[0]; |
|
| 1413 |
+ |
|
| 1414 |
+ uint32_t ShiftedIBank; |
|
| 1415 |
+ uint16_t IAddr; |
|
| 1416 |
+ bool temp; |
|
| 1417 |
+ int32_t tmpch; |
|
| 1418 |
+ int d = 0; |
|
| 1419 |
+ |
|
| 1420 |
+ CPU.InHDMA = true; |
|
| 1421 |
+ CPU.InDMAorHDMA = true; |
|
| 1422 |
+ CPU.HDMARanInDMA = CPU.InDMA ? byte : 0; |
|
| 1423 |
+ temp = CPU.InWRAMDMAorHDMA; |
|
| 1424 |
+ tmpch = CPU.CurrentDMAorHDMAChannel; |
|
| 1425 |
+ |
|
| 1426 |
+ // XXX: Not quite right... |
|
| 1427 |
+ ADD_CYCLES(Timings.DMACPUSync); |
|
| 1428 |
+ |
|
| 1429 |
+ for (uint8_t mask = 1; mask; mask <<= 1, p++, d++) |
|
| 1430 |
+ {
|
|
| 1431 |
+ if (byte & mask) |
|
| 1432 |
+ {
|
|
| 1433 |
+ CPU.InWRAMDMAorHDMA = false; |
|
| 1434 |
+ CPU.CurrentDMAorHDMAChannel = d; |
|
| 1435 |
+ |
|
| 1436 |
+ if (p->HDMAIndirectAddressing) |
|
| 1437 |
+ {
|
|
| 1438 |
+ ShiftedIBank = (p->IndirectBank << 16); |
|
| 1439 |
+ IAddr = p->IndirectAddress; |
|
| 1440 |
+ } |
|
| 1441 |
+ else |
|
| 1442 |
+ {
|
|
| 1443 |
+ ShiftedIBank = (p->ABank << 16); |
|
| 1444 |
+ IAddr = p->Address; |
|
| 1445 |
+ } |
|
| 1446 |
+ |
|
| 1447 |
+ if (!HDMAMemPointers[d]) |
|
| 1448 |
+ HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr); |
|
| 1449 |
+ |
|
| 1450 |
+ if (p->DoTransfer) |
|
| 1451 |
+ {
|
|
| 1452 |
+ // XXX: Hack for Uniracers, because we don't understand |
|
| 1453 |
+ // OAM Address Invalidation |
|
| 1454 |
+ if (p->BAddress == 0x04) |
|
| 1455 |
+ {
|
|
| 1456 |
+ if (SNESGameFixes.Uniracers) |
|
| 1457 |
+ {
|
|
| 1458 |
+ PPU.OAMAddr = 0x10c; |
|
| 1459 |
+ PPU.OAMFlip = 0; |
|
| 1460 |
+ } |
|
| 1461 |
+ } |
|
| 1462 |
+ |
|
| 1463 |
+ #ifdef DEBUGGER |
|
| 1464 |
+ if (Settings.TraceHDMA && p->DoTransfer) |
|
| 1465 |
+ {
|
|
| 1466 |
+ sprintf(String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X", |
|
| 1467 |
+ p-DMA, p->ReverseTransfer? "read" : "write", |
|
| 1468 |
+ p->TransferMode, ShiftedIBank+IAddr, p->BAddress, |
|
| 1469 |
+ p->HDMAIndirectAddressing ? "ind" : "abs", |
|
| 1470 |
+ p->LineCount, |
|
| 1471 |
+ p->Repeat ? "yes" : "no ", (long) CPU.V_Counter, |
|
| 1472 |
+ p->ABank, p->Address); |
|
| 1473 |
+ S9xMessage(S9X_TRACE, S9X_HDMA_TRACE, String); |
|
| 1474 |
+ } |
|
| 1475 |
+ #endif |
|
| 1476 |
+ |
|
| 1477 |
+ if (!p->ReverseTransfer) |
|
| 1478 |
+ {
|
|
| 1479 |
+ if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE) |
|
| 1480 |
+ {
|
|
| 1481 |
+ // HDMA REALLY-SLOW PATH |
|
| 1482 |
+ HDMAMemPointers[d] = NULL; |
|
| 1483 |
+ |
|
| 1484 |
+ #define DOBYTE(Addr, RegOff) \ |
|
| 1485 |
+ CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ |
|
| 1486 |
+ (!(ShiftedIBank & 0x400000) && ((uint16_t) (Addr)) < 0x2000)); \ |
|
| 1487 |
+ S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16_t) (Addr))), 0x2100 + p->BAddress + (RegOff)); |
|
| 1488 |
+ |
|
| 1489 |
+ switch (p->TransferMode) |
|
| 1490 |
+ {
|
|
| 1491 |
+ case 0: |
|
| 1492 |
+ DOBYTE(IAddr, 0); |
|
| 1493 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1494 |
+ break; |
|
| 1495 |
+ |
|
| 1496 |
+ case 5: |
|
| 1497 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1498 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1499 |
+ DOBYTE(IAddr + 1, 1); |
|
| 1500 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1501 |
+ DOBYTE(IAddr + 2, 0); |
|
| 1502 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1503 |
+ DOBYTE(IAddr + 3, 1); |
|
| 1504 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1505 |
+ break; |
|
| 1506 |
+ |
|
| 1507 |
+ case 1: |
|
| 1508 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1509 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1510 |
+ DOBYTE(IAddr + 1, 1); |
|
| 1511 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1512 |
+ break; |
|
| 1513 |
+ |
|
| 1514 |
+ case 2: |
|
| 1515 |
+ case 6: |
|
| 1516 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1517 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1518 |
+ DOBYTE(IAddr + 1, 0); |
|
| 1519 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1520 |
+ break; |
|
| 1521 |
+ |
|
| 1522 |
+ case 3: |
|
| 1523 |
+ case 7: |
|
| 1524 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1525 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1526 |
+ DOBYTE(IAddr + 1, 0); |
|
| 1527 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1528 |
+ DOBYTE(IAddr + 2, 1); |
|
| 1529 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1530 |
+ DOBYTE(IAddr + 3, 1); |
|
| 1531 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1532 |
+ break; |
|
| 1533 |
+ |
|
| 1534 |
+ case 4: |
|
| 1535 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1536 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1537 |
+ DOBYTE(IAddr + 1, 1); |
|
| 1538 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1539 |
+ DOBYTE(IAddr + 2, 2); |
|
| 1540 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1541 |
+ DOBYTE(IAddr + 3, 3); |
|
| 1542 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1543 |
+ break; |
|
| 1544 |
+ } |
|
| 1545 |
+ |
|
| 1546 |
+ #undef DOBYTE |
|
| 1547 |
+ } |
|
| 1548 |
+ else |
|
| 1549 |
+ {
|
|
| 1550 |
+ CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || |
|
| 1551 |
+ (!(ShiftedIBank & 0x400000) && IAddr < 0x2000)); |
|
| 1552 |
+ |
|
| 1553 |
+ if (!HDMAMemPointers[d]) |
|
| 1554 |
+ {
|
|
| 1555 |
+ // HDMA SLOW PATH |
|
| 1556 |
+ uint32_t Addr = ShiftedIBank + IAddr; |
|
| 1557 |
+ |
|
| 1558 |
+ switch (p->TransferMode) |
|
| 1559 |
+ {
|
|
| 1560 |
+ case 0: |
|
| 1561 |
+ S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); |
|
| 1562 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1563 |
+ break; |
|
| 1564 |
+ |
|
| 1565 |
+ case 5: |
|
| 1566 |
+ S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1567 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1568 |
+ S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); |
|
| 1569 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1570 |
+ Addr += 2; |
|
| 1571 |
+ /* fall through */ |
|
| 1572 |
+ case 1: |
|
| 1573 |
+ S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1574 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1575 |
+ S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); |
|
| 1576 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1577 |
+ break; |
|
| 1578 |
+ |
|
| 1579 |
+ case 2: |
|
| 1580 |
+ case 6: |
|
| 1581 |
+ S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1582 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1583 |
+ S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); |
|
| 1584 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1585 |
+ break; |
|
| 1586 |
+ |
|
| 1587 |
+ case 3: |
|
| 1588 |
+ case 7: |
|
| 1589 |
+ S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1590 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1591 |
+ S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); |
|
| 1592 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1593 |
+ S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress); |
|
| 1594 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1595 |
+ S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress); |
|
| 1596 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1597 |
+ break; |
|
| 1598 |
+ |
|
| 1599 |
+ case 4: |
|
| 1600 |
+ S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); |
|
| 1601 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1602 |
+ S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); |
|
| 1603 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1604 |
+ S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress); |
|
| 1605 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1606 |
+ S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); |
|
| 1607 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1608 |
+ break; |
|
| 1609 |
+ } |
|
| 1610 |
+ } |
|
| 1611 |
+ else |
|
| 1612 |
+ {
|
|
| 1613 |
+ // HDMA FAST PATH |
|
| 1614 |
+ switch (p->TransferMode) |
|
| 1615 |
+ {
|
|
| 1616 |
+ case 0: |
|
| 1617 |
+ S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress); |
|
| 1618 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1619 |
+ break; |
|
| 1620 |
+ |
|
| 1621 |
+ case 5: |
|
| 1622 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1623 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1624 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); |
|
| 1625 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1626 |
+ HDMAMemPointers[d] += 2; |
|
| 1627 |
+ /* fall through */ |
|
| 1628 |
+ case 1: |
|
| 1629 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1630 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1631 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); |
|
| 1632 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1633 |
+ HDMAMemPointers[d] += 2; |
|
| 1634 |
+ break; |
|
| 1635 |
+ |
|
| 1636 |
+ case 2: |
|
| 1637 |
+ case 6: |
|
| 1638 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1639 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1640 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); |
|
| 1641 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1642 |
+ HDMAMemPointers[d] += 2; |
|
| 1643 |
+ break; |
|
| 1644 |
+ |
|
| 1645 |
+ case 3: |
|
| 1646 |
+ case 7: |
|
| 1647 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1648 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1649 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); |
|
| 1650 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1651 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress); |
|
| 1652 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1653 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress); |
|
| 1654 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1655 |
+ HDMAMemPointers[d] += 4; |
|
| 1656 |
+ break; |
|
| 1657 |
+ |
|
| 1658 |
+ case 4: |
|
| 1659 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); |
|
| 1660 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1661 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); |
|
| 1662 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1663 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress); |
|
| 1664 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1665 |
+ S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress); |
|
| 1666 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1667 |
+ HDMAMemPointers[d] += 4; |
|
| 1668 |
+ break; |
|
| 1669 |
+ } |
|
| 1670 |
+ } |
|
| 1671 |
+ } |
|
| 1672 |
+ } |
|
| 1673 |
+ else |
|
| 1674 |
+ {
|
|
| 1675 |
+ // REVERSE HDMA REALLY-SLOW PATH |
|
| 1676 |
+ // anomie says: Since this is apparently never used |
|
| 1677 |
+ // (otherwise we would have noticed before now), let's not bother with faster paths. |
|
| 1678 |
+ HDMAMemPointers[d] = NULL; |
|
| 1679 |
+ |
|
| 1680 |
+ #define DOBYTE(Addr, RegOff) \ |
|
| 1681 |
+ CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ |
|
| 1682 |
+ (!(ShiftedIBank & 0x400000) && ((uint16_t) (Addr)) < 0x2000)); \ |
|
| 1683 |
+ S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + (RegOff)), ShiftedIBank + ((uint16_t) (Addr))); |
|
| 1684 |
+ |
|
| 1685 |
+ switch (p->TransferMode) |
|
| 1686 |
+ {
|
|
| 1687 |
+ case 0: |
|
| 1688 |
+ DOBYTE(IAddr, 0); |
|
| 1689 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1690 |
+ break; |
|
| 1691 |
+ |
|
| 1692 |
+ case 5: |
|
| 1693 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1694 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1695 |
+ DOBYTE(IAddr + 1, 1); |
|
| 1696 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1697 |
+ DOBYTE(IAddr + 2, 0); |
|
| 1698 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1699 |
+ DOBYTE(IAddr + 3, 1); |
|
| 1700 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1701 |
+ break; |
|
| 1702 |
+ |
|
| 1703 |
+ case 1: |
|
| 1704 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1705 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1706 |
+ DOBYTE(IAddr + 1, 1); |
|
| 1707 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1708 |
+ break; |
|
| 1709 |
+ |
|
| 1710 |
+ case 2: |
|
| 1711 |
+ case 6: |
|
| 1712 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1713 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1714 |
+ DOBYTE(IAddr + 1, 0); |
|
| 1715 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1716 |
+ break; |
|
| 1717 |
+ |
|
| 1718 |
+ case 3: |
|
| 1719 |
+ case 7: |
|
| 1720 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1721 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1722 |
+ DOBYTE(IAddr + 1, 0); |
|
| 1723 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1724 |
+ DOBYTE(IAddr + 2, 1); |
|
| 1725 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1726 |
+ DOBYTE(IAddr + 3, 1); |
|
| 1727 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1728 |
+ break; |
|
| 1729 |
+ |
|
| 1730 |
+ case 4: |
|
| 1731 |
+ DOBYTE(IAddr + 0, 0); |
|
| 1732 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1733 |
+ DOBYTE(IAddr + 1, 1); |
|
| 1734 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1735 |
+ DOBYTE(IAddr + 2, 2); |
|
| 1736 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1737 |
+ DOBYTE(IAddr + 3, 3); |
|
| 1738 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1739 |
+ break; |
|
| 1740 |
+ } |
|
| 1741 |
+ |
|
| 1742 |
+ #undef DOBYTE |
|
| 1743 |
+ } |
|
| 1744 |
+ |
|
| 1745 |
+ if (p->HDMAIndirectAddressing) |
|
| 1746 |
+ p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; |
|
| 1747 |
+ else |
|
| 1748 |
+ p->Address += HDMA_ModeByteCounts[p->TransferMode]; |
|
| 1749 |
+ } |
|
| 1750 |
+ |
|
| 1751 |
+ p->DoTransfer = !p->Repeat; |
|
| 1752 |
+ |
|
| 1753 |
+ if (!--p->LineCount) |
|
| 1754 |
+ {
|
|
| 1755 |
+ if (!HDMAReadLineCount(d)) |
|
| 1756 |
+ {
|
|
| 1757 |
+ byte &= ~mask; |
|
| 1758 |
+ PPU.HDMAEnded |= mask; |
|
| 1759 |
+ p->DoTransfer = false; |
|
| 1760 |
+ continue; |
|
| 1761 |
+ } |
|
| 1762 |
+ } |
|
| 1763 |
+ else |
|
| 1764 |
+ ADD_CYCLES(SLOW_ONE_CYCLE); |
|
| 1765 |
+ } |
|
| 1766 |
+ } |
|
| 1767 |
+ |
|
| 1768 |
+ CPU.InHDMA = false; |
|
| 1769 |
+ CPU.InDMAorHDMA = CPU.InDMA; |
|
| 1770 |
+ CPU.InWRAMDMAorHDMA = temp; |
|
| 1771 |
+ CPU.CurrentDMAorHDMAChannel = tmpch; |
|
| 1772 |
+ |
|
| 1773 |
+ return byte; |
|
| 1774 |
+} |
|
| 1775 |
+ |
|
| 1776 |
+void S9xResetDMA() |
|
| 1777 |
+{
|
|
| 1778 |
+ for (int d = 0; d < 8; d++) |
|
| 1779 |
+ {
|
|
| 1780 |
+ DMA[d].ReverseTransfer = true; |
|
| 1781 |
+ DMA[d].HDMAIndirectAddressing = true; |
|
| 1782 |
+ DMA[d].AAddressFixed = true; |
|
| 1783 |
+ DMA[d].AAddressDecrement = true; |
|
| 1784 |
+ DMA[d].TransferMode = 7; |
|
| 1785 |
+ DMA[d].BAddress = 0xff; |
|
| 1786 |
+ DMA[d].AAddress = 0xffff; |
|
| 1787 |
+ DMA[d].ABank = 0xff; |
|
| 1788 |
+ DMA[d].DMACount_Or_HDMAIndirectAddress = 0xffff; |
|
| 1789 |
+ DMA[d].IndirectBank = 0xff; |
|
| 1790 |
+ DMA[d].Address = 0xffff; |
|
| 1791 |
+ DMA[d].Repeat = false; |
|
| 1792 |
+ DMA[d].LineCount = 0x7f; |
|
| 1793 |
+ DMA[d].UnknownByte = 0xff; |
|
| 1794 |
+ DMA[d].DoTransfer = false; |
|
| 1795 |
+ DMA[d].UnusedBit43x0 = 1; |
|
| 1796 |
+ } |
|
| 1797 |
+} |