From 736484548ea021452415a1711aab10e04b521451 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 10 Jan 2013 18:01:32 -0500 Subject: 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 . --- source/gfx.cpp | 97 ++++++++++------------ source/gfx.h | 66 ++++++++------- source/tile.cpp | 250 +++++++++++++++++++++++++++++++++++++++++++------------- 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, -- cgit v1.2.3