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
+}