Browse code

Update snes9x code from 1.53 to 1.6.0.

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.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 1 changed files
... ...
@@ -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
Browse code

[SNSF] Replaced most uses of fill/copy with fill_n/copy_n, and a few other minor code cleanups.

Naram Qashat authored on 2013/05/27 22:34:22
Showing 1 changed files
... ...
@@ -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;
Browse code

[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.

Naram Qashat authored on 2013/05/23 06:02:16
Showing 1 changed files
... ...
@@ -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
 }
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
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
+}