aboutsummaryrefslogtreecommitdiff
path: root/source/ppu.h
diff options
context:
space:
mode:
authorKitty Draper2011-03-05 21:39:25 -0500
committerKitty Draper2011-03-05 21:39:25 -0500
commitd40ae99422e118188a7f48055dc340c6aca022aa (patch)
tree83ab93f49fd9e66e43bcd824091ae1dbcaa0c173 /source/ppu.h
downloadsnes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.tar.gz
snes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.tar.bz2
snes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.zip
first commit
Diffstat (limited to 'source/ppu.h')
-rw-r--r--source/ppu.h633
1 files changed, 633 insertions, 0 deletions
diff --git a/source/ppu.h b/source/ppu.h
new file mode 100644
index 0000000..99dde34
--- /dev/null
+++ b/source/ppu.h
@@ -0,0 +1,633 @@
+/*******************************************************************************
+ Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+
+ (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and
+ Jerremy Koot (jkoot@snes9x.com)
+
+ (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net)
+
+ (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net),
+ funkyass (funkyass@spam.shaw.ca),
+ Joel Yliluoma (http://iki.fi/bisqwit/)
+ Kris Bleakley (codeviolation@hotmail.com),
+ Matthew Kendora,
+ Nach (n-a-c-h@users.sourceforge.net),
+ Peter Bortas (peter@bortas.org) and
+ zones (kasumitokoduck@yahoo.com)
+
+ C4 x86 assembler and some C emulation code
+ (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),
+ _Demo_ (_demo_@zsnes.com), and Nach
+
+ C4 C++ code
+ (c) Copyright 2003 Brad Jorsch
+
+ DSP-1 emulator code
+ (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,
+ John Weidman, neviksti (neviksti@hotmail.com),
+ Kris Bleakley, Andreas Naive
+
+ DSP-2 emulator code
+ (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and
+ Lord Nightmare (lord_nightmare@users.sourceforge.net
+
+ OBC1 emulator code
+ (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and
+ Kris Bleakley
+ Ported from x86 assembler to C by sanmaiwashi
+
+ SPC7110 and RTC C++ emulator code
+ (c) Copyright 2002 Matthew Kendora with research by
+ zsKnight, John Weidman, and Dark Force
+
+ S-DD1 C emulator code
+ (c) Copyright 2003 Brad Jorsch with research by
+ Andreas Naive and John Weidman
+
+ S-RTC C emulator code
+ (c) Copyright 2001 John Weidman
+
+ ST010 C++ emulator code
+ (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora
+
+ Super FX x86 assembler emulator code
+ (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault
+
+ Super FX C emulator code
+ (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman
+
+
+ SH assembler code partly based on x86 assembler code
+ (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
+
+
+ Specific ports contains the works of other authors. See headers in
+ individual files.
+
+ Snes9x homepage: http://www.snes9x.com
+
+ Permission to use, copy, modify and distribute Snes9x in both binary and
+ source form, for non-commercial purposes, is hereby granted without fee,
+ providing that this license information and copyright notice appear with
+ all copies and any derived work.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event shall the authors be held liable for any damages
+ arising from the use of this software.
+
+ Snes9x is freeware for PERSONAL USE only. Commercial users should
+ seek permission of the copyright holders first. Commercial use includes
+ charging money for Snes9x or software derived from Snes9x.
+
+ The copyright holders request that bug fixes and improvements to the code
+ should be forwarded to them so everyone can benefit from the modifications
+ in future versions.
+
+ Super NES and Super Nintendo Entertainment System are trademarks of
+ Nintendo Co., Limited and its subsidiary companies.
+*******************************************************************************/
+
+#ifndef _PPU_H_
+#define _PPU_H_
+
+#define FIRST_VISIBLE_LINE 1
+
+extern uint8 GetBank;
+extern uint16 SignExtend [2];
+
+#define TILE_2BIT 0
+#define TILE_4BIT 1
+#define TILE_8BIT 2
+
+#define MAX_2BIT_TILES 4096
+#define MAX_4BIT_TILES 2048
+#define MAX_8BIT_TILES 1024
+
+#define PPU_H_BEAM_IRQ_SOURCE (1 << 0)
+#define PPU_V_BEAM_IRQ_SOURCE (1 << 1)
+#define GSU_IRQ_SOURCE (1 << 2)
+#define SA1_IRQ_SOURCE (1 << 7)
+#define SA1_DMA_IRQ_SOURCE (1 << 5)
+
+struct ClipData {
+ uint32 Count [6];
+ uint32 Left [6][6];
+ uint32 Right [6][6];
+};
+
+struct InternalPPU {
+ bool8 ColorsChanged;
+ uint8 HDMA;
+ bool8 HDMAStarted;
+ uint8 MaxBrightness;
+ bool8 LatchedBlanking;
+ bool8 OBJChanged;
+ bool8 RenderThisFrame;
+ bool8 DirectColourMapsNeedRebuild;
+ uint32 FrameCount;
+ uint32 RenderedFramesCount;
+ uint32 DisplayedRenderedFrameCount;
+ uint32 SkippedFrames;
+ uint32 FrameSkip;
+ uint8 *TileCache [3];
+ uint8 *TileCached [3];
+#ifdef CORRECT_VRAM_READS
+ uint16 VRAMReadBuffer;
+#else
+ bool8 FirstVRAMRead;
+#endif
+ bool8 DoubleHeightPixels;
+ bool8 Interlace;
+ bool8 InterlaceSprites;
+ bool8 DoubleWidthPixels;
+ int RenderedScreenHeight;
+ int RenderedScreenWidth;
+ uint32 Red [256];
+ uint32 Green [256];
+ uint32 Blue [256];
+ uint8 *XB;
+ uint16 ScreenColors [256];
+ int PreviousLine;
+ int CurrentLine;
+ int Controller;
+ uint32 Joypads[5];
+ uint32 SuperScope;
+ uint32 Mouse[2];
+ int PrevMouseX[2];
+ int PrevMouseY[2];
+ struct ClipData Clip [2];
+};
+
+struct SOBJ
+{
+ short HPos;
+ uint16 VPos;
+ uint16 Name;
+ uint8 VFlip;
+ uint8 HFlip;
+ uint8 Priority;
+ uint8 Palette;
+ uint8 Size;
+};
+
+struct SPPU {
+ uint8 BGMode;
+ uint8 BG3Priority;
+ uint8 Brightness;
+
+ struct {
+ bool8 High;
+ uint8 Increment;
+ uint16 Address;
+ uint16 Mask1;
+ uint16 FullGraphicCount;
+ uint16 Shift;
+ } VMA;
+
+ struct {
+ uint16 SCBase;
+ uint16 VOffset;
+ uint16 HOffset;
+ uint8 BGSize;
+ uint16 NameBase;
+ uint16 SCSize;
+ } BG [4];
+
+ bool8 CGFLIP;
+ uint16 CGDATA [256];
+ uint8 FirstSprite;
+ uint8 LastSprite;
+ struct SOBJ OBJ [128];
+ uint8 OAMPriorityRotation;
+ uint16 OAMAddr;
+ uint8 RangeTimeOver;
+
+ uint8 OAMFlip;
+ uint16 OAMTileAddress;
+ uint16 IRQVBeamPos;
+ uint16 IRQHBeamPos;
+ uint16 VBeamPosLatched;
+ uint16 HBeamPosLatched;
+
+ uint8 HBeamFlip;
+ uint8 VBeamFlip;
+ uint8 HVBeamCounterLatched;
+
+ short MatrixA;
+ short MatrixB;
+ short MatrixC;
+ short MatrixD;
+ short CentreX;
+ short CentreY;
+ uint8 Joypad1ButtonReadPos;
+ uint8 Joypad2ButtonReadPos;
+
+ uint8 CGADD;
+ uint8 FixedColourRed;
+ uint8 FixedColourGreen;
+ uint8 FixedColourBlue;
+ uint16 SavedOAMAddr;
+ uint16 ScreenHeight;
+ uint32 WRAM;
+ uint8 BG_Forced;
+ bool8 ForcedBlanking;
+ bool8 OBJThroughMain;
+ bool8 OBJThroughSub;
+ uint8 OBJSizeSelect;
+ uint16 OBJNameBase;
+ bool8 OBJAddition;
+ uint8 OAMReadFlip;
+ uint8 OAMData [512 + 32];
+ bool8 VTimerEnabled;
+ bool8 HTimerEnabled;
+ short HTimerPosition;
+ uint8 Mosaic;
+ bool8 BGMosaic [4];
+ bool8 Mode7HFlip;
+ bool8 Mode7VFlip;
+ uint8 Mode7Repeat;
+ uint8 Window1Left;
+ uint8 Window1Right;
+ uint8 Window2Left;
+ uint8 Window2Right;
+ uint8 ClipCounts [6];
+ uint8 ClipWindowOverlapLogic [6];
+ uint8 ClipWindow1Enable [6];
+ uint8 ClipWindow2Enable [6];
+ bool8 ClipWindow1Inside [6];
+ bool8 ClipWindow2Inside [6];
+ bool8 RecomputeClipWindows;
+ uint8 CGFLIPRead;
+ uint16 OBJNameSelect;
+ bool8 Need16x8Mulitply;
+ uint8 Joypad3ButtonReadPos;
+ uint8 MouseSpeed[2];
+
+ // XXX Do these need to be added to snapshot.cpp?
+ uint16 OAMWriteRegister;
+ uint8 BGnxOFSbyte;
+ uint8 OpenBus1;
+ uint8 OpenBus2;
+};
+
+#define CLIP_OR 0
+#define CLIP_AND 1
+#define CLIP_XOR 2
+#define CLIP_XNOR 3
+
+struct SDMA {
+ bool8 TransferDirection;
+ bool8 AAddressFixed;
+ bool8 AAddressDecrement;
+ uint8 TransferMode;
+
+ uint8 ABank;
+ uint16 AAddress;
+ uint16 Address;
+ uint8 BAddress;
+
+ // General DMA only:
+ uint16 TransferBytes;
+
+ // H-DMA only:
+ bool8 HDMAIndirectAddressing;
+ uint16 IndirectAddress;
+ uint8 IndirectBank;
+ uint8 Repeat;
+ uint8 LineCount;
+ uint8 FirstLine;
+};
+
+START_EXTERN_C
+void S9xUpdateScreen ();
+void S9xResetPPU ();
+void S9xSoftResetPPU ();
+void S9xFixColourBrightness ();
+void S9xUpdateJoypads ();
+void S9xProcessMouse(int which1);
+void S9xSuperFXExec ();
+
+void S9xSetPPU (uint8 Byte, uint16 Address);
+uint8 S9xGetPPU (uint16 Address);
+void S9xSetCPU (uint8 Byte, uint16 Address);
+uint8 S9xGetCPU (uint16 Address);
+
+void S9xInitC4 ();
+void S9xSetC4 (uint8 Byte, uint16 Address);
+uint8 S9xGetC4 (uint16 Address);
+void S9xSetC4RAM (uint8 Byte, uint16 Address);
+uint8 S9xGetC4RAM (uint16 Address);
+
+extern struct SPPU PPU;
+extern struct SDMA DMA [8];
+extern struct InternalPPU IPPU;
+END_EXTERN_C
+
+#include "gfx.h"
+#include "memmap.h"
+
+typedef struct{
+ uint8 _5C77;
+ uint8 _5C78;
+ uint8 _5A22;
+} SnesModel;
+
+START_EXTERN_C
+extern SnesModel* Model;
+extern SnesModel M1SNES;
+extern SnesModel M2SNES;
+END_EXTERN_C
+
+#define MAX_5C77_VERSION 0x01
+#define MAX_5C78_VERSION 0x03
+#define MAX_5A22_VERSION 0x02
+
+STATIC inline uint8 REGISTER_4212()
+{
+ GetBank = 0;
+ if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE &&
+ CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3)
+ GetBank = 1;
+
+ GetBank |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0;
+ if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE)
+ GetBank |= 0x80; /* XXX: 0x80 or 0xc0 ? */
+
+ return (GetBank);
+}
+
+STATIC inline void FLUSH_REDRAW ()
+{
+ if (IPPU.PreviousLine != IPPU.CurrentLine)
+ S9xUpdateScreen ();
+}
+
+STATIC inline void REGISTER_2104 (uint8 byte)
+{
+ if (PPU.OAMAddr & 0x100)
+ {
+ int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1);
+ if (byte != PPU.OAMData [addr]){
+ FLUSH_REDRAW ();
+ PPU.OAMData [addr] = byte;
+ IPPU.OBJChanged = TRUE;
+
+ // X position high bit, and sprite size (x4)
+ struct SOBJ *pObj = &PPU.OBJ [(addr & 0x1f) * 4];
+
+ pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 0) & 1];
+ pObj++->Size = byte & 2;
+ pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 2) & 1];
+ pObj++->Size = byte & 8;
+ pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 4) & 1];
+ pObj++->Size = byte & 32;
+ pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 6) & 1];
+ pObj->Size = byte & 128;
+ }
+ PPU.OAMFlip ^= 1;
+ if(!(PPU.OAMFlip & 1)){
+ ++PPU.OAMAddr;
+ PPU.OAMAddr &= 0x1ff;
+ if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
+ {
+ PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1;
+ IPPU.OBJChanged = TRUE;
+ }
+ } else {
+ if (PPU.OAMPriorityRotation && (PPU.OAMAddr&1)) IPPU.OBJChanged = TRUE;
+ }
+ } else if(!(PPU.OAMFlip & 1)){
+ PPU.OAMWriteRegister &= 0xff00;
+ PPU.OAMWriteRegister |= byte;
+ PPU.OAMFlip |= 1;
+ if (PPU.OAMPriorityRotation && (PPU.OAMAddr&1)) IPPU.OBJChanged = TRUE;
+ } else {
+ PPU.OAMWriteRegister &= 0x00ff;
+ uint8 lowbyte = (uint8)(PPU.OAMWriteRegister);
+ uint8 highbyte = byte;
+ PPU.OAMWriteRegister |= byte << 8;
+
+ int addr = (PPU.OAMAddr << 1);
+
+ if (lowbyte != PPU.OAMData [addr] ||
+ highbyte != PPU.OAMData [addr+1])
+ {
+ FLUSH_REDRAW ();
+ PPU.OAMData [addr] = lowbyte;
+ PPU.OAMData [addr+1] = highbyte;
+ IPPU.OBJChanged = TRUE;
+ if (addr & 2)
+ {
+ // Tile
+ PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff;
+
+ // priority, h and v flip.
+ PPU.OBJ[addr].Palette = (highbyte >> 1) & 7;
+ PPU.OBJ[addr].Priority = (highbyte >> 4) & 3;
+ PPU.OBJ[addr].HFlip = (highbyte >> 6) & 1;
+ PPU.OBJ[addr].VFlip = (highbyte >> 7) & 1;
+ }
+ else
+ {
+ // X position (low)
+ PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xFF00;
+ PPU.OBJ[addr].HPos |= lowbyte;
+
+ // Sprite Y position
+ PPU.OBJ[addr].VPos = highbyte;
+ }
+ }
+ PPU.OAMFlip &= ~1;
+ ++PPU.OAMAddr;
+ if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
+ {
+ PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1;
+ IPPU.OBJChanged = TRUE;
+ }
+ }
+
+ Memory.FillRAM [0x2104] = byte;
+}
+
+STATIC inline void REGISTER_2118 (uint8 Byte)
+{
+ uint32 address;
+ if (PPU.VMA.FullGraphicCount)
+ {
+ uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1;
+ address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) +
+ (rem >> PPU.VMA.Shift) +
+ ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff;
+ Memory.VRAM [address] = Byte;
+ }
+ else
+ {
+ Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte;
+ }
+ IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE;
+ IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE;
+ IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE;
+ if (!PPU.VMA.High)
+ {
+#ifdef DEBUGGER
+ if (Settings.TraceVRAM && !CPU.InDMA)
+ {
+ printf ("VRAM write byte: $%04X (%d,%d)\n", PPU.VMA.Address,
+ Memory.FillRAM[0x2115] & 3,
+ (Memory.FillRAM [0x2115] & 0x0c) >> 2);
+ }
+#endif
+ PPU.VMA.Address += PPU.VMA.Increment;
+ }
+// Memory.FillRAM [0x2118] = Byte;
+}
+
+STATIC inline void REGISTER_2118_tile (uint8 Byte)
+{
+ uint32 address;
+ uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1;
+ address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) +
+ (rem >> PPU.VMA.Shift) +
+ ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff;
+ Memory.VRAM [address] = Byte;
+ IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE;
+ IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE;
+ IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE;
+ if (!PPU.VMA.High)
+ PPU.VMA.Address += PPU.VMA.Increment;
+// Memory.FillRAM [0x2118] = Byte;
+}
+
+STATIC inline void REGISTER_2118_linear (uint8 Byte)
+{
+ uint32 address;
+ Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte;
+ IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE;
+ IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE;
+ IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE;
+ if (!PPU.VMA.High)
+ PPU.VMA.Address += PPU.VMA.Increment;
+// Memory.FillRAM [0x2118] = Byte;
+}
+
+STATIC inline void REGISTER_2119 (uint8 Byte)
+{
+ uint32 address;
+ if (PPU.VMA.FullGraphicCount)
+ {
+ uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1;
+ address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) +
+ (rem >> PPU.VMA.Shift) +
+ ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF;
+ Memory.VRAM [address] = Byte;
+ }
+ else
+ {
+ Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte;
+ }
+ IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE;
+ IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE;
+ IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE;
+ if (PPU.VMA.High)
+ {
+#ifdef DEBUGGER
+ if (Settings.TraceVRAM && !CPU.InDMA)
+ {
+ printf ("VRAM write word: $%04X (%d,%d)\n", PPU.VMA.Address,
+ Memory.FillRAM[0x2115] & 3,
+ (Memory.FillRAM [0x2115] & 0x0c) >> 2);
+ }
+#endif
+ PPU.VMA.Address += PPU.VMA.Increment;
+ }
+// Memory.FillRAM [0x2119] = Byte;
+}
+
+STATIC inline void REGISTER_2119_tile (uint8 Byte)
+{
+ uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1;
+ uint32 address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) +
+ (rem >> PPU.VMA.Shift) +
+ ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF;
+ Memory.VRAM [address] = Byte;
+ IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE;
+ IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE;
+ IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE;
+ if (PPU.VMA.High)
+ PPU.VMA.Address += PPU.VMA.Increment;
+// Memory.FillRAM [0x2119] = Byte;
+}
+
+STATIC inline void REGISTER_2119_linear (uint8 Byte)
+{
+ uint32 address;
+ Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte;
+ IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE;
+ IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE;
+ IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE;
+ if (PPU.VMA.High)
+ PPU.VMA.Address += PPU.VMA.Increment;
+// Memory.FillRAM [0x2119] = Byte;
+}
+
+STATIC inline void REGISTER_2122(uint8 Byte)
+{
+ // CG-RAM (palette) write
+
+ if (PPU.CGFLIP)
+ {
+ if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8))
+ {
+ if (Settings.SixteenBit)
+ FLUSH_REDRAW ();
+ PPU.CGDATA[PPU.CGADD] &= 0x00FF;
+ PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8;
+ IPPU.ColorsChanged = TRUE;
+ if (Settings.SixteenBit)
+ {
+ IPPU.Blue [PPU.CGADD] = IPPU.XB [(Byte >> 2) & 0x1f];
+ IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f];
+ IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD],
+ IPPU.Green [PPU.CGADD],
+ IPPU.Blue [PPU.CGADD]);
+ }
+ }
+ PPU.CGADD++;
+ }
+ else
+ {
+ if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff))
+ {
+ if (Settings.SixteenBit)
+ FLUSH_REDRAW ();
+ PPU.CGDATA[PPU.CGADD] &= 0x7F00;
+ PPU.CGDATA[PPU.CGADD] |= Byte;
+ IPPU.ColorsChanged = TRUE;
+ if (Settings.SixteenBit)
+ {
+ IPPU.Red [PPU.CGADD] = IPPU.XB [Byte & 0x1f];
+ IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f];
+ IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD],
+ IPPU.Green [PPU.CGADD],
+ IPPU.Blue [PPU.CGADD]);
+ }
+ }
+ }
+ PPU.CGFLIP ^= 1;
+// Memory.FillRAM [0x2122] = Byte;
+}
+
+STATIC inline void REGISTER_2180(uint8 Byte)
+{
+ Memory.RAM[PPU.WRAM++] = Byte;
+ PPU.WRAM &= 0x1FFFF;
+ Memory.FillRAM [0x2180] = Byte;
+}
+
+
+//Platform specific input functions used by PPU.CPP
+void JustifierButtons(uint32&);
+bool JustifierOffscreen();
+
+#endif
+