aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorNebuleon Fumika2013-01-10 18:01:32 -0500
committerNebuleon Fumika2013-01-10 18:01:32 -0500
commit736484548ea021452415a1711aab10e04b521451 (patch)
tree63cedb0dd10dbbf9c84a0ab19fbc7facbd978d37 /source
parente1ec72de1078f0e371e212852a9273746b1aa42e (diff)
downloadsnes9x2005-736484548ea021452415a1711aab10e04b521451.tar.gz
snes9x2005-736484548ea021452415a1711aab10e04b521451.tar.bz2
snes9x2005-736484548ea021452415a1711aab10e04b521451.zip
Attempt to optimise the ADD background drawing mode so it's playable on automatic frameskip in games like Super Metroid. It doesn't work well.
See the video for this bug at <http://www.youtube.com/watch?v=sUWjVxAD9Q8>.
Diffstat (limited to 'source')
-rw-r--r--source/gfx.cpp97
-rw-r--r--source/gfx.h66
-rw-r--r--source/tile.cpp250
3 files changed, 272 insertions, 141 deletions
diff --git a/source/gfx.cpp b/source/gfx.cpp
index f6a6217..decd195 100644
--- a/source/gfx.cpp
+++ b/source/gfx.cpp
@@ -892,8 +892,8 @@ void S9xSetInfoString (const char *string)
inline void SelectTileRenderer (bool8 normal)
{
- if (normal)
- {
+ if (normal)
+ {
if (IPPU.HalfWidthPixels)
{
DrawTilePtr = DrawTile16HalfWidth;
@@ -906,58 +906,51 @@ inline void SelectTileRenderer (bool8 normal)
DrawClippedTilePtr = DrawClippedTile16;
DrawLargePixelPtr = DrawLargePixel16;
}
- }
- else
- {
- if (GFX.r2131 & 0x80)
- {
- if (GFX.r2131 & 0x40)
- {
- if (GFX.r2130 & 2)
- {
- DrawTilePtr = DrawTile16Sub1_2;
- DrawClippedTilePtr = DrawClippedTile16Sub1_2;
- }
- else
- {
- // Fixed colour substraction
- DrawTilePtr = DrawTile16FixedSub1_2;
- DrawClippedTilePtr = DrawClippedTile16FixedSub1_2;
- }
- DrawLargePixelPtr = DrawLargePixel16Sub1_2;
- }
- else
- {
- DrawTilePtr = DrawTile16Sub;
- DrawClippedTilePtr = DrawClippedTile16Sub;
- DrawLargePixelPtr = DrawLargePixel16Sub;
- }
- }
- else
+ }
+ else
+ {
+ switch (GFX.r2131 & 0xC0)
{
- if (GFX.r2131 & 0x40)
- {
- if (GFX.r2130 & 2)
- {
- DrawTilePtr = DrawTile16Add1_2;
- DrawClippedTilePtr = DrawClippedTile16Add1_2;
- }
- else
- {
- // Fixed colour addition
- DrawTilePtr = DrawTile16FixedAdd1_2;
- DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2;
- }
- DrawLargePixelPtr = DrawLargePixel16Add1_2;
- }
- else
- {
- DrawTilePtr = DrawTile16Add;
- DrawClippedTilePtr = DrawClippedTile16Add;
- DrawLargePixelPtr = DrawLargePixel16Add;
- }
+ case 0x00:
+ DrawTilePtr = DrawTile16Add;
+ DrawClippedTilePtr = DrawClippedTile16Add;
+ DrawLargePixelPtr = DrawLargePixel16Add;
+ break;
+ case 0x40:
+ if (GFX.r2130 & 2)
+ {
+ DrawTilePtr = DrawTile16Add1_2;
+ DrawClippedTilePtr = DrawClippedTile16Add1_2;
+ }
+ else
+ {
+ // Fixed colour addition
+ DrawTilePtr = DrawTile16FixedAdd1_2;
+ DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2;
+ }
+ DrawLargePixelPtr = DrawLargePixel16Add1_2;
+ break;
+ case 0x80:
+ DrawTilePtr = DrawTile16Sub;
+ DrawClippedTilePtr = DrawClippedTile16Sub;
+ DrawLargePixelPtr = DrawLargePixel16Sub;
+ break;
+ case 0xC0:
+ if (GFX.r2130 & 2)
+ {
+ DrawTilePtr = DrawTile16Sub1_2;
+ DrawClippedTilePtr = DrawClippedTile16Sub1_2;
+ }
+ else
+ {
+ // Fixed colour substraction
+ DrawTilePtr = DrawTile16FixedSub1_2;
+ DrawClippedTilePtr = DrawClippedTile16FixedSub1_2;
+ }
+ DrawLargePixelPtr = DrawLargePixel16Sub1_2;
+ break;
}
- }
+ }
}
void S9xSetupOBJ ()
diff --git a/source/gfx.h b/source/gfx.h
index d6da783..88b2640 100644
--- a/source/gfx.h
+++ b/source/gfx.h
@@ -93,6 +93,31 @@
#include "port.h"
#include "snes9x.h"
+START_EXTERN_C
+void S9xStartScreenRefresh ();
+void S9xDrawScanLine (uint8 Line);
+void S9xEndScreenRefresh ();
+void S9xSetupOBJ ();
+void S9xUpdateScreen ();
+void RenderLine (uint8 line);
+void S9xBuildDirectColourMaps ();
+
+// External port interface which must be implemented or initialised for each
+// port.
+extern struct SGFX GFX;
+
+bool8 S9xGraphicsInit ();
+void S9xGraphicsDeinit();
+bool8 S9xInitUpdate (void);
+bool8 S9xDeinitUpdate (int Width, int Height, bool8 sixteen_bit);
+void S9xSyncSpeed ();
+
+#ifdef GFX_MULTI_FORMAT
+bool8 S9xSetRenderPixelFormat (int format);
+#endif
+
+END_EXTERN_C
+
struct SGFX{
// Initialize these variables
uint8 *Screen;
@@ -231,11 +256,17 @@ GFX.X2 [((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \
((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \
((C1) & (C2) & RGB_LOW_BITS_MASK)]
#else
-#define COLOR_ADD(C1, C2) \
-(GFX.X2 [((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \
- ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \
- ((C1) & (C2) & RGB_LOW_BITS_MASK)] | \
- (((C1) ^ (C2)) & RGB_LOW_BITS_MASK))
+inline uint16 COLOR_ADD (uint16, uint16);
+
+inline uint16 COLOR_ADD (uint16 C1, uint16 C2)
+{
+ if (C1 == 0)
+ return C2;
+ else if (C2 == 0)
+ return C1;
+ else
+ return GFX.X2 [(((C1 & RGB_REMOVE_LOW_BITS_MASK) + (C2 & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + (C1 & C2 & RGB_LOW_BITS_MASK)] | ((C1 ^ C2) & RGB_LOW_BITS_MASK);
+}
#endif
#define COLOR_ADD1_2(C1, C2) \
@@ -288,30 +319,5 @@ typedef void (*LargePixelRenderer) (uint32 Tile, uint32 Offset,
uint32 StartPixel, uint32 Pixels,
uint32 StartLine, uint32 LineCount);
-START_EXTERN_C
-void S9xStartScreenRefresh ();
-void S9xDrawScanLine (uint8 Line);
-void S9xEndScreenRefresh ();
-void S9xSetupOBJ ();
-void S9xUpdateScreen ();
-void RenderLine (uint8 line);
-void S9xBuildDirectColourMaps ();
-
-// External port interface which must be implemented or initialised for each
-// port.
-extern struct SGFX GFX;
-
-bool8 S9xGraphicsInit ();
-void S9xGraphicsDeinit();
-bool8 S9xInitUpdate (void);
-bool8 S9xDeinitUpdate (int Width, int Height, bool8 sixteen_bit);
-void S9xSyncSpeed ();
-
-#ifdef GFX_MULTI_FORMAT
-bool8 S9xSetRenderPixelFormat (int format);
-#endif
-
-END_EXTERN_C
-
#endif
diff --git a/source/tile.cpp b/source/tile.cpp
index e18182d..653a6d7 100644
--- a/source/tile.cpp
+++ b/source/tile.cpp
@@ -764,15 +764,18 @@ static void WRITE_4PIXELS16_ADD (uint32 Offset, uint8 *Pixels, uint16 *ScreenCol
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
- else
- Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -789,15 +792,18 @@ static void WRITE_4PIXELS16_FLIPPED_ADD (uint32 Offset, uint8 *Pixels, uint16 *S
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
- else
- Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -814,15 +820,18 @@ static void WRITE_4PIXELS16_ADD1_2 (uint32 Offset, uint8 *Pixels, uint16 *Screen
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]));
- else
- Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]));
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -839,15 +848,18 @@ static void WRITE_4PIXELS16_FLIPPED_ADD1_2 (uint32 Offset, uint8 *Pixels, uint16
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]));
- else
- Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = (uint16) (COLOR_ADD1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]));
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -864,15 +876,18 @@ static void WRITE_4PIXELS16_SUB (uint32 Offset, uint8 *Pixels, uint16 *ScreenCol
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]);
- else
- Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -889,15 +904,18 @@ static void WRITE_4PIXELS16_FLIPPED_SUB (uint32 Offset, uint8 *Pixels, uint16 *S
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]);
- else
- Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -914,15 +932,18 @@ static void WRITE_4PIXELS16_SUB1_2 (uint32 Offset, uint8 *Pixels, uint16 *Screen
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]);
- else
- Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -939,15 +960,18 @@ static void WRITE_4PIXELS16_FLIPPED_SUB1_2 (uint32 Offset, uint8 *Pixels, uint16
{
if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N]))
{
- if (SubDepth [N])
+ switch (SubDepth [N])
{
- if (SubDepth [N] != 1)
- Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]);
- else
- Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
- }
- else
+ case 0:
Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = (uint16) COLOR_SUB (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = (uint16) COLOR_SUB1_2 (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
Depth [N] = GFX.Z2;
}
}
@@ -957,10 +981,118 @@ static void WRITE_4PIXELS16_FLIPPED_SUB1_2 (uint32 Offset, uint8 *Pixels, uint16
void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine,
uint32 LineCount)
{
- TILE_PREAMBLE
- register uint8 *bp;
+ TILE_PREAMBLE
+ register uint8 *bp;
+ uint8 Pixel;
+ uint16 *Screen = (uint16 *) GFX.S + Offset;
+ uint8 *Depth = GFX.ZBuffer + Offset;
+ uint8 *SubDepth = GFX.SubZBuffer + Offset;
- RENDER_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4)
+ switch (Tile & (V_FLIP | H_FLIP))
+ {
+ case 0:
+ bp = pCache + StartLine;
+ for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL)
+ {
+ for (uint8 N = 0; N < 8; N++)
+ {
+ if (GFX.Z1 > Depth [N] && (Pixel = bp[N]))
+ {
+ switch (SubDepth [N])
+ {
+ case 0:
+ Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
+ Depth [N] = GFX.Z2;
+ }
+ }
+ }
+ break;
+ case H_FLIP:
+ bp = pCache + StartLine;
+ for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL)
+ {
+ for (uint8 N = 0; N < 8; N++)
+ {
+ if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N]))
+ {
+ switch (SubDepth [N])
+ {
+ case 0:
+ Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
+ Depth [N] = GFX.Z2;
+ }
+ }
+ }
+ break;
+ case H_FLIP | V_FLIP:
+ bp = pCache + 56 - StartLine;
+ for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL)
+ {
+ for (uint8 N = 0; N < 8; N++)
+ {
+ if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N]))
+ {
+ switch (SubDepth [N])
+ {
+ case 0:
+ Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
+ Depth [N] = GFX.Z2;
+ }
+ }
+ }
+ break;
+ case V_FLIP:
+ bp = pCache + 56 - StartLine;
+ for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL)
+ {
+ for (uint8 N = 0; N < 8; N++)
+ {
+ if (GFX.Z1 > Depth [N] && (Pixel = bp[N]))
+ {
+ switch (SubDepth [N])
+ {
+ case 0:
+ Screen [N] = ScreenColors [Pixel];
+ break;
+ case 1:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], GFX.FixedColour);
+ break;
+ default:
+ Screen [N] = COLOR_ADD (ScreenColors [Pixel], Screen [GFX.Delta + N]);
+ break;
+ }
+ Depth [N] = GFX.Z2;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
void DrawClippedTile16Add (uint32 Tile, uint32 Offset,