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