Browse code

Update snes9x code from 1.53 to 1.6.0.

Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 1 changed files
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include <algorithm>
179 8
 #include "snes9x.h"
... ...
@@ -184,26 +13,92 @@
184 13
 
185 14
 extern uint8_t *HDMAMemPointers[8];
186 15
 
187
-void S9xUpdateHVTimerPosition()
16
+static int CyclesUntilNext(int hc, int vc)
188 17
 {
189
-	PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
190
-	if (Timings.H_Max == Timings.H_Max_Master) // 1364
18
+	int32_t total = 0;
19
+	int vpos = CPU.V_Counter;
20
+
21
+	if (vc - vpos > 0)
191 22
 	{
192
-		if (PPU.IRQHBeamPos > 322)
193
-			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
194
-		if (PPU.IRQHBeamPos > 326)
195
-			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
23
+		// It's still in this frame */
24
+		// Add number of lines
25
+		total += (vc - vpos) * Timings.H_Max_Master;
26
+		// If line 240 is in there and we're odd, subtract a dot
27
+		if (vpos <= 240 && vc > 240 && Timings.InterlaceField && !IPPU.Interlace)
28
+			total -= ONE_DOT_CYCLE;
196 29
 	}
30
+	else
31
+	{
32
+		if (vc == vpos && hc > CPU.Cycles)
33
+			return hc;
34
+
35
+		total += (Timings.V_Max - vpos) * Timings.H_Max_Master;
36
+		if (vpos <= 240 && Timings.InterlaceField && !IPPU.Interlace)
37
+			total -= ONE_DOT_CYCLE;
38
+
39
+		total += vc * Timings.H_Max_Master;
40
+		if (vc > 240 && !Timings.InterlaceField && !IPPU.Interlace)
41
+			total -= ONE_DOT_CYCLE;
42
+	}
43
+
44
+	total += hc;
45
+
46
+	return total;
47
+}
48
+
49
+void S9xUpdateIRQPositions(bool initial)
50
+{
51
+	PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
52
+	PPU.HTimerPosition -= PPU.IRQHBeamPos ? 0 : ONE_DOT_CYCLE;
53
+	PPU.HTimerPosition += PPU.IRQHBeamPos > 322 ? (ONE_DOT_CYCLE / 2) : 0;
54
+	PPU.HTimerPosition += PPU.IRQHBeamPos > 326 ? (ONE_DOT_CYCLE / 2) : 0;
197 55
 
198 56
 	PPU.VTimerPosition = PPU.IRQVBeamPos;
199 57
 
200
-	if (PPU.HTimerPosition >= Timings.H_Max && PPU.IRQHBeamPos < 340)
58
+	if (PPU.VTimerEnabled && PPU.VTimerPosition >= Timings.V_Max + (IPPU.Interlace ? 1 : 0))
59
+		Timings.NextIRQTimer = 0x0fffffff;
60
+	else if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
61
+		Timings.NextIRQTimer = 0x0fffffff;
62
+	else if (PPU.HTimerEnabled && !PPU.VTimerEnabled)
201 63
 	{
202
-		PPU.HTimerPosition -= Timings.H_Max;
203
-		++PPU.VTimerPosition;
204
-		// FIXME
205
-		if (PPU.VTimerPosition >= Timings.V_Max)
206
-			PPU.VTimerPosition = 0;
64
+		int v_pos = CPU.V_Counter;
65
+
66
+		Timings.NextIRQTimer = PPU.HTimerPosition;
67
+		if (CPU.Cycles > Timings.NextIRQTimer - Timings.IRQTriggerCycles)
68
+		{
69
+			Timings.NextIRQTimer += Timings.H_Max;
70
+			++v_pos;
71
+		}
72
+
73
+		// Check for short dot scanline
74
+		if (v_pos == 240 && Timings.InterlaceField && !IPPU.Interlace)
75
+		{
76
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
77
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
78
+		}
79
+	}
80
+	else if (!PPU.HTimerEnabled && PPU.VTimerEnabled)
81
+	{
82
+		if (CPU.V_Counter == PPU.VTimerPosition && initial)
83
+			Timings.NextIRQTimer = CPU.Cycles + Timings.IRQTriggerCycles - ONE_DOT_CYCLE;
84
+		else
85
+			Timings.NextIRQTimer = CyclesUntilNext(Timings.IRQTriggerCycles - ONE_DOT_CYCLE, PPU.VTimerPosition);
86
+	}
87
+	else
88
+	{
89
+		Timings.NextIRQTimer = CyclesUntilNext(PPU.HTimerPosition, PPU.VTimerPosition);
90
+
91
+		// Check for short dot scanline
92
+		int field = Timings.InterlaceField;
93
+
94
+		if (PPU.VTimerPosition < CPU.V_Counter || (PPU.VTimerPosition == CPU.V_Counter && Timings.NextIRQTimer > Timings.H_Max))
95
+			field = !field;
96
+
97
+		if (PPU.VTimerPosition == 240 && field && !IPPU.Interlace)
98
+		{
99
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 322 ? ONE_DOT_CYCLE / 2 : 0;
100
+			Timings.NextIRQTimer -= PPU.IRQHBeamPos <= 326 ? ONE_DOT_CYCLE / 2 : 0;
101
+		}
207 102
 	}
208 103
 }
209 104
 
... ...
@@ -252,7 +147,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
252 147
 
253 148
 			case 0x2102: // OAMADDL
254 149
 				PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte;
255
-				PPU.OAMFlip = 2;
150
+				PPU.OAMFlip = 0;
256 151
 				PPU.SavedOAMAddr = PPU.OAMAddr;
257 152
 				if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
258 153
 					PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
... ...
@@ -281,7 +176,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
281 176
 
282 177
 			case 0x2105: // BGMODE
283 178
 				if (Byte != Memory.FillRAM[0x2105])
284
-					IPPU.Interlace = !!(Memory.FillRAM[0x2133] & 1);
179
+					IPPU.Interlace = 0;
285 180
 
286 181
 				break;
287 182
 
... ...
@@ -326,15 +221,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
326 221
 				PPU.VMA.Address &= 0xff00;
327 222
 				PPU.VMA.Address |= Byte;
328 223
 
329
-				if (PPU.VMA.FullGraphicCount)
330
-				{
331
-					uint32_t addr = PPU.VMA.Address;
332
-					uint32_t rem = addr & PPU.VMA.Mask1;
333
-					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
334
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
335
-				}
336
-				else
337
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
224
+				S9xUpdateVRAMReadBuffer();
338 225
 
339 226
 				break;
340 227
 
... ...
@@ -342,15 +229,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
342 229
 				PPU.VMA.Address &= 0x00ff;
343 230
 				PPU.VMA.Address |= Byte << 8;
344 231
 
345
-				if (PPU.VMA.FullGraphicCount)
346
-				{
347
-					uint32_t addr = PPU.VMA.Address;
348
-					uint32_t rem = addr & PPU.VMA.Mask1;
349
-					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
350
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
351
-				}
352
-				else
353
-					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
232
+				S9xUpdateVRAMReadBuffer();
354 233
 
355 234
 				break;
356 235
 
... ...
@@ -499,7 +378,7 @@ uint8_t S9xGetPPU(uint16_t Address)
499 378
 				return (PPU.OpenBus1 = Memory.FillRAM[Address]);
500 379
 
501 380
 			case 0x2137: // SLHV
502
-				return OpenBus;
381
+				return PPU.OpenBus1;
503 382
 
504 383
 			case 0x2138: // OAMDATAREAD
505 384
 				if (PPU.OAMAddr & 0x100)
... ...
@@ -531,36 +410,20 @@ uint8_t S9xGetPPU(uint16_t Address)
531 410
 				return (PPU.OpenBus1 = byte);
532 411
 
533 412
 			case 0x2139: // VMDATALREAD
534
-				byte = IPPU.VRAMReadBuffer & 0xff;
413
+				byte = PPU.VRAMReadBuffer & 0xff;
535 414
 				if (!PPU.VMA.High)
536 415
 				{
537
-					if (PPU.VMA.FullGraphicCount)
538
-					{
539
-						uint32_t addr = PPU.VMA.Address;
540
-						uint32_t rem = addr & PPU.VMA.Mask1;
541
-						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
542
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
543
-					}
544
-					else
545
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
416
+					S9xUpdateVRAMReadBuffer();
546 417
 
547 418
 					PPU.VMA.Address += PPU.VMA.Increment;
548 419
 				}
549 420
 				return (PPU.OpenBus1 = byte);
550 421
 
551 422
 			case 0x213a: // VMDATAHREAD
552
-				byte = (IPPU.VRAMReadBuffer >> 8) & 0xff;
423
+				byte = (PPU.VRAMReadBuffer >> 8) & 0xff;
553 424
 				if (PPU.VMA.High)
554 425
 				{
555
-					if (PPU.VMA.FullGraphicCount)
556
-					{
557
-						uint32_t addr = PPU.VMA.Address;
558
-						uint32_t rem = addr & PPU.VMA.Mask1;
559
-						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
560
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
561
-					}
562
-					else
563
-						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
426
+					S9xUpdateVRAMReadBuffer();
564 427
 
565 428
 					PPU.VMA.Address += PPU.VMA.Increment;
566 429
 				}
... ...
@@ -729,23 +592,24 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
729 592
 		switch (Address)
730 593
 		{
731 594
 			case 0x4200: // NMITIMEN
595
+				if (Byte == Memory.FillRAM[0x4200])
596
+					break;
597
+
732 598
 				PPU.VTimerEnabled = !!(Byte & 0x20);
733 599
 				PPU.HTimerEnabled = !!(Byte & 0x10);
734 600
 
735
-				if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled)
736
-					CPU.IRQTransition = true;
737
-
738
-				if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
601
+				if (!(Byte & 0x10) && !(Byte & 0x20))
739 602
 					CPU.IRQLine = CPU.IRQTransition = false;
740 603
 
604
+				if ((Byte & 0x30) != (Memory.FillRAM[0x4200] & 0x30))
605
+					// Only allow instantaneous IRQ if turning it completely on or off
606
+					S9xUpdateIRQPositions(!(Byte & 0x30) || !(Memory.FillRAM[0x4200] & 0x30));
607
+
741 608
 				// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
742 609
 				if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && (Memory.FillRAM[0x4210] & 0x80))
743
-				{
744 610
 					// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
745 611
 					// then, when to call S9xOpcode_NMI()?
746
-					CPU.NMILine = true;
747
-					Timings.NMITriggerPos = CPU.Cycles + 12;
748
-				}
612
+					Timings.IRQFlagChanging |= IRQ_TRIGGER_NMI;
749 613
 
750 614
 				break;
751 615
 
... ...
@@ -779,28 +643,28 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
779 643
 				pos = PPU.IRQHBeamPos;
780 644
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
781 645
 				if (PPU.IRQHBeamPos != pos)
782
-					S9xUpdateHVTimerPosition();
646
+					S9xUpdateIRQPositions(false);
783 647
 				break;
784 648
 
785 649
 			case 0x4208: // HTIMEH
786 650
 				pos = PPU.IRQHBeamPos;
787 651
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
788 652
 				if (PPU.IRQHBeamPos != pos)
789
-					S9xUpdateHVTimerPosition();
653
+					S9xUpdateIRQPositions(false);
790 654
 				break;
791 655
 
792 656
 			case 0x4209: // VTIMEL
793 657
 				pos = PPU.IRQVBeamPos;
794 658
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
795 659
 				if (PPU.IRQVBeamPos != pos)
796
-					S9xUpdateHVTimerPosition();
660
+					S9xUpdateIRQPositions(true);
797 661
 				break;
798 662
 
799 663
 			case 0x420a: // VTIMEH
800 664
 				pos = PPU.IRQVBeamPos;
801 665
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
802 666
 				if (PPU.IRQVBeamPos != pos)
803
-					S9xUpdateHVTimerPosition();
667
+					S9xUpdateIRQPositions(true);
804 668
 				break;
805 669
 
806 670
 			case 0x420b: // MDMAEN
... ...
@@ -837,7 +701,11 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
837 701
 
838 702
 			case 0x420d: // MEMSEL
839 703
 				if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1))
704
+				{
840 705
 					CPU.FastROMSpeed = Byte & 1 ? ONE_CYCLE : SLOW_ONE_CYCLE;
706
+					// we might currently be in FastROMSpeed region, S9xSetPCBase will update CPU.MemSpeed
707
+					S9xSetPCBase(Registers.PC.xPBPC);
708
+				}
841 709
 
842 710
 				break;
843 711
 
... ...
@@ -1021,7 +889,7 @@ void S9xSoftResetPPU()
1021 889
 
1022 890
 	PPU.OpenBus1 = PPU.OpenBus2 = 0;
1023 891
 
1024
-	IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
892
+	PPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
1025 893
 	IPPU.Interlace = false;
1026 894
 
1027 895
 	for (int c = 0; c < 0x8000; c += 0x100)
... ...
@@ -1033,4 +901,5 @@ void S9xSoftResetPPU()
1033 901
 	std::fill_n(&Memory.FillRAM[0x1000], 0x1000, 0);
1034 902
 
1035 903
 	Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff;
904
+	Memory.FillRAM[0x2126] = Memory.FillRAM[0x2128] = 1;
1036 905
 }
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
... ...
@@ -229,15 +229,11 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
229 229
 		// write_port will run the APU until given clock before writing value
230 230
 		S9xAPUWritePort(Address & 3, Byte);
231 231
 	else if (Address <= 0x2183)
232
-	{
233 232
 		switch (Address)
234 233
 		{
235 234
 			case 0x2100: // INIDISP
236
-				if (Byte != Memory.FillRAM[0x2100])
237
-				{
238
-					if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80))
239
-						PPU.ForcedBlanking = !!((Byte >> 7) & 1);
240
-				}
235
+				if (Byte != Memory.FillRAM[0x2100] && (Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80))
236
+					PPU.ForcedBlanking = !!((Byte >> 7) & 1);
241 237
 
242 238
 				if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
243 239
 				{
... ...
@@ -434,10 +430,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address)
434 430
 					PPU.WRAM |= Byte << 16;
435 431
 					PPU.WRAM &= 0x1ffff;
436 432
 				}
437
-
438
-				break;
439 433
 		}
440
-	}
441 434
 
442 435
 	Memory.FillRAM[Address] = Byte;
443 436
 }
... ...
@@ -658,7 +651,7 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
658 651
 				DMA[d].UnusedBit43x0 = !!(Byte & 0x20);
659 652
 				DMA[d].AAddressDecrement = !!(Byte & 0x10);
660 653
 				DMA[d].AAddressFixed = !!(Byte & 0x08);
661
-				DMA[d].TransferMode = (Byte & 7);
654
+				DMA[d].TransferMode = Byte & 7;
662 655
 				return;
663 656
 
664 657
 			case 0x1: // 0x43x1: BBADx
... ...
@@ -775,9 +768,9 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
775 768
 				uint16_t div = Byte ? a / Byte : 0xffff;
776 769
 				uint16_t rem = Byte ? a % Byte : a;
777 770
 				// FIXME: The update occurs 16 machine cycles after $4206 is set.
778
-				Memory.FillRAM[0x4214] = static_cast<uint8_t>(div);
771
+				Memory.FillRAM[0x4214] = div & 0xff;
779 772
 				Memory.FillRAM[0x4215] = div >> 8;
780
-				Memory.FillRAM[0x4216] = static_cast<uint8_t>(rem);
773
+				Memory.FillRAM[0x4216] = rem & 0xff;
781 774
 				Memory.FillRAM[0x4217] = rem >> 8;
782 775
 				break;
783 776
 			}
... ...
@@ -844,12 +837,7 @@ void S9xSetCPU(uint8_t Byte, uint16_t Address)
844 837
 
845 838
 			case 0x420d: // MEMSEL
846 839
 				if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1))
847
-				{
848
-					if (Byte & 1)
849
-						CPU.FastROMSpeed = ONE_CYCLE;
850
-					else
851
-						CPU.FastROMSpeed = SLOW_ONE_CYCLE;
852
-				}
840
+					CPU.FastROMSpeed = Byte & 1 ? ONE_CYCLE : SLOW_ONE_CYCLE;
853 841
 
854 842
 				break;
855 843
 
... ...
@@ -948,8 +936,7 @@ uint8_t S9xGetCPU(uint16_t Address)
948 936
 
949 937
 			case 0x4211: // TIMEUP
950 938
 				byte = CPU.IRQLine ? 0x80 : 0;
951
-				CPU.IRQLine = false;
952
-				CPU.IRQTransition = false;
939
+				CPU.IRQLine = CPU.IRQTransition = false;
953 940
 				return byte | (OpenBus & 0x7f);
954 941
 
955 942
 			case 0x4212: // HVBJOY
... ...
@@ -1011,7 +998,7 @@ void S9xSoftResetPPU()
1011 998
 	PPU.OAMPriorityRotation = false;
1012 999
 	PPU.OAMFlip = 0;
1013 1000
 	PPU.OAMWriteRegister = 0;
1014
-	std::fill(&PPU.OAMData[0], &PPU.OAMData[512 + 32], 0);
1001
+	std::fill_n(&PPU.OAMData[0], sizeof(PPU.OAMData), 0);
1015 1002
 
1016 1003
 	PPU.FirstSprite = 0;
1017 1004
 
... ...
@@ -1038,12 +1025,12 @@ void S9xSoftResetPPU()
1038 1025
 	IPPU.Interlace = false;
1039 1026
 
1040 1027
 	for (int c = 0; c < 0x8000; c += 0x100)
1041
-		std::fill(&Memory.FillRAM[c], &Memory.FillRAM[c + 0x100], c >> 8);
1042
-	std::fill(&Memory.FillRAM[0x2100], &Memory.FillRAM[0x2200], 0);
1043
-	std::fill(&Memory.FillRAM[0x4200], &Memory.FillRAM[0x4300], 0);
1044
-	std::fill(&Memory.FillRAM[0x4000], &Memory.FillRAM[0x4100], 0);
1028
+		std::fill_n(&Memory.FillRAM[c], 0x100, c >> 8);
1029
+	std::fill_n(&Memory.FillRAM[0x2100], 0x0100, 0);
1030
+	std::fill_n(&Memory.FillRAM[0x4200], 0x0100, 0);
1031
+	std::fill_n(&Memory.FillRAM[0x4000], 0x0100, 0);
1045 1032
 	// For BS Suttehakkun 2...
1046
-	std::fill(&Memory.FillRAM[0x1000], &Memory.FillRAM[0x2000], 0);
1033
+	std::fill_n(&Memory.FillRAM[0x1000], 0x1000, 0);
1047 1034
 
1048 1035
 	Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff;
1049 1036
 }
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
... ...
@@ -175,147 +175,47 @@
175 175
   Nintendo Co., Limited and its subsidiary companies.
176 176
  ***********************************************************************************/
177 177
 
178
+#include <algorithm>
178 179
 #include "snes9x.h"
179 180
 #include "memmap.h"
180 181
 #include "dma.h"
181 182
 #include "apu/apu.h"
182
-//#include "fxemu.h"
183 183
 #include "sdd1.h"
184
-//#include "srtc.h"
185
-//#include "controls.h"
186
-//#include "movie.h"
187
-//#include "display.h"
188
-#ifdef NETPLAY_SUPPORT
189
-#include "netplay.h"
190
-#endif
191
-#ifdef DEBUGGER
192
-#include "debug.h"
193
-#include "missing.h"
194
-#endif
195
-
196
-extern uint8_t	*HDMAMemPointers[8];
197
-
198
-static inline void S9xLatchCounters (bool force)
199
-{
200
-	if (force || (Memory.FillRAM[0x4213] & 0x80))
201
-	{
202
-		// Latch h and v counters, like the gun
203
-	#ifdef DEBUGGER
204
-		missing.h_v_latch = 1;
205
-	#endif
206
-
207
-		PPU.HVBeamCounterLatched = 1;
208
-		PPU.VBeamPosLatched = (uint16_t) CPU.V_Counter;
209
-
210
-		// From byuu:
211
-		// All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long.
212
-		// This holds true for all scanlines except scanline 240 on non-interlace odd frames.
213
-		// The reason for this is because this scanline is only 1360 cycles long,
214
-		// instead of 1364 like all other scanlines.
215
-		// This makes the effective range of hscan_pos 0-339 at all times.
216
-		int32_t	hc = CPU.Cycles;
217
-
218
-		if (Timings.H_Max == Timings.H_Max_Master) // 1364
219
-		{
220
-			if (hc >= 1292)
221
-				hc -= (ONE_DOT_CYCLE / 2);
222
-			if (hc >= 1308)
223
-				hc -= (ONE_DOT_CYCLE / 2);
224
-		}
225
-
226
-		PPU.HBeamPosLatched = (uint16_t) (hc / ONE_DOT_CYCLE);
227 184
 
228
-		Memory.FillRAM[0x213f] |= 0x40;
229
-	}
230
-
231
-	if (CPU.V_Counter >  PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE))
232
-		PPU.GunVLatch = 1000;
233
-}
234
-
235
-static inline void S9xTryGunLatch (bool force)
236
-{
237
-	if (CPU.V_Counter >  PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE))
238
-	{
239
-		if (force || (Memory.FillRAM[0x4213] & 0x80))
240
-		{
241
-		#ifdef DEBUGGER
242
-			missing.h_v_latch = 1;
243
-		#endif
244
-
245
-			PPU.HVBeamCounterLatched = 1;
246
-			PPU.VBeamPosLatched = (uint16_t) PPU.GunVLatch;
247
-			PPU.HBeamPosLatched = (uint16_t) PPU.GunHLatch;
248
-
249
-			Memory.FillRAM[0x213f] |= 0x40;
250
-		}
251
-
252
-		PPU.GunVLatch = 1000;
253
-	}
254
-}
185
+extern uint8_t *HDMAMemPointers[8];
255 186
 
256 187
 void S9xUpdateHVTimerPosition()
257 188
 {
258 189
 	PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
259
-	if (Timings.H_Max == Timings.H_Max_Master)	// 1364
190
+	if (Timings.H_Max == Timings.H_Max_Master) // 1364
260 191
 	{
261 192
 		if (PPU.IRQHBeamPos > 322)
262
-			PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
193
+			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
263 194
 		if (PPU.IRQHBeamPos > 326)
264
-			PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
195
+			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
265 196
 	}
266 197
 
267 198
 	PPU.VTimerPosition = PPU.IRQVBeamPos;
268 199
 
269
-	if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340))
200
+	if (PPU.HTimerPosition >= Timings.H_Max && PPU.IRQHBeamPos < 340)
270 201
 	{
271 202
 		PPU.HTimerPosition -= Timings.H_Max;
272
-		PPU.VTimerPosition++;
203
+		++PPU.VTimerPosition;
273 204
 		// FIXME
274 205
 		if (PPU.VTimerPosition >= Timings.V_Max)
275 206
 			PPU.VTimerPosition = 0;
276 207
 	}
277
-
278
-#ifdef DEBUGGER
279
-	S9xTraceFormattedMessage("--- IRQ Timer set  HTimer:%d Pos:%04d  VTimer:%d Pos:%03d",
280
-		PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
281
-#endif
282 208
 }
283 209
 
284
-/*void S9xFixColourBrightness()
285
-{
286
-	IPPU.XB = mul_brightness[PPU.Brightness];
287
-
288
-	for (int i = 0; i < 256; i++)
289
-	{
290
-		IPPU.Red[i]   = IPPU.XB[(PPU.CGDATA[i])       & 0x1f];
291
-		IPPU.Green[i] = IPPU.XB[(PPU.CGDATA[i] >>  5) & 0x1f];
292
-		IPPU.Blue[i]  = IPPU.XB[(PPU.CGDATA[i] >> 10) & 0x1f];
293
-		IPPU.ScreenColors[i] = BUILD_PIXEL(IPPU.Red[i], IPPU.Green[i], IPPU.Blue[i]);
294
-	}
295
-}*/
296
-
297
-void S9xSetPPU (uint8_t Byte, uint16_t Address)
210
+void S9xSetPPU(uint8_t Byte, uint16_t Address)
298 211
 {
299 212
 	// MAP_PPU: $2000-$3FFF
300 213
 
301 214
 	if (CPU.InDMAorHDMA)
302 215
 	{
303 216
 		if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer)
304
-		{
305 217
 			// S9xSetPPU() is called to write to DMA[].AAddress
306
-			if ((Address & 0xff00) == 0x2100)
307
-			{
308
-				// Cannot access to Address Bus B ($2100-$21ff) via (H)DMA
309
-				return;
310
-			}
311
-			else
312
-			{
313
-				// 0x2000-0x3FFF is connected to Address Bus A
314
-				// SA1, SuperFX and SRTC are mapped here
315
-				// I don't bother for now...
316
-				return;
317
-			}
318
-		}
218
+			return;
319 219
 		else
320 220
 		{
321 221
 			// S9xSetPPU() is called to read from $21xx
... ...
@@ -325,39 +225,18 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
325 225
 		}
326 226
 	}
327 227
 
328
-#ifdef DEBUGGER
329
-	if (CPU.InHDMA)
330
-		S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte);
331
-#endif
332
-
333 228
 	if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3
334 229
 		// write_port will run the APU until given clock before writing value
335 230
 		S9xAPUWritePort(Address & 3, Byte);
336
-	else
337
-	if (Address <= 0x2183)
231
+	else if (Address <= 0x2183)
338 232
 	{
339 233
 		switch (Address)
340 234
 		{
341 235
 			case 0x2100: // INIDISP
342 236
 				if (Byte != Memory.FillRAM[0x2100])
343 237
 				{
344
-					//FLUSH_REDRAW();
345
-
346
-					if (PPU.Brightness != (Byte & 0xf))
347
-					{
348
-						IPPU.ColorsChanged = true;
349
-						IPPU.DirectColourMapsNeedRebuild = true;
350
-						PPU.Brightness = Byte & 0xf;
351
-						//S9xFixColourBrightness();
352
-						if (PPU.Brightness > IPPU.MaxBrightness)
353
-							IPPU.MaxBrightness = PPU.Brightness;
354
-					}
355
-
356 238
 					if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80))
357
-					{
358
-						IPPU.ColorsChanged = true;
359
-						PPU.ForcedBlanking = (Byte >> 7) & 1;
360
-					}
239
+						PPU.ForcedBlanking = !!((Byte >> 7) & 1);
361 240
 				}
362 241
 
363 242
 				if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
... ...
@@ -368,72 +247,34 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
368 247
 					if (PPU.OAMPriorityRotation)
369 248
 						tmp = (PPU.OAMAddr & 0xfe) >> 1;
370 249
 					if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp)
371
-					{
372 250
 						PPU.FirstSprite = tmp;
373
-						IPPU.OBJChanged = true;
374
-					}
375 251
 
376 252
 					PPU.OAMFlip = 0;
377 253
 				}
378 254
 
379 255
 				break;
380 256
 
381
-			case 0x2101: // OBSEL
382
-				if (Byte != Memory.FillRAM[0x2101])
383
-				{
384
-					//FLUSH_REDRAW();
385
-					PPU.OBJNameBase = (Byte & 3) << 14;
386
-					PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13;
387
-					PPU.OBJSizeSelect = (Byte >> 5) & 7;
388
-					IPPU.OBJChanged = true;
389
-				}
390
-
391
-				break;
392
-
393 257
 			case 0x2102: // OAMADDL
394 258
 				PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte;
395 259
 				PPU.OAMFlip = 2;
396
-				PPU.OAMReadFlip = 0;
397 260
 				PPU.SavedOAMAddr = PPU.OAMAddr;
398 261
 				if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
399
-				{
400 262
 					PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
401
-					IPPU.OBJChanged = true;
402
-				#ifdef DEBUGGER
403
-					missing.sprite_priority_rotation = 1;
404
-				#endif
405
-				}
406 263
 
407 264
 				break;
408 265
 
409 266
 			case 0x2103: // OAMADDH
410 267
 				PPU.OAMAddr = ((Byte & 1) << 8) | Memory.FillRAM[0x2102];
411
-				PPU.OAMPriorityRotation = (Byte & 0x80) ? 1 : 0;
268
+				PPU.OAMPriorityRotation = !!(Byte & 0x80);
412 269
 				if (PPU.OAMPriorityRotation)
413 270
 				{
414 271
 					if (PPU.FirstSprite != (PPU.OAMAddr >> 1))
415
-					{
416 272
 						PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
417
-						IPPU.OBJChanged = true;
418
-					#ifdef DEBUGGER
419
-						missing.sprite_priority_rotation = 1;
420
-					#endif
421
-					}
422
-				}
423
-				else
424
-				{
425
-					if (PPU.FirstSprite != 0)
426
-					{
427
-						PPU.FirstSprite = 0;
428
-						IPPU.OBJChanged = true;
429
-					#ifdef DEBUGGER
430
-						missing.sprite_priority_rotation = 1;
431
-					#endif
432
-					}
433 273
 				}
274
+				else if (PPU.FirstSprite)
275
+					PPU.FirstSprite = 0;
434 276
 
435 277
 				PPU.OAMFlip = 0;
436
-				PPU.OAMReadFlip = 0;
437 278
 				PPU.SavedOAMAddr = PPU.OAMAddr;
438 279
 
439 280
 				break;
... ...
@@ -444,176 +285,45 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
444 285
 
445 286
 			case 0x2105: // BGMODE
446 287
 				if (Byte != Memory.FillRAM[0x2105])
447
-				{
448
-					//FLUSH_REDRAW();
449
-					PPU.BG[0].BGSize = (Byte >> 4) & 1;
450
-					PPU.BG[1].BGSize = (Byte >> 5) & 1;
451
-					PPU.BG[2].BGSize = (Byte >> 6) & 1;
452
-					PPU.BG[3].BGSize = (Byte >> 7) & 1;
453
-					PPU.BGMode = Byte & 7;
454
-					// BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set
455
-					PPU.BG3Priority = ((Byte & 0x0f) == 0x09);
456
-					IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
457
-				#ifdef DEBUGGER
458
-					missing.modes[PPU.BGMode] = 1;
459
-				#endif
460
-				}
461
-
462
-				break;
463
-
464
-			case 0x2106: // MOSAIC
465
-				if (Byte != Memory.FillRAM[0x2106])
466
-				{
467
-					//FLUSH_REDRAW();
468
-					PPU.MosaicStart = CPU.V_Counter;
469
-					if (PPU.MosaicStart > PPU.ScreenHeight)
470
-						PPU.MosaicStart = 0;
471
-					PPU.Mosaic = (Byte >> 4) + 1;
472
-					PPU.BGMosaic[0] = (Byte & 1);
473
-					PPU.BGMosaic[1] = !!(Byte & 2);
474
-					PPU.BGMosaic[2] = !!(Byte & 4);
475
-					PPU.BGMosaic[3] = !!(Byte & 8);
476
-				#ifdef DEBUGGER
477
-					if ((Byte & 0xf0) && (Byte & 0x0f))
478
-						missing.mosaic = 1;
479
-				#endif
480
-				}
481
-
482
-				break;
483
-
484
-			case 0x2107: // BG1SC
485
-				if (Byte != Memory.FillRAM[0x2107])
486
-				{
487
-					//FLUSH_REDRAW();
488
-					PPU.BG[0].SCSize = Byte & 3;
489
-					PPU.BG[0].SCBase = (Byte & 0x7c) << 8;
490
-				}
491
-
492
-				break;
493
-
494
-			case 0x2108: // BG2SC
495
-				if (Byte != Memory.FillRAM[0x2108])
496
-				{
497
-					//FLUSH_REDRAW();
498
-					PPU.BG[1].SCSize = Byte & 3;
499
-					PPU.BG[1].SCBase = (Byte & 0x7c) << 8;
500
-				}
501
-
502
-				break;
503
-
504
-			case 0x2109: // BG3SC
505
-				if (Byte != Memory.FillRAM[0x2109])
506
-				{
507
-					//FLUSH_REDRAW();
508
-					PPU.BG[2].SCSize = Byte & 3;
509
-					PPU.BG[2].SCBase = (Byte & 0x7c) << 8;
510
-				}
511
-
512
-				break;
513
-
514
-			case 0x210a: // BG4SC
515
-				if (Byte != Memory.FillRAM[0x210a])
516
-				{
517
-					//FLUSH_REDRAW();
518
-					PPU.BG[3].SCSize = Byte & 3;
519
-					PPU.BG[3].SCBase = (Byte & 0x7c) << 8;
520
-				}
521
-
522
-				break;
523
-
524
-			case 0x210b: // BG12NBA
525
-				if (Byte != Memory.FillRAM[0x210b])
526
-				{
527
-					//FLUSH_REDRAW();
528
-					PPU.BG[0].NameBase = (Byte & 7) << 12;
529
-					PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12;
530
-				}
531
-
532
-				break;
533
-
534
-			case 0x210c: // BG34NBA
535
-				if (Byte != Memory.FillRAM[0x210c])
536
-				{
537
-					//FLUSH_REDRAW();
538
-					PPU.BG[2].NameBase = (Byte & 7) << 12;
539
-					PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12;
540
-				}
288
+					IPPU.Interlace = !!(Memory.FillRAM[0x2133] & 1);
541 289
 
542 290
 				break;
543 291
 
544 292
 			case 0x210d: // BG1HOFS, M7HOFS
545
-				PPU.BG[0].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[0].HOffset >> 8) & 7);
546
-				PPU.M7HOFS = (Byte << 8) | PPU.M7byte;
547
-				PPU.BGnxOFSbyte = Byte;
548 293
 				PPU.M7byte = Byte;
549 294
 				break;
550 295
 
551 296
 			case 0x210e: // BG1VOFS, M7VOFS
552
-				PPU.BG[0].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
553
-				PPU.M7VOFS = (Byte << 8) | PPU.M7byte;
554
-				PPU.BGnxOFSbyte = Byte;
555 297
 				PPU.M7byte = Byte;
556 298
 				break;
557 299
 
558
-			case 0x210f: // BG2HOFS
559
-				PPU.BG[1].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[1].HOffset >> 8) & 7);
560
-				PPU.BGnxOFSbyte = Byte;
561
-				break;
562
-
563
-			case 0x2110: // BG2VOFS
564
-				PPU.BG[1].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
565
-				PPU.BGnxOFSbyte = Byte;
566
-				break;
567
-
568
-			case 0x2111: // BG3HOFS
569
-				PPU.BG[2].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[2].HOffset >> 8) & 7);
570
-				PPU.BGnxOFSbyte = Byte;
571
-				break;
572
-
573
-			case 0x2112: // BG3VOFS
574
-				PPU.BG[2].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
575
-				PPU.BGnxOFSbyte = Byte;
576
-				break;
577
-
578
-			case 0x2113: // BG4HOFS
579
-				PPU.BG[3].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[3].HOffset >> 8) & 7);
580
-				PPU.BGnxOFSbyte = Byte;
581
-				break;
582
-
583
-			case 0x2114: // BG4VOFS
584
-				PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
585
-				PPU.BGnxOFSbyte = Byte;
586
-				break;
587
-
588 300
 			case 0x2115: // VMAIN
589
-				PPU.VMA.High = (Byte & 0x80) == 0 ? false : true;
301
+				PPU.VMA.High = !!(Byte & 0x80);
590 302
 				switch (Byte & 3)
591 303
 				{
592
-					case 0: PPU.VMA.Increment = 1;   break;
593
-					case 1: PPU.VMA.Increment = 32;  break;
594
-					case 2: PPU.VMA.Increment = 128; break;
595
-					case 3: PPU.VMA.Increment = 128; break;
304
+					case 0:
305
+						PPU.VMA.Increment = 1;
306
+						break;
307
+					case 1:
308
+						PPU.VMA.Increment = 32;
309
+						break;
310
+					case 2:
311
+					case 3:
312
+						PPU.VMA.Increment = 128;
596 313
 				}
597 314
 
598 315
 				if (Byte & 0x0c)
599 316
 				{
600
-					static uint16_t Shift[4]    = { 0, 5, 6, 7 };
601
-					static uint16_t IncCount[4] = { 0, 32, 64, 128 };
317
+					static const uint16_t Shift[] = { 0, 5, 6, 7 };
318
+					static const uint16_t IncCount[] = { 0, 32, 64, 128 };
602 319
 
603 320
 					uint8_t i = (Byte & 0x0c) >> 2;
604 321
 					PPU.VMA.FullGraphicCount = IncCount[i];
605 322
 					PPU.VMA.Mask1 = IncCount[i] * 8 - 1;
606 323
 					PPU.VMA.Shift = Shift[i];
607
-				#ifdef DEBUGGER
608
-					missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2;
609
-				#endif
610 324
 				}
611 325
 				else
612 326
 					PPU.VMA.FullGraphicCount = 0;
613
-			#ifdef DEBUGGER
614
-				if (Byte & 3)
615
-					missing.vram_inc = Byte & 3;
616
-			#endif
617 327
 				break;
618 328
 
619 329
 			case 0x2116: // VMADDL
... ...
@@ -625,10 +335,10 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
625 335
 					uint32_t addr = PPU.VMA.Address;
626 336
 					uint32_t rem = addr & PPU.VMA.Mask1;
627 337
 					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
628
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
338
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
629 339
 				}
630 340
 				else
631
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
341
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
632 342
 
633 343
 				break;
634 344
 
... ...
@@ -641,10 +351,10 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
641 351
 					uint32_t addr = PPU.VMA.Address;
642 352
 					uint32_t rem = addr & PPU.VMA.Mask1;
643 353
 					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
644
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
354
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
645 355
 				}
646 356
 				else
647
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
357
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
648 358
 
649 359
 				break;
650 360
 
... ...
@@ -656,19 +366,6 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
656 366
 				REGISTER_2119(Byte);
657 367
 				break;
658 368
 
659
-			case 0x211a: // M7SEL
660
-				if (Byte != Memory.FillRAM[0x211a])
661
-				{
662
-					//FLUSH_REDRAW();
663
-					PPU.Mode7Repeat = Byte >> 6;
664
-					if (PPU.Mode7Repeat == 1)
665
-						PPU.Mode7Repeat = 0;
666
-					PPU.Mode7VFlip = !!((Byte & 2) >> 1);
667
-					PPU.Mode7HFlip = Byte & 1;
668
-				}
669
-
670
-				break;
671
-
672 369
 			case 0x211b: // M7A
673 370
 				PPU.MatrixA = PPU.M7byte | (Byte << 8);
674 371
 				PPU.Need16x8Mulitply = true;
... ...
@@ -682,330 +379,31 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
682 379
 				break;
683 380
 
684 381
 			case 0x211d: // M7C
685
-				PPU.MatrixC = PPU.M7byte | (Byte << 8);
686
-				PPU.M7byte = Byte;
687
-				break;
688
-
689 382
 			case 0x211e: // M7D
690
-				PPU.MatrixD = PPU.M7byte | (Byte << 8);
691
-				PPU.M7byte = Byte;
692
-				break;
693
-
694 383
 			case 0x211f: // M7X
695
-				PPU.CentreX = PPU.M7byte | (Byte << 8);
696
-				PPU.M7byte = Byte;
697
-				break;
698
-
699 384
 			case 0x2120: // M7Y
700
-				PPU.CentreY = PPU.M7byte | (Byte << 8);
701 385
 				PPU.M7byte = Byte;
702 386
 				break;
703 387
 
704 388
 			case 0x2121: // CGADD
705
-				PPU.CGFLIP = 0;
706
-				PPU.CGFLIPRead = 0;
389
+				PPU.CGFLIPRead = false;
707 390
 				PPU.CGADD = Byte;
708 391
 				break;
709 392
 
710
-			/*case 0x2122: // CGDATA
711
-				REGISTER_2122(Byte);
712
-				break;*/
713
-
714
-			case 0x2123: // W12SEL
715
-				if (Byte != Memory.FillRAM[0x2123])
716
-				{
717
-					//FLUSH_REDRAW();
718
-					PPU.ClipWindow1Enable[0] = !!(Byte & 0x02);
719
-					PPU.ClipWindow1Enable[1] = !!(Byte & 0x20);
720
-					PPU.ClipWindow2Enable[0] = !!(Byte & 0x08);
721
-					PPU.ClipWindow2Enable[1] = !!(Byte & 0x80);
722
-					PPU.ClipWindow1Inside[0] = !(Byte & 0x01);
723
-					PPU.ClipWindow1Inside[1] = !(Byte & 0x10);
724
-					PPU.ClipWindow2Inside[0] = !(Byte & 0x04);
725
-					PPU.ClipWindow2Inside[1] = !(Byte & 0x40);
726
-					PPU.RecomputeClipWindows = true;
727
-				#ifdef DEBUGGER
728
-					if (Byte & 0x80)
729
-						missing.window2[1] = 1;
730
-					if (Byte & 0x20)
731
-						missing.window1[1] = 1;
732
-					if (Byte & 0x08)
733
-						missing.window2[0] = 1;
734
-					if (Byte & 0x02)
735
-						missing.window1[0] = 1;
736
-				#endif
737
-				}
738
-
739
-				break;
740
-
741
-			case 0x2124: // W34SEL
742
-				if (Byte != Memory.FillRAM[0x2124])
743
-				{
744
-					//FLUSH_REDRAW();
745
-					PPU.ClipWindow1Enable[2] = !!(Byte & 0x02);
746
-					PPU.ClipWindow1Enable[3] = !!(Byte & 0x20);
747
-					PPU.ClipWindow2Enable[2] = !!(Byte & 0x08);
748
-					PPU.ClipWindow2Enable[3] = !!(Byte & 0x80);
749
-					PPU.ClipWindow1Inside[2] = !(Byte & 0x01);
750
-					PPU.ClipWindow1Inside[3] = !(Byte & 0x10);
751
-					PPU.ClipWindow2Inside[2] = !(Byte & 0x04);
752
-					PPU.ClipWindow2Inside[3] = !(Byte & 0x40);
753
-					PPU.RecomputeClipWindows = true;
754
-				#ifdef DEBUGGER
755
-					if (Byte & 0x80)
756
-						missing.window2[3] = 1;
757
-					if (Byte & 0x20)
758
-						missing.window1[3] = 1;
759
-					if (Byte & 0x08)
760
-						missing.window2[2] = 1;
761
-					if (Byte & 0x02)
762
-						missing.window1[2] = 1;
763
-				#endif
764
-				}
765
-
766
-				break;
767
-
768
-			case 0x2125: // WOBJSEL
769
-				if (Byte != Memory.FillRAM[0x2125])
770
-				{
771
-					//FLUSH_REDRAW();
772
-					PPU.ClipWindow1Enable[4] = !!(Byte & 0x02);
773
-					PPU.ClipWindow1Enable[5] = !!(Byte & 0x20);
774
-					PPU.ClipWindow2Enable[4] = !!(Byte & 0x08);
775
-					PPU.ClipWindow2Enable[5] = !!(Byte & 0x80);
776
-					PPU.ClipWindow1Inside[4] = !(Byte & 0x01);
777
-					PPU.ClipWindow1Inside[5] = !(Byte & 0x10);
778
-					PPU.ClipWindow2Inside[4] = !(Byte & 0x04);
779
-					PPU.ClipWindow2Inside[5] = !(Byte & 0x40);
780
-					PPU.RecomputeClipWindows = true;
781
-				#ifdef DEBUGGER
782
-					if (Byte & 0x80)
783
-						missing.window2[5] = 1;
784
-					if (Byte & 0x20)
785
-						missing.window1[5] = 1;
786
-					if (Byte & 0x08)
787
-						missing.window2[4] = 1;
788
-					if (Byte & 0x02)
789
-						missing.window1[4] = 1;
790
-				#endif
791
-				}
792
-
793
-				break;
794
-
795
-			case 0x2126: // WH0
796
-				if (Byte != Memory.FillRAM[0x2126])
797
-				{
798
-					//FLUSH_REDRAW();
799
-					PPU.Window1Left = Byte;
800
-					PPU.RecomputeClipWindows = true;
801
-				}
802
-
803
-				break;
804
-
805
-			case 0x2127: // WH1
806
-				if (Byte != Memory.FillRAM[0x2127])
807
-				{
808
-					//FLUSH_REDRAW();
809
-					PPU.Window1Right = Byte;
810
-					PPU.RecomputeClipWindows = true;
811
-				}
812
-
813
-				break;
814
-
815
-			case 0x2128: // WH2
816
-				if (Byte != Memory.FillRAM[0x2128])
817
-				{
818
-					//FLUSH_REDRAW();
819
-					PPU.Window2Left = Byte;
820
-					PPU.RecomputeClipWindows = true;
821
-				}
822
-
823
-				break;
824
-
825
-			case 0x2129: // WH3
826
-				if (Byte != Memory.FillRAM[0x2129])
827
-				{
828
-					//FLUSH_REDRAW();
829
-					PPU.Window2Right = Byte;
830
-					PPU.RecomputeClipWindows = true;
831
-				}
832
-
833
-				break;
834
-
835
-			case 0x212a: // WBGLOG
836
-				if (Byte != Memory.FillRAM[0x212a])
837
-				{
838
-					//FLUSH_REDRAW();
839
-					PPU.ClipWindowOverlapLogic[0] = (Byte & 0x03);
840
-					PPU.ClipWindowOverlapLogic[1] = (Byte & 0x0c) >> 2;
841
-					PPU.ClipWindowOverlapLogic[2] = (Byte & 0x30) >> 4;
842
-					PPU.ClipWindowOverlapLogic[3] = (Byte & 0xc0) >> 6;
843
-					PPU.RecomputeClipWindows = true;
844
-				}
845
-
846
-				break;
847
-
848
-			case 0x212b: // WOBJLOG
849
-				if (Byte != Memory.FillRAM[0x212b])
850
-				{
851
-					//FLUSH_REDRAW();
852
-					PPU.ClipWindowOverlapLogic[4] = (Byte & 0x03);
853
-					PPU.ClipWindowOverlapLogic[5] = (Byte & 0x0c) >> 2;
854
-					PPU.RecomputeClipWindows = true;
855
-				}
856
-
857
-				break;
858
-
859
-			case 0x212c: // TM
860
-				if (Byte != Memory.FillRAM[0x212c])
861
-				{
862
-					//FLUSH_REDRAW();
863
-					PPU.RecomputeClipWindows = true;
864
-				}
865
-
866
-				break;
867
-
868
-			case 0x212d: // TS
869
-				if (Byte != Memory.FillRAM[0x212d])
870
-				{
871
-					//FLUSH_REDRAW();
872
-					PPU.RecomputeClipWindows = true;
873
-				#ifdef DEBUGGER
874
-					if (Byte & 0x1f)
875
-						missing.subscreen = 1;
876
-				#endif
877
-				}
878
-
879
-				break;
880
-
881
-			case 0x212e: // TMW
882
-				if (Byte != Memory.FillRAM[0x212e])
883
-				{
884
-					//FLUSH_REDRAW();
885
-					PPU.RecomputeClipWindows = true;
886
-				}
887
-
888
-				break;
889
-
890
-			case 0x212f: // TSW
891
-				if (Byte != Memory.FillRAM[0x212f])
892
-				{
893
-					//FLUSH_REDRAW();
894
-					PPU.RecomputeClipWindows = true;
895
-				}
896
-
897
-				break;
898
-
899
-			case 0x2130: // CGWSEL
900
-				if (Byte != Memory.FillRAM[0x2130])
901
-				{
902
-					//FLUSH_REDRAW();
903
-					PPU.RecomputeClipWindows = true;
904
-				#ifdef DEBUGGER
905
-					if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7))
906
-						missing.direct = 1;
907
-				#endif
908
-				}
909
-
910
-				break;
911
-
912
-			case 0x2131: // CGADSUB
913
-				if (Byte != Memory.FillRAM[0x2131])
914
-				{
915
-					//FLUSH_REDRAW();
916
-				#ifdef DEBUGGER
917
-					if (Byte & 0x80)
918
-					{
919
-						if (Memory.FillRAM[0x2130] & 0x02)
920
-							missing.subscreen_sub = 1;
921
-						else
922
-							missing.fixed_colour_sub = 1;
923
-					}
924
-					else
925
-					{
926
-						if (Memory.FillRAM[0x2130] & 0x02)
927
-							missing.subscreen_add = 1;
928
-						else
929
-							missing.fixed_colour_add = 1;
930
-					}
931
-				#endif
932
-				}
933
-
934
-				break;
935
-
936
-			case 0x2132: // COLDATA
937
-				if (Byte != Memory.FillRAM[0x2132])
938
-				{
939
-					//FLUSH_REDRAW();
940
-					if (Byte & 0x80)
941
-						PPU.FixedColourBlue  = Byte & 0x1f;
942
-					if (Byte & 0x40)
943
-						PPU.FixedColourGreen = Byte & 0x1f;
944
-					if (Byte & 0x20)
945
-						PPU.FixedColourRed   = Byte & 0x1f;
946
-				}
947
-
948
-				break;
949
-
950 393
 			case 0x2133: // SETINI
951 394
 				if (Byte != Memory.FillRAM[0x2133])
952 395
 				{
953
-					if ((Memory.FillRAM[0x2133] ^ Byte) & 8)
954
-					{
955
-						//FLUSH_REDRAW();
956
-						IPPU.PseudoHires = !!(Byte & 8);
957
-					}
958
-
959 396
 					if (Byte & 0x04)
960
-					{
961 397
 						PPU.ScreenHeight = SNES_HEIGHT_EXTENDED;
962
-						if (IPPU.DoubleHeightPixels)
963
-							IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
964
-						else
965
-							IPPU.RenderedScreenHeight = PPU.ScreenHeight;
966
-					#ifdef DEBUGGER
967
-						missing.lines_239 = 1;
968
-					#endif
969
-					}
970 398
 					else
971 399
 						PPU.ScreenHeight = SNES_HEIGHT;
972 400
 
973 401
 					if ((Memory.FillRAM[0x2133] ^ Byte) & 3)
974
-					{
975
-						//FLUSH_REDRAW();
976
-						if ((Memory.FillRAM[0x2133] ^ Byte) & 2)
977
-							IPPU.OBJChanged = true;
978
-						IPPU.Interlace = Byte & 1;
979
-						IPPU.InterlaceOBJ = !!(Byte & 2);
980
-					}
981
-				#ifdef DEBUGGER
982
-					if (Byte & 0x40)
983
-						missing.mode7_bgmode = 1;
984
-					if (Byte & 0x08)
985
-						missing.pseudo_512 = 1;
986
-					if (Byte & 0x02)
987
-						missing.sprite_double_height = 1;
988
-					if (Byte & 0x01)
989
-						missing.interlace = 1;
990
-				#endif
402
+						IPPU.Interlace = !!(Byte & 1);
991 403
 				}
992 404
 
993 405
 				break;
994 406
 
995
-			case 0x2134: // MPYL
996
-			case 0x2135: // MPYM
997
-			case 0x2136: // MPYH
998
-			case 0x2137: // SLHV
999
-			case 0x2138: // OAMDATAREAD
1000
-			case 0x2139: // VMDATALREAD
1001
-			case 0x213a: // VMDATAHREAD
1002
-			case 0x213b: // CGDATAREAD
1003
-			case 0x213c: // OPHCT
1004
-			case 0x213d: // OPVCT
1005
-			case 0x213e: // STAT77
1006
-			case 0x213f: // STAT78
1007
-				return;
1008
-
1009 407
 			case 0x2180: // WMDATA
1010 408
 				if (!CPU.InWRAMDMAorHDMA)
1011 409
 					REGISTER_2180(Byte);
... ...
@@ -1040,45 +438,11 @@ void S9xSetPPU (uint8_t Byte, uint16_t Address)
1040 438
 				break;
1041 439
 		}
1042 440
 	}
1043
-	/*else
1044
-	{
1045
-		if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff)
1046
-		{
1047
-			S9xSetSuperFX(Byte, Address);
1048
-			return;
1049
-		}
1050
-		else
1051
-		if (Settings.SA1     && Address >= 0x2200)
1052
-		{
1053
-			if (Address <= 0x23ff)
1054
-				S9xSetSA1(Byte, Address);
1055
-			else
1056
-				Memory.FillRAM[Address] = Byte;
1057
-			return;
1058
-		}
1059
-		else
1060
-		if (Settings.BS      && Address >= 0x2188 && Address <= 0x219f)
1061
-			S9xSetBSXPPU(Byte, Address);
1062
-		else
1063
-		if (Settings.SRTC    && Address == 0x2801)
1064
-			S9xSetSRTC(Byte, Address);
1065
-	#ifdef DEBUGGER
1066
-		else
1067
-		{
1068
-			missing.unknownppu_write = Address;
1069
-			if (Settings.TraceUnknownRegisters)
1070
-			{
1071
-				sprintf(String, "Unknown register write: $%02X->$%04X\n", Byte, Address);
1072
-				S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
1073
-			}
1074
-		}
1075
-	#endif
1076
-	}*/
1077 441
 
1078 442
 	Memory.FillRAM[Address] = Byte;
1079 443
 }
1080 444
 
1081
-uint8_t S9xGetPPU (uint16_t Address)
445
+uint8_t S9xGetPPU(uint16_t Address)
1082 446
 {
1083 447
 	// MAP_PPU: $2000-$3FFF
1084 448
 
... ...
@@ -1088,17 +452,8 @@ uint8_t S9xGetPPU (uint16_t Address)
1088 452
 	if (CPU.InDMAorHDMA)
1089 453
 	{
1090 454
 		if (CPU.CurrentDMAorHDMAChannel >= 0 && !DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer)
1091
-		{
1092 455
 			// S9xGetPPU() is called to read from DMA[].AAddress
1093
-			if ((Address & 0xff00) == 0x2100)
1094
-				// Cannot access to Address Bus B ($2100-$21FF) via (H)DMA
1095
-				return OpenBus;
1096
-			else
1097
-				// $2200-$3FFF are connected to Address Bus A
1098
-				// SA1, SuperFX and SRTC are mapped here
1099
-				// I don't bother for now...
1100
-				return OpenBus;
1101
-		}
456
+			return OpenBus;
1102 457
 		else
1103 458
 		{
1104 459
 			// S9xGetPPU() is called to write to $21xx
... ...
@@ -1111,10 +466,9 @@ uint8_t S9xGetPPU (uint16_t Address)
1111 466
 	if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3
1112 467
 		// read_port will run the APU until given APU time before reading value
1113 468
 		return S9xAPUReadPort(Address & 3);
1114
-	else
1115
-	if (Address <= 0x2183)
1116
-    {
1117
-		uint8_t	byte;
469
+	else if (Address <= 0x2183)
470
+	{
471
+		uint8_t byte;
1118 472
 
1119 473
 		switch (Address)
1120 474
 		{
... ...
@@ -1143,19 +497,15 @@ uint8_t S9xGetPPU (uint16_t Address)
1143 497
 			case 0x2136: // MPYH
1144 498
 				if (PPU.Need16x8Mulitply)
1145 499
 				{
1146
-					int32_t r = (int32_t) PPU.MatrixA * (int32_t) (PPU.MatrixB >> 8);
1147
-					Memory.FillRAM[0x2134] = (uint8_t) r;
1148
-					Memory.FillRAM[0x2135] = (uint8_t) (r >> 8);
1149
-					Memory.FillRAM[0x2136] = (uint8_t) (r >> 16);
500
+					int32_t r = static_cast<int32_t>(PPU.MatrixA) * static_cast<int32_t>(PPU.MatrixB >> 8);
501
+					Memory.FillRAM[0x2134] = static_cast<uint8_t>(r);
502
+					Memory.FillRAM[0x2135] = static_cast<uint8_t>(r >> 8);
503
+					Memory.FillRAM[0x2136] = static_cast<uint8_t>(r >> 16);
1150 504
 					PPU.Need16x8Mulitply = false;
1151 505
 				}
1152
-			#ifdef DEBUGGER
1153
-				missing.matrix_multiply = 1;
1154
-			#endif
1155 506
 				return (PPU.OpenBus1 = Memory.FillRAM[Address]);
1156 507
 
1157 508
 			case 0x2137: // SLHV
1158
-				S9xLatchCounters(0);
1159 509
 				return OpenBus;
1160 510
 
1161 511
 			case 0x2138: // OAMDATAREAD
... ...
@@ -1168,13 +518,7 @@ uint8_t S9xGetPPU (uint16_t Address)
1168 518
 						byte = PPU.OAMData[((PPU.OAMAddr & 0x10f) << 1) + 1];
1169 519
 						PPU.OAMAddr = (PPU.OAMAddr + 1) & 0x1ff;
1170 520
 						if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
1171
-						{
1172 521
 							PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
1173
-							IPPU.OBJChanged = true;
1174
-						#ifdef DEBUGGER
1175
-							missing.sprite_priority_rotation = 1;
1176
-						#endif
1177
-						}
1178 522
 					}
1179 523
 				}
1180 524
 				else
... ...
@@ -1186,20 +530,11 @@ uint8_t S9xGetPPU (uint16_t Address)
1186 530
 						byte = PPU.OAMData[(PPU.OAMAddr << 1) + 1];
1187 531
 						++PPU.OAMAddr;
1188 532
 						if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
1189
-						{
1190 533
 							PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
1191
-							IPPU.OBJChanged = true;
1192
-						#ifdef DEBUGGER
1193
-							missing.sprite_priority_rotation = 1;
1194
-						#endif
1195
-						}
1196 534
 					}
1197 535
 				}
1198 536
 
1199 537
 				PPU.OAMFlip ^= 1;
1200
-			#ifdef DEBUGGER
1201
-				missing.oam_read = 1;
1202
-			#endif
1203 538
 				return (PPU.OpenBus1 = byte);
1204 539
 
1205 540
 			case 0x2139: // VMDATALREAD
... ...
@@ -1211,17 +546,13 @@ uint8_t S9xGetPPU (uint16_t Address)
1211 546
 						uint32_t addr = PPU.VMA.Address;
1212 547
 						uint32_t rem = addr & PPU.VMA.Mask1;
1213 548
 						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
1214
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
549
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
1215 550
 					}
1216 551
 					else
1217
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
552
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
1218 553
 
1219 554
 					PPU.VMA.Address += PPU.VMA.Increment;
1220 555
 				}
1221
-
1222
-			#ifdef DEBUGGER
1223
-				missing.vram_read = 1;
1224
-			#endif
1225 556
 				return (PPU.OpenBus1 = byte);
1226 557
 
1227 558
 			case 0x213a: // VMDATAHREAD
... ...
@@ -1233,16 +564,13 @@ uint8_t S9xGetPPU (uint16_t Address)
1233 564
 						uint32_t addr = PPU.VMA.Address;
1234 565
 						uint32_t rem = addr & PPU.VMA.Mask1;
1235 566
 						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
1236
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
567
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
1237 568
 					}
1238 569
 					else
1239
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
570
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
1240 571
 
1241 572
 					PPU.VMA.Address += PPU.VMA.Increment;
1242 573
 				}
1243
-			#ifdef DEBUGGER
1244
-				missing.vram_read = 1;
1245
-			#endif
1246 574
 				return (PPU.OpenBus1 = byte);
1247 575
 
1248 576
 			case 0x213b: // CGDATAREAD
... ...
@@ -1250,44 +578,31 @@ uint8_t S9xGetPPU (uint16_t Address)
1250 578
 					byte = (PPU.OpenBus2 & 0x80) | ((PPU.CGDATA[PPU.CGADD++] >> 8) & 0x7f);
1251 579
 				else
1252 580
 					byte = PPU.CGDATA[PPU.CGADD] & 0xff;
1253
-				PPU.CGFLIPRead ^= 1;
1254
-			#ifdef DEBUGGER
1255
-				missing.cgram_read = 1;
1256
-			#endif
581
+				PPU.CGFLIPRead = !PPU.CGFLIPRead;
1257 582
 				return (PPU.OpenBus2 = byte);
1258 583
 
1259 584
 			case 0x213c: // OPHCT
1260
-				S9xTryGunLatch(false);
1261 585
 				if (PPU.HBeamFlip)
1262
-					byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01);
586
+					byte = PPU.OpenBus2 & 0xfe;
1263 587
 				else
1264
-					byte = (uint8_t) PPU.HBeamPosLatched;
1265
-				PPU.HBeamFlip ^= 1;
1266
-			#ifdef DEBUGGER
1267
-				missing.h_counter_read = 1;
1268
-			#endif
588
+					byte = 0;
589
+				PPU.HBeamFlip = !PPU.HBeamFlip;
1269 590
 				return (PPU.OpenBus2 = byte);
1270 591
 
1271 592
 			case 0x213d: // OPVCT
1272
-				S9xTryGunLatch(false);
1273 593
 				if (PPU.VBeamFlip)
1274
-					byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01);
594
+					byte = PPU.OpenBus2 & 0xfe;
1275 595
 				else
1276
-					byte = (uint8_t) PPU.VBeamPosLatched;
1277
-				PPU.VBeamFlip ^= 1;
1278
-			#ifdef DEBUGGER
1279
-				missing.v_counter_read = 1;
1280
-			#endif
596
+					byte = 0;
597
+				PPU.VBeamFlip = !PPU.VBeamFlip;
1281 598
 				return (PPU.OpenBus2 = byte);
1282 599
 
1283 600
 			case 0x213e: // STAT77
1284
-				//FLUSH_REDRAW();
1285
-				byte = (PPU.OpenBus1 & 0x10) | PPU.RangeTimeOver | Model->_5C77;
601
+				byte = (PPU.OpenBus1 & 0x10) | Model->_5C77;
1286 602
 				return (PPU.OpenBus1 = byte);
1287 603
 
1288 604
 			case 0x213f: // STAT78
1289
-				S9xTryGunLatch(false);
1290
-				PPU.VBeamFlip = PPU.HBeamFlip = 0;
605
+				PPU.VBeamFlip = PPU.HBeamFlip = false;
1291 606
 				byte = (PPU.OpenBus2 & 0x20) | (Memory.FillRAM[0x213f] & 0xc0) | (Settings.PAL ? 0x10 : 0) | Model->_5C78;
1292 607
 				Memory.FillRAM[0x213f] &= ~0x40;
1293 608
 				return (PPU.OpenBus2 = byte);
... ...
@@ -1300,9 +615,6 @@ uint8_t S9xGetPPU (uint16_t Address)
1300 615
 				}
1301 616
 				else
1302 617
 					byte = OpenBus;
1303
-			#ifdef DEBUGGER
1304
-				missing.wram_read = 1;
1305
-			#endif
1306 618
 				return byte;
1307 619
 
1308 620
 			default:
... ...
@@ -1310,19 +622,7 @@ uint8_t S9xGetPPU (uint16_t Address)
1310 622
 		}
1311 623
 	}
1312 624
 	else
1313
-    {
1314
-		/*if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff)
1315
-			return S9xGetSuperFX(Address);
1316
-		else
1317
-		if (Settings.SA1     && Address >= 0x2200)
1318
-			return S9xGetSA1(Address);
1319
-		else
1320
-		if (Settings.BS      && Address >= 0x2188 && Address <= 0x219f)
1321
-			return S9xGetBSXPPU(Address);
1322
-		else	
1323
-		if (Settings.SRTC    && Address == 0x2800)
1324
-			return S9xGetSRTC(Address);
1325
-		else*/
625
+	{
1326 626
 		switch (Address)
1327 627
 		{
1328 628
 			case 0x21c2:
... ...
@@ -1341,40 +641,24 @@ uint8_t S9xGetPPU (uint16_t Address)
1341 641
 	}
1342 642
 }
1343 643
 
1344
-void S9xSetCPU (uint8_t Byte, uint16_t Address)
644
+void S9xSetCPU(uint8_t Byte, uint16_t Address)
1345 645
 {
1346
-	if (Address < 0x4200)
1347
-	{
1348
-		/*switch (Address)
1349
-		{
1350
-			case 0x4016: // JOYSER0
1351
-				S9xSetJoypadLatch(Byte & 1);
1352
-				break;
1353
-
1354
-			case 0x4017: // JOYSER1
1355
-				return;
1356
-
1357
-			default:
1358
-				break;
1359
-		}*/
1360
-	}
1361
-	else
1362 646
 	if ((Address & 0xff80) == 0x4300)
1363 647
 	{
1364 648
 		if (CPU.InDMAorHDMA)
1365 649
 			return;
1366 650
 
1367
-		int	d = (Address >> 4) & 0x7;
651
+		int d = (Address >> 4) & 0x7;
1368 652
 
1369 653
 		switch (Address & 0xf)
1370 654
 		{
1371 655
 			case 0x0: // 0x43x0: DMAPx
1372
-				DMA[d].ReverseTransfer        = (Byte & 0x80) ? true : false;
1373
-				DMA[d].HDMAIndirectAddressing = (Byte & 0x40) ? true : false;
1374
-				DMA[d].UnusedBit43x0          = (Byte & 0x20) ? true : false;
1375
-				DMA[d].AAddressDecrement      = (Byte & 0x10) ? true : false;
1376
-				DMA[d].AAddressFixed          = (Byte & 0x08) ? true : false;
1377
-				DMA[d].TransferMode           = (Byte & 7);
656
+				DMA[d].ReverseTransfer = !!(Byte & 0x80);
657
+				DMA[d].HDMAIndirectAddressing = !!(Byte & 0x40);
658
+				DMA[d].UnusedBit43x0 = !!(Byte & 0x20);
659
+				DMA[d].AAddressDecrement = !!(Byte & 0x10);
660
+				DMA[d].AAddressFixed = !!(Byte & 0x08);
661
+				DMA[d].TransferMode = (Byte & 7);
1378 662
 				return;
1379 663
 
1380 664
 			case 0x1: // 0x43x1: BBADx
... ...
@@ -1393,36 +677,36 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1393 677
 
1394 678
 			case 0x4: // 0x43x4: A1Bx
1395 679
 				DMA[d].ABank = Byte;
1396
-				HDMAMemPointers[d] = NULL;
680
+				HDMAMemPointers[d] = nullptr;
1397 681
 				return;
1398 682
 
1399 683
 			case 0x5: // 0x43x5: DASxL
1400 684
 				DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00;
1401 685
 				DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte;
1402
-				HDMAMemPointers[d] = NULL;
686
+				HDMAMemPointers[d] = nullptr;
1403 687
 				return;
1404 688
 
1405 689
 			case 0x6: // 0x43x6: DASxH
1406 690
 				DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff;
1407 691
 				DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte << 8;
1408
-				HDMAMemPointers[d] = NULL;
692
+				HDMAMemPointers[d] = nullptr;
1409 693
 				return;
1410 694
 
1411 695
 			case 0x7: // 0x43x7: DASBx
1412 696
 				DMA[d].IndirectBank = Byte;
1413
-				HDMAMemPointers[d] = NULL;
697
+				HDMAMemPointers[d] = nullptr;
1414 698
 				return;
1415 699
 
1416 700
 			case 0x8: // 0x43x8: A2AxL
1417 701
 				DMA[d].Address &= 0xff00;
1418 702
 				DMA[d].Address |= Byte;
1419
-				HDMAMemPointers[d] = NULL;
703
+				HDMAMemPointers[d] = nullptr;
1420 704
 				return;
1421 705
 
1422 706
 			case 0x9: // 0x43x9: A2AxH
1423 707
 				DMA[d].Address &= 0xff;
1424 708
 				DMA[d].Address |= Byte << 8;
1425
-				HDMAMemPointers[d] = NULL;
709
+				HDMAMemPointers[d] = nullptr;
1426 710
 				return;
1427 711
 
1428 712
 			case 0xa: // 0x43xa: NLTRx
... ...
@@ -1443,94 +727,57 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1443 727
 			case 0xf: // 0x43xf: mirror of 0x43xb
1444 728
 				DMA[d].UnknownByte = Byte;
1445 729
 				return;
1446
-
1447
-			default:
1448
-				break;
1449 730
 		}
1450 731
 	}
1451
-	else
732
+	else if (Address >= 0x4200)
1452 733
 	{
1453
-		uint16_t	pos;
734
+		uint16_t pos;
1454 735
 
1455 736
 		switch (Address)
1456 737
 		{
1457 738
 			case 0x4200: // NMITIMEN
1458
-				if (Byte & 0x20)
1459
-				{
1460
-					PPU.VTimerEnabled = true;
1461
-				#ifdef DEBUGGER
1462
-					missing.virq = 1;
1463
-					missing.virq_pos = PPU.IRQVBeamPos;
1464
-				#endif
1465
-				}
1466
-				else
1467
-					PPU.VTimerEnabled = false;
1468
-
1469
-				if (Byte & 0x10)
1470
-				{
1471
-					PPU.HTimerEnabled = true;
1472
-				#ifdef DEBUGGER
1473
-					missing.hirq = 1;
1474
-					missing.hirq_pos = PPU.IRQHBeamPos;
1475
-				#endif
1476
-				}
1477
-				else
1478
-					PPU.HTimerEnabled = false;
739
+				PPU.VTimerEnabled = !!(Byte & 0x20);
740
+				PPU.HTimerEnabled = !!(Byte & 0x10);
1479 741
 
1480 742
 				if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled)
1481 743
 					CPU.IRQTransition = true;
1482 744
 
1483 745
 				if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
1484
-				{
1485
-					CPU.IRQLine = false;
1486
-					CPU.IRQTransition = false;
1487
-				}
746
+					CPU.IRQLine = CPU.IRQTransition = false;
1488 747
 
1489 748
 				// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
1490
-				if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
1491
-					(CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80))
749
+				if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && (Memory.FillRAM[0x4210] & 0x80))
1492 750
 				{
1493 751
 					// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
1494 752
 					// then, when to call S9xOpcode_NMI()?
1495 753
 					CPU.NMILine = true;
1496
-					Timings.NMITriggerPos = CPU.Cycles + 6 + 6;
754
+					Timings.NMITriggerPos = CPU.Cycles + 12;
1497 755
 				}
1498 756
 
1499 757
 				break;
1500 758
 
1501 759
 			case 0x4201: // WRIO
1502
-				if ((Byte & 0x80) == 0 && (Memory.FillRAM[0x4213] & 0x80) == 0x80)
1503
-					S9xLatchCounters(1);
1504
-				else
1505
-					S9xTryGunLatch((Byte & 0x80) ? true : false);
1506 760
 				Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = Byte;
1507 761
 				break;
1508 762
 
1509
-			case 0x4202: // WRMPYA
1510
-				break;
1511
-
1512 763
 			case 0x4203: // WRMPYB
1513 764
 			{
1514 765
 				uint32_t res = Memory.FillRAM[0x4202] * Byte;
1515 766
 				// FIXME: The update occurs 8 machine cycles after $4203 is set.
1516
-				Memory.FillRAM[0x4216] = (uint8_t) res;
1517
-				Memory.FillRAM[0x4217] = (uint8_t) (res >> 8);
767
+				Memory.FillRAM[0x4216] = static_cast<uint8_t>(res);
768
+				Memory.FillRAM[0x4217] = static_cast<uint8_t>(res >> 8);
1518 769
 				break;
1519 770
 			}
1520 771
 
1521
-			case 0x4204: // WRDIVL
1522
-			case 0x4205: // WRDIVH
1523
-				break;
1524
-
1525 772
 			case 0x4206: // WRDIVB
1526 773
 			{
1527 774
 				uint16_t a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8);
1528 775
 				uint16_t div = Byte ? a / Byte : 0xffff;
1529 776
 				uint16_t rem = Byte ? a % Byte : a;
1530 777
 				// FIXME: The update occurs 16 machine cycles after $4206 is set.
1531
-				Memory.FillRAM[0x4214] = (uint8_t) div;
778
+				Memory.FillRAM[0x4214] = static_cast<uint8_t>(div);
1532 779
 				Memory.FillRAM[0x4215] = div >> 8;
1533
-				Memory.FillRAM[0x4216] = (uint8_t) rem;
780
+				Memory.FillRAM[0x4216] = static_cast<uint8_t>(rem);
1534 781
 				Memory.FillRAM[0x4217] = rem >> 8;
1535 782
 				break;
1536 783
 			}
... ...
@@ -1540,9 +787,6 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1540 787
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
1541 788
 				if (PPU.IRQHBeamPos != pos)
1542 789
 					S9xUpdateHVTimerPosition();
1543
-			#ifdef DEBUGGER
1544
-				missing.hirq_pos = PPU.IRQHBeamPos;
1545
-			#endif
1546 790
 				break;
1547 791
 
1548 792
 			case 0x4208: // HTIMEH
... ...
@@ -1550,9 +794,6 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1550 794
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
1551 795
 				if (PPU.IRQHBeamPos != pos)
1552 796
 					S9xUpdateHVTimerPosition();
1553
-			#ifdef DEBUGGER
1554
-				missing.hirq_pos = PPU.IRQHBeamPos;
1555
-			#endif
1556 797
 				break;
1557 798
 
1558 799
 			case 0x4209: // VTIMEL
... ...
@@ -1560,9 +801,6 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1560 801
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
1561 802
 				if (PPU.IRQVBeamPos != pos)
1562 803
 					S9xUpdateHVTimerPosition();
1563
-			#ifdef DEBUGGER
1564
-				missing.virq_pos = PPU.IRQVBeamPos;
1565
-			#endif
1566 804
 				break;
1567 805
 
1568 806
 			case 0x420a: // VTIMEH
... ...
@@ -1570,9 +808,6 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1570 808
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
1571 809
 				if (PPU.IRQVBeamPos != pos)
1572 810
 					S9xUpdateHVTimerPosition();
1573
-			#ifdef DEBUGGER
1574
-				missing.virq_pos = PPU.IRQVBeamPos;
1575
-			#endif
1576 811
 				break;
1577 812
 
1578 813
 			case 0x420b: // MDMAEN
... ...
@@ -1597,10 +832,6 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1597 832
 					S9xDoDMA(6);
1598 833
 				if (Byte & 0x80)
1599 834
 					S9xDoDMA(7);
1600
-			#ifdef DEBUGGER
1601
-				missing.dma_this_frame = Byte;
1602
-				missing.dma_channels = Byte;
1603
-			#endif
1604 835
 				break;
1605 836
 
1606 837
 			case 0x420c: // HDMAEN
... ...
@@ -1609,22 +840,13 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1609 840
 				Memory.FillRAM[0x420c] = Byte;
1610 841
 				// Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
1611 842
 				PPU.HDMA = Byte & ~PPU.HDMAEnded;
1612
-			#ifdef DEBUGGER
1613
-				missing.hdma_this_frame |= Byte;
1614
-				missing.hdma_channels |= Byte;
1615
-			#endif
1616 843
 				break;
1617 844
 
1618 845
 			case 0x420d: // MEMSEL
1619 846
 				if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1))
1620 847
 				{
1621 848
 					if (Byte & 1)
1622
-					{
1623 849
 						CPU.FastROMSpeed = ONE_CYCLE;
1624
-					#ifdef DEBUGGER
1625
-						missing.fast_rom = 1;
1626
-					#endif
1627
-					}
1628 850
 					else
1629 851
 						CPU.FastROMSpeed = SLOW_ONE_CYCLE;
1630 852
 				}
... ...
@@ -1650,58 +872,30 @@ void S9xSetCPU (uint8_t Byte, uint16_t Address)
1650 872
 				return;
1651 873
 
1652 874
 			default:
1653
-				/*if (Settings.SPC7110 && Address >= 0x4800)
1654
-					S9xSetSPC7110(Byte, Address);
1655
-				else*/
1656 875
 				if (Settings.SDD1 && Address >= 0x4804 && Address <= 0x4807)
1657 876
 					S9xSetSDD1MemoryMap(Address - 0x4804, Byte & 7);
1658
-				break;
1659 877
 		}
1660 878
 	}
1661 879
 
1662 880
 	Memory.FillRAM[Address] = Byte;
1663 881
 }
1664 882
 
1665
-uint8_t S9xGetCPU (uint16_t Address)
883
+uint8_t S9xGetCPU(uint16_t Address)
1666 884
 {
1667 885
 	if (Address < 0x4200)
1668
-	{
1669
-	#ifdef SNES_JOY_READ_CALLBACKS
1670
-		extern bool pad_read;
1671
-		if (Address == 0x4016 || Address == 0x4017)
1672
-		{
1673
-			S9xOnSNESPadRead();
1674
-			pad_read = true;
1675
-		}
1676
-	#endif
1677
-
1678
-		/*switch (Address)
1679
-		{
1680
-			case 0x4016: // JOYSER0
1681
-			case 0x4017: // JOYSER1
1682
-				return S9xReadJOYSERn(Address);
1683
-
1684
-			default:*/
1685
-				return OpenBus;
1686
-		//}
1687
-	}
1688
-	else
1689
-	if ((Address & 0xff80) == 0x4300)
886
+		return OpenBus;
887
+	else if ((Address & 0xff80) == 0x4300)
1690 888
 	{
1691 889
 		if (CPU.InDMAorHDMA)
1692 890
 			return OpenBus;
1693 891
 
1694
-		int	d = (Address >> 4) & 0x7;
892
+		int d = (Address >> 4) & 0x7;
1695 893
 
1696 894
 		switch (Address & 0xf)
1697 895
 		{
1698 896
 			case 0x0: // 0x43x0: DMAPx
1699
-				return  (DMA[d].ReverseTransfer        ? 0x80 : 0) |
1700
-						(DMA[d].HDMAIndirectAddressing ? 0x40 : 0) |
1701
-						(DMA[d].UnusedBit43x0          ? 0x20 : 0) |
1702
-						(DMA[d].AAddressDecrement      ? 0x10 : 0) |
1703
-						(DMA[d].AAddressFixed          ? 0x08 : 0) |
1704
-						(DMA[d].TransferMode & 7);
897
+				return (DMA[d].ReverseTransfer ? 0x80 : 0) | (DMA[d].HDMAIndirectAddressing ? 0x40 : 0) | (DMA[d].UnusedBit43x0 ? 0x20 : 0) | (DMA[d].AAddressDecrement ? 0x10 : 0) |
898
+					(DMA[d].AAddressFixed ? 0x08 : 0) | (DMA[d].TransferMode & 7);
1705 899
 
1706 900
 			case 0x1: // 0x43x1: BBADx
1707 901
 				return DMA[d].BAddress;
... ...
@@ -1743,7 +937,7 @@ uint8_t S9xGetCPU (uint16_t Address)
1743 937
 	}
1744 938
 	else
1745 939
 	{
1746
-		uint8_t	byte;
940
+		uint8_t byte;
1747 941
 
1748 942
 		switch (Address)
1749 943
 		{
... ...
@@ -1778,19 +972,9 @@ uint8_t S9xGetCPU (uint16_t Address)
1778 972
 			case 0x421d: // JOY3H
1779 973
 			case 0x421e: // JOY4L
1780 974
 			case 0x421f: // JOY4H
1781
-			#ifdef SNES_JOY_READ_CALLBACKS
1782
-				extern bool pad_read;
1783
-				if (Memory.FillRAM[0x4200] & 1)
1784
-				{
1785
-					S9xOnSNESPadRead();
1786
-					pad_read = true;
1787
-				}
1788
-			#endif
1789 975
 				return Memory.FillRAM[Address];
1790 976
 
1791 977
 			default:
1792
-				/*if (Settings.SPC7110 && Address >= 0x4800)
1793
-					return S9xGetSPC7110(Address);*/
1794 978
 				if (Settings.SDD1 && Address >= 0x4800 && Address <= 0x4807)
1795 979
 					return Memory.FillRAM[Address];
1796 980
 				return OpenBus;
... ...
@@ -1801,186 +985,65 @@ uint8_t S9xGetCPU (uint16_t Address)
1801 985
 void S9xResetPPU()
1802 986
 {
1803 987
 	S9xSoftResetPPU();
1804
-	//S9xControlsReset();
1805
-	PPU.M7HOFS = 0;
1806
-	PPU.M7VOFS = 0;
1807 988
 	PPU.M7byte = 0;
1808 989
 }
1809 990
 
1810 991
 void S9xSoftResetPPU()
1811 992
 {
1812
-	//S9xControlsSoftReset();
1813
-
1814
-	PPU.VMA.High = 0;
993
+	PPU.VMA.High = false;
1815 994
 	PPU.VMA.Increment = 1;
1816
-	PPU.VMA.Address = 0;
1817
-	PPU.VMA.FullGraphicCount = 0;
1818
-	PPU.VMA.Shift = 0;
995
+	PPU.VMA.Address = PPU.VMA.FullGraphicCount = PPU.VMA.Shift = 0;
1819 996
 
1820 997
 	PPU.WRAM = 0;
1821 998
 
1822
-	for (int c = 0; c < 4; c++)
1823
-	{
1824
-		PPU.BG[c].SCBase = 0;
1825
-		PPU.BG[c].HOffset = 0;
1826
-		PPU.BG[c].VOffset = 0;
1827
-		PPU.BG[c].BGSize = 0;
1828
-		PPU.BG[c].NameBase = 0;
1829
-		PPU.BG[c].SCSize = 0;
1830
-	}
1831
-
1832
-	PPU.BGMode = 0;
1833
-	PPU.BG3Priority = 0;
1834
-
1835
-	PPU.CGFLIP = 0;
1836
-	PPU.CGFLIPRead = 0;
999
+	PPU.CGFLIPRead = false;
1837 1000
 	PPU.CGADD = 0;
1838 1001
 
1839
-	for (int c = 0; c < 256; c++)
1002
+	for (int c = 0; c < 256; ++c)
1840 1003
 	{
1841
-		IPPU.Red[c]   = (c & 7) << 2;
1004
+		IPPU.Red[c] = (c & 7) << 2;
1842 1005
 		IPPU.Green[c] = ((c >> 3) & 7) << 2;
1843
-		IPPU.Blue[c]  = ((c >> 6) & 2) << 3;
1006
+		IPPU.Blue[c] = ((c >> 6) & 2) << 3;
1844 1007
 		PPU.CGDATA[c] = IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10);
1845 1008
 	}
1846 1009
 
1847
-	for (int c = 0; c < 128; c++)
1848
-	{
1849
-		PPU.OBJ[c].HPos = 0;
1850
-		PPU.OBJ[c].VPos = 0;
1851
-		PPU.OBJ[c].HFlip = 0;
1852
-		PPU.OBJ[c].VFlip = 0;
1853
-		PPU.OBJ[c].Name = 0;
1854
-		PPU.OBJ[c].Priority = 0;
1855
-		PPU.OBJ[c].Palette = 0;
1856
-		PPU.OBJ[c].Size = 0;
1857
-	}
1858
-
1859
-	PPU.OBJThroughMain = false;
1860
-	PPU.OBJThroughSub = false;
1861
-	PPU.OBJAddition = false;
1862
-	PPU.OBJNameBase = 0;
1863
-	PPU.OBJNameSelect = 0;
1864
-	PPU.OBJSizeSelect = 0;
1865
-
1866
-	PPU.OAMAddr = 0;
1867
-	PPU.SavedOAMAddr = 0;
1868
-	PPU.OAMPriorityRotation = 0;
1010
+	PPU.OAMAddr = PPU.SavedOAMAddr = 0;
1011
+	PPU.OAMPriorityRotation = false;
1869 1012
 	PPU.OAMFlip = 0;
1870
-	PPU.OAMReadFlip = 0;
1871
-	PPU.OAMTileAddress = 0;
1872 1013
 	PPU.OAMWriteRegister = 0;
1873
-	ZeroMemory(PPU.OAMData, 512 + 32);
1014
+	std::fill(&PPU.OAMData[0], &PPU.OAMData[512 + 32], 0);
1874 1015
 
1875 1016
 	PPU.FirstSprite = 0;
1876
-	PPU.LastSprite = 127;
1877
-	PPU.RangeTimeOver = 0;
1878 1017
 
1879
-	PPU.HTimerEnabled = false;
1880
-	PPU.VTimerEnabled = false;
1018
+	PPU.HTimerEnabled = PPU.VTimerEnabled = false;
1881 1019
 	PPU.HTimerPosition = Timings.H_Max + 1;
1882 1020
 	PPU.VTimerPosition = Timings.V_Max + 1;
1883
-	PPU.IRQHBeamPos = 0x1ff;
1884
-	PPU.IRQVBeamPos = 0x1ff;
1885
-
1886
-	PPU.HBeamFlip = 0;
1887
-	PPU.VBeamFlip = 0;
1888
-	PPU.HBeamPosLatched = 0;
1889
-	PPU.VBeamPosLatched = 0;
1890
-	PPU.GunHLatch = 0;
1891
-	PPU.GunVLatch = 1000;
1892
-	PPU.HVBeamCounterLatched = 0;
1893
-
1894
-	PPU.Mode7HFlip = false;
1895
-	PPU.Mode7VFlip = false;
1896
-	PPU.Mode7Repeat = 0;
1897
-	PPU.MatrixA = 0;
1898
-	PPU.MatrixB = 0;
1899
-	PPU.MatrixC = 0;
1900
-	PPU.MatrixD = 0;
1901
-	PPU.CentreX = 0;
1902
-	PPU.CentreY = 0;
1903
-
1904
-	PPU.Mosaic = 0;
1905
-	PPU.BGMosaic[0] = false;
1906
-	PPU.BGMosaic[1] = false;
1907
-	PPU.BGMosaic[2] = false;
1908
-	PPU.BGMosaic[3] = false;
1909
-	
1910
-	PPU.Window1Left = 1;
1911
-	PPU.Window1Right = 0;
1912
-	PPU.Window2Left = 1;
1913
-	PPU.Window2Right = 0;
1914
-	PPU.RecomputeClipWindows = true;
1915
-
1916
-	for (int c = 0; c < 6; c++)
1917
-	{
1918
-		PPU.ClipCounts[c] = 0;
1919
-		PPU.ClipWindowOverlapLogic[c] = CLIP_OR;
1920
-		PPU.ClipWindow1Enable[c] = false;
1921
-		PPU.ClipWindow2Enable[c] = false;
1922
-		PPU.ClipWindow1Inside[c] = true;
1923
-		PPU.ClipWindow2Inside[c] = true;
1924
-	}
1021
+	PPU.IRQHBeamPos = PPU.IRQVBeamPos = 0x1ff;
1022
+
1023
+	PPU.HBeamFlip = PPU.VBeamFlip = false;
1024
+
1025
+	PPU.MatrixA = PPU.MatrixB = 0;
1925 1026
 
1926 1027
 	PPU.ForcedBlanking = true;
1927 1028
 
1928
-	PPU.FixedColourRed = 0;
1929
-	PPU.FixedColourGreen = 0;
1930
-	PPU.FixedColourBlue = 0;
1931
-	PPU.Brightness = 0;
1932 1029
 	PPU.ScreenHeight = SNES_HEIGHT;
1933 1030
 
1934 1031
 	PPU.Need16x8Mulitply = false;
1935
-	PPU.BGnxOFSbyte = 0;
1936
-
1937
-	PPU.HDMA = 0;
1938
-	PPU.HDMAEnded = 0;
1939
-
1940
-	PPU.OpenBus1 = 0;
1941
-	PPU.OpenBus2 = 0;
1942
-
1943
-	for (int c = 0; c < 2; c++)
1944
-		memset(&IPPU.Clip[c], 0, sizeof(struct ClipData));
1945
-	IPPU.ColorsChanged = true;
1946
-	IPPU.OBJChanged = true;
1947
-	IPPU.DirectColourMapsNeedRebuild = true;
1948
-	ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES);
1949
-	ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES);
1950
-	ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES);
1951
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES);
1952
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD],  MAX_2BIT_TILES);
1953
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
1954
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD],  MAX_4BIT_TILES);
1032
+
1033
+	PPU.HDMA = PPU.HDMAEnded = 0;
1034
+
1035
+	PPU.OpenBus1 = PPU.OpenBus2 = 0;
1036
+
1955 1037
 	IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
1956 1038
 	IPPU.Interlace = false;
1957
-	IPPU.InterlaceOBJ = false;
1958
-	IPPU.DoubleWidthPixels = false;
1959
-	IPPU.DoubleHeightPixels = false;
1960
-	IPPU.CurrentLine = 0;
1961
-	IPPU.PreviousLine = 0;
1962
-	IPPU.XB = NULL;
1963
-	for (int c = 0; c < 256; c++)
1964
-		IPPU.ScreenColors[c] = c;
1965
-	IPPU.MaxBrightness = 0;
1966
-	IPPU.RenderThisFrame = true;
1967
-	IPPU.RenderedScreenWidth = SNES_WIDTH;
1968
-	IPPU.RenderedScreenHeight = SNES_HEIGHT;
1969
-	IPPU.FrameCount = 0;
1970
-	IPPU.RenderedFramesCount = 0;
1971
-	IPPU.DisplayedRenderedFrameCount = 0;
1972
-	IPPU.SkippedFrames = 0;
1973
-	IPPU.FrameSkip = 0;
1974
-
1975
-	//S9xFixColourBrightness();
1976 1039
 
1977 1040
 	for (int c = 0; c < 0x8000; c += 0x100)
1978
-		memset(&Memory.FillRAM[c], c >> 8, 0x100);
1979
-	ZeroMemory(&Memory.FillRAM[0x2100], 0x100);
1980
-	ZeroMemory(&Memory.FillRAM[0x4200], 0x100);
1981
-	ZeroMemory(&Memory.FillRAM[0x4000], 0x100);
1041
+		std::fill(&Memory.FillRAM[c], &Memory.FillRAM[c + 0x100], c >> 8);
1042
+	std::fill(&Memory.FillRAM[0x2100], &Memory.FillRAM[0x2200], 0);
1043
+	std::fill(&Memory.FillRAM[0x4200], &Memory.FillRAM[0x4300], 0);
1044
+	std::fill(&Memory.FillRAM[0x4000], &Memory.FillRAM[0x4100], 0);
1982 1045
 	// For BS Suttehakkun 2...
1983
-	ZeroMemory(&Memory.FillRAM[0x1000], 0x1000);
1046
+	std::fill(&Memory.FillRAM[0x1000], &Memory.FillRAM[0x2000], 0);
1984 1047
 
1985 1048
 	Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff;
1986 1049
 }
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,1986 @@
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 "fxemu.h"
183
+#include "sdd1.h"
184
+//#include "srtc.h"
185
+//#include "controls.h"
186
+//#include "movie.h"
187
+//#include "display.h"
188
+#ifdef NETPLAY_SUPPORT
189
+#include "netplay.h"
190
+#endif
191
+#ifdef DEBUGGER
192
+#include "debug.h"
193
+#include "missing.h"
194
+#endif
195
+
196
+extern uint8_t	*HDMAMemPointers[8];
197
+
198
+static inline void S9xLatchCounters (bool force)
199
+{
200
+	if (force || (Memory.FillRAM[0x4213] & 0x80))
201
+	{
202
+		// Latch h and v counters, like the gun
203
+	#ifdef DEBUGGER
204
+		missing.h_v_latch = 1;
205
+	#endif
206
+
207
+		PPU.HVBeamCounterLatched = 1;
208
+		PPU.VBeamPosLatched = (uint16_t) CPU.V_Counter;
209
+
210
+		// From byuu:
211
+		// All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long.
212
+		// This holds true for all scanlines except scanline 240 on non-interlace odd frames.
213
+		// The reason for this is because this scanline is only 1360 cycles long,
214
+		// instead of 1364 like all other scanlines.
215
+		// This makes the effective range of hscan_pos 0-339 at all times.
216
+		int32_t	hc = CPU.Cycles;
217
+
218
+		if (Timings.H_Max == Timings.H_Max_Master) // 1364
219
+		{
220
+			if (hc >= 1292)
221
+				hc -= (ONE_DOT_CYCLE / 2);
222
+			if (hc >= 1308)
223
+				hc -= (ONE_DOT_CYCLE / 2);
224
+		}
225
+
226
+		PPU.HBeamPosLatched = (uint16_t) (hc / ONE_DOT_CYCLE);
227
+
228
+		Memory.FillRAM[0x213f] |= 0x40;
229
+	}
230
+
231
+	if (CPU.V_Counter >  PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE))
232
+		PPU.GunVLatch = 1000;
233
+}
234
+
235
+static inline void S9xTryGunLatch (bool force)
236
+{
237
+	if (CPU.V_Counter >  PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE))
238
+	{
239
+		if (force || (Memory.FillRAM[0x4213] & 0x80))
240
+		{
241
+		#ifdef DEBUGGER
242
+			missing.h_v_latch = 1;
243
+		#endif
244
+
245
+			PPU.HVBeamCounterLatched = 1;
246
+			PPU.VBeamPosLatched = (uint16_t) PPU.GunVLatch;
247
+			PPU.HBeamPosLatched = (uint16_t) PPU.GunHLatch;
248
+
249
+			Memory.FillRAM[0x213f] |= 0x40;
250
+		}
251
+
252
+		PPU.GunVLatch = 1000;
253
+	}
254
+}
255
+
256
+void S9xUpdateHVTimerPosition()
257
+{
258
+	PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
259
+	if (Timings.H_Max == Timings.H_Max_Master)	// 1364
260
+	{
261
+		if (PPU.IRQHBeamPos > 322)
262
+			PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
263
+		if (PPU.IRQHBeamPos > 326)
264
+			PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
265
+	}
266
+
267
+	PPU.VTimerPosition = PPU.IRQVBeamPos;
268
+
269
+	if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340))
270
+	{
271
+		PPU.HTimerPosition -= Timings.H_Max;
272
+		PPU.VTimerPosition++;
273
+		// FIXME
274
+		if (PPU.VTimerPosition >= Timings.V_Max)
275
+			PPU.VTimerPosition = 0;
276
+	}
277
+
278
+#ifdef DEBUGGER
279
+	S9xTraceFormattedMessage("--- IRQ Timer set  HTimer:%d Pos:%04d  VTimer:%d Pos:%03d",
280
+		PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
281
+#endif
282
+}
283
+
284
+/*void S9xFixColourBrightness()
285
+{
286
+	IPPU.XB = mul_brightness[PPU.Brightness];
287
+
288
+	for (int i = 0; i < 256; i++)
289
+	{
290
+		IPPU.Red[i]   = IPPU.XB[(PPU.CGDATA[i])       & 0x1f];
291
+		IPPU.Green[i] = IPPU.XB[(PPU.CGDATA[i] >>  5) & 0x1f];
292
+		IPPU.Blue[i]  = IPPU.XB[(PPU.CGDATA[i] >> 10) & 0x1f];
293
+		IPPU.ScreenColors[i] = BUILD_PIXEL(IPPU.Red[i], IPPU.Green[i], IPPU.Blue[i]);
294
+	}
295
+}*/
296
+
297
+void S9xSetPPU (uint8_t Byte, uint16_t Address)
298
+{
299
+	// MAP_PPU: $2000-$3FFF
300
+
301
+	if (CPU.InDMAorHDMA)
302
+	{
303
+		if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer)
304
+		{
305
+			// S9xSetPPU() is called to write to DMA[].AAddress
306
+			if ((Address & 0xff00) == 0x2100)
307
+			{
308
+				// Cannot access to Address Bus B ($2100-$21ff) via (H)DMA
309
+				return;
310
+			}
311
+			else
312
+			{
313
+				// 0x2000-0x3FFF is connected to Address Bus A
314
+				// SA1, SuperFX and SRTC are mapped here
315
+				// I don't bother for now...
316
+				return;
317
+			}
318
+		}
319
+		else
320
+		{
321
+			// S9xSetPPU() is called to read from $21xx
322
+			// Take care of DMA wrapping
323
+			if (Address > 0x21ff)
324
+				Address = 0x2100 + (Address & 0xff);
325
+		}
326
+	}
327
+
328
+#ifdef DEBUGGER
329
+	if (CPU.InHDMA)
330
+		S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte);
331
+#endif
332
+
333
+	if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3
334
+		// write_port will run the APU until given clock before writing value
335
+		S9xAPUWritePort(Address & 3, Byte);
336
+	else
337
+	if (Address <= 0x2183)
338
+	{
339
+		switch (Address)
340
+		{
341
+			case 0x2100: // INIDISP
342
+				if (Byte != Memory.FillRAM[0x2100])
343
+				{
344
+					//FLUSH_REDRAW();
345
+
346
+					if (PPU.Brightness != (Byte & 0xf))
347
+					{
348
+						IPPU.ColorsChanged = true;
349
+						IPPU.DirectColourMapsNeedRebuild = true;
350
+						PPU.Brightness = Byte & 0xf;
351
+						//S9xFixColourBrightness();
352
+						if (PPU.Brightness > IPPU.MaxBrightness)
353
+							IPPU.MaxBrightness = PPU.Brightness;
354
+					}
355
+
356
+					if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80))
357
+					{
358
+						IPPU.ColorsChanged = true;
359
+						PPU.ForcedBlanking = (Byte >> 7) & 1;
360
+					}
361
+				}
362
+
363
+				if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
364
+				{
365
+					PPU.OAMAddr = PPU.SavedOAMAddr;
366
+
367
+					uint8_t tmp = 0;
368
+					if (PPU.OAMPriorityRotation)
369
+						tmp = (PPU.OAMAddr & 0xfe) >> 1;
370
+					if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp)
371
+					{
372
+						PPU.FirstSprite = tmp;
373
+						IPPU.OBJChanged = true;
374
+					}
375
+
376
+					PPU.OAMFlip = 0;
377
+				}
378
+
379
+				break;
380
+
381
+			case 0x2101: // OBSEL
382
+				if (Byte != Memory.FillRAM[0x2101])
383
+				{
384
+					//FLUSH_REDRAW();
385
+					PPU.OBJNameBase = (Byte & 3) << 14;
386
+					PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13;
387
+					PPU.OBJSizeSelect = (Byte >> 5) & 7;
388
+					IPPU.OBJChanged = true;
389
+				}
390
+
391
+				break;
392
+
393
+			case 0x2102: // OAMADDL
394
+				PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte;
395
+				PPU.OAMFlip = 2;
396
+				PPU.OAMReadFlip = 0;
397
+				PPU.SavedOAMAddr = PPU.OAMAddr;
398
+				if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
399
+				{
400
+					PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
401
+					IPPU.OBJChanged = true;
402
+				#ifdef DEBUGGER
403
+					missing.sprite_priority_rotation = 1;
404
+				#endif
405
+				}
406
+
407
+				break;
408
+
409
+			case 0x2103: // OAMADDH
410
+				PPU.OAMAddr = ((Byte & 1) << 8) | Memory.FillRAM[0x2102];
411
+				PPU.OAMPriorityRotation = (Byte & 0x80) ? 1 : 0;
412
+				if (PPU.OAMPriorityRotation)
413
+				{
414
+					if (PPU.FirstSprite != (PPU.OAMAddr >> 1))
415
+					{
416
+						PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
417
+						IPPU.OBJChanged = true;
418
+					#ifdef DEBUGGER
419
+						missing.sprite_priority_rotation = 1;
420
+					#endif
421
+					}
422
+				}
423
+				else
424
+				{
425
+					if (PPU.FirstSprite != 0)
426
+					{
427
+						PPU.FirstSprite = 0;
428
+						IPPU.OBJChanged = true;
429
+					#ifdef DEBUGGER
430
+						missing.sprite_priority_rotation = 1;
431
+					#endif
432
+					}
433
+				}
434
+
435
+				PPU.OAMFlip = 0;
436
+				PPU.OAMReadFlip = 0;
437
+				PPU.SavedOAMAddr = PPU.OAMAddr;
438
+
439
+				break;
440
+
441
+			case 0x2104: // OAMDATA
442
+				REGISTER_2104(Byte);
443
+				break;
444
+
445
+			case 0x2105: // BGMODE
446
+				if (Byte != Memory.FillRAM[0x2105])
447
+				{
448
+					//FLUSH_REDRAW();
449
+					PPU.BG[0].BGSize = (Byte >> 4) & 1;
450
+					PPU.BG[1].BGSize = (Byte >> 5) & 1;
451
+					PPU.BG[2].BGSize = (Byte >> 6) & 1;
452
+					PPU.BG[3].BGSize = (Byte >> 7) & 1;
453
+					PPU.BGMode = Byte & 7;
454
+					// BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set
455
+					PPU.BG3Priority = ((Byte & 0x0f) == 0x09);
456
+					IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
457
+				#ifdef DEBUGGER
458
+					missing.modes[PPU.BGMode] = 1;
459
+				#endif
460
+				}
461
+
462
+				break;
463
+
464
+			case 0x2106: // MOSAIC
465
+				if (Byte != Memory.FillRAM[0x2106])
466
+				{
467
+					//FLUSH_REDRAW();
468
+					PPU.MosaicStart = CPU.V_Counter;
469
+					if (PPU.MosaicStart > PPU.ScreenHeight)
470
+						PPU.MosaicStart = 0;
471
+					PPU.Mosaic = (Byte >> 4) + 1;
472
+					PPU.BGMosaic[0] = (Byte & 1);
473
+					PPU.BGMosaic[1] = !!(Byte & 2);
474
+					PPU.BGMosaic[2] = !!(Byte & 4);
475
+					PPU.BGMosaic[3] = !!(Byte & 8);
476
+				#ifdef DEBUGGER
477
+					if ((Byte & 0xf0) && (Byte & 0x0f))
478
+						missing.mosaic = 1;
479
+				#endif
480
+				}
481
+
482
+				break;
483
+
484
+			case 0x2107: // BG1SC
485
+				if (Byte != Memory.FillRAM[0x2107])
486
+				{
487
+					//FLUSH_REDRAW();
488
+					PPU.BG[0].SCSize = Byte & 3;
489
+					PPU.BG[0].SCBase = (Byte & 0x7c) << 8;
490
+				}
491
+
492
+				break;
493
+
494
+			case 0x2108: // BG2SC
495
+				if (Byte != Memory.FillRAM[0x2108])
496
+				{
497
+					//FLUSH_REDRAW();
498
+					PPU.BG[1].SCSize = Byte & 3;
499
+					PPU.BG[1].SCBase = (Byte & 0x7c) << 8;
500
+				}
501
+
502
+				break;
503
+
504
+			case 0x2109: // BG3SC
505
+				if (Byte != Memory.FillRAM[0x2109])
506
+				{
507
+					//FLUSH_REDRAW();
508
+					PPU.BG[2].SCSize = Byte & 3;
509
+					PPU.BG[2].SCBase = (Byte & 0x7c) << 8;
510
+				}
511
+
512
+				break;
513
+
514
+			case 0x210a: // BG4SC
515
+				if (Byte != Memory.FillRAM[0x210a])
516
+				{
517
+					//FLUSH_REDRAW();
518
+					PPU.BG[3].SCSize = Byte & 3;
519
+					PPU.BG[3].SCBase = (Byte & 0x7c) << 8;
520
+				}
521
+
522
+				break;
523
+
524
+			case 0x210b: // BG12NBA
525
+				if (Byte != Memory.FillRAM[0x210b])
526
+				{
527
+					//FLUSH_REDRAW();
528
+					PPU.BG[0].NameBase = (Byte & 7) << 12;
529
+					PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12;
530
+				}
531
+
532
+				break;
533
+
534
+			case 0x210c: // BG34NBA
535
+				if (Byte != Memory.FillRAM[0x210c])
536
+				{
537
+					//FLUSH_REDRAW();
538
+					PPU.BG[2].NameBase = (Byte & 7) << 12;
539
+					PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12;
540
+				}
541
+
542
+				break;
543
+
544
+			case 0x210d: // BG1HOFS, M7HOFS
545
+				PPU.BG[0].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[0].HOffset >> 8) & 7);
546
+				PPU.M7HOFS = (Byte << 8) | PPU.M7byte;
547
+				PPU.BGnxOFSbyte = Byte;
548
+				PPU.M7byte = Byte;
549
+				break;
550
+
551
+			case 0x210e: // BG1VOFS, M7VOFS
552
+				PPU.BG[0].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
553
+				PPU.M7VOFS = (Byte << 8) | PPU.M7byte;
554
+				PPU.BGnxOFSbyte = Byte;
555
+				PPU.M7byte = Byte;
556
+				break;
557
+
558
+			case 0x210f: // BG2HOFS
559
+				PPU.BG[1].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[1].HOffset >> 8) & 7);
560
+				PPU.BGnxOFSbyte = Byte;
561
+				break;
562
+
563
+			case 0x2110: // BG2VOFS
564
+				PPU.BG[1].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
565
+				PPU.BGnxOFSbyte = Byte;
566
+				break;
567
+
568
+			case 0x2111: // BG3HOFS
569
+				PPU.BG[2].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[2].HOffset >> 8) & 7);
570
+				PPU.BGnxOFSbyte = Byte;
571
+				break;
572
+
573
+			case 0x2112: // BG3VOFS
574
+				PPU.BG[2].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
575
+				PPU.BGnxOFSbyte = Byte;
576
+				break;
577
+
578
+			case 0x2113: // BG4HOFS
579
+				PPU.BG[3].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[3].HOffset >> 8) & 7);
580
+				PPU.BGnxOFSbyte = Byte;
581
+				break;
582
+
583
+			case 0x2114: // BG4VOFS
584
+				PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
585
+				PPU.BGnxOFSbyte = Byte;
586
+				break;
587
+
588
+			case 0x2115: // VMAIN
589
+				PPU.VMA.High = (Byte & 0x80) == 0 ? false : true;
590
+				switch (Byte & 3)
591
+				{
592
+					case 0: PPU.VMA.Increment = 1;   break;
593
+					case 1: PPU.VMA.Increment = 32;  break;
594
+					case 2: PPU.VMA.Increment = 128; break;
595
+					case 3: PPU.VMA.Increment = 128; break;
596
+				}
597
+
598
+				if (Byte & 0x0c)
599
+				{
600
+					static uint16_t Shift[4]    = { 0, 5, 6, 7 };
601
+					static uint16_t IncCount[4] = { 0, 32, 64, 128 };
602
+
603
+					uint8_t i = (Byte & 0x0c) >> 2;
604
+					PPU.VMA.FullGraphicCount = IncCount[i];
605
+					PPU.VMA.Mask1 = IncCount[i] * 8 - 1;
606
+					PPU.VMA.Shift = Shift[i];
607
+				#ifdef DEBUGGER
608
+					missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2;
609
+				#endif
610
+				}
611
+				else
612
+					PPU.VMA.FullGraphicCount = 0;
613
+			#ifdef DEBUGGER
614
+				if (Byte & 3)
615
+					missing.vram_inc = Byte & 3;
616
+			#endif
617
+				break;
618
+
619
+			case 0x2116: // VMADDL
620
+				PPU.VMA.Address &= 0xff00;
621
+				PPU.VMA.Address |= Byte;
622
+
623
+				if (PPU.VMA.FullGraphicCount)
624
+				{
625
+					uint32_t addr = PPU.VMA.Address;
626
+					uint32_t rem = addr & PPU.VMA.Mask1;
627
+					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
628
+					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
629
+				}
630
+				else
631
+					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
632
+
633
+				break;
634
+
635
+			case 0x2117: // VMADDH
636
+				PPU.VMA.Address &= 0x00ff;
637
+				PPU.VMA.Address |= Byte << 8;
638
+
639
+				if (PPU.VMA.FullGraphicCount)
640
+				{
641
+					uint32_t addr = PPU.VMA.Address;
642
+					uint32_t rem = addr & PPU.VMA.Mask1;
643
+					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
644
+					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
645
+				}
646
+				else
647
+					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
648
+
649
+				break;
650
+
651
+			case 0x2118: // VMDATAL
652
+				REGISTER_2118(Byte);
653
+				break;
654
+
655
+			case 0x2119: // VMDATAH
656
+				REGISTER_2119(Byte);
657
+				break;
658
+
659
+			case 0x211a: // M7SEL
660
+				if (Byte != Memory.FillRAM[0x211a])
661
+				{
662
+					//FLUSH_REDRAW();
663
+					PPU.Mode7Repeat = Byte >> 6;
664
+					if (PPU.Mode7Repeat == 1)
665
+						PPU.Mode7Repeat = 0;
666
+					PPU.Mode7VFlip = !!((Byte & 2) >> 1);
667
+					PPU.Mode7HFlip = Byte & 1;
668
+				}
669
+
670
+				break;
671
+
672
+			case 0x211b: // M7A
673
+				PPU.MatrixA = PPU.M7byte | (Byte << 8);
674
+				PPU.Need16x8Mulitply = true;
675
+				PPU.M7byte = Byte;
676
+				break;
677
+
678
+			case 0x211c: // M7B
679
+				PPU.MatrixB = PPU.M7byte | (Byte << 8);
680
+				PPU.Need16x8Mulitply = true;
681
+				PPU.M7byte = Byte;
682
+				break;
683
+
684
+			case 0x211d: // M7C
685
+				PPU.MatrixC = PPU.M7byte | (Byte << 8);
686
+				PPU.M7byte = Byte;
687
+				break;
688
+
689
+			case 0x211e: // M7D
690
+				PPU.MatrixD = PPU.M7byte | (Byte << 8);
691
+				PPU.M7byte = Byte;
692
+				break;
693
+
694
+			case 0x211f: // M7X
695
+				PPU.CentreX = PPU.M7byte | (Byte << 8);
696
+				PPU.M7byte = Byte;
697
+				break;
698
+
699
+			case 0x2120: // M7Y
700
+				PPU.CentreY = PPU.M7byte | (Byte << 8);
701
+				PPU.M7byte = Byte;
702
+				break;
703
+
704
+			case 0x2121: // CGADD
705
+				PPU.CGFLIP = 0;
706
+				PPU.CGFLIPRead = 0;
707
+				PPU.CGADD = Byte;
708
+				break;
709
+
710
+			/*case 0x2122: // CGDATA
711
+				REGISTER_2122(Byte);
712
+				break;*/
713
+
714
+			case 0x2123: // W12SEL
715
+				if (Byte != Memory.FillRAM[0x2123])
716
+				{
717
+					//FLUSH_REDRAW();
718
+					PPU.ClipWindow1Enable[0] = !!(Byte & 0x02);
719
+					PPU.ClipWindow1Enable[1] = !!(Byte & 0x20);
720
+					PPU.ClipWindow2Enable[0] = !!(Byte & 0x08);
721
+					PPU.ClipWindow2Enable[1] = !!(Byte & 0x80);
722
+					PPU.ClipWindow1Inside[0] = !(Byte & 0x01);
723
+					PPU.ClipWindow1Inside[1] = !(Byte & 0x10);
724
+					PPU.ClipWindow2Inside[0] = !(Byte & 0x04);
725
+					PPU.ClipWindow2Inside[1] = !(Byte & 0x40);
726
+					PPU.RecomputeClipWindows = true;
727
+				#ifdef DEBUGGER
728
+					if (Byte & 0x80)
729
+						missing.window2[1] = 1;
730
+					if (Byte & 0x20)
731
+						missing.window1[1] = 1;
732
+					if (Byte & 0x08)
733
+						missing.window2[0] = 1;
734
+					if (Byte & 0x02)
735
+						missing.window1[0] = 1;
736
+				#endif
737
+				}
738
+
739
+				break;
740
+
741
+			case 0x2124: // W34SEL
742
+				if (Byte != Memory.FillRAM[0x2124])
743
+				{
744
+					//FLUSH_REDRAW();
745
+					PPU.ClipWindow1Enable[2] = !!(Byte & 0x02);
746
+					PPU.ClipWindow1Enable[3] = !!(Byte & 0x20);
747
+					PPU.ClipWindow2Enable[2] = !!(Byte & 0x08);
748
+					PPU.ClipWindow2Enable[3] = !!(Byte & 0x80);
749
+					PPU.ClipWindow1Inside[2] = !(Byte & 0x01);
750
+					PPU.ClipWindow1Inside[3] = !(Byte & 0x10);
751
+					PPU.ClipWindow2Inside[2] = !(Byte & 0x04);
752
+					PPU.ClipWindow2Inside[3] = !(Byte & 0x40);
753
+					PPU.RecomputeClipWindows = true;
754
+				#ifdef DEBUGGER
755
+					if (Byte & 0x80)
756
+						missing.window2[3] = 1;
757
+					if (Byte & 0x20)
758
+						missing.window1[3] = 1;
759
+					if (Byte & 0x08)
760
+						missing.window2[2] = 1;
761
+					if (Byte & 0x02)
762
+						missing.window1[2] = 1;
763
+				#endif
764
+				}
765
+
766
+				break;
767
+
768
+			case 0x2125: // WOBJSEL
769
+				if (Byte != Memory.FillRAM[0x2125])
770
+				{
771
+					//FLUSH_REDRAW();
772
+					PPU.ClipWindow1Enable[4] = !!(Byte & 0x02);
773
+					PPU.ClipWindow1Enable[5] = !!(Byte & 0x20);
774
+					PPU.ClipWindow2Enable[4] = !!(Byte & 0x08);
775
+					PPU.ClipWindow2Enable[5] = !!(Byte & 0x80);
776
+					PPU.ClipWindow1Inside[4] = !(Byte & 0x01);
777
+					PPU.ClipWindow1Inside[5] = !(Byte & 0x10);
778
+					PPU.ClipWindow2Inside[4] = !(Byte & 0x04);
779
+					PPU.ClipWindow2Inside[5] = !(Byte & 0x40);
780
+					PPU.RecomputeClipWindows = true;
781
+				#ifdef DEBUGGER
782
+					if (Byte & 0x80)
783
+						missing.window2[5] = 1;
784
+					if (Byte & 0x20)
785
+						missing.window1[5] = 1;
786
+					if (Byte & 0x08)
787
+						missing.window2[4] = 1;
788
+					if (Byte & 0x02)
789
+						missing.window1[4] = 1;
790
+				#endif
791
+				}
792
+
793
+				break;
794
+
795
+			case 0x2126: // WH0
796
+				if (Byte != Memory.FillRAM[0x2126])
797
+				{
798
+					//FLUSH_REDRAW();
799
+					PPU.Window1Left = Byte;
800
+					PPU.RecomputeClipWindows = true;
801
+				}
802
+
803
+				break;
804
+
805
+			case 0x2127: // WH1
806
+				if (Byte != Memory.FillRAM[0x2127])
807
+				{
808
+					//FLUSH_REDRAW();
809
+					PPU.Window1Right = Byte;
810
+					PPU.RecomputeClipWindows = true;
811
+				}
812
+
813
+				break;
814
+
815
+			case 0x2128: // WH2
816
+				if (Byte != Memory.FillRAM[0x2128])
817
+				{
818
+					//FLUSH_REDRAW();
819
+					PPU.Window2Left = Byte;
820
+					PPU.RecomputeClipWindows = true;
821
+				}
822
+
823
+				break;
824
+
825
+			case 0x2129: // WH3
826
+				if (Byte != Memory.FillRAM[0x2129])
827
+				{
828
+					//FLUSH_REDRAW();
829
+					PPU.Window2Right = Byte;
830
+					PPU.RecomputeClipWindows = true;
831
+				}
832
+
833
+				break;
834
+
835
+			case 0x212a: // WBGLOG
836
+				if (Byte != Memory.FillRAM[0x212a])
837
+				{
838
+					//FLUSH_REDRAW();
839
+					PPU.ClipWindowOverlapLogic[0] = (Byte & 0x03);
840
+					PPU.ClipWindowOverlapLogic[1] = (Byte & 0x0c) >> 2;
841
+					PPU.ClipWindowOverlapLogic[2] = (Byte & 0x30) >> 4;
842
+					PPU.ClipWindowOverlapLogic[3] = (Byte & 0xc0) >> 6;
843
+					PPU.RecomputeClipWindows = true;
844
+				}
845
+
846
+				break;
847
+
848
+			case 0x212b: // WOBJLOG
849
+				if (Byte != Memory.FillRAM[0x212b])
850
+				{
851
+					//FLUSH_REDRAW();
852
+					PPU.ClipWindowOverlapLogic[4] = (Byte & 0x03);
853
+					PPU.ClipWindowOverlapLogic[5] = (Byte & 0x0c) >> 2;
854
+					PPU.RecomputeClipWindows = true;
855
+				}
856
+
857
+				break;
858
+
859
+			case 0x212c: // TM
860
+				if (Byte != Memory.FillRAM[0x212c])
861
+				{
862
+					//FLUSH_REDRAW();
863
+					PPU.RecomputeClipWindows = true;
864
+				}
865
+
866
+				break;
867
+
868
+			case 0x212d: // TS
869
+				if (Byte != Memory.FillRAM[0x212d])
870
+				{
871
+					//FLUSH_REDRAW();
872
+					PPU.RecomputeClipWindows = true;
873
+				#ifdef DEBUGGER
874
+					if (Byte & 0x1f)
875
+						missing.subscreen = 1;
876
+				#endif
877
+				}
878
+
879
+				break;
880
+
881
+			case 0x212e: // TMW
882
+				if (Byte != Memory.FillRAM[0x212e])
883
+				{
884
+					//FLUSH_REDRAW();
885
+					PPU.RecomputeClipWindows = true;
886
+				}
887
+
888
+				break;
889
+
890
+			case 0x212f: // TSW
891
+				if (Byte != Memory.FillRAM[0x212f])
892
+				{
893
+					//FLUSH_REDRAW();
894
+					PPU.RecomputeClipWindows = true;
895
+				}
896
+
897
+				break;
898
+
899
+			case 0x2130: // CGWSEL
900
+				if (Byte != Memory.FillRAM[0x2130])
901
+				{
902
+					//FLUSH_REDRAW();
903
+					PPU.RecomputeClipWindows = true;
904
+				#ifdef DEBUGGER
905
+					if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7))
906
+						missing.direct = 1;
907
+				#endif
908
+				}
909
+
910
+				break;
911
+
912
+			case 0x2131: // CGADSUB
913
+				if (Byte != Memory.FillRAM[0x2131])
914
+				{
915
+					//FLUSH_REDRAW();
916
+				#ifdef DEBUGGER
917
+					if (Byte & 0x80)
918
+					{
919
+						if (Memory.FillRAM[0x2130] & 0x02)
920
+							missing.subscreen_sub = 1;
921
+						else
922
+							missing.fixed_colour_sub = 1;
923
+					}
924
+					else
925
+					{
926
+						if (Memory.FillRAM[0x2130] & 0x02)
927
+							missing.subscreen_add = 1;
928
+						else
929
+							missing.fixed_colour_add = 1;
930
+					}
931
+				#endif
932
+				}
933
+
934
+				break;
935
+
936
+			case 0x2132: // COLDATA
937
+				if (Byte != Memory.FillRAM[0x2132])
938
+				{
939
+					//FLUSH_REDRAW();
940
+					if (Byte & 0x80)
941
+						PPU.FixedColourBlue  = Byte & 0x1f;
942
+					if (Byte & 0x40)
943
+						PPU.FixedColourGreen = Byte & 0x1f;
944
+					if (Byte & 0x20)
945
+						PPU.FixedColourRed   = Byte & 0x1f;
946
+				}
947
+
948
+				break;
949
+
950
+			case 0x2133: // SETINI
951
+				if (Byte != Memory.FillRAM[0x2133])
952
+				{
953
+					if ((Memory.FillRAM[0x2133] ^ Byte) & 8)
954
+					{
955
+						//FLUSH_REDRAW();
956
+						IPPU.PseudoHires = !!(Byte & 8);
957
+					}
958
+
959
+					if (Byte & 0x04)
960
+					{
961
+						PPU.ScreenHeight = SNES_HEIGHT_EXTENDED;
962
+						if (IPPU.DoubleHeightPixels)
963
+							IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
964
+						else
965
+							IPPU.RenderedScreenHeight = PPU.ScreenHeight;
966
+					#ifdef DEBUGGER
967
+						missing.lines_239 = 1;
968
+					#endif
969
+					}
970
+					else
971
+						PPU.ScreenHeight = SNES_HEIGHT;
972
+
973
+					if ((Memory.FillRAM[0x2133] ^ Byte) & 3)
974
+					{
975
+						//FLUSH_REDRAW();
976
+						if ((Memory.FillRAM[0x2133] ^ Byte) & 2)
977
+							IPPU.OBJChanged = true;
978
+						IPPU.Interlace = Byte & 1;
979
+						IPPU.InterlaceOBJ = !!(Byte & 2);
980
+					}
981
+				#ifdef DEBUGGER
982
+					if (Byte & 0x40)
983
+						missing.mode7_bgmode = 1;
984
+					if (Byte & 0x08)
985
+						missing.pseudo_512 = 1;
986
+					if (Byte & 0x02)
987
+						missing.sprite_double_height = 1;
988
+					if (Byte & 0x01)
989
+						missing.interlace = 1;
990
+				#endif
991
+				}
992
+
993
+				break;
994
+
995
+			case 0x2134: // MPYL
996
+			case 0x2135: // MPYM
997
+			case 0x2136: // MPYH
998
+			case 0x2137: // SLHV
999
+			case 0x2138: // OAMDATAREAD
1000
+			case 0x2139: // VMDATALREAD
1001
+			case 0x213a: // VMDATAHREAD
1002
+			case 0x213b: // CGDATAREAD
1003
+			case 0x213c: // OPHCT
1004
+			case 0x213d: // OPVCT
1005
+			case 0x213e: // STAT77
1006
+			case 0x213f: // STAT78
1007
+				return;
1008
+
1009
+			case 0x2180: // WMDATA
1010
+				if (!CPU.InWRAMDMAorHDMA)
1011
+					REGISTER_2180(Byte);
1012
+				break;
1013
+
1014
+			case 0x2181: // WMADDL
1015
+				if (!CPU.InWRAMDMAorHDMA)
1016
+				{
1017
+					PPU.WRAM &= 0x1ff00;
1018
+					PPU.WRAM |= Byte;
1019
+				}
1020
+
1021
+				break;
1022
+
1023
+			case 0x2182: // WMADDM
1024
+				if (!CPU.InWRAMDMAorHDMA)
1025
+				{
1026
+					PPU.WRAM &= 0x100ff;
1027
+					PPU.WRAM |= Byte << 8;
1028
+				}
1029
+
1030
+				break;
1031
+
1032
+			case 0x2183: // WMADDH
1033
+				if (!CPU.InWRAMDMAorHDMA)
1034
+				{
1035
+					PPU.WRAM &= 0x0ffff;
1036
+					PPU.WRAM |= Byte << 16;
1037
+					PPU.WRAM &= 0x1ffff;
1038
+				}
1039
+
1040
+				break;
1041
+		}
1042
+	}
1043
+	/*else
1044
+	{
1045
+		if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff)
1046
+		{
1047
+			S9xSetSuperFX(Byte, Address);
1048
+			return;
1049
+		}
1050
+		else
1051
+		if (Settings.SA1     && Address >= 0x2200)
1052
+		{
1053
+			if (Address <= 0x23ff)
1054
+				S9xSetSA1(Byte, Address);
1055
+			else
1056
+				Memory.FillRAM[Address] = Byte;
1057
+			return;
1058
+		}
1059
+		else
1060
+		if (Settings.BS      && Address >= 0x2188 && Address <= 0x219f)
1061
+			S9xSetBSXPPU(Byte, Address);
1062
+		else
1063
+		if (Settings.SRTC    && Address == 0x2801)
1064
+			S9xSetSRTC(Byte, Address);
1065
+	#ifdef DEBUGGER
1066
+		else
1067
+		{
1068
+			missing.unknownppu_write = Address;
1069
+			if (Settings.TraceUnknownRegisters)
1070
+			{
1071
+				sprintf(String, "Unknown register write: $%02X->$%04X\n", Byte, Address);
1072
+				S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
1073
+			}
1074
+		}
1075
+	#endif
1076
+	}*/
1077
+
1078
+	Memory.FillRAM[Address] = Byte;
1079
+}
1080
+
1081
+uint8_t S9xGetPPU (uint16_t Address)
1082
+{
1083
+	// MAP_PPU: $2000-$3FFF
1084
+
1085
+	if (Address < 0x2100)
1086
+		return OpenBus;
1087
+
1088
+	if (CPU.InDMAorHDMA)
1089
+	{
1090
+		if (CPU.CurrentDMAorHDMAChannel >= 0 && !DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer)
1091
+		{
1092
+			// S9xGetPPU() is called to read from DMA[].AAddress
1093
+			if ((Address & 0xff00) == 0x2100)
1094
+				// Cannot access to Address Bus B ($2100-$21FF) via (H)DMA
1095
+				return OpenBus;
1096
+			else
1097
+				// $2200-$3FFF are connected to Address Bus A
1098
+				// SA1, SuperFX and SRTC are mapped here
1099
+				// I don't bother for now...
1100
+				return OpenBus;
1101
+		}
1102
+		else
1103
+		{
1104
+			// S9xGetPPU() is called to write to $21xx
1105
+			// Take care of DMA wrapping
1106
+			if (Address > 0x21ff)
1107
+				Address = 0x2100 + (Address & 0xff);
1108
+		}
1109
+	}
1110
+
1111
+	if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3
1112
+		// read_port will run the APU until given APU time before reading value
1113
+		return S9xAPUReadPort(Address & 3);
1114
+	else
1115
+	if (Address <= 0x2183)
1116
+    {
1117
+		uint8_t	byte;
1118
+
1119
+		switch (Address)
1120
+		{
1121
+			case 0x2104: // OAMDATA
1122
+			case 0x2105: // BGMODE
1123
+			case 0x2106: // MOSAIC
1124
+			case 0x2108: // BG2SC
1125
+			case 0x2109: // BG3SC
1126
+			case 0x210a: // BG4SC
1127
+			case 0x2114: // BG4VOFS
1128
+			case 0x2115: // VMAIN
1129
+			case 0x2116: // VMADDL
1130
+			case 0x2118: // VMDATAL
1131
+			case 0x2119: // VMDATAH
1132
+			case 0x211a: // M7SEL
1133
+			case 0x2124: // W34SEL
1134
+			case 0x2125: // WOBJSEL
1135
+			case 0x2126: // WH0
1136
+			case 0x2128: // WH2
1137
+			case 0x2129: // WH3
1138
+			case 0x212a: // WBGLOG
1139
+				return PPU.OpenBus1;
1140
+
1141
+			case 0x2134: // MPYL
1142
+			case 0x2135: // MPYM
1143
+			case 0x2136: // MPYH
1144
+				if (PPU.Need16x8Mulitply)
1145
+				{
1146
+					int32_t r = (int32_t) PPU.MatrixA * (int32_t) (PPU.MatrixB >> 8);
1147
+					Memory.FillRAM[0x2134] = (uint8_t) r;
1148
+					Memory.FillRAM[0x2135] = (uint8_t) (r >> 8);
1149
+					Memory.FillRAM[0x2136] = (uint8_t) (r >> 16);
1150
+					PPU.Need16x8Mulitply = false;
1151
+				}
1152
+			#ifdef DEBUGGER
1153
+				missing.matrix_multiply = 1;
1154
+			#endif
1155
+				return (PPU.OpenBus1 = Memory.FillRAM[Address]);
1156
+
1157
+			case 0x2137: // SLHV
1158
+				S9xLatchCounters(0);
1159
+				return OpenBus;
1160
+
1161
+			case 0x2138: // OAMDATAREAD
1162
+				if (PPU.OAMAddr & 0x100)
1163
+				{
1164
+					if (!(PPU.OAMFlip & 1))
1165
+						byte = PPU.OAMData[(PPU.OAMAddr & 0x10f) << 1];
1166
+					else
1167
+					{
1168
+						byte = PPU.OAMData[((PPU.OAMAddr & 0x10f) << 1) + 1];
1169
+						PPU.OAMAddr = (PPU.OAMAddr + 1) & 0x1ff;
1170
+						if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
1171
+						{
1172
+							PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
1173
+							IPPU.OBJChanged = true;
1174
+						#ifdef DEBUGGER
1175
+							missing.sprite_priority_rotation = 1;
1176
+						#endif
1177
+						}
1178
+					}
1179
+				}
1180
+				else
1181
+				{
1182
+					if (!(PPU.OAMFlip & 1))
1183
+						byte = PPU.OAMData[PPU.OAMAddr << 1];
1184
+					else
1185
+					{
1186
+						byte = PPU.OAMData[(PPU.OAMAddr << 1) + 1];
1187
+						++PPU.OAMAddr;
1188
+						if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
1189
+						{
1190
+							PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
1191
+							IPPU.OBJChanged = true;
1192
+						#ifdef DEBUGGER
1193
+							missing.sprite_priority_rotation = 1;
1194
+						#endif
1195
+						}
1196
+					}
1197
+				}
1198
+
1199
+				PPU.OAMFlip ^= 1;
1200
+			#ifdef DEBUGGER
1201
+				missing.oam_read = 1;
1202
+			#endif
1203
+				return (PPU.OpenBus1 = byte);
1204
+
1205
+			case 0x2139: // VMDATALREAD
1206
+				byte = IPPU.VRAMReadBuffer & 0xff;
1207
+				if (!PPU.VMA.High)
1208
+				{
1209
+					if (PPU.VMA.FullGraphicCount)
1210
+					{
1211
+						uint32_t addr = PPU.VMA.Address;
1212
+						uint32_t rem = addr & PPU.VMA.Mask1;
1213
+						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
1214
+						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
1215
+					}
1216
+					else
1217
+						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
1218
+
1219
+					PPU.VMA.Address += PPU.VMA.Increment;
1220
+				}
1221
+
1222
+			#ifdef DEBUGGER
1223
+				missing.vram_read = 1;
1224
+			#endif
1225
+				return (PPU.OpenBus1 = byte);
1226
+
1227
+			case 0x213a: // VMDATAHREAD
1228
+				byte = (IPPU.VRAMReadBuffer >> 8) & 0xff;
1229
+				if (PPU.VMA.High)
1230
+				{
1231
+					if (PPU.VMA.FullGraphicCount)
1232
+					{
1233
+						uint32_t addr = PPU.VMA.Address;
1234
+						uint32_t rem = addr & PPU.VMA.Mask1;
1235
+						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
1236
+						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
1237
+					}
1238
+					else
1239
+						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
1240
+
1241
+					PPU.VMA.Address += PPU.VMA.Increment;
1242
+				}
1243
+			#ifdef DEBUGGER
1244
+				missing.vram_read = 1;
1245
+			#endif
1246
+				return (PPU.OpenBus1 = byte);
1247
+
1248
+			case 0x213b: // CGDATAREAD
1249
+				if (PPU.CGFLIPRead)
1250
+					byte = (PPU.OpenBus2 & 0x80) | ((PPU.CGDATA[PPU.CGADD++] >> 8) & 0x7f);
1251
+				else
1252
+					byte = PPU.CGDATA[PPU.CGADD] & 0xff;
1253
+				PPU.CGFLIPRead ^= 1;
1254
+			#ifdef DEBUGGER
1255
+				missing.cgram_read = 1;
1256
+			#endif
1257
+				return (PPU.OpenBus2 = byte);
1258
+
1259
+			case 0x213c: // OPHCT
1260
+				S9xTryGunLatch(false);
1261
+				if (PPU.HBeamFlip)
1262
+					byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01);
1263
+				else
1264
+					byte = (uint8_t) PPU.HBeamPosLatched;
1265
+				PPU.HBeamFlip ^= 1;
1266
+			#ifdef DEBUGGER
1267
+				missing.h_counter_read = 1;
1268
+			#endif
1269
+				return (PPU.OpenBus2 = byte);
1270
+
1271
+			case 0x213d: // OPVCT
1272
+				S9xTryGunLatch(false);
1273
+				if (PPU.VBeamFlip)
1274
+					byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01);
1275
+				else
1276
+					byte = (uint8_t) PPU.VBeamPosLatched;
1277
+				PPU.VBeamFlip ^= 1;
1278
+			#ifdef DEBUGGER
1279
+				missing.v_counter_read = 1;
1280
+			#endif
1281
+				return (PPU.OpenBus2 = byte);
1282
+
1283
+			case 0x213e: // STAT77
1284
+				//FLUSH_REDRAW();
1285
+				byte = (PPU.OpenBus1 & 0x10) | PPU.RangeTimeOver | Model->_5C77;
1286
+				return (PPU.OpenBus1 = byte);
1287
+
1288
+			case 0x213f: // STAT78
1289
+				S9xTryGunLatch(false);
1290
+				PPU.VBeamFlip = PPU.HBeamFlip = 0;
1291
+				byte = (PPU.OpenBus2 & 0x20) | (Memory.FillRAM[0x213f] & 0xc0) | (Settings.PAL ? 0x10 : 0) | Model->_5C78;
1292
+				Memory.FillRAM[0x213f] &= ~0x40;
1293
+				return (PPU.OpenBus2 = byte);
1294
+
1295
+			case 0x2180: // WMDATA
1296
+				if (!CPU.InWRAMDMAorHDMA)
1297
+				{
1298
+					byte = Memory.RAM[PPU.WRAM++];
1299
+					PPU.WRAM &= 0x1ffff;
1300
+				}
1301
+				else
1302
+					byte = OpenBus;
1303
+			#ifdef DEBUGGER
1304
+				missing.wram_read = 1;
1305
+			#endif
1306
+				return byte;
1307
+
1308
+			default:
1309
+				return OpenBus;
1310
+		}
1311
+	}
1312
+	else
1313
+    {
1314
+		/*if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff)
1315
+			return S9xGetSuperFX(Address);
1316
+		else
1317
+		if (Settings.SA1     && Address >= 0x2200)
1318
+			return S9xGetSA1(Address);
1319
+		else
1320
+		if (Settings.BS      && Address >= 0x2188 && Address <= 0x219f)
1321
+			return S9xGetBSXPPU(Address);
1322
+		else	
1323
+		if (Settings.SRTC    && Address == 0x2800)
1324
+			return S9xGetSRTC(Address);
1325
+		else*/
1326
+		switch (Address)
1327
+		{
1328
+			case 0x21c2:
1329
+				if (Model->_5C77 == 2)
1330
+					return 0x20;
1331
+				return OpenBus;
1332
+
1333
+			case 0x21c3:
1334
+				if (Model->_5C77 == 2)
1335
+					return 0;
1336
+				return OpenBus;
1337
+
1338
+			default:
1339
+				return OpenBus;
1340
+		}
1341
+	}
1342
+}
1343
+
1344
+void S9xSetCPU (uint8_t Byte, uint16_t Address)
1345
+{
1346
+	if (Address < 0x4200)
1347
+	{
1348
+		/*switch (Address)
1349
+		{
1350
+			case 0x4016: // JOYSER0
1351
+				S9xSetJoypadLatch(Byte & 1);
1352
+				break;
1353
+
1354
+			case 0x4017: // JOYSER1
1355
+				return;
1356
+
1357
+			default:
1358
+				break;
1359
+		}*/
1360
+	}
1361
+	else
1362
+	if ((Address & 0xff80) == 0x4300)
1363
+	{
1364
+		if (CPU.InDMAorHDMA)
1365
+			return;
1366
+
1367
+		int	d = (Address >> 4) & 0x7;
1368
+
1369
+		switch (Address & 0xf)
1370
+		{
1371
+			case 0x0: // 0x43x0: DMAPx
1372
+				DMA[d].ReverseTransfer        = (Byte & 0x80) ? true : false;
1373
+				DMA[d].HDMAIndirectAddressing = (Byte & 0x40) ? true : false;
1374
+				DMA[d].UnusedBit43x0          = (Byte & 0x20) ? true : false;
1375
+				DMA[d].AAddressDecrement      = (Byte & 0x10) ? true : false;
1376
+				DMA[d].AAddressFixed          = (Byte & 0x08) ? true : false;
1377
+				DMA[d].TransferMode           = (Byte & 7);
1378
+				return;
1379
+
1380
+			case 0x1: // 0x43x1: BBADx
1381
+				DMA[d].BAddress = Byte;
1382
+				return;
1383
+
1384
+			case 0x2: // 0x43x2: A1TxL
1385
+				DMA[d].AAddress &= 0xff00;
1386
+				DMA[d].AAddress |= Byte;
1387
+				return;
1388
+
1389
+			case 0x3: // 0x43x3: A1TxH
1390
+				DMA[d].AAddress &= 0xff;
1391
+				DMA[d].AAddress |= Byte << 8;
1392
+				return;
1393
+
1394
+			case 0x4: // 0x43x4: A1Bx
1395
+				DMA[d].ABank = Byte;
1396
+				HDMAMemPointers[d] = NULL;
1397
+				return;
1398
+
1399
+			case 0x5: // 0x43x5: DASxL
1400
+				DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00;
1401
+				DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte;
1402
+				HDMAMemPointers[d] = NULL;
1403
+				return;
1404
+
1405
+			case 0x6: // 0x43x6: DASxH
1406
+				DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff;
1407
+				DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte << 8;
1408
+				HDMAMemPointers[d] = NULL;
1409
+				return;
1410
+
1411
+			case 0x7: // 0x43x7: DASBx
1412
+				DMA[d].IndirectBank = Byte;
1413
+				HDMAMemPointers[d] = NULL;
1414
+				return;
1415
+
1416
+			case 0x8: // 0x43x8: A2AxL
1417
+				DMA[d].Address &= 0xff00;
1418
+				DMA[d].Address |= Byte;
1419
+				HDMAMemPointers[d] = NULL;
1420
+				return;
1421
+
1422
+			case 0x9: // 0x43x9: A2AxH
1423
+				DMA[d].Address &= 0xff;
1424
+				DMA[d].Address |= Byte << 8;
1425
+				HDMAMemPointers[d] = NULL;
1426
+				return;
1427
+
1428
+			case 0xa: // 0x43xa: NLTRx
1429
+				if (Byte & 0x7f)
1430
+				{
1431
+					DMA[d].LineCount = Byte & 0x7f;
1432
+					DMA[d].Repeat = !(Byte & 0x80);
1433
+				}
1434
+				else
1435
+				{
1436
+					DMA[d].LineCount = 128;
1437
+					DMA[d].Repeat = !!(Byte & 0x80);
1438
+				}
1439
+
1440
+				return;
1441
+
1442
+			case 0xb: // 0x43xb: ????x
1443
+			case 0xf: // 0x43xf: mirror of 0x43xb
1444
+				DMA[d].UnknownByte = Byte;
1445
+				return;
1446
+
1447
+			default:
1448
+				break;
1449
+		}
1450
+	}
1451
+	else
1452
+	{
1453
+		uint16_t	pos;
1454
+
1455
+		switch (Address)
1456
+		{
1457
+			case 0x4200: // NMITIMEN
1458
+				if (Byte & 0x20)
1459
+				{
1460
+					PPU.VTimerEnabled = true;
1461
+				#ifdef DEBUGGER
1462
+					missing.virq = 1;
1463
+					missing.virq_pos = PPU.IRQVBeamPos;
1464
+				#endif
1465
+				}
1466
+				else
1467
+					PPU.VTimerEnabled = false;
1468
+
1469
+				if (Byte & 0x10)
1470
+				{
1471
+					PPU.HTimerEnabled = true;
1472
+				#ifdef DEBUGGER
1473
+					missing.hirq = 1;
1474
+					missing.hirq_pos = PPU.IRQHBeamPos;
1475
+				#endif
1476
+				}
1477
+				else
1478
+					PPU.HTimerEnabled = false;
1479
+
1480
+				if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled)
1481
+					CPU.IRQTransition = true;
1482
+
1483
+				if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
1484
+				{
1485
+					CPU.IRQLine = false;
1486
+					CPU.IRQTransition = false;
1487
+				}
1488
+
1489
+				// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
1490
+				if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
1491
+					(CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80))
1492
+				{
1493
+					// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
1494
+					// then, when to call S9xOpcode_NMI()?
1495
+					CPU.NMILine = true;
1496
+					Timings.NMITriggerPos = CPU.Cycles + 6 + 6;
1497
+				}
1498
+
1499
+				break;
1500
+
1501
+			case 0x4201: // WRIO
1502
+				if ((Byte & 0x80) == 0 && (Memory.FillRAM[0x4213] & 0x80) == 0x80)
1503
+					S9xLatchCounters(1);
1504
+				else
1505
+					S9xTryGunLatch((Byte & 0x80) ? true : false);
1506
+				Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = Byte;
1507
+				break;
1508
+
1509
+			case 0x4202: // WRMPYA
1510
+				break;
1511
+
1512
+			case 0x4203: // WRMPYB
1513
+			{
1514
+				uint32_t res = Memory.FillRAM[0x4202] * Byte;
1515
+				// FIXME: The update occurs 8 machine cycles after $4203 is set.
1516
+				Memory.FillRAM[0x4216] = (uint8_t) res;
1517
+				Memory.FillRAM[0x4217] = (uint8_t) (res >> 8);
1518
+				break;
1519
+			}
1520
+
1521
+			case 0x4204: // WRDIVL
1522
+			case 0x4205: // WRDIVH
1523
+				break;
1524
+
1525
+			case 0x4206: // WRDIVB
1526
+			{
1527
+				uint16_t a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8);
1528
+				uint16_t div = Byte ? a / Byte : 0xffff;
1529
+				uint16_t rem = Byte ? a % Byte : a;
1530
+				// FIXME: The update occurs 16 machine cycles after $4206 is set.
1531
+				Memory.FillRAM[0x4214] = (uint8_t) div;
1532
+				Memory.FillRAM[0x4215] = div >> 8;
1533
+				Memory.FillRAM[0x4216] = (uint8_t) rem;
1534
+				Memory.FillRAM[0x4217] = rem >> 8;
1535
+				break;
1536
+			}
1537
+
1538
+			case 0x4207: // HTIMEL
1539
+				pos = PPU.IRQHBeamPos;
1540
+				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
1541
+				if (PPU.IRQHBeamPos != pos)
1542
+					S9xUpdateHVTimerPosition();
1543
+			#ifdef DEBUGGER
1544
+				missing.hirq_pos = PPU.IRQHBeamPos;
1545
+			#endif
1546
+				break;
1547
+
1548
+			case 0x4208: // HTIMEH
1549
+				pos = PPU.IRQHBeamPos;
1550
+				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
1551
+				if (PPU.IRQHBeamPos != pos)
1552
+					S9xUpdateHVTimerPosition();
1553
+			#ifdef DEBUGGER
1554
+				missing.hirq_pos = PPU.IRQHBeamPos;
1555
+			#endif
1556
+				break;
1557
+
1558
+			case 0x4209: // VTIMEL
1559
+				pos = PPU.IRQVBeamPos;
1560
+				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
1561
+				if (PPU.IRQVBeamPos != pos)
1562
+					S9xUpdateHVTimerPosition();
1563
+			#ifdef DEBUGGER
1564
+				missing.virq_pos = PPU.IRQVBeamPos;
1565
+			#endif
1566
+				break;
1567
+
1568
+			case 0x420a: // VTIMEH
1569
+				pos = PPU.IRQVBeamPos;
1570
+				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
1571
+				if (PPU.IRQVBeamPos != pos)
1572
+					S9xUpdateHVTimerPosition();
1573
+			#ifdef DEBUGGER
1574
+				missing.virq_pos = PPU.IRQVBeamPos;
1575
+			#endif
1576
+				break;
1577
+
1578
+			case 0x420b: // MDMAEN
1579
+				if (CPU.InDMAorHDMA)
1580
+					return;
1581
+				// XXX: Not quite right...
1582
+				if (Byte)
1583
+					CPU.Cycles += Timings.DMACPUSync;
1584
+				if (Byte & 0x01)
1585
+					S9xDoDMA(0);
1586
+				if (Byte & 0x02)
1587
+					S9xDoDMA(1);
1588
+				if (Byte & 0x04)
1589
+					S9xDoDMA(2);
1590
+				if (Byte & 0x08)
1591
+					S9xDoDMA(3);
1592
+				if (Byte & 0x10)
1593
+					S9xDoDMA(4);
1594
+				if (Byte & 0x20)
1595
+					S9xDoDMA(5);
1596
+				if (Byte & 0x40)
1597
+					S9xDoDMA(6);
1598
+				if (Byte & 0x80)
1599
+					S9xDoDMA(7);
1600
+			#ifdef DEBUGGER
1601
+				missing.dma_this_frame = Byte;
1602
+				missing.dma_channels = Byte;
1603
+			#endif
1604
+				break;
1605
+
1606
+			case 0x420c: // HDMAEN
1607
+				if (CPU.InDMAorHDMA)
1608
+					return;
1609
+				Memory.FillRAM[0x420c] = Byte;
1610
+				// Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
1611
+				PPU.HDMA = Byte & ~PPU.HDMAEnded;
1612
+			#ifdef DEBUGGER
1613
+				missing.hdma_this_frame |= Byte;
1614
+				missing.hdma_channels |= Byte;
1615
+			#endif
1616
+				break;
1617
+
1618
+			case 0x420d: // MEMSEL
1619
+				if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1))
1620
+				{
1621
+					if (Byte & 1)
1622
+					{
1623
+						CPU.FastROMSpeed = ONE_CYCLE;
1624
+					#ifdef DEBUGGER
1625
+						missing.fast_rom = 1;
1626
+					#endif
1627
+					}
1628
+					else
1629
+						CPU.FastROMSpeed = SLOW_ONE_CYCLE;
1630
+				}
1631
+
1632
+				break;
1633
+
1634
+			case 0x4210: // RDNMI
1635
+			case 0x4211: // TIMEUP
1636
+			case 0x4212: // HVBJOY
1637
+			case 0x4213: // RDIO
1638
+			case 0x4214: // RDDIVL
1639
+			case 0x4215: // RDDIVH
1640
+			case 0x4216: // RDMPYL
1641
+			case 0x4217: // RDMPYH
1642
+			case 0x4218: // JOY1L
1643
+			case 0x4219: // JOY1H
1644
+			case 0x421a: // JOY2L
1645
+			case 0x421b: // JOY2H
1646
+			case 0x421c: // JOY3L
1647
+			case 0x421d: // JOY3H
1648
+			case 0x421e: // JOY4L
1649
+			case 0x421f: // JOY4H
1650
+				return;
1651
+
1652
+			default:
1653
+				/*if (Settings.SPC7110 && Address >= 0x4800)
1654
+					S9xSetSPC7110(Byte, Address);
1655
+				else*/
1656
+				if (Settings.SDD1 && Address >= 0x4804 && Address <= 0x4807)
1657
+					S9xSetSDD1MemoryMap(Address - 0x4804, Byte & 7);
1658
+				break;
1659
+		}
1660
+	}
1661
+
1662
+	Memory.FillRAM[Address] = Byte;
1663
+}
1664
+
1665
+uint8_t S9xGetCPU (uint16_t Address)
1666
+{
1667
+	if (Address < 0x4200)
1668
+	{
1669
+	#ifdef SNES_JOY_READ_CALLBACKS
1670
+		extern bool pad_read;
1671
+		if (Address == 0x4016 || Address == 0x4017)
1672
+		{
1673
+			S9xOnSNESPadRead();
1674
+			pad_read = true;
1675
+		}
1676
+	#endif
1677
+
1678
+		/*switch (Address)
1679
+		{
1680
+			case 0x4016: // JOYSER0
1681
+			case 0x4017: // JOYSER1
1682
+				return S9xReadJOYSERn(Address);
1683
+
1684
+			default:*/
1685
+				return OpenBus;
1686
+		//}
1687
+	}
1688
+	else
1689
+	if ((Address & 0xff80) == 0x4300)
1690
+	{
1691
+		if (CPU.InDMAorHDMA)
1692
+			return OpenBus;
1693
+
1694
+		int	d = (Address >> 4) & 0x7;
1695
+
1696
+		switch (Address & 0xf)
1697
+		{
1698
+			case 0x0: // 0x43x0: DMAPx
1699
+				return  (DMA[d].ReverseTransfer        ? 0x80 : 0) |
1700
+						(DMA[d].HDMAIndirectAddressing ? 0x40 : 0) |
1701
+						(DMA[d].UnusedBit43x0          ? 0x20 : 0) |
1702
+						(DMA[d].AAddressDecrement      ? 0x10 : 0) |
1703
+						(DMA[d].AAddressFixed          ? 0x08 : 0) |
1704
+						(DMA[d].TransferMode & 7);
1705
+
1706
+			case 0x1: // 0x43x1: BBADx
1707
+				return DMA[d].BAddress;
1708
+
1709
+			case 0x2: // 0x43x2: A1TxL
1710
+				return DMA[d].AAddress & 0xff;
1711
+
1712
+			case 0x3: // 0x43x3: A1TxH
1713
+				return DMA[d].AAddress >> 8;
1714
+
1715
+			case 0x4: // 0x43x4: A1Bx
1716
+				return DMA[d].ABank;
1717
+
1718
+			case 0x5: // 0x43x5: DASxL
1719
+				return DMA[d].DMACount_Or_HDMAIndirectAddress & 0xff;
1720
+
1721
+			case 0x6: // 0x43x6: DASxH
1722
+				return DMA[d].DMACount_Or_HDMAIndirectAddress >> 8;
1723
+
1724
+			case 0x7: // 0x43x7: DASBx
1725
+				return DMA[d].IndirectBank;
1726
+
1727
+			case 0x8: // 0x43x8: A2AxL
1728
+				return DMA[d].Address & 0xff;
1729
+
1730
+			case 0x9: // 0x43x9: A2AxH
1731
+				return DMA[d].Address >> 8;
1732
+
1733
+			case 0xa: // 0x43xa: NLTRx
1734
+				return DMA[d].LineCount ^ (DMA[d].Repeat ? 0x00 : 0x80);
1735
+
1736
+			case 0xb: // 0x43xb: ????x
1737
+			case 0xf: // 0x43xf: mirror of 0x43xb
1738
+				return DMA[d].UnknownByte;
1739
+
1740
+			default:
1741
+				return OpenBus;
1742
+		}
1743
+	}
1744
+	else
1745
+	{
1746
+		uint8_t	byte;
1747
+
1748
+		switch (Address)
1749
+		{
1750
+			case 0x4210: // RDNMI
1751
+				byte = Memory.FillRAM[0x4210];
1752
+				Memory.FillRAM[0x4210] = Model->_5A22;
1753
+				return (byte & 0x80) | (OpenBus & 0x70) | Model->_5A22;
1754
+
1755
+			case 0x4211: // TIMEUP
1756
+				byte = CPU.IRQLine ? 0x80 : 0;
1757
+				CPU.IRQLine = false;
1758
+				CPU.IRQTransition = false;
1759
+				return byte | (OpenBus & 0x7f);
1760
+
1761
+			case 0x4212: // HVBJOY
1762
+				return REGISTER_4212() | (OpenBus & 0x3e);
1763
+
1764
+			case 0x4213: // RDIO
1765
+				return Memory.FillRAM[0x4213];
1766
+
1767
+			case 0x4214: // RDDIVL
1768
+			case 0x4215: // RDDIVH
1769
+			case 0x4216: // RDMPYL
1770
+			case 0x4217: // RDMPYH
1771
+				return Memory.FillRAM[Address];
1772
+
1773
+			case 0x4218: // JOY1L
1774
+			case 0x4219: // JOY1H
1775
+			case 0x421a: // JOY2L
1776
+			case 0x421b: // JOY2H
1777
+			case 0x421c: // JOY3L
1778
+			case 0x421d: // JOY3H
1779
+			case 0x421e: // JOY4L
1780
+			case 0x421f: // JOY4H
1781
+			#ifdef SNES_JOY_READ_CALLBACKS
1782
+				extern bool pad_read;
1783
+				if (Memory.FillRAM[0x4200] & 1)
1784
+				{
1785
+					S9xOnSNESPadRead();
1786
+					pad_read = true;
1787
+				}
1788
+			#endif
1789
+				return Memory.FillRAM[Address];
1790
+
1791
+			default:
1792
+				/*if (Settings.SPC7110 && Address >= 0x4800)
1793
+					return S9xGetSPC7110(Address);*/
1794
+				if (Settings.SDD1 && Address >= 0x4800 && Address <= 0x4807)
1795
+					return Memory.FillRAM[Address];
1796
+				return OpenBus;
1797
+		}
1798
+	}
1799
+}
1800
+
1801
+void S9xResetPPU()
1802
+{
1803
+	S9xSoftResetPPU();
1804
+	//S9xControlsReset();
1805
+	PPU.M7HOFS = 0;
1806
+	PPU.M7VOFS = 0;
1807
+	PPU.M7byte = 0;
1808
+}
1809
+
1810
+void S9xSoftResetPPU()
1811
+{
1812
+	//S9xControlsSoftReset();
1813
+
1814
+	PPU.VMA.High = 0;
1815
+	PPU.VMA.Increment = 1;
1816
+	PPU.VMA.Address = 0;
1817
+	PPU.VMA.FullGraphicCount = 0;
1818
+	PPU.VMA.Shift = 0;
1819
+
1820
+	PPU.WRAM = 0;
1821
+
1822
+	for (int c = 0; c < 4; c++)
1823
+	{
1824
+		PPU.BG[c].SCBase = 0;
1825
+		PPU.BG[c].HOffset = 0;
1826
+		PPU.BG[c].VOffset = 0;
1827
+		PPU.BG[c].BGSize = 0;
1828
+		PPU.BG[c].NameBase = 0;
1829
+		PPU.BG[c].SCSize = 0;
1830
+	}
1831
+
1832
+	PPU.BGMode = 0;
1833
+	PPU.BG3Priority = 0;
1834
+
1835
+	PPU.CGFLIP = 0;
1836
+	PPU.CGFLIPRead = 0;
1837
+	PPU.CGADD = 0;
1838
+
1839
+	for (int c = 0; c < 256; c++)
1840
+	{
1841
+		IPPU.Red[c]   = (c & 7) << 2;
1842
+		IPPU.Green[c] = ((c >> 3) & 7) << 2;
1843
+		IPPU.Blue[c]  = ((c >> 6) & 2) << 3;
1844
+		PPU.CGDATA[c] = IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10);
1845
+	}
1846
+
1847
+	for (int c = 0; c < 128; c++)
1848
+	{
1849
+		PPU.OBJ[c].HPos = 0;
1850
+		PPU.OBJ[c].VPos = 0;
1851
+		PPU.OBJ[c].HFlip = 0;
1852
+		PPU.OBJ[c].VFlip = 0;
1853
+		PPU.OBJ[c].Name = 0;
1854
+		PPU.OBJ[c].Priority = 0;
1855
+		PPU.OBJ[c].Palette = 0;
1856
+		PPU.OBJ[c].Size = 0;
1857
+	}
1858
+
1859
+	PPU.OBJThroughMain = false;
1860
+	PPU.OBJThroughSub = false;
1861
+	PPU.OBJAddition = false;
1862
+	PPU.OBJNameBase = 0;
1863
+	PPU.OBJNameSelect = 0;
1864
+	PPU.OBJSizeSelect = 0;
1865
+
1866
+	PPU.OAMAddr = 0;
1867
+	PPU.SavedOAMAddr = 0;
1868
+	PPU.OAMPriorityRotation = 0;
1869
+	PPU.OAMFlip = 0;
1870
+	PPU.OAMReadFlip = 0;
1871
+	PPU.OAMTileAddress = 0;
1872
+	PPU.OAMWriteRegister = 0;
1873
+	ZeroMemory(PPU.OAMData, 512 + 32);
1874
+
1875
+	PPU.FirstSprite = 0;
1876
+	PPU.LastSprite = 127;
1877
+	PPU.RangeTimeOver = 0;
1878
+
1879
+	PPU.HTimerEnabled = false;
1880
+	PPU.VTimerEnabled = false;
1881
+	PPU.HTimerPosition = Timings.H_Max + 1;
1882
+	PPU.VTimerPosition = Timings.V_Max + 1;
1883
+	PPU.IRQHBeamPos = 0x1ff;
1884
+	PPU.IRQVBeamPos = 0x1ff;
1885
+
1886
+	PPU.HBeamFlip = 0;
1887
+	PPU.VBeamFlip = 0;
1888
+	PPU.HBeamPosLatched = 0;
1889
+	PPU.VBeamPosLatched = 0;
1890
+	PPU.GunHLatch = 0;
1891
+	PPU.GunVLatch = 1000;
1892
+	PPU.HVBeamCounterLatched = 0;
1893
+
1894
+	PPU.Mode7HFlip = false;
1895
+	PPU.Mode7VFlip = false;
1896
+	PPU.Mode7Repeat = 0;
1897
+	PPU.MatrixA = 0;
1898
+	PPU.MatrixB = 0;
1899
+	PPU.MatrixC = 0;
1900
+	PPU.MatrixD = 0;
1901
+	PPU.CentreX = 0;
1902
+	PPU.CentreY = 0;
1903
+
1904
+	PPU.Mosaic = 0;
1905
+	PPU.BGMosaic[0] = false;
1906
+	PPU.BGMosaic[1] = false;
1907
+	PPU.BGMosaic[2] = false;
1908
+	PPU.BGMosaic[3] = false;
1909
+	
1910
+	PPU.Window1Left = 1;
1911
+	PPU.Window1Right = 0;
1912
+	PPU.Window2Left = 1;
1913
+	PPU.Window2Right = 0;
1914
+	PPU.RecomputeClipWindows = true;
1915
+
1916
+	for (int c = 0; c < 6; c++)
1917
+	{
1918
+		PPU.ClipCounts[c] = 0;
1919
+		PPU.ClipWindowOverlapLogic[c] = CLIP_OR;
1920
+		PPU.ClipWindow1Enable[c] = false;
1921
+		PPU.ClipWindow2Enable[c] = false;
1922
+		PPU.ClipWindow1Inside[c] = true;
1923
+		PPU.ClipWindow2Inside[c] = true;
1924
+	}
1925
+
1926
+	PPU.ForcedBlanking = true;
1927
+
1928
+	PPU.FixedColourRed = 0;
1929
+	PPU.FixedColourGreen = 0;
1930
+	PPU.FixedColourBlue = 0;
1931
+	PPU.Brightness = 0;
1932
+	PPU.ScreenHeight = SNES_HEIGHT;
1933
+
1934
+	PPU.Need16x8Mulitply = false;
1935
+	PPU.BGnxOFSbyte = 0;
1936
+
1937
+	PPU.HDMA = 0;
1938
+	PPU.HDMAEnded = 0;
1939
+
1940
+	PPU.OpenBus1 = 0;
1941
+	PPU.OpenBus2 = 0;
1942
+
1943
+	for (int c = 0; c < 2; c++)
1944
+		memset(&IPPU.Clip[c], 0, sizeof(struct ClipData));
1945
+	IPPU.ColorsChanged = true;
1946
+	IPPU.OBJChanged = true;
1947
+	IPPU.DirectColourMapsNeedRebuild = true;
1948
+	ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES);
1949
+	ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES);
1950
+	ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES);
1951
+	ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES);
1952
+	ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD],  MAX_2BIT_TILES);
1953
+	ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
1954
+	ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD],  MAX_4BIT_TILES);
1955
+	IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
1956
+	IPPU.Interlace = false;
1957
+	IPPU.InterlaceOBJ = false;
1958
+	IPPU.DoubleWidthPixels = false;
1959
+	IPPU.DoubleHeightPixels = false;
1960
+	IPPU.CurrentLine = 0;
1961
+	IPPU.PreviousLine = 0;
1962
+	IPPU.XB = NULL;
1963
+	for (int c = 0; c < 256; c++)
1964
+		IPPU.ScreenColors[c] = c;
1965
+	IPPU.MaxBrightness = 0;
1966
+	IPPU.RenderThisFrame = true;
1967
+	IPPU.RenderedScreenWidth = SNES_WIDTH;
1968
+	IPPU.RenderedScreenHeight = SNES_HEIGHT;
1969
+	IPPU.FrameCount = 0;
1970
+	IPPU.RenderedFramesCount = 0;
1971
+	IPPU.DisplayedRenderedFrameCount = 0;
1972
+	IPPU.SkippedFrames = 0;
1973
+	IPPU.FrameSkip = 0;
1974
+
1975
+	//S9xFixColourBrightness();
1976
+
1977
+	for (int c = 0; c < 0x8000; c += 0x100)
1978
+		memset(&Memory.FillRAM[c], c >> 8, 0x100);
1979
+	ZeroMemory(&Memory.FillRAM[0x2100], 0x100);
1980
+	ZeroMemory(&Memory.FillRAM[0x4200], 0x100);
1981
+	ZeroMemory(&Memory.FillRAM[0x4000], 0x100);
1982
+	// For BS Suttehakkun 2...
1983
+	ZeroMemory(&Memory.FillRAM[0x1000], 0x1000);
1984
+
1985
+	Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff;
1986
+}