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