workaround a problem with the harmattan gcc
[drnoksnes] / ppu.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
12  * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13  * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14  * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
21  * Permission to use, copy, modify and distribute Snes9x in both binary and
22  * source form, for non-commercial purposes, is hereby granted without fee,
23  * providing that this license information and copyright notice appear with
24  * all copies and any derived work.
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event shall the authors be held liable for any damages
28  * arising from the use of this software.
29  *
30  * Snes9x is freeware for PERSONAL USE only. Commercial users should
31  * seek permission of the copyright holders first. Commercial use includes
32  * charging money for Snes9x or software derived from Snes9x.
33  *
34  * The copyright holders request that bug fixes and improvements to the code
35  * should be forwarded to them so everyone can benefit from the modifications
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41 #include "snes9x.h"
42 #include "memmap.h"
43 #include "ppu.h"
44 #include "cpuexec.h"
45 #include "missing.h"
46 #include "apu.h"
47 #include "dma.h"
48 #include "gfx.h"
49 #include "sa1.h"
50 #include "sdd1.h"
51 #include "srtc.h"
52
53 #include "port.h"
54
55 #ifndef ZSNES_FX
56 #include "fxemu.h"
57 #include "fxinst.h"
58 extern struct FxInit_s SuperFX;
59 extern struct FxRegs_s GSU;
60 #else
61 EXTERN_C void S9xSuperFXWriteReg (uint8, uint32);
62 EXTERN_C uint8 S9xSuperFXReadReg (uint32);
63 #endif
64
65 void S9xUpdateHTimer ()
66 {
67     if (PPU.HTimerEnabled)
68     {
69 #ifdef DEBUGGER
70         missing.hirq_pos = PPU.IRQHBeamPos;
71 #endif
72         PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX;
73         if (PPU.HTimerPosition == Settings.H_Max ||
74             PPU.HTimerPosition == Settings.HBlankStart)
75         {
76             PPU.HTimerPosition--;
77         }
78
79         if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)
80         {
81             if (PPU.HTimerPosition < CPU.Cycles)
82             {
83                 // Missed the IRQ on this line already
84                 if (CPU.WhichEvent == HBLANK_END_EVENT ||
85                     CPU.WhichEvent == HTIMER_AFTER_EVENT)
86                 {
87                     CPU.WhichEvent = HBLANK_END_EVENT;
88                     CPU.NextEvent = Settings.H_Max;
89                 }
90                 else
91                 {
92                     CPU.WhichEvent = HBLANK_START_EVENT;
93                     CPU.NextEvent = Settings.HBlankStart;
94                 }
95             }
96             else
97             {
98                         if (CPU.WhichEvent == HTIMER_BEFORE_EVENT ||
99                                 CPU.WhichEvent == HBLANK_START_EVENT)
100                         {
101                                 if (PPU.HTimerPosition > Settings.HBlankStart)
102                                 {
103                                         // HTimer was to trigger before h-blank start,
104                                         // now triggers after start of h-blank
105                                         CPU.NextEvent = Settings.HBlankStart;
106                                         CPU.WhichEvent = HBLANK_START_EVENT;
107                                 }
108                                 else
109                                 {
110                                         CPU.NextEvent = PPU.HTimerPosition;
111                                         CPU.WhichEvent = HTIMER_BEFORE_EVENT;
112                                 }
113                         }
114                         else
115                         {
116                                 CPU.WhichEvent = HTIMER_AFTER_EVENT;
117                                 CPU.NextEvent = PPU.HTimerPosition;
118                         }
119             }
120         }
121     }
122 }
123
124 void S9xFixColourBrightness ()
125 {
126     IPPU.XB = mul_brightness [PPU.Brightness];
127         for (int i = 0; i < 256; i++)
128         {
129             IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f];
130             IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f];
131             IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f];
132             IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i],
133                                                  IPPU.Blue [i]);
134         }
135 }
136
137 /**********************************************************************************************/
138 /* S9xSetPPU()                                                                                   */
139 /* This function sets a PPU Register to a specific byte                                       */
140 /**********************************************************************************************/
141 void S9xSetPPU(uint8 Byte, uint16 Address)
142 {
143         if (Address <= 0x2183)
144         {
145                 switch (Address)
146                 {
147                         case 0x2100 :
148                                 // Brightness and screen blank bit
149                                 if (Byte != Memory.FillRAM[0x2100])
150                                 {
151                                         FLUSH_REDRAW();
152                                         if (PPU.Brightness != (Byte & 0xF))
153                                         {
154                                                 IPPU.ColorsChanged = TRUE;
155                                                 IPPU.DirectColourMapsNeedRebuild = TRUE;
156                                                 PPU.Brightness = Byte & 0xF;
157                                                 S9xFixColourBrightness();
158                                                 if (PPU.Brightness > IPPU.MaxBrightness)
159                                                         IPPU.MaxBrightness = PPU.Brightness;
160                                         }
161                                         if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80))
162                                         {
163                                                 IPPU.ColorsChanged = TRUE;
164                                                 PPU.ForcedBlanking = (Byte >> 7) & 1;
165                                         }
166                                 }
167                                 break;
168
169                         case 0x2101 :
170                                 // Sprite (OBJ) tile address
171                                 if (Byte != Memory.FillRAM[0x2101])
172                                 {
173                                         FLUSH_REDRAW();
174                                         PPU.OBJNameBase = (Byte & 3) << 14;
175                                         PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13;
176                                         PPU.OBJSizeSelect = (Byte >> 5) & 7;
177                                         IPPU.OBJChanged = TRUE;
178                                 }
179                                 break;
180
181                         case 0x2102 :
182                                 // Sprite write address (low)
183                                 PPU.OAMAddr = Byte;
184                                 PPU.OAMFlip = 2;
185                                 PPU.OAMReadFlip = 0;
186                                 PPU.SavedOAMAddr = PPU.OAMAddr;
187                                 if (PPU.OAMPriorityRotation)
188                                 {
189                                         PPU.FirstSprite = PPU.OAMAddr & 0x7f;
190 #ifdef DEBUGGER
191                                         missing.sprite_priority_rotation = 1;
192 #endif
193                                 }
194                                 break;
195
196                         case 0x2103 :
197                                 // Sprite register write address (high), sprite priority rotation
198                                 // bit.
199                                 if ((PPU.OAMPriorityRotation = (Byte & 0x80) == 0 ? 0 : 1))
200                                 {
201                                         PPU.FirstSprite = PPU.OAMAddr & 0x7f;
202 #ifdef DEBUGGER
203                                         missing.sprite_priority_rotation = 1;
204 #endif
205                                 }
206                                 // Only update the sprite write address top bit if the low byte has
207                                 // been written to first.
208                                 if (PPU.OAMFlip & 2)
209                                 {
210                                         PPU.OAMAddr &= 0x00FF;
211                                         PPU.OAMAddr |= (Byte & 1) << 8;
212                                 }
213                                 PPU.OAMFlip = 0;
214                                 PPU.OAMReadFlip = 0;
215                                 PPU.SavedOAMAddr = PPU.OAMAddr;
216                                 break;
217
218                         case 0x2104 :
219                                 // Sprite register write
220                                 REGISTER_2104(Byte);
221
222                                 break;
223
224                         case 0x2105 :
225                                 // Screen mode (0 - 7), background tile sizes and background 3
226                                 // priority
227                                 if (Byte != Memory.FillRAM[0x2105])
228                                 {
229                                         FLUSH_REDRAW();
230                                         PPU.BG[0].BGSize = (Byte >> 4) & 1;
231                                         PPU.BG[1].BGSize = (Byte >> 5) & 1;
232                                         PPU.BG[2].BGSize = (Byte >> 6) & 1;
233                                         PPU.BG[3].BGSize = (Byte >> 7) & 1;
234                                         PPU.BGMode = Byte & 7;
235                                 // BJ: BG3Priority only takes effect if BGMode==1 and the bit is set
236                                 PPU.BG3Priority  = ((Byte & 0x0f) == 0x09);
237 #ifdef DEBUGGER
238                                         missing.modes[PPU.BGMode] = 1;
239 #endif
240                                 }
241                                 break;
242
243                         case 0x2106 :
244                                 // Mosaic pixel size and enable
245                                 if (Byte != Memory.FillRAM[0x2106])
246                                 {
247                                         FLUSH_REDRAW();
248 #ifdef DEBUGGER
249                                         if ((Byte & 0xf0) && (Byte & 0x0f))
250                                                 missing.mosaic = 1;
251 #endif
252                                         PPU.Mosaic = (Byte >> 4) + 1;
253                                         PPU.BGMosaic[0] = (Byte & 1) && PPU.Mosaic > 1;
254                                         PPU.BGMosaic[1] = (Byte & 2) && PPU.Mosaic > 1;
255                                         PPU.BGMosaic[2] = (Byte & 4) && PPU.Mosaic > 1;
256                                         PPU.BGMosaic[3] = (Byte & 8) && PPU.Mosaic > 1;
257                                 }
258                                 break;
259                         case 0x2107 : // [BG0SC]
260                                 if (Byte != Memory.FillRAM[0x2107])
261                                 {
262                                         FLUSH_REDRAW();
263                                         PPU.BG[0].SCSize = Byte & 3;
264                                         PPU.BG[0].SCBase = (Byte & 0x7c) << 8;
265                                 }
266                                 break;
267
268                         case 0x2108 : // [BG1SC]
269                                 if (Byte != Memory.FillRAM[0x2108])
270                                 {
271                                         FLUSH_REDRAW();
272                                         PPU.BG[1].SCSize = Byte & 3;
273                                         PPU.BG[1].SCBase = (Byte & 0x7c) << 8;
274                                 }
275                                 break;
276
277                         case 0x2109 : // [BG2SC]
278                                 if (Byte != Memory.FillRAM[0x2109])
279                                 {
280                                         FLUSH_REDRAW();
281                                         PPU.BG[2].SCSize = Byte & 3;
282                                         PPU.BG[2].SCBase = (Byte & 0x7c) << 8;
283                                 }
284                                 break;
285
286                         case 0x210A : // [BG3SC]
287                                 if (Byte != Memory.FillRAM[0x210a])
288                                 {
289                                         FLUSH_REDRAW();
290                                         PPU.BG[3].SCSize = Byte & 3;
291                                         PPU.BG[3].SCBase = (Byte & 0x7c) << 8;
292                                 }
293                                 break;
294
295                         case 0x210B : // [BG01NBA]
296                                 if (Byte != Memory.FillRAM[0x210b])
297                                 {
298                                         FLUSH_REDRAW();
299                                         PPU.BG[0].NameBase = (Byte & 7) << 12;
300                                         PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12;
301                                 }
302                                 break;
303
304                         case 0x210C : // [BG23NBA]
305                                 if (Byte != Memory.FillRAM[0x210c])
306                                 {
307                                         FLUSH_REDRAW();
308                                         PPU.BG[2].NameBase = (Byte & 7) << 12;
309                                         PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12;
310                                 }
311                                 break;
312
313                         case 0x210D :
314                                 PPU.BG[0].HOffset =
315                                         ((PPU.BG[0].HOffset >> 8) & 0xff) | ((uint16) Byte << 8);
316                                 break;
317
318                         case 0x210E :
319                                 PPU.BG[0].VOffset =
320                                         ((PPU.BG[0].VOffset >> 8) & 0xff) | ((uint16) Byte << 8);
321                                 break;
322                         case 0x210F :
323                                 PPU.BG[1].HOffset =
324                                         ((PPU.BG[1].HOffset >> 8) & 0xff) | ((uint16) Byte << 8);
325                                 break;
326
327                         case 0x2110 :
328                                 PPU.BG[1].VOffset =
329                                         ((PPU.BG[1].VOffset >> 8) & 0xff) | ((uint16) Byte << 8);
330                                 break;
331
332                         case 0x2111 :
333                                 PPU.BG[2].HOffset =
334                                         ((PPU.BG[2].HOffset >> 8) & 0xff) | ((uint16) Byte << 8);
335                                 break;
336
337                         case 0x2112 :
338                                 PPU.BG[2].VOffset =
339                                         ((PPU.BG[2].VOffset >> 8) & 0xff) | ((uint16) Byte << 8);
340                                 break;
341
342                         case 0x2113 :
343                                 PPU.BG[3].HOffset =
344                                         ((PPU.BG[3].HOffset >> 8) & 0xff) | ((uint16) Byte << 8);
345                                 break;
346
347                         case 0x2114 :
348                                 PPU.BG[3].VOffset =
349                                         ((PPU.BG[3].VOffset >> 8) & 0xff) | ((uint16) Byte << 8);
350                                 break;
351
352                         case 0x2115 :
353                                 // VRAM byte/word access flag and increment
354                                 PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE;
355                                 switch (Byte & 3)
356                                 {
357                                         case 0 :
358                                                 PPU.VMA.Increment = 1;
359                                                 break;
360                                         case 1 :
361                                                 PPU.VMA.Increment = 32;
362                                                 break;
363                                         case 2 :
364                                                 PPU.VMA.Increment = 128;
365                                                 break;
366                                         case 3 :
367                                                 PPU.VMA.Increment = 128;
368                                                 break;
369                                 }
370 #ifdef DEBUGGER
371                                 if ((Byte & 3) != 0)
372                                         missing.vram_inc = Byte & 3;
373 #endif
374                                 if (Byte & 0x0c)
375                                 {
376                                         static uint16 IncCount[4] = { 0, 32, 64, 128 };
377                                         static uint16 Shift[4] = { 0, 5, 6, 7 };
378 #ifdef DEBUGGER
379                                         missing.vram_full_graphic_inc =
380                                                 (Byte & 0x0c) >> 2;
381 #endif
382                                         PPU.VMA.Increment = 1;
383                                         uint8 i = (Byte & 0x0c) >> 2;
384                                         PPU.VMA.FullGraphicCount = IncCount[i];
385                                         PPU.VMA.Mask1 = IncCount[i] * 8 - 1;
386                                         PPU.VMA.Shift = Shift[i];
387                                 }
388                                 else
389                                         PPU.VMA.FullGraphicCount = 0;
390                                 break;
391
392                         case 0x2116 :
393                                 // VRAM read/write address (low)
394                                 PPU.VMA.Address &= 0xFF00;
395                                 PPU.VMA.Address |= Byte;
396                                 IPPU.FirstVRAMRead = TRUE;
397                                 break;
398
399                         case 0x2117 :
400                                 // VRAM read/write address (high)
401                                 PPU.VMA.Address &= 0x00FF;
402                                 PPU.VMA.Address |= Byte << 8;
403                                 IPPU.FirstVRAMRead = TRUE;
404                                 break;
405
406                         case 0x2118 :
407                                 // VRAM write data (low)
408                                 IPPU.FirstVRAMRead = TRUE;
409                                 REGISTER_2118(Byte);
410                                 break;
411
412                         case 0x2119 :
413                                 // VRAM write data (high)
414                                 IPPU.FirstVRAMRead = TRUE;
415                                 REGISTER_2119(Byte);
416                                 break;
417
418                         case 0x211a :
419                                 // Mode 7 outside rotation area display mode and flipping
420                                 if (Byte != Memory.FillRAM[0x211a])
421                                 {
422                                         FLUSH_REDRAW();
423                                         PPU.Mode7Repeat = Byte >> 6;
424                                         PPU.Mode7VFlip = (Byte & 2) >> 1;
425                                         PPU.Mode7HFlip = Byte & 1;
426                                 }
427                                 break;
428                         case 0x211b :
429                                 // Mode 7 matrix A (low & high)
430                                 PPU.MatrixA = ((PPU.MatrixA >> 8) & 0xff) | (Byte << 8);
431                                 PPU.Need16x8Mulitply = TRUE;
432                                 break;
433                         case 0x211c :
434                                 // Mode 7 matrix B (low & high)
435                                 PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8);
436                                 PPU.Need16x8Mulitply = TRUE;
437                                 break;
438                         case 0x211d :
439                                 // Mode 7 matrix C (low & high)
440                                 PPU.MatrixC = ((PPU.MatrixC >> 8) & 0xff) | (Byte << 8);
441                                 break;
442                         case 0x211e :
443                                 // Mode 7 matrix D (low & high)
444                                 PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8);
445                                 break;
446                         case 0x211f :
447                                 // Mode 7 centre of rotation X (low & high)
448                                 PPU.CentreX = ((PPU.CentreX >> 8) & 0xff) | (Byte << 8);
449                                 break;
450                         case 0x2120 :
451                                 // Mode 7 centre of rotation Y (low & high)
452                                 PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8);
453                                 break;
454
455                         case 0x2121 :
456                                 // CG-RAM address
457                                 PPU.CGFLIP = 0;
458                                 PPU.CGFLIPRead = 0;
459                                 PPU.CGADD = Byte;
460                                 break;
461
462                         case 0x2122 :
463                                 REGISTER_2122(Byte);
464                                 break;
465
466                         case 0x2123 :
467                                 // Window 1 and 2 enable for backgrounds 1 and 2
468                                 if (Byte != Memory.FillRAM[0x2123])
469                                 {
470                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
471                                         FLUSH_REDRAW();
472
473                                         PPU.ClipWindow1Enable[0] = !!(Byte & 0x02);
474                                         PPU.ClipWindow1Enable[1] = !!(Byte & 0x20);
475                                         PPU.ClipWindow2Enable[0] = !!(Byte & 0x08);
476                                         PPU.ClipWindow2Enable[1] = !!(Byte & 0x80);
477                                         PPU.ClipWindow1Inside[0] = !(Byte & 0x01);
478                                         PPU.ClipWindow1Inside[1] = !(Byte & 0x10);
479                                         PPU.ClipWindow2Inside[0] = !(Byte & 0x04);
480                                         PPU.ClipWindow2Inside[1] = !(Byte & 0x40);
481                                         PPU.RecomputeClipWindows = TRUE;
482 #ifdef DEBUGGER
483                                         if (Byte & 0x80)
484                                                 missing.window2[1] = 1;
485                                         if (Byte & 0x20)
486                                                 missing.window1[1] = 1;
487                                         if (Byte & 0x08)
488                                                 missing.window2[0] = 1;
489                                         if (Byte & 0x02)
490                                                 missing.window1[0] = 1;
491 #endif
492                                 }
493                                 break;
494                         case 0x2124 :
495                                 // Window 1 and 2 enable for backgrounds 3 and 4
496                                 if (Byte != Memory.FillRAM[0x2124])
497                                 {
498                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
499                                         FLUSH_REDRAW();
500
501                                         PPU.ClipWindow1Enable[2] = !!(Byte & 0x02);
502                                         PPU.ClipWindow1Enable[3] = !!(Byte & 0x20);
503                                         PPU.ClipWindow2Enable[2] = !!(Byte & 0x08);
504                                         PPU.ClipWindow2Enable[3] = !!(Byte & 0x80);
505                                         PPU.ClipWindow1Inside[2] = !(Byte & 0x01);
506                                         PPU.ClipWindow1Inside[3] = !(Byte & 0x10);
507                                         PPU.ClipWindow2Inside[2] = !(Byte & 0x04);
508                                         PPU.ClipWindow2Inside[3] = !(Byte & 0x40);
509                                         PPU.RecomputeClipWindows = TRUE;
510 #ifdef DEBUGGER
511                                         if (Byte & 0x80)
512                                                 missing.window2[3] = 1;
513                                         if (Byte & 0x20)
514                                                 missing.window1[3] = 1;
515                                         if (Byte & 0x08)
516                                                 missing.window2[2] = 1;
517                                         if (Byte & 0x02)
518                                                 missing.window1[2] = 1;
519 #endif
520                                 }
521                                 break;
522                         case 0x2125 :
523                                 // Window 1 and 2 enable for objects and colour window
524                                 if (Byte != Memory.FillRAM[0x2125])
525                                 {
526                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
527                                         FLUSH_REDRAW();
528
529                                         PPU.ClipWindow1Enable[4] = !!(Byte & 0x02);
530                                         PPU.ClipWindow1Enable[5] = !!(Byte & 0x20);
531                                         PPU.ClipWindow2Enable[4] = !!(Byte & 0x08);
532                                         PPU.ClipWindow2Enable[5] = !!(Byte & 0x80);
533                                         PPU.ClipWindow1Inside[4] = !(Byte & 0x01);
534                                         PPU.ClipWindow1Inside[5] = !(Byte & 0x10);
535                                         PPU.ClipWindow2Inside[4] = !(Byte & 0x04);
536                                         PPU.ClipWindow2Inside[5] = !(Byte & 0x40);
537                                         PPU.RecomputeClipWindows = TRUE;
538 #ifdef DEBUGGER
539                                         if (Byte & 0x80)
540                                                 missing.window2[5] = 1;
541                                         if (Byte & 0x20)
542                                                 missing.window1[5] = 1;
543                                         if (Byte & 0x08)
544                                                 missing.window2[4] = 1;
545                                         if (Byte & 0x02)
546                                                 missing.window1[4] = 1;
547 #endif
548                                 }
549                                 break;
550                         case 0x2126 :
551                                 // Window 1 left position
552                                 if (Byte != Memory.FillRAM[0x2126])
553                                 {
554                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
555                                         FLUSH_REDRAW();
556
557                                         PPU.Window1Left = Byte;
558                                         PPU.RecomputeClipWindows = TRUE;
559                                 }
560                                 break;
561                         case 0x2127 :
562                                 // Window 1 right position
563                                 if (Byte != Memory.FillRAM[0x2127])
564                                 {
565                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
566                                         FLUSH_REDRAW();
567
568                                         PPU.Window1Right = Byte;
569                                         PPU.RecomputeClipWindows = TRUE;
570                                 }
571                                 break;
572                         case 0x2128 :
573                                 // Window 2 left position
574                                 if (Byte != Memory.FillRAM[0x2128])
575                                 {
576                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
577                                         FLUSH_REDRAW();
578
579                                         PPU.Window2Left = Byte;
580                                         PPU.RecomputeClipWindows = TRUE;
581                                 }
582                                 break;
583                         case 0x2129 :
584                                 // Window 2 right position
585                                 if (Byte != Memory.FillRAM[0x2129])
586                                 {
587                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
588                                         FLUSH_REDRAW();
589
590                                         PPU.Window2Right = Byte;
591                                         PPU.RecomputeClipWindows = TRUE;
592                                 }
593                                 break;
594                         case 0x212a :
595                                 // Windows 1 & 2 overlap logic for backgrounds 1 - 4
596                                 if (Byte != Memory.FillRAM[0x212a])
597                                 {
598                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
599                                         FLUSH_REDRAW();
600
601                                         PPU.ClipWindowOverlapLogic[0] = (Byte & 0x03);
602                                         PPU.ClipWindowOverlapLogic[1] = (Byte & 0x0c) >> 2;
603                                         PPU.ClipWindowOverlapLogic[2] = (Byte & 0x30) >> 4;
604                                         PPU.ClipWindowOverlapLogic[3] = (Byte & 0xc0) >> 6;
605                                         PPU.RecomputeClipWindows = TRUE;
606                                 }
607                                 break;
608                         case 0x212b :
609                                 // Windows 1 & 2 overlap logic for objects and colour window
610                                 if (Byte != Memory.FillRAM[0x212b])
611                                 {
612                                         if (Settings.os9x_hack&PPU_IGNORE_WINDOW) return;
613                                         FLUSH_REDRAW();
614
615                                         PPU.ClipWindowOverlapLogic[4] = Byte & 0x03;
616                                         PPU.ClipWindowOverlapLogic[5] = (Byte & 0x0c) >> 2;
617                                         PPU.RecomputeClipWindows = TRUE;
618                                 }
619                                 break;
620                         case 0x212c :
621                                 // Main screen designation (backgrounds 1 - 4 and objects)
622                                 if (Byte != Memory.FillRAM[0x212c])
623                                 {
624                                         FLUSH_REDRAW();
625
626                                         PPU.RecomputeClipWindows = TRUE;
627                                         Memory.FillRAM[Address] = Byte;
628                                         return;
629                                 }
630                                 break;
631                         case 0x212d :
632                                 // Sub-screen designation (backgrounds 1 - 4 and objects)
633                                 if (Byte != Memory.FillRAM[0x212d])
634                                 {
635                                         FLUSH_REDRAW();
636
637 #ifdef DEBUGGER
638                                         if (Byte & 0x1f)
639                                                 missing.subscreen = 1;
640 #endif
641                                         PPU.RecomputeClipWindows = TRUE;
642                                         Memory.FillRAM[Address] = Byte;
643                                         return;
644                                 }
645                                 break;
646                         case 0x212e :
647                                 // Window mask designation for main screen ?
648                                 if (Byte != Memory.FillRAM[0x212e])
649                                 {
650                                         FLUSH_REDRAW();
651
652                                         PPU.RecomputeClipWindows = TRUE;
653                                 }
654                                 break;
655                         case 0x212f :
656                                 // Window mask designation for sub-screen ?
657                                 if (Byte != Memory.FillRAM[0x212f])
658                                 {
659                                         FLUSH_REDRAW();
660
661                                         PPU.RecomputeClipWindows = TRUE;
662                                 }
663                                 break;
664                         case 0x2130 :
665                                 // Fixed colour addition or screen addition
666                                 if (Byte != Memory.FillRAM[0x2130])
667                                 {
668                                         if (Settings.os9x_hack&PPU_IGNORE_ADDSUB) return;
669                                         FLUSH_REDRAW();
670
671                                         PPU.RecomputeClipWindows = TRUE;
672 #ifdef DEBUGGER
673                                         if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4
674                                                 || PPU.BGMode == 7))
675                                                 missing.direct = 1;
676 #endif
677                                 }
678                                 break;
679                         case 0x2131 :
680                                 // Colour addition or subtraction select
681                                 if (Byte != Memory.FillRAM[0x2131])
682                                 {
683                                         if (Settings.os9x_hack&PPU_IGNORE_ADDSUB) return;
684                                         FLUSH_REDRAW();
685
686                                         // Backgrounds 1 - 4, objects and backdrop colour add/sub enable
687 #ifdef DEBUGGER
688                                         if (Byte & 0x80)
689                                         {
690                                                 // Subtract
691                                                 if (Memory.FillRAM[0x2130] & 0x02)
692                                                         missing.subscreen_sub = 1;
693                                                 else
694                                                         missing.fixed_colour_sub = 1;
695                                         }
696                                         else
697                                         {
698                                                 // Addition
699                                                 if (Memory.FillRAM[0x2130] & 0x02)
700                                                         missing.subscreen_add = 1;
701                                                 else
702                                                         missing.fixed_colour_add = 1;
703                                         }
704 #endif
705                                         Memory.FillRAM[0x2131] = Byte;
706                                 }
707                                 break;
708                         case 0x2132 :
709                                 if (Byte != Memory.FillRAM[0x2132])
710                                 {
711                                         int new_fixedcol;
712                                         //FLUSH_REDRAW ();
713                                         // Colour data for fixed colour addition/subtraction
714                                         if (Byte & 0x80) {
715                                                 //PPU.FixedColourBlue = Byte & 0x1f;
716                                                 new_fixedcol=(Byte & 0x1f);
717                                                 if (new_fixedcol!=PPU.FixedColourBlue) {if (!(Settings.os9x_hack&PPU_IGNORE_FIXEDCOLCHANGES)) FLUSH_REDRAW();PPU.FixedColourBlue=new_fixedcol;}
718                                         }
719                                         if (Byte & 0x40) {
720                                                 //PPU.FixedColourGreen = Byte & 0x1f;
721                                                 new_fixedcol=(Byte & 0x1f);
722                                                 if (new_fixedcol!=PPU.FixedColourGreen) {if (!(Settings.os9x_hack&PPU_IGNORE_FIXEDCOLCHANGES)) FLUSH_REDRAW();PPU.FixedColourGreen=new_fixedcol;}
723                                         }
724                                         if (Byte & 0x20) {
725                                                 //PPU.FixedColourRed = Byte & 0x1f;
726                                                 new_fixedcol=(Byte & 0x1f);
727                                                 if (new_fixedcol!=PPU.FixedColourRed) {if (!(Settings.os9x_hack&PPU_IGNORE_FIXEDCOLCHANGES)) FLUSH_REDRAW();PPU.FixedColourRed=new_fixedcol;}
728                                         }
729
730                                         /*FLUSH_REDRAW ();
731                                         // Colour data for fixed colour addition/subtraction
732                                         if (Byte & 0x80)
733                                                 PPU.FixedColourBlue = Byte & 0x1f;
734                                         if (Byte & 0x40)
735                                                 PPU.FixedColourGreen = Byte & 0x1f;
736                                         if (Byte & 0x20)
737                                         PPU.FixedColourRed = Byte & 0x1f;*/
738
739                                 }
740                                 break;
741                         case 0x2133 :
742                                 // Screen settings
743                                 if (Byte != Memory.FillRAM[0x2133])
744                                 {
745 #ifdef DEBUGGER
746                                         if (Byte & 0x40)
747                                                 missing.mode7_bgmode = 1;
748                                         if (Byte & 0x08)
749                                                 missing.pseudo_512 = 1;
750 #endif
751                                         if (Byte & 0x04)
752                                         {
753                                                 PPU.ScreenHeight = SNES_HEIGHT_EXTENDED;
754 #ifdef DEBUGGER
755                                                 missing.lines_239 = 1;
756 #endif
757                                         }
758                                         else
759                                                 PPU.ScreenHeight = SNES_HEIGHT;
760 #ifdef DEBUGGER
761                                         if (Byte & 0x02)
762                                                 missing.sprite_double_height = 1;
763
764                                         if (Byte & 1)
765                                                 missing.interlace = 1;
766 #endif
767                                 }
768                                 break;
769                         case 0x2134 :
770                         case 0x2135 :
771                         case 0x2136 :
772                                 // Matrix 16bit x 8bit multiply result (read-only)
773                                 return;
774
775                         case 0x2137 :
776                                 // Software latch for horizontal and vertical timers (read-only)
777                                 return;
778                         case 0x2138 :
779                                 // OAM read data (read-only)
780                                 return;
781                         case 0x2139 :
782                         case 0x213a :
783                                 // VRAM read data (read-only)
784                                 return;
785                         case 0x213b :
786                                 // CG-RAM read data (read-only)
787                                 return;
788                         case 0x213c :
789                         case 0x213d :
790                                 // Horizontal and vertical (low/high) read counter (read-only)
791                                 return;
792                         case 0x213e :
793                                 // PPU status (time over and range over)
794                                 return;
795                         case 0x213f :
796                                 // NTSC/PAL select and field (read-only)
797                                 return;
798                         case 0x2140 :
799                         case 0x2141 :
800                         case 0x2142 :
801                         case 0x2143 :
802                         case 0x2144 :
803                         case 0x2145 :
804                         case 0x2146 :
805                         case 0x2147 :
806                         case 0x2148 :
807                         case 0x2149 :
808                         case 0x214a :
809                         case 0x214b :
810                         case 0x214c :
811                         case 0x214d :
812                         case 0x214e :
813                         case 0x214f :
814                         case 0x2150 :
815                         case 0x2151 :
816                         case 0x2152 :
817                         case 0x2153 :
818                         case 0x2154 :
819                         case 0x2155 :
820                         case 0x2156 :
821                         case 0x2157 :
822                         case 0x2158 :
823                         case 0x2159 :
824                         case 0x215a :
825                         case 0x215b :
826                         case 0x215c :
827                         case 0x215d :
828                         case 0x215e :
829                         case 0x215f :
830                         case 0x2160 :
831                         case 0x2161 :
832                         case 0x2162 :
833                         case 0x2163 :
834                         case 0x2164 :
835                         case 0x2165 :
836                         case 0x2166 :
837                         case 0x2167 :
838                         case 0x2168 :
839                         case 0x2169 :
840                         case 0x216a :
841                         case 0x216b :
842                         case 0x216c :
843                         case 0x216d :
844                         case 0x216e :
845                         case 0x216f :
846                         case 0x2170 :
847                         case 0x2171 :
848                         case 0x2172 :
849                         case 0x2173 :
850                         case 0x2174 :
851                         case 0x2175 :
852                         case 0x2176 :
853                         case 0x2177 :
854                         case 0x2178 :
855                         case 0x2179 :
856                         case 0x217a :
857                         case 0x217b :
858                         case 0x217c :
859                         case 0x217d :
860                         case 0x217e :
861                         case 0x217f :
862 #ifdef SPCTOOL
863                                 _SPCInPB(Address & 3, Byte);
864 #else
865                                 //      CPU.Flags |= DEBUG_MODE_FLAG;
866                                 Memory.FillRAM[Address] = Byte;
867                                 IAPU.RAM[(Address & 3) + 0xf4] = Byte;
868         #ifdef SPC700_SHUTDOWN
869                                 CPU.APU_APUExecuting = Settings.APUEnabled;
870                                 IAPU.WaitCounter++;
871         #endif 
872 #endif // SPCTOOL
873                                 break;
874                         case 0x2180 :
875                                 REGISTER_2180(Byte);
876                                 break;
877                         case 0x2181 :
878                                 PPU.WRAM &= 0x1FF00;
879                                 PPU.WRAM |= Byte;
880                                 break;
881                         case 0x2182 :
882                                 PPU.WRAM &= 0x100FF;
883                                 PPU.WRAM |= Byte << 8;
884                                 break;
885                         case 0x2183 :
886                                 PPU.WRAM &= 0x0FFFF;
887                                 PPU.WRAM |= Byte << 16;
888                                 PPU.WRAM &= 0x1FFFF;
889                                 break;
890                 }
891         }
892         else
893         {
894 #ifdef USE_SA1
895                 if (Settings.SA1)
896                 {
897                         if (Address >= 0x2200 && Address < 0x23ff)
898                                 S9xSetSA1(Byte, Address);
899                         else
900                                 Memory.FillRAM[Address] = Byte;
901                         return;
902                 }
903                 else
904 #endif
905                         // Dai Kaijyu Monogatari II
906                         if (Address == 0x2801 && Settings.SRTC)
907                                 S9xSetSRTC(Byte, Address);
908                         else if (Address < 0x3000 || Address >= 0x3000 + 768)
909                         {
910 #ifdef DEBUGGER
911                                 missing.unknownppu_write = Address;
912                                 if (Settings.TraceUnknownRegisters)
913                                 {
914                                         sprintf(
915                                                 String,
916                                                 "Unknown register write: $%02X->$%04X\n",
917                                                 Byte,
918                                                 Address);
919                                         S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
920                                 }
921 #endif
922                         }
923                         else
924                         {
925                                 if (!Settings.SuperFX)
926                                         return;
927
928                                         switch (Address)
929                                         {
930                                                 case 0x3030 :
931                                                         if ((Memory.FillRAM[0x3030] ^ Byte) & FLG_G)
932                                                         {
933                                                                 Memory.FillRAM[Address] = Byte;
934                                                                 // Go flag has been changed
935                                                                 if (Byte & FLG_G)
936                                                                         S9xSuperFXExec();
937                                                                 else
938                                                                         FxFlushCache();
939                                                         }
940                                                         else
941                                                                 Memory.FillRAM[Address] = Byte;
942                                                         break;
943
944                                                 case 0x3031 :
945                                                         Memory.FillRAM[Address] = Byte;
946                                                         break;
947                                                 case 0x3033 :
948                                                         Memory.FillRAM[Address] = Byte;
949                                                         break;
950                                                 case 0x3034 :
951                                                         Memory.FillRAM[Address] = Byte & 0x7f;
952                                                         break;
953                                                 case 0x3036 :
954                                                         Memory.FillRAM[Address] = Byte & 0x7f;
955                                                         break;
956                                                 case 0x3037 :
957                                                         Memory.FillRAM[Address] = Byte;
958                                                         break;
959                                                 case 0x3038 :
960                                                         Memory.FillRAM[Address] = Byte;
961                                                         break;
962                                                 case 0x3039 :
963                                                         Memory.FillRAM[Address] = Byte;
964                                                         break;
965                                                 case 0x303a :
966                                                         Memory.FillRAM[Address] = Byte;
967                                                         break;
968                                                 case 0x303b :
969                                                         break;
970                                                 case 0x303f :
971                                                         Memory.FillRAM[Address] = Byte;
972                                                         break;
973                                                 case 0x301f :
974                                                         Memory.FillRAM[Address] = Byte;
975                                                         Memory.FillRAM[0x3000 + GSU_SFR] |= FLG_G;
976                                                         S9xSuperFXExec();
977                                                         return;
978
979                                                 default :
980                                                         Memory.FillRAM[Address] = Byte;
981                                                         if (Address >= 0x3100)
982                                                         {
983                                                                 FxCacheWriteAccess(Address);
984                                                         }
985                                                         break;
986                                         }
987                                         return;
988                         }
989         }
990         Memory.FillRAM[Address] = Byte;
991 }
992
993 /**********************************************************************************************/
994 /* S9xGetPPU()                                                                                   */
995 /* This function retrieves a PPU Register                                                     */
996 /**********************************************************************************************/
997 uint8 S9xGetPPU(uint16 Address)
998 {
999         uint8 byte = 0;
1000
1001         if (Address <= 0x2190)
1002         {
1003                 switch (Address)
1004                 {
1005                         case 0x2100 :
1006                         case 0x2101 :
1007                                 return (Memory.FillRAM[Address]);
1008                         case 0x2102 :
1009 #ifdef DEBUGGER
1010                                 missing.oam_address_read = 1;
1011 #endif
1012                                 return (uint8) (PPU.OAMAddr);
1013                         case 0x2103 :
1014                                 return (((PPU.OAMAddr >> 8) & 1) | (PPU.OAMPriorityRotation << 7));
1015                         case 0x2104 :
1016                         case 0x2105 :
1017                         case 0x2106 :
1018                         case 0x2107 :
1019                         case 0x2108 :
1020                         case 0x2109 :
1021                         case 0x210a :
1022                         case 0x210b :
1023                         case 0x210c :
1024                                 return (Memory.FillRAM[Address]);
1025                         case 0x210d :
1026                         case 0x210e :
1027                         case 0x210f :
1028                         case 0x2110 :
1029                         case 0x2111 :
1030                         case 0x2112 :
1031                         case 0x2113 :
1032                         case 0x2114 :
1033 #ifdef DEBUGGER
1034                                 missing.bg_offset_read = 1;
1035 #endif
1036                                 return (Memory.FillRAM[Address]);
1037                         case 0x2115 :
1038                                 return (Memory.FillRAM[Address]);
1039                         case 0x2116 :
1040                                 return (uint8) (PPU.VMA.Address);
1041                         case 0x2117 :
1042                                 return (PPU.VMA.Address >> 8);
1043                         case 0x2118 :
1044                         case 0x2119 :
1045                         case 0x211a :
1046                                 return (Memory.FillRAM[Address]);
1047                         case 0x211b :
1048                         case 0x211c :
1049                         case 0x211d :
1050                         case 0x211e :
1051                         case 0x211f :
1052                         case 0x2120 :
1053 #ifdef DEBUGGER
1054                                 missing.matrix_read = 1;
1055 #endif
1056                                 return (Memory.FillRAM[Address]);
1057                         case 0x2121 :
1058                                 return (PPU.CGADD);
1059                         case 0x2122 :
1060                         case 0x2123 :
1061                         case 0x2124 :
1062                         case 0x2125 :
1063                         case 0x2126 :
1064                         case 0x2127 :
1065                         case 0x2128 :
1066                         case 0x2129 :
1067                         case 0x212a :
1068                         case 0x212b :
1069                         case 0x212c :
1070                         case 0x212d :
1071                         case 0x212e :
1072                         case 0x212f :
1073                         case 0x2130 :
1074                         case 0x2131 :
1075                         case 0x2132 :
1076                         case 0x2133 :
1077                                 return (Memory.FillRAM[Address]);
1078
1079                         case 0x2134 :
1080                         case 0x2135 :
1081                         case 0x2136 :
1082                                 // 16bit x 8bit multiply read result.
1083                                 if (PPU.Need16x8Mulitply)
1084                                 {
1085                                         int32 r = (int32) PPU.MatrixA * (int32) (PPU.MatrixB >> 8);
1086
1087                                         Memory.FillRAM[0x2134] = (uint8) r;
1088                                         Memory.FillRAM[0x2135] = (uint8) (r >> 8);
1089                                         Memory.FillRAM[0x2136] = (uint8) (r >> 16);
1090                                         PPU.Need16x8Mulitply = FALSE;
1091                                 }
1092 #ifdef DEBUGGER
1093                                 missing.matrix_multiply = 1;
1094 #endif
1095                                 return (Memory.FillRAM[Address]);
1096                         case 0x2137 :
1097                                 // Latch h and v counters
1098 #ifdef DEBUGGER
1099                                 missing.h_v_latch = 1;
1100 #endif
1101 #if 0
1102         #ifdef CPU_SHUTDOWN
1103                                 CPU.WaitAddress = CPU.PCAtOpcodeStart;
1104         #endif
1105 #endif
1106                                 PPU.HVBeamCounterLatched = 1;
1107                                 PPU.VBeamPosLatched = (uint16)
1108                                 CPU.V_Counter;
1109                                 PPU.HBeamPosLatched = (uint16) ((CPU.Cycles * SNES_HCOUNTER_MAX) / Settings.H_Max);
1110
1111                                 // Causes screen flicker for Yoshi's Island if uncommented
1112                                 //CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE);
1113
1114                                 if (SNESGameFixes.NeedInit0x2137)
1115                                         PPU.VBeamFlip = 0; //jyam sword world sfc2 & godzill
1116                                 return (0);
1117                         case 0x2138 :
1118                                 // Read OAM (sprite) control data
1119                                 if (!PPU.OAMReadFlip)
1120                                 {
1121                                         byte = PPU.OAMData[PPU.OAMAddr << 1];
1122                                 }
1123                                 else
1124                                 {
1125                                         byte = PPU.OAMData[(PPU.OAMAddr << 1) + 1];
1126                                         if (++PPU.OAMAddr >= 0x110)
1127                                                 PPU.OAMAddr = 0;
1128                                 }
1129                                 PPU.OAMReadFlip ^= 1;
1130 #ifdef DEBUGGER
1131                                 missing.oam_read = 1;
1132 #endif
1133                                 return (byte);
1134
1135                         case 0x2139 :
1136                                 // Read vram low byte
1137 #ifdef DEBUGGER
1138                                 missing.vram_read = 1;
1139 #endif
1140                                 if (IPPU.FirstVRAMRead)
1141                                         byte = Memory.VRAM[PPU.VMA.Address << 1];
1142                                 else if (PPU.VMA.FullGraphicCount)
1143                                 {
1144                                         uint32 addr = PPU.VMA.Address - 1;
1145                                         uint32 rem = addr & PPU.VMA.Mask1;
1146                                         uint32 address =
1147                                                 (addr & ~PPU.VMA.Mask1)
1148                                                         + (rem >> PPU.VMA.Shift)
1149                                                         + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
1150                                         byte = Memory.VRAM[((address << 1) - 2) & 0xFFFF];
1151                                 }
1152                                 else
1153                                         byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff];
1154
1155                                 if (!PPU.VMA.High)
1156                                 {
1157                                         PPU.VMA.Address += PPU.VMA.Increment;
1158                                         IPPU.FirstVRAMRead = FALSE;
1159                                 }
1160                                 break;
1161                         case 0x213A :
1162                                 // Read vram high byte
1163 #ifdef DEBUGGER
1164                                 missing.vram_read = 1;
1165 #endif
1166                                 if (IPPU.FirstVRAMRead)
1167                                         byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff];
1168                                 else if (PPU.VMA.FullGraphicCount)
1169                                 {
1170                                         uint32 addr = PPU.VMA.Address - 1;
1171                                         uint32 rem = addr & PPU.VMA.Mask1;
1172                                         uint32 address =
1173                                                 (addr & ~PPU.VMA.Mask1)
1174                                                         + (rem >> PPU.VMA.Shift)
1175                                                         + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
1176                                         byte = Memory.VRAM[((address << 1) - 1) & 0xFFFF];
1177                                 }
1178                                 else
1179                                         byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xFFFF];
1180                                 if (PPU.VMA.High)
1181                                 {
1182                                         PPU.VMA.Address += PPU.VMA.Increment;
1183                                         IPPU.FirstVRAMRead = FALSE;
1184                                 }
1185                                 break;
1186
1187                         case 0x213B :
1188                                 // Read palette data
1189 #ifdef DEBUGGER
1190                                 missing.cgram_read = 1;
1191 #endif
1192                                 if (PPU.CGFLIPRead)
1193                                         byte = PPU.CGDATA[PPU.CGADD++] >> 8;
1194                                 else
1195                                         byte = PPU.CGDATA[PPU.CGADD] & 0xff;
1196
1197                                 PPU.CGFLIPRead ^= 1;
1198                                 return (byte);
1199
1200                         case 0x213C :
1201                                 // Horizontal counter value 0-339
1202 #ifdef DEBUGGER
1203                                 missing.h_counter_read = 1;
1204 #endif
1205                                 if (PPU.HBeamFlip)
1206                                         byte = PPU.HBeamPosLatched >> 8;
1207                                 else
1208                                         byte = (uint8) PPU.HBeamPosLatched;
1209                                 PPU.HBeamFlip ^= 1;
1210                                 break;
1211                         case 0x213D :
1212                                 // Vertical counter value 0-262
1213 #ifdef DEBUGGER
1214                                 missing.v_counter_read = 1;
1215 #endif
1216                                 if (PPU.VBeamFlip)
1217                                         byte = PPU.VBeamPosLatched >> 8;
1218                                 else
1219                                         byte = (uint8) PPU.VBeamPosLatched;
1220                                 PPU.VBeamFlip ^= 1;
1221                                 break;
1222                         case 0x213E :
1223                                 // PPU time and range over flags
1224                                 return (SNESGameFixes._0x213E_ReturnValue);
1225
1226                         case 0x213F :
1227                                 // NTSC/PAL and which field flags
1228                                 PPU.VBeamFlip = PPU.HBeamFlip = 0;
1229                                 return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0));
1230
1231                         case 0x2140 :
1232                         case 0x2141 :
1233                         case 0x2142 :
1234                         case 0x2143 :
1235                         case 0x2144 :
1236                         case 0x2145 :
1237                         case 0x2146 :
1238                         case 0x2147 :
1239                         case 0x2148 :
1240                         case 0x2149 :
1241                         case 0x214a :
1242                         case 0x214b :
1243                         case 0x214c :
1244                         case 0x214d :
1245                         case 0x214e :
1246                         case 0x214f :
1247                         case 0x2150 :
1248                         case 0x2151 :
1249                         case 0x2152 :
1250                         case 0x2153 :
1251                         case 0x2154 :
1252                         case 0x2155 :
1253                         case 0x2156 :
1254                         case 0x2157 :
1255                         case 0x2158 :
1256                         case 0x2159 :
1257                         case 0x215a :
1258                         case 0x215b :
1259                         case 0x215c :
1260                         case 0x215d :
1261                         case 0x215e :
1262                         case 0x215f :
1263                         case 0x2160 :
1264                         case 0x2161 :
1265                         case 0x2162 :
1266                         case 0x2163 :
1267                         case 0x2164 :
1268                         case 0x2165 :
1269                         case 0x2166 :
1270                         case 0x2167 :
1271                         case 0x2168 :
1272                         case 0x2169 :
1273                         case 0x216a :
1274                         case 0x216b :
1275                         case 0x216c :
1276                         case 0x216d :
1277                         case 0x216e :
1278                         case 0x216f :
1279                         case 0x2170 :
1280                         case 0x2171 :
1281                         case 0x2172 :
1282                         case 0x2173 :
1283                         case 0x2174 :
1284                         case 0x2175 :
1285                         case 0x2176 :
1286                         case 0x2177 :
1287                         case 0x2178 :
1288                         case 0x2179 :
1289                         case 0x217a :
1290                         case 0x217b :
1291                         case 0x217c :
1292                         case 0x217d :
1293                         case 0x217e :
1294                         case 0x217f :
1295 #ifdef SPCTOOL
1296                                 return ((uint8) _SPCOutP[Address & 3]);
1297 #else
1298                                 //      CPU.Flags |= DEBUG_MODE_FLAG;
1299         #ifdef SPC700_SHUTDOWN
1300                                 CPU.APU_APUExecuting =  Settings.APUEnabled;
1301                                 IAPU.WaitCounter++;
1302         #endif
1303                                 if(Settings.APUEnabled)
1304                                 {
1305         #ifdef CPU_SHUTDOWN
1306                                         //CPU.WaitAddress = CPU.PCAtOpcodeStart;
1307         #endif
1308                                         if(SNESGameFixes.APU_OutPorts_ReturnValueFix
1309                                                 && Address >= 0x2140
1310                                                 && Address <= 0x2143
1311                                                 && !CPU.V_Counter)
1312                                         {
1313                                                 return (uint8) ((Address & 1) ? 
1314                                                         ((rand() & 0xff00) >> 8) : (rand() & 0xff));
1315                                         }
1316
1317                                         return (APU.OutPorts[Address & 3]);
1318                                 }
1319
1320                                 switch (Settings.SoundSkipMethod)
1321                                 {
1322                                         case 0 :
1323                                         case 1 :
1324                                                 CPU.BranchSkip = TRUE;
1325                                                 break;
1326                                         case 2 :
1327                                                 break;
1328                                         case 3 :
1329                                                 CPU.BranchSkip = TRUE;
1330                                                 break;
1331                                 }
1332                                 if ((Address & 3) < 2)
1333                                 {
1334                                         int r = rand();
1335                                         if (r & 2)
1336                                         {
1337                                                 if (r & 4)
1338                                                         return ((Address & 3) == 1 ? 0xaa : 0xbb);
1339                                                 else
1340                                                         return ((r >> 3) & 0xff);
1341                                         }
1342                                 }
1343                                 else
1344                                 {
1345                                         int r = rand();
1346                                         if (r & 2)
1347                                                 return ((r >> 3) & 0xff);
1348                                 }
1349                                 return (Memory.FillRAM[Address]);
1350 #endif // SPCTOOL
1351
1352                         case 0x2180 :
1353                                 // Read WRAM
1354 #ifdef DEBUGGER
1355                                 missing.wram_read = 1;
1356 #endif
1357                                 byte = Memory.RAM[PPU.WRAM++];
1358                                 PPU.WRAM &= 0x1FFFF;
1359                                 break;
1360                         case 0x2181 :
1361                         case 0x2182 :
1362                         case 0x2183 :
1363                                 return (Memory.FillRAM[Address]);
1364                         case 0x2190 :
1365                                 return (1);
1366                 }
1367         }
1368         else
1369         {
1370 #ifdef USE_SA1
1371                 if (Settings.SA1)
1372                         return (S9xGetSA1(Address));
1373 #endif
1374                 if (Address <= 0x2fff || Address >= 0x3000 + 768)
1375                 {
1376                         switch (Address)
1377                         {
1378                                 case 0x21c2 :
1379                                         return (0x20);
1380                                 case 0x21c3 :
1381                                         return (0);
1382                                 case 0x2800 :
1383                                         // For Dai Kaijyu Monogatari II
1384                                         if (Settings.SRTC)
1385                                                 return (S9xGetSRTC(Address));
1386                                         /*FALL*/
1387
1388                                 default :
1389 #ifdef DEBUGGER
1390                                         missing.unknownppu_read = Address;
1391                                         if (Settings.TraceUnknownRegisters)
1392                                         {
1393                                                 sprintf(String, "Unknown register read: $%04X\n", Address);
1394                                                 S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
1395                                         }
1396 #endif
1397                                         // XXX:
1398                                         return (0); //Memory.FillRAM[Address]);
1399                         }
1400                 }
1401
1402                 if (!Settings.SuperFX)
1403                         return (0x30);
1404                         byte = Memory.FillRAM[Address];
1405
1406                 //if (Address != 0x3030 && Address != 0x3031)
1407                 //printf ("%04x\n", Address);
1408         #ifdef CPU_SHUTDOWN
1409                 if (Address == 0x3030)
1410                 {
1411                         CPU.WaitAddress = CPU.PCAtOpcodeStart;
1412                 }
1413                 else
1414         #endif
1415                 if (Address == 0x3031)
1416                 {
1417                         CLEAR_IRQ_SOURCE(GSU_IRQ_SOURCE);
1418                         Memory.FillRAM[0x3031] = byte & 0x7f;
1419                 }
1420                 return (byte);
1421         }
1422
1423         return (byte);
1424 }
1425
1426 /**********************************************************************************************/
1427 /* S9xSetCPU()                                                                                   */
1428 /* This function sets a CPU/DMA Register to a specific byte                                   */
1429 /**********************************************************************************************/
1430 void S9xSetCPU(uint8 byte, uint16 Address)
1431 {
1432         int d;
1433
1434         if (Address < 0x4200)
1435         {
1436 #ifdef VAR_CYCLES
1437                 CPU.Cycles += ONE_CYCLE;
1438 #endif
1439                 switch (Address)
1440                 {
1441                         case 0x4016 :
1442                                 // S9xReset reading of old-style joypads
1443                                 if ((byte & 1) && !(Memory.FillRAM[Address] & 1))
1444                                 {
1445                                         PPU.Joypad1ButtonReadPos = 0;
1446                                         PPU.Joypad2ButtonReadPos = 0;
1447                                         PPU.Joypad3ButtonReadPos = 0;
1448                                 }
1449                                 break;
1450                         case 0x4017 :
1451                                 break;
1452                         default :
1453 #ifdef DEBUGGER
1454                                 missing.unknowncpu_write = Address;
1455                                 if (Settings.TraceUnknownRegisters)
1456                                 {
1457                                         sprintf(String, "Unknown register register write: $%02X->$%04X\n", byte, Address);
1458                                         S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
1459                                 }
1460 #endif
1461                                 break;
1462                 }
1463         }
1464         else
1465                 switch (Address)
1466                 {
1467                         case 0x4200 :
1468                                 // NMI, V & H IRQ and joypad reading enable flags
1469                                 if ((byte & 0x20)
1470                                         && (!SNESGameFixes.umiharakawaseFix || PPU.IRQVBeamPos < 209))
1471                                 {
1472                                         if (!PPU.VTimerEnabled)
1473                                         {
1474 #ifdef DEBUGGER
1475                                                 missing.virq = 1;
1476                                                 missing.virq_pos = PPU.IRQVBeamPos;
1477 #endif
1478                                                 PPU.VTimerEnabled = TRUE;
1479                                                 if (PPU.HTimerEnabled)
1480                                                         S9xUpdateHTimer();
1481                                                 else if (PPU.IRQVBeamPos == CPU.V_Counter)
1482                                                         S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE);
1483                                         }
1484                                 }
1485                                 else
1486                                 {
1487                                         PPU.VTimerEnabled = FALSE;
1488 #ifndef RC_OPTIMIZED
1489                                         if (SNESGameFixes.umiharakawaseFix)
1490                                                 byte &= ~0x20;
1491 #endif
1492                                 }
1493
1494                                 if (byte & 0x10)
1495                                 {
1496                                         if (!PPU.HTimerEnabled)
1497                                         {
1498 #ifdef DEBUGGER
1499                                                 missing.hirq = 1;
1500                                                 missing.hirq_pos = PPU.IRQHBeamPos;
1501 #endif
1502                                                 PPU.HTimerEnabled = TRUE;
1503                                                 S9xUpdateHTimer();
1504                                         }
1505                                 }
1506                                 else
1507                                 {
1508                                         // No need to check for HTimer being disabled as the scanline
1509                                         // event trigger code won't trigger an H-IRQ unless its enabled.
1510                                         PPU.HTimerEnabled = FALSE;
1511                                         PPU.HTimerPosition = Settings.H_Max + 1;
1512                                 }
1513
1514 #ifndef RC_OPTIMIZED
1515                                 if (!Settings.DaffyDuck)
1516                                         CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE);
1517
1518                                 if ((byte & 0x80)
1519                                         && !(Memory.FillRAM[0x4200] & 0x80)
1520                                         && CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE
1521                                         && CPU.V_Counter <= PPU.ScreenHeight + (SNESGameFixes.alienVSpredetorFix ? 25 : 15)
1522                                         && //jyam 15->25 alien vs predetor
1523                                 // Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling
1524                                 // NMIs again. The NMI routine crashes the CPU if it is called without the NMI
1525                                 // pending flag being set...
1526                                  (Memory.FillRAM[0x4210] & 0x80) && !CPU.NMIActive)
1527                                 {
1528                                         CPU.Flags |= NMI_FLAG;
1529                                         CPU.NMIActive = TRUE;
1530                                         CPU.NMICycleCount = CPU.NMITriggerPoint;
1531                                 }
1532 #endif
1533                                 break;
1534                         case 0x4201 :
1535                                 // I/O port output 
1536                         case 0x4202 :
1537                                 // Multiplier (for multply)
1538                                 break;
1539                         case 0x4203 :
1540                                 {
1541                                         // Multiplicand
1542                                         uint32 res = Memory.FillRAM[0x4202] * byte;
1543
1544                                         Memory.FillRAM[0x4216] = (uint8) res;
1545                                         Memory.FillRAM[0x4217] = (uint8) (res >> 8);
1546                                         break;
1547                                 }
1548                         case 0x4204 :
1549                         case 0x4205 :
1550                                 // Low and high muliplier (for divide)
1551                                 break;
1552                         case 0x4206 :
1553                                 {
1554                                         // Divisor
1555                                         uint16 a =
1556                                                 Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8);
1557                                         uint16 div = byte ? a / byte : 0xffff;
1558                                         uint16 rem = byte ? a % byte : a;
1559
1560                                         Memory.FillRAM[0x4214] = (uint8) div;
1561                                         Memory.FillRAM[0x4215] = div >> 8;
1562                                         Memory.FillRAM[0x4216] = (uint8) rem;
1563                                         Memory.FillRAM[0x4217] = rem >> 8;
1564                                         break;
1565                                 }
1566                         case 0x4207 :
1567                                 d = PPU.IRQHBeamPos;
1568                                 PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte;
1569
1570                                 if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d)
1571                                         S9xUpdateHTimer();
1572                                 break;
1573
1574                         case 0x4208 :
1575                                 d = PPU.IRQHBeamPos;
1576                                 PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8);
1577
1578                                 if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d)
1579                                         S9xUpdateHTimer();
1580
1581                                 break;
1582
1583                         case 0x4209 :
1584                                 d = PPU.IRQVBeamPos;
1585                                 PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte;
1586 #ifdef DEBUGGER
1587                                 missing.virq_pos = PPU.IRQVBeamPos;
1588 #endif
1589                                 if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d)
1590                                 {
1591                                         if (PPU.HTimerEnabled)
1592                                                 S9xUpdateHTimer();
1593                                         else
1594                                         {
1595                                                 if (PPU.IRQVBeamPos == CPU.V_Counter)
1596                                                         S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE);
1597                                         }
1598                                 }
1599                                 break;
1600
1601                         case 0x420A :
1602                                 d = PPU.IRQVBeamPos;
1603                                 PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8);
1604 #ifdef DEBUGGER
1605                                 missing.virq_pos = PPU.IRQVBeamPos;
1606 #endif
1607                                 if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d)
1608                                 {
1609                                         if (PPU.HTimerEnabled)
1610                                                 S9xUpdateHTimer();
1611                                         else
1612                                         {
1613                                                 if (PPU.IRQVBeamPos == CPU.V_Counter)
1614                                                         S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE);
1615                                         }
1616                                 }
1617                                 break;
1618
1619                         case 0x420B :
1620 #ifdef DEBUGGER
1621                                 missing.dma_this_frame = byte;
1622                                 missing.dma_channels = byte;
1623 #endif
1624                                 if ((byte & 0x01) != 0)
1625                                         S9xDoDMA(0);
1626                                 if ((byte & 0x02) != 0)
1627                                         S9xDoDMA(1);
1628                                 if ((byte & 0x04) != 0)
1629                                         S9xDoDMA(2);
1630                                 if ((byte & 0x08) != 0)
1631                                         S9xDoDMA(3);
1632                                 if ((byte & 0x10) != 0)
1633                                         S9xDoDMA(4);
1634                                 if ((byte & 0x20) != 0)
1635                                         S9xDoDMA(5);
1636                                 if ((byte & 0x40) != 0)
1637                                         S9xDoDMA(6);
1638                                 if ((byte & 0x80) != 0)
1639                                         S9xDoDMA(7);
1640                                 break;
1641                         case 0x420C :
1642 #ifdef DEBUGGER
1643                                 missing.hdma_this_frame |= byte;
1644                                 missing.hdma_channels |= byte;
1645 #endif
1646                                 if (Settings.DisableHDMA)
1647                                         byte = 0;
1648                                 Memory.FillRAM[0x420c] = byte;
1649                                 IPPU.HDMA = byte;
1650                                 break;
1651
1652                         case 0x420d :
1653                                 // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +)
1654                                 if ((byte & 1) != (Memory.FillRAM[0x420d] & 1))
1655                                 {
1656                                         if (byte & 1)
1657                                         {
1658                                                 CPU.FastROMSpeed = ONE_CYCLE;
1659 #ifdef DEBUGGER
1660                                                 missing.fast_rom = 1;
1661 #endif
1662                                         }
1663                                         else
1664                                                 CPU.FastROMSpeed = SLOW_ONE_CYCLE;
1665
1666                                         Memory.FixROMSpeed();
1667                                 }
1668                                 /* FALL */
1669                         case 0x420e :
1670                         case 0x420f :
1671                                 // --->>> Unknown
1672                                 break;
1673                         case 0x4210 :
1674                                 // NMI ocurred flag (reset on read or write)
1675                                 Memory.FillRAM[0x4210] = 0;
1676                                 return;
1677                         case 0x4211 :
1678                                 // IRQ ocurred flag (reset on read or write)
1679                                 CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE);
1680                                 break;
1681                         case 0x4212 :
1682                                 // v-blank, h-blank and joypad being scanned flags (read-only)
1683                         case 0x4213 :
1684                                 // I/O Port (read-only)
1685                         case 0x4214 :
1686                         case 0x4215 :
1687                                 // Quotent of divide (read-only)
1688                         case 0x4216 :
1689                         case 0x4217 :
1690                                 // Multiply product (read-only)
1691                                 return;
1692                         case 0x4218 :
1693                         case 0x4219 :
1694                         case 0x421a :
1695                         case 0x421b :
1696                         case 0x421c :
1697                         case 0x421d :
1698                         case 0x421e :
1699                         case 0x421f :
1700                                 // Joypad values (read-only)
1701                                 return;
1702
1703                         case 0x4300 :
1704                         case 0x4310 :
1705                         case 0x4320 :
1706                         case 0x4330 :
1707                         case 0x4340 :
1708                         case 0x4350 :
1709                         case 0x4360 :
1710                         case 0x4370 :
1711                                 d = (Address >> 4) & 0x7;
1712                                 DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0;
1713                                 DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0;
1714                                 DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0;
1715                                 DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0;
1716                                 DMA[d].TransferMode = (byte & 7);
1717                                 break;
1718
1719                         case 0x4301 :
1720                         case 0x4311 :
1721                         case 0x4321 :
1722                         case 0x4331 :
1723                         case 0x4341 :
1724                         case 0x4351 :
1725                         case 0x4361 :
1726                         case 0x4371 :
1727                                 DMA[((Address >> 4) & 0x7)].BAddress = byte;
1728                                 break;
1729
1730                         case 0x4302 :
1731                         case 0x4312 :
1732                         case 0x4322 :
1733                         case 0x4332 :
1734                         case 0x4342 :
1735                         case 0x4352 :
1736                         case 0x4362 :
1737                         case 0x4372 :
1738                                 d = (Address >> 4) & 0x7;
1739                                 DMA[d].AAddress &= 0xFF00;
1740                                 DMA[d].AAddress |= byte;
1741                                 break;
1742
1743                         case 0x4303 :
1744                         case 0x4313 :
1745                         case 0x4323 :
1746                         case 0x4333 :
1747                         case 0x4343 :
1748                         case 0x4353 :
1749                         case 0x4363 :
1750                         case 0x4373 :
1751                                 d = (Address >> 4) & 0x7;
1752                                 DMA[d].AAddress &= 0xFF;
1753                                 DMA[d].AAddress |= byte << 8;
1754                                 break;
1755
1756                         case 0x4304 :
1757                         case 0x4314 :
1758                         case 0x4324 :
1759                         case 0x4334 :
1760                         case 0x4344 :
1761                         case 0x4354 :
1762                         case 0x4364 :
1763                         case 0x4374 :
1764                                 DMA[((Address >> 4) & 0x7)].ABank = byte;
1765                                 break;
1766
1767                         case 0x4305 :
1768                         case 0x4315 :
1769                         case 0x4325 :
1770                         case 0x4335 :
1771                         case 0x4345 :
1772                         case 0x4355 :
1773                         case 0x4365 :
1774                         case 0x4375 :
1775                                 d = (Address >> 4) & 0x7;
1776                                 DMA[d].TransferBytes &= 0xFF00;
1777                                 DMA[d].TransferBytes |= byte;
1778                                 DMA[d].IndirectAddress &= 0xff00;
1779                                 DMA[d].IndirectAddress |= byte;
1780                                 break;
1781
1782                         case 0x4306 :
1783                         case 0x4316 :
1784                         case 0x4326 :
1785                         case 0x4336 :
1786                         case 0x4346 :
1787                         case 0x4356 :
1788                         case 0x4366 :
1789                         case 0x4376 :
1790                                 d = (Address >> 4) & 0x7;
1791                                 DMA[d].TransferBytes &= 0xFF;
1792                                 DMA[d].TransferBytes |= byte << 8;
1793                                 DMA[d].IndirectAddress &= 0xff;
1794                                 DMA[d].IndirectAddress |= byte << 8;
1795                                 break;
1796
1797                         case 0x4307 :
1798                         case 0x4317 :
1799                         case 0x4327 :
1800                         case 0x4337 :
1801                         case 0x4347 :
1802                         case 0x4357 :
1803                         case 0x4367 :
1804                         case 0x4377 :
1805                                 DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte;
1806                                 break;
1807
1808                         case 0x4308 :
1809                         case 0x4318 :
1810                         case 0x4328 :
1811                         case 0x4338 :
1812                         case 0x4348 :
1813                         case 0x4358 :
1814                         case 0x4368 :
1815                         case 0x4378 :
1816                                 d = (Address >> 4) & 7;
1817                                 DMA[d].Address &= 0xff00;
1818                                 DMA[d].Address |= byte;
1819                                 break;
1820
1821                         case 0x4309 :
1822                         case 0x4319 :
1823                         case 0x4329 :
1824                         case 0x4339 :
1825                         case 0x4349 :
1826                         case 0x4359 :
1827                         case 0x4369 :
1828                         case 0x4379 :
1829                                 d = (Address >> 4) & 0x7;
1830                                 DMA[d].Address &= 0xff;
1831                                 DMA[d].Address |= byte << 8;
1832                                 break;
1833
1834                         case 0x430A :
1835                         case 0x431A :
1836                         case 0x432A :
1837                         case 0x433A :
1838                         case 0x434A :
1839                         case 0x435A :
1840                         case 0x436A :
1841                         case 0x437A :
1842                                 d = (Address >> 4) & 0x7;
1843                                 DMA[d].LineCount = byte & 0x7f;
1844                                 DMA[d].Repeat = !(byte & 0x80);
1845                                 break;
1846
1847                         case 0x4800 :
1848                         case 0x4801 :
1849                         case 0x4802 :
1850                         case 0x4803 :
1851                                 //printf ("%02x->%04x\n", byte, Address);
1852                                 break;
1853
1854                         case 0x4804 :
1855                         case 0x4805 :
1856                         case 0x4806 :
1857                         case 0x4807 :
1858                                 //printf ("%02x->%04x\n", byte, Address);
1859
1860                                 S9xSetSDD1MemoryMap(Address - 0x4804, byte & 7);
1861                                 break;
1862                         default :
1863 #ifdef DEBUGGER
1864                                 missing.unknowncpu_write = Address;
1865                                 if (Settings.TraceUnknownRegisters)
1866                                 {
1867                                         sprintf(
1868                                                 String,
1869                                                 "Unknown register write: $%02X->$%04X\n",
1870                                                 byte,
1871                                                 Address);
1872                                         S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
1873                                 }
1874 #endif
1875                                 break;
1876                 }
1877         Memory.FillRAM[Address] = byte;
1878 }
1879
1880 /**********************************************************************************************/
1881 /* S9xGetCPU()                                                                                   */
1882 /* This function retrieves a CPU/DMA Register                                                 */
1883 /**********************************************************************************************/
1884 uint8 S9xGetCPU(uint16 Address)
1885 {
1886         uint8 byte;
1887
1888         if (Address < 0x4200)
1889         {
1890 #ifdef VAR_CYCLES
1891                 CPU.Cycles += ONE_CYCLE;
1892 #endif
1893                 switch (Address)
1894                 {
1895                         // Secret of the Evermore
1896                         case 0x4000 :
1897                         case 0x4001 :
1898                                 return (0x40);
1899
1900                         case 0x4016 :
1901                                 {
1902                                         if (Memory.FillRAM[0x4016] & 1)
1903                                         {
1904                                                 if ((!Settings.SwapJoypads
1905                                                         && IPPU.Controller == SNES_MOUSE_SWAPPED)
1906                                                         || (Settings.SwapJoypads
1907                                                                 && IPPU.Controller == SNES_MOUSE))
1908                                                 {
1909                                                         if (++PPU.MouseSpeed[0] > 2)
1910                                                                 PPU.MouseSpeed[0] = 0;
1911                                                 }
1912                                                 return (0);
1913                                         }
1914
1915                                         int ind = Settings.SwapJoypads ? 1 : 0;
1916                                         byte = IPPU.Joypads[ind] >> (PPU.Joypad1ButtonReadPos ^ 15);
1917                                         PPU.Joypad1ButtonReadPos++;
1918                                         return (byte & 1);
1919                                 }
1920                         case 0x4017 :
1921                                 {
1922                                         if (Memory.FillRAM[0x4016] & 1)
1923                                         {
1924                                                 // MultiPlayer5 adaptor is only allowed to be plugged into port 2
1925                                                 switch (IPPU.Controller)
1926                                                 {
1927                                                         case SNES_MULTIPLAYER5 :
1928                                                                 return (2);
1929                                                         case SNES_MOUSE_SWAPPED :
1930                                                                 if (Settings.SwapJoypads
1931                                                                         && ++PPU.MouseSpeed[0] > 2)
1932                                                                         PPU.MouseSpeed[0] = 0;
1933                                                                 break;
1934
1935                                                         case SNES_MOUSE :
1936                                                                 if (!Settings.SwapJoypads
1937                                                                         && ++PPU.MouseSpeed[0] > 2)
1938                                                                         PPU.MouseSpeed[0] = 0;
1939                                                                 break;
1940                                                 }
1941                                                 return (0x00);
1942                                         }
1943
1944                                         int ind = Settings.SwapJoypads ? 0 : 1;
1945
1946                                         if (IPPU.Controller == SNES_MULTIPLAYER5)
1947                                         {
1948                                                 if (Memory.FillRAM[0x4201] & 0x80)
1949                                                 {
1950                                                         byte =
1951                                                                 ((IPPU.Joypads[ind]
1952                                                                         >> (PPU.Joypad2ButtonReadPos ^ 15))
1953                                                                         & 1)
1954                                                                         | (((IPPU.Joypads[2]
1955                                                                                 >> (PPU.Joypad2ButtonReadPos ^ 15))
1956                                                                                 & 1)
1957                                                                                 << 1);
1958                                                         PPU.Joypad2ButtonReadPos++;
1959                                                         return (byte);
1960                                                 }
1961                                                 else
1962                                                 {
1963                                                         byte =
1964                                                                 ((IPPU.Joypads[3]
1965                                                                         >> (PPU.Joypad3ButtonReadPos ^ 15))
1966                                                                         & 1)
1967                                                                         | (((IPPU.Joypads[4]
1968                                                                                 >> (PPU.Joypad3ButtonReadPos ^ 15))
1969                                                                                 & 1)
1970                                                                                 << 1);
1971                                                         PPU.Joypad3ButtonReadPos++;
1972                                                         return (byte);
1973                                                 }
1974                                         }
1975                                         return (
1976                                                 (IPPU.Joypads[ind]
1977                                                         >> (PPU.Joypad2ButtonReadPos++ ^ 15))
1978                                                         & 1);
1979                                 }
1980                         default :
1981 #ifdef DEBUGGER
1982                                 missing.unknowncpu_read = Address;
1983                                 if (Settings.TraceUnknownRegisters)
1984                                 {
1985                                         sprintf(String, "Unknown register read: $%04X\n", Address);
1986                                         S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
1987                                 }
1988 #endif
1989                                 break;
1990                 }
1991                 return (Memory.FillRAM[Address]);
1992         }
1993         else
1994                 switch (Address)
1995                 {
1996                         // BS Dynami Tracer! needs to be able to check if NMIs are enabled
1997                         // already, otherwise the game locks up.
1998                         case 0x4200 :
1999                                 // NMI, h & v timers and joypad reading enable
2000                                 if (SNESGameFixes.Old_Read0x4200)
2001                                 {
2002 #ifdef CPU_SHUTDOWN
2003                                         CPU.WaitAddress = CPU.PCAtOpcodeStart;
2004 #endif
2005                                         return (REGISTER_4212());
2006                                 }
2007                         case 0x4201 :
2008                                 // I/O port (output - write only?)
2009                         case 0x4202 :
2010                         case 0x4203 :
2011                                 // Multiplier and multiplicand (write)
2012                         case 0x4204 :
2013                         case 0x4205 :
2014                         case 0x4206 :
2015                                 // Divisor and dividend (write)
2016                                 return (Memory.FillRAM[Address]);
2017                         case 0x4207 :
2018                                 return (uint8) (PPU.IRQHBeamPos);
2019                         case 0x4208 :
2020                                 return (PPU.IRQHBeamPos >> 8);
2021                         case 0x4209 :
2022                                 return (uint8) (PPU.IRQVBeamPos);
2023                         case 0x420a :
2024                                 return (PPU.IRQVBeamPos >> 8);
2025                         case 0x420b :
2026                                 // General purpose DMA enable
2027                                 // Super Formation Soccer 95 della Serie A UCC Xaqua requires this
2028                                 // register should not always return zero.
2029                                 // .. But Aero 2 waits until this register goes zero..
2030                                 // Just keep toggling the value for now in the hope that it breaks
2031                                 // the game out of its wait loop...
2032                                 Memory.FillRAM[0x420b] = !Memory.FillRAM[0x420b];
2033                                 return (Memory.FillRAM[0x420b]);
2034                         case 0x420c :
2035                                 // H-DMA enable
2036                                 return (IPPU.HDMA);
2037                         case 0x420d :
2038                                 // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +)
2039                                 return (Memory.FillRAM[Address]);
2040                         case 0x420e :
2041                         case 0x420f :
2042                                 // --->>> Unknown
2043                                 return (Memory.FillRAM[Address]);
2044                         case 0x4210 :
2045 #ifdef CPU_SHUTDOWN
2046                                 CPU.WaitAddress = CPU.PCAtOpcodeStart;
2047 #endif
2048                                 byte = Memory.FillRAM[0x4210];
2049                                 Memory.FillRAM[0x4210] = 0;
2050                                 return (byte);
2051                         case 0x4211 :
2052                                 byte =
2053                                         (CPU.IRQActive
2054                                                 & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE))
2055                                                 ? 0x80
2056                                                 : 0;
2057                                 // Super Robot Wars Ex ROM bug requires this.
2058                                 byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0;
2059                                 CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE);
2060                                 return (byte);
2061                         case 0x4212 :
2062                                 // V-blank, h-blank and joypads being read flags (read-only)
2063 #ifdef CPU_SHUTDOWN
2064                                 CPU.WaitAddress = CPU.PCAtOpcodeStart;
2065 #endif
2066                                 return (REGISTER_4212());
2067                         case 0x4213 :
2068                                 // I/O port input
2069                         case 0x4214 :
2070                         case 0x4215 :
2071                                 // Quotient of divide result
2072                         case 0x4216 :
2073                         case 0x4217 :
2074                                 // Multiplcation result (for multiply) or remainder of
2075                                 // divison.
2076                                 return (Memory.FillRAM[Address]);
2077                         case 0x4218 :
2078                         case 0x4219 :
2079                         case 0x421a :
2080                         case 0x421b :
2081                         case 0x421c :
2082                         case 0x421d :
2083                         case 0x421e :
2084                         case 0x421f :
2085                                 // Joypads 1-4 button and direction state.
2086                                 return (Memory.FillRAM[Address]);
2087
2088                         case 0x4300 :
2089                         case 0x4310 :
2090                         case 0x4320 :
2091                         case 0x4330 :
2092                         case 0x4340 :
2093                         case 0x4350 :
2094                         case 0x4360 :
2095                         case 0x4370 :
2096                                 // DMA direction, address type, fixed flag,
2097                                 return (Memory.FillRAM[Address]);
2098
2099                         case 0x4301 :
2100                         case 0x4311 :
2101                         case 0x4321 :
2102                         case 0x4331 :
2103                         case 0x4341 :
2104                         case 0x4351 :
2105                         case 0x4361 :
2106                         case 0x4371 :
2107                                 return (Memory.FillRAM[Address]);
2108
2109                         case 0x4302 :
2110                         case 0x4312 :
2111                         case 0x4322 :
2112                         case 0x4332 :
2113                         case 0x4342 :
2114                         case 0x4352 :
2115                         case 0x4362 :
2116                         case 0x4372 :
2117                                 return (Memory.FillRAM[Address]);
2118
2119                         case 0x4303 :
2120                         case 0x4313 :
2121                         case 0x4323 :
2122                         case 0x4333 :
2123                         case 0x4343 :
2124                         case 0x4353 :
2125                         case 0x4363 :
2126                         case 0x4373 :
2127                                 return (Memory.FillRAM[Address]);
2128
2129                         case 0x4304 :
2130                         case 0x4314 :
2131                         case 0x4324 :
2132                         case 0x4334 :
2133                         case 0x4344 :
2134                         case 0x4354 :
2135                         case 0x4364 :
2136                         case 0x4374 :
2137                                 return (Memory.FillRAM[Address]);
2138
2139                         case 0x4305 :
2140                         case 0x4315 :
2141                         case 0x4325 :
2142                         case 0x4335 :
2143                         case 0x4345 :
2144                         case 0x4355 :
2145                         case 0x4365 :
2146                         case 0x4375 :
2147                                 return (Memory.FillRAM[Address]);
2148
2149                         case 0x4306 :
2150                         case 0x4316 :
2151                         case 0x4326 :
2152                         case 0x4336 :
2153                         case 0x4346 :
2154                         case 0x4356 :
2155                         case 0x4366 :
2156                         case 0x4376 :
2157                                 return (Memory.FillRAM[Address]);
2158
2159                         case 0x4307 :
2160                         case 0x4317 :
2161                         case 0x4327 :
2162                         case 0x4337 :
2163                         case 0x4347 :
2164                         case 0x4357 :
2165                         case 0x4367 :
2166                         case 0x4377 :
2167                                 return (DMA[(Address >> 4) & 7].IndirectBank);
2168
2169                         case 0x4308 :
2170                         case 0x4318 :
2171                         case 0x4328 :
2172                         case 0x4338 :
2173                         case 0x4348 :
2174                         case 0x4358 :
2175                         case 0x4368 :
2176                         case 0x4378 :
2177                                 return (Memory.FillRAM[Address]);
2178
2179                         case 0x4309 :
2180                         case 0x4319 :
2181                         case 0x4329 :
2182                         case 0x4339 :
2183                         case 0x4349 :
2184                         case 0x4359 :
2185                         case 0x4369 :
2186                         case 0x4379 :
2187                                 return (Memory.FillRAM[Address]);
2188
2189                         case 0x430A :
2190                         case 0x431A :
2191                         case 0x432A :
2192                         case 0x433A :
2193                         case 0x434A :
2194                         case 0x435A :
2195                         case 0x436A :
2196                         case 0x437A :
2197                                 {
2198                                         int d = (Address & 0x70) >> 4;
2199                                         if (IPPU.HDMA & (1 << d))
2200                                         {
2201                                                 return (DMA[d].LineCount);
2202                                         }
2203                                         return (Memory.FillRAM[Address]);
2204                                 }
2205                         default :
2206 #ifdef DEBUGGER
2207                                 missing.unknowncpu_read = Address;
2208                                 if (Settings.TraceUnknownRegisters)
2209                                 {
2210                                         sprintf(String, "Unknown register read: $%04X\n", Address);
2211                                         S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
2212                                 }
2213
2214 #endif
2215                                 break;
2216                 }
2217         return (Memory.FillRAM[Address]);
2218 }
2219
2220 void S9xResetPPU()
2221 {
2222         PPU.BGMode = 0;
2223         PPU.BG3Priority = 0;
2224         PPU.Brightness = 0;
2225         PPU.VMA.High = 0;
2226         PPU.VMA.Increment = 1;
2227         PPU.VMA.Address = 0;
2228         PPU.VMA.FullGraphicCount = 0;
2229         PPU.VMA.Shift = 0;
2230
2231         for (uint8 B = 0; B != 4; B++)
2232         {
2233                 PPU.BG[B].SCBase = 0;
2234                 PPU.BG[B].VOffset = 0;
2235                 PPU.BG[B].HOffset = 0;
2236                 PPU.BG[B].BGSize = 0;
2237                 PPU.BG[B].NameBase = 0;
2238                 PPU.BG[B].SCSize = 0;
2239
2240                 PPU.ClipCounts[B] = 0;
2241                 PPU.ClipWindowOverlapLogic[B] = CLIP_OR;
2242                 PPU.ClipWindow1Enable[B] = FALSE;
2243                 PPU.ClipWindow2Enable[B] = FALSE;
2244                 PPU.ClipWindow1Inside[B] = TRUE;
2245                 PPU.ClipWindow2Inside[B] = TRUE;
2246         }
2247
2248         PPU.ClipCounts[4] = 0;
2249         PPU.ClipCounts[5] = 0;
2250         PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR;
2251         PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE;
2252         PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE;
2253         PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE;
2254         PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE;
2255
2256         PPU.CGFLIP = 0;
2257         int c;
2258         for (c = 0; c < 256; c++)
2259         {
2260                 IPPU.Red[c] = (c & 7) << 2;
2261                 IPPU.Green[c] = ((c >> 3) & 7) << 2;
2262                 IPPU.Blue[c] = ((c >> 6) & 2) << 3;
2263                 PPU.CGDATA[c] =
2264                         IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10);
2265         }
2266
2267         PPU.FirstSprite = 0;
2268         PPU.LastSprite = 127;
2269         for (int Sprite = 0; Sprite < 128; Sprite++)
2270         {
2271                 PPU.OBJ[Sprite].HPos = 0;
2272                 PPU.OBJ[Sprite].VPos = 0;
2273                 PPU.OBJ[Sprite].VFlip = 0;
2274                 PPU.OBJ[Sprite].HFlip = 0;
2275                 PPU.OBJ[Sprite].Priority = 0;
2276                 PPU.OBJ[Sprite].Palette = 0;
2277                 PPU.OBJ[Sprite].Name = 0;
2278                 PPU.OBJ[Sprite].Size = 0;
2279         }
2280         PPU.OAMPriorityRotation = 0;
2281
2282         PPU.OAMFlip = 0;
2283         PPU.OAMTileAddress = 0;
2284         PPU.OAMAddr = 0;
2285         PPU.IRQVBeamPos = 0;
2286         PPU.IRQHBeamPos = 0;
2287         PPU.VBeamPosLatched = 0;
2288         PPU.HBeamPosLatched = 0;
2289
2290         PPU.HBeamFlip = 0;
2291         PPU.VBeamFlip = 0;
2292         PPU.HVBeamCounterLatched = 0;
2293
2294         PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0;
2295         PPU.CentreX = PPU.CentreY = 0;
2296         PPU.Joypad1ButtonReadPos = 0;
2297         PPU.Joypad2ButtonReadPos = 0;
2298         PPU.Joypad3ButtonReadPos = 0;
2299
2300         PPU.CGADD = 0;
2301         PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0;
2302         PPU.SavedOAMAddr = 0;
2303         PPU.ScreenHeight = SNES_HEIGHT;
2304         PPU.WRAM = 0;
2305         PPU.BG_Forced = 0;
2306         PPU.ForcedBlanking = TRUE;
2307         PPU.OBJThroughMain = FALSE;
2308         PPU.OBJThroughSub = FALSE;
2309         PPU.OBJSizeSelect = 0;
2310         PPU.OBJNameSelect = 0;
2311         PPU.OBJNameBase = 0;
2312         PPU.OBJAddition = FALSE;
2313         PPU.OAMReadFlip = 0;
2314         ZeroMemory(PPU.OAMData, 512 + 32);
2315
2316         PPU.VTimerEnabled = FALSE;
2317         PPU.HTimerEnabled = FALSE;
2318         PPU.HTimerPosition = Settings.H_Max + 1;
2319         PPU.Mosaic = 0;
2320         PPU.BGMosaic[0] = PPU.BGMosaic[1] = FALSE;
2321         PPU.BGMosaic[2] = PPU.BGMosaic[3] = FALSE;
2322         PPU.Mode7HFlip = FALSE;
2323         PPU.Mode7VFlip = FALSE;
2324         PPU.Mode7Repeat = 0;
2325         PPU.Window1Left = 1;
2326         PPU.Window1Right = 0;
2327         PPU.Window2Left = 1;
2328         PPU.Window2Right = 0;
2329         PPU.RecomputeClipWindows = TRUE;
2330         PPU.CGFLIPRead = 0;
2331         PPU.Need16x8Mulitply = FALSE;
2332         PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0;
2333
2334         IPPU.ColorsChanged = TRUE;
2335         IPPU.HDMA = 0;
2336         IPPU.HDMAStarted = FALSE;
2337         IPPU.MaxBrightness = 0;
2338         IPPU.LatchedBlanking = 0;
2339         IPPU.OBJChanged = TRUE;
2340         IPPU.RenderThisFrame = TRUE;
2341         IPPU.DirectColourMapsNeedRebuild = TRUE;
2342         IPPU.FrameCount = 0;
2343         IPPU.RenderedFramesCount = 0;
2344         IPPU.DisplayedRenderedFrameCount = 0;
2345         IPPU.SkippedFrames = 0;
2346         IPPU.FrameSkip = 0;
2347         ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES);
2348         ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES);
2349         ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES);
2350         IPPU.FirstVRAMRead = FALSE;
2351         IPPU.LatchedInterlace = FALSE;
2352         IPPU.DoubleWidthPixels = FALSE;
2353         IPPU.RenderedScreenWidth = SNES_WIDTH;
2354         IPPU.RenderedScreenHeight = SNES_HEIGHT;
2355         IPPU.XB = NULL;
2356         for (c = 0; c < 256; c++)
2357                 IPPU.ScreenColors[c] = c;
2358         S9xFixColourBrightness();
2359         IPPU.PreviousLine = IPPU.CurrentLine = 0;
2360         IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0;
2361         IPPU.Joypads[3] = IPPU.Joypads[4] = 0;
2362         IPPU.SuperScope = 0;
2363         IPPU.Mouse[0] = IPPU.Mouse[1] = 0;
2364         IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2;
2365         IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2;
2366
2367         if (Settings.ControllerOption == 0)
2368                 IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1;
2369         else
2370                 IPPU.Controller = Settings.ControllerOption - 1;
2371         S9xNextController();
2372
2373         for (c = 0; c < 2; c++)
2374                 memset(& IPPU.Clip[c], 0, sizeof(struct ClipData));
2375
2376         if (Settings.MouseMaster)
2377         {
2378                 S9xProcessMouse(0);
2379                 S9xProcessMouse(1);
2380         }
2381         for (c = 0; c < 0x8000; c += 0x100)
2382                 memset(& Memory.FillRAM[c], c >> 8, 0x100);
2383
2384         ZeroMemory(& Memory.FillRAM[0x2100], 0x100);
2385         ZeroMemory(& Memory.FillRAM[0x4200], 0x100);
2386         ZeroMemory(& Memory.FillRAM[0x4000], 0x100);
2387         // For BS Suttehakkun 2...
2388         ZeroMemory(& Memory.FillRAM[0x1000], 0x1000);
2389 }
2390
2391 void S9xProcessMouse(int which1)
2392 {
2393         int x, y;
2394         uint32 buttons;
2395
2396         if ((IPPU.Controller == SNES_MOUSE
2397                 || IPPU.Controller == SNES_MOUSE_SWAPPED)
2398                 && S9xReadMousePosition(which1, &x, &y, &buttons))
2399         {
2400                 int delta_x, delta_y;
2401 #define MOUSE_SIGNATURE 0x1
2402                 IPPU.Mouse[which1] =
2403                         MOUSE_SIGNATURE
2404                                 | (PPU.MouseSpeed[which1] << 4)
2405                                 | ((buttons & 1) << 6)
2406                                 | ((buttons & 2) << 6);
2407
2408                 delta_x = x - IPPU.PrevMouseX[which1];
2409                 delta_y = y - IPPU.PrevMouseY[which1];
2410
2411                 if (delta_x > 63)
2412                 {
2413                         delta_x = 63;
2414                         IPPU.PrevMouseX[which1] += 63;
2415                 }
2416                 else if (delta_x < -63)
2417                 {
2418                         delta_x = -63;
2419                         IPPU.PrevMouseX[which1] -= 63;
2420                 }
2421                 else
2422                         IPPU.PrevMouseX[which1] = x;
2423
2424                 if (delta_y > 63)
2425                 {
2426                         delta_y = 63;
2427                         IPPU.PrevMouseY[which1] += 63;
2428                 }
2429                 else if (delta_y < -63)
2430                 {
2431                         delta_y = -63;
2432                         IPPU.PrevMouseY[which1] -= 63;
2433                 }
2434                 else
2435                         IPPU.PrevMouseY[which1] = y;
2436
2437                 if (delta_x < 0)
2438                 {
2439                         delta_x = -delta_x;
2440                         IPPU.Mouse[which1] |= (delta_x | 0x80) << 16;
2441                 }
2442                 else
2443                         IPPU.Mouse[which1] |= delta_x << 16;
2444
2445                 if (delta_y < 0)
2446                 {
2447                         delta_y = -delta_y;
2448                         IPPU.Mouse[which1] |= (delta_y | 0x80) << 24;
2449                 }
2450                 else
2451                         IPPU.Mouse[which1] |= delta_y << 24;
2452
2453                 if (IPPU.Controller == SNES_MOUSE_SWAPPED)
2454                         IPPU.Joypads[0] = IPPU.Mouse[which1];
2455                 else
2456                         IPPU.Joypads[1] = IPPU.Mouse[which1];
2457         }
2458 }
2459
2460 void ProcessSuperScope()
2461 {
2462         int x, y;
2463         uint32 buttons;
2464
2465         if (IPPU.Controller == SNES_SUPERSCOPE
2466                 && S9xReadSuperScopePosition(&x, &y, &buttons))
2467         {
2468 #define SUPERSCOPE_SIGNATURE 0x00ff
2469                 uint32 scope;
2470
2471                 scope =
2472                         SUPERSCOPE_SIGNATURE
2473                                 | ((buttons & 1) << (7 + 8))
2474                                 | ((buttons & 2) << (5 + 8))
2475                                 | ((buttons & 4) << (3 + 8))
2476                                 | ((buttons & 8) << (1 + 8));
2477                 if (x > 255)
2478                         x = 255;
2479                 if (x < 0)
2480                         x = 0;
2481                 if (y > PPU.ScreenHeight - 1)
2482                         y = PPU.ScreenHeight - 1;
2483                 if (y < 0)
2484                         y = 0;
2485
2486                 PPU.VBeamPosLatched = (uint16) (y + 1);
2487                 PPU.HBeamPosLatched = (uint16) x;
2488                 PPU.HVBeamCounterLatched = TRUE;
2489                 Memory.FillRAM[0x213F] |= 0x40;
2490                 IPPU.Joypads[1] = scope;
2491         }
2492 }
2493
2494 void S9xNextController()
2495 {
2496         switch (IPPU.Controller)
2497         {
2498                 case SNES_MULTIPLAYER5 :
2499                         IPPU.Controller = SNES_JOYPAD;
2500                         break;
2501                 case SNES_JOYPAD :
2502                         if (Settings.MouseMaster)
2503                         {
2504                                 IPPU.Controller = SNES_MOUSE_SWAPPED;
2505                                 break;
2506                         }
2507                 case SNES_MOUSE_SWAPPED :
2508                         if (Settings.MouseMaster)
2509                         {
2510                                 IPPU.Controller = SNES_MOUSE;
2511                                 break;
2512                         }
2513                 case SNES_MOUSE :
2514                         if (Settings.SuperScopeMaster)
2515                         {
2516                                 IPPU.Controller = SNES_SUPERSCOPE;
2517                                 break;
2518                         }
2519                 case SNES_SUPERSCOPE :
2520                         if (Settings.MultiPlayer5Master)
2521                         {
2522                                 IPPU.Controller = SNES_MULTIPLAYER5;
2523                                 break;
2524                         }
2525                 default :
2526                         IPPU.Controller = SNES_JOYPAD;
2527                         break;
2528         }
2529 }
2530
2531 void S9xUpdateJoypads()
2532 {
2533 #ifdef _SNESPPC
2534         int i = 0;
2535 #else
2536         int i;
2537
2538         for (i = 0; i < 5; i++)
2539 #endif
2540         {
2541                 IPPU.Joypads[i] = S9xReadJoypad(i);
2542                 if (IPPU.Joypads[i] & SNES_LEFT_MASK)
2543                         IPPU.Joypads[i] &= ~SNES_RIGHT_MASK;
2544                 if (IPPU.Joypads[i] & SNES_UP_MASK)
2545                         IPPU.Joypads[i] &= ~SNES_DOWN_MASK;
2546         }
2547
2548         //touhaiden controller Fix
2549         if (SNESGameFixes.TouhaidenControllerFix
2550                 && (IPPU.Controller == SNES_JOYPAD
2551                         || IPPU.Controller == SNES_MULTIPLAYER5))
2552         {
2553                 for (i = 0; i < 5; i++)
2554                 {
2555                         if (IPPU.Joypads[i])
2556                                 IPPU.Joypads[i] |= 0xffff0000;
2557                 }
2558         }
2559
2560         // Read mouse position if enabled
2561         if (Settings.MouseMaster)
2562         {
2563                 for (i = 0; i < 2; i++)
2564                         S9xProcessMouse(i);
2565         }
2566
2567         // Read SuperScope if enabled
2568         if (Settings.SuperScopeMaster)
2569                 ProcessSuperScope();
2570
2571         if (Memory.FillRAM[0x4200] & 1)
2572         {
2573                 PPU.Joypad1ButtonReadPos = 16;
2574                 if (Memory.FillRAM[0x4201] & 0x80)
2575                 {
2576                         PPU.Joypad2ButtonReadPos = 16;
2577                         PPU.Joypad3ButtonReadPos = 0;
2578                 }
2579                 else
2580                 {
2581                         PPU.Joypad2ButtonReadPos = 0;
2582                         PPU.Joypad3ButtonReadPos = 16;
2583                 }
2584                 int ind = Settings.SwapJoypads ? 1 : 0;
2585
2586                 Memory.FillRAM[0x4218] = (uint8) IPPU.Joypads[ind];
2587                 Memory.FillRAM[0x4219] = (uint8) (IPPU.Joypads[ind] >> 8);
2588                 Memory.FillRAM[0x421a] = (uint8) IPPU.Joypads[ind ^ 1];
2589                 Memory.FillRAM[0x421b] = (uint8) (IPPU.Joypads[ind ^ 1] >> 8);
2590                 if (Memory.FillRAM[0x4201] & 0x80)
2591                 {
2592                         Memory.FillRAM[0x421c] = (uint8) IPPU.Joypads[ind];
2593                         Memory.FillRAM[0x421d] = (uint8) (IPPU.Joypads[ind] >> 8);
2594                         Memory.FillRAM[0x421e] = (uint8) IPPU.Joypads[2];
2595                         Memory.FillRAM[0x421f] = (uint8) (IPPU.Joypads[2] >> 8);
2596                 }
2597                 else
2598                 {
2599                         Memory.FillRAM[0x421c] = (uint8) IPPU.Joypads[3];
2600                         Memory.FillRAM[0x421d] = (uint8) (IPPU.Joypads[3] >> 8);
2601                         Memory.FillRAM[0x421e] = (uint8) IPPU.Joypads[4];
2602                         Memory.FillRAM[0x421f] = (uint8) (IPPU.Joypads[4] >> 8);
2603                 }
2604         }
2605 }
2606
2607 #ifndef ZSNES_FX
2608 void S9xSuperFXExec()
2609 {
2610 #if 1
2611         if (Settings.SuperFX)
2612         {
2613                 if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G)
2614                         && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18)
2615                 {
2616                         if (!Settings.WinterGold)
2617                                 FxEmulate(~0);
2618                         else FxEmulate((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? 700 : 350);
2619                         int GSUStatus = Memory.FillRAM[0x3000
2620                                         + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8);
2621                         if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ)
2622                         {
2623                                 // Trigger a GSU IRQ.
2624                                 S9xSetIRQ(GSU_IRQ_SOURCE);
2625                         }
2626                 }
2627         }
2628 #else
2629         uint32 tmp = (Memory.FillRAM[0x3034] << 16)
2630                 + * (uint16 *) & Memory.FillRAM[0x301e];
2631         #if 0
2632         if (tmp == 0x018428)
2633         {
2634                 * (uint16 *)
2635                 & SRAM[0x0064] = 0xbc00;
2636                 * (uint16 *) & SRAM[0x002c] = 0x8000;
2637         }
2638         #endif
2639         if (tmp == -1) //0x018428) //0x01bfc3) //0x09edaf) //-1) //0x57edaf)
2640         {
2641                 while (Memory.FillRAM[0x3030] & 0x20)
2642                 {
2643                         int i;
2644                         int32 vError;
2645                         uint8 avReg[0x40];
2646                         char tmp[128];
2647                         uint8 vPipe;
2648                         uint8 vColr;
2649                         uint8 vPor;
2650
2651                         FxPipeString(tmp);
2652                         /* Make the string 32 chars long */
2653                         if (strlen(tmp) < 32)
2654                         {
2655                                 memset(& tmp[strlen(tmp)], ' ', 32 - strlen(tmp));
2656                                 tmp[32] = 0;
2657                         }
2658
2659                         /* Copy registers (so we can see if any changed) */
2660                         vColr = FxGetColorRegister();
2661                         vPor = FxGetPlotOptionRegister();
2662                         memcpy(avReg, SuperFX.pvRegisters, 0x40);
2663
2664                         /* Print the pipe string */
2665                         printf(tmp);
2666
2667                         /* Execute the instruction in the pipe */
2668                         vPipe = FxPipe();
2669                         vError = FxEmulate(1);
2670
2671                         /* Check if any registers changed (and print them if they did) */
2672                         for (i = 0; i < 16; i++)
2673                         {
2674                                 uint32 a = 0;
2675                                 uint32 r1 =
2676                                         ((uint32) avReg[i * 2])
2677                                                 | (((uint32) avReg[(i * 2) + 1]) << 8);
2678                                 uint32 r2 =
2679                                         (uint32) (SuperFX.pvRegisters[i * 2])
2680                                                 | (((uint32) SuperFX.pvRegisters[(i * 2) + 1]) << 8);
2681                                 if (i == 15)
2682                                         a = OPCODE_BYTES(vPipe);
2683                                 if (((r1 + a) & 0xffff) != r2)
2684                                         printf(" r%d=$%04x", i, r2);
2685                         }
2686                         {
2687                                 /* Check SFR */
2688                                 uint32 r1 =
2689                                         ((uint32) avReg[0x30]) | (((uint32) avReg[0x31]) << 8);
2690                                 uint32 r2 =
2691                                         (uint32) (SuperFX.pvRegisters[0x30])
2692                                                 | (((uint32) SuperFX.pvRegisters[0x31]) << 8);
2693                                 if ((r1 & (1 << 1)) != (r2 & (1 << 1)))
2694                                         printf(" Z=%d", (uint32) (!!(r2 & (1 << 1))));
2695                                 if ((r1 & (1 << 2)) != (r2 & (1 << 2)))
2696                                         printf(" CY=%d", (uint32) (!!(r2 & (1 << 2))));
2697                                 if ((r1 & (1 << 3)) != (r2 & (1 << 3)))
2698                                         printf(" S=%d", (uint32) (!!(r2 & (1 << 3))));
2699                                 if ((r1 & (1 << 4)) != (r2 & (1 << 4)))
2700                                         printf(" OV=%d", (uint32) (!!(r2 & (1 << 4))));
2701                                 if ((r1 & (1 << 5)) != (r2 & (1 << 5)))
2702                                         printf(" G=%d", (uint32) (!!(r2 & (1 << 5))));
2703                                 if ((r1 & (1 << 6)) != (r2 & (1 << 6)))
2704                                         printf(" R=%d", (uint32) (!!(r2 & (1 << 6))));
2705                                 if ((r1 & (1 << 8)) != (r2 & (1 << 8)))
2706                                         printf(" ALT1=%d", (uint32) (!!(r2 & (1 << 8))));
2707                                 if ((r1 & (1 << 9)) != (r2 & (1 << 9)))
2708                                         printf(" ALT2=%d", (uint32) (!!(r2 & (1 << 9))));
2709                                 if ((r1 & (1 << 10)) != (r2 & (1 << 10)))
2710                                         printf(" IL=%d", (uint32) (!!(r2 & (1 << 10))));
2711                                 if ((r1 & (1 << 11)) != (r2 & (1 << 11)))
2712                                         printf(" IH=%d", (uint32) (!!(r2 & (1 << 11))));
2713                                 if ((r1 & (1 << 12)) != (r2 & (1 << 12)))
2714                                         printf(" B=%d", (uint32) (!!(r2 & (1 << 12))));
2715                                 if ((r1 & (1 << 15)) != (r2 & (1 << 15)))
2716                                         printf(" IRQ=%d", (uint32) (!!(r2 & (1 << 15))));
2717                         }
2718                         {
2719                                 /* Check PBR */
2720                                 uint32 r1 = ((uint32) avReg[0x34]);
2721                                 uint32 r2 = (uint32) (SuperFX.pvRegisters[0x34]);
2722                                 if (r1 != r2)
2723                                         printf(" PBR=$%02x", r2);
2724                         }
2725                         {
2726                                 /* Check ROMBR */
2727                                 uint32 r1 = ((uint32) avReg[0x36]);
2728                                 uint32 r2 = (uint32) (SuperFX.pvRegisters[0x36]);
2729                                 if (r1 != r2)
2730                                         printf(" ROMBR=$%02x", r2);
2731                         }
2732                         {
2733                                 /* Check RAMBR */
2734                                 uint32 r1 = ((uint32) avReg[0x3c]);
2735                                 uint32 r2 = (uint32) (SuperFX.pvRegisters[0x3c]);
2736                                 if (r1 != r2)
2737                                         printf(" RAMBR=$%02x", r2);
2738                         }
2739                         {
2740                                 /* Check CBR */
2741                                 uint32 r1 =
2742                                         ((uint32) avReg[0x3e]) | (((uint32) avReg[0x3f]) << 8);
2743                                 uint32 r2 =
2744                                         (uint32) (SuperFX.pvRegisters[0x3e])
2745                                                 | (((uint32) SuperFX.pvRegisters[0x3f]) << 8);
2746                                 if (r1 != r2)
2747                                         printf(" CBR=$%04x", r2);
2748                         }
2749                         {
2750                                 /* Check COLR */
2751                                 if (vColr != FxGetColorRegister())
2752                                         printf(" COLR=$%02x", FxGetColorRegister());
2753                         }
2754                         {
2755                                 /* Check POR */
2756                                 if (vPor != FxGetPlotOptionRegister())
2757                                         printf(" POR=$%02x", FxGetPlotOptionRegister());
2758                         }
2759                         printf("\n");
2760                 }
2761                 S9xExit();
2762         }
2763         else
2764         {
2765                 uint32 t =
2766                         (Memory.FillRAM[0x3034] << 16)
2767                                 + (Memory.FillRAM[0x301f] << 8)
2768                                 + (Memory.FillRAM[0x301e] << 0);
2769
2770                 printf("%06x: %d\n", t, FxEmulate(2000000));
2771                 //      FxEmulate (2000000);
2772         }
2773                 #if 0
2774         if (!(CPU.Flags & TRACE_FLAG))
2775         {
2776                 static int z = 1; if (z == 0)
2777                 {
2778                         extern FILE * trace;
2779                                 CPU.Flags |= TRACE_FLAG;
2780                                 trace = fopen("trace.log", "wb");
2781                 }
2782                 else
2783                         z--;
2784         }
2785                 #endif
2786         Memory.FillRAM[0x3030] &= ~0x20;
2787         if (Memory.FillRAM[0x3031] & 0x80)
2788         {
2789                 S9xSetIRQ(GSU_IRQ_SOURCE);
2790         }
2791         #endif
2792 }
2793 #endif
2794