From 7603ed09d250d2c6d520d05f7f6fda5c4689e3ce Mon Sep 17 00:00:00 2001 From: Kenta Yoshimura Date: Sat, 4 May 2019 12:58:53 +0900 Subject: [PATCH] tile: Divide instantiations. This enables parallel compilation. --- macosx/snes9x.xcodeproj/project.pbxproj | 32 + tile.cpp | 809 +----------------------- tileimpl-h2x1.cpp | 47 ++ tileimpl-n1x1.cpp | 34 + tileimpl-n2x1.cpp | 44 ++ tileimpl.h | 801 +++++++++++++++++++++++ unix/Makefile.in | 2 +- win32/snes9xw.vcxproj | 4 + win32/snes9xw.vcxproj.filters | 14 +- 9 files changed, 978 insertions(+), 809 deletions(-) create mode 100644 tileimpl-h2x1.cpp create mode 100644 tileimpl-n1x1.cpp create mode 100644 tileimpl-n2x1.cpp create mode 100644 tileimpl.h diff --git a/macosx/snes9x.xcodeproj/project.pbxproj b/macosx/snes9x.xcodeproj/project.pbxproj index d6f00a53..0fd5dae8 100755 --- a/macosx/snes9x.xcodeproj/project.pbxproj +++ b/macosx/snes9x.xcodeproj/project.pbxproj @@ -59,6 +59,18 @@ BF0B3A011FA5816D002B04D3 /* snes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BF0B39AB1FA5792F002B04D3 /* snes.hpp */; }; BF0B3A041FA58172002B04D3 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = BF0B39AD1FA5792F002B04D3 /* resampler.h */; }; BF0B3A051FA58172002B04D3 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = BF0B39AD1FA5792F002B04D3 /* resampler.h */; }; + CE6E9065227D5E0F00C3FFC6 /* tileimpl.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6E9064227D5E0F00C3FFC6 /* tileimpl.h */; }; + CE6E9066227D5E0F00C3FFC6 /* tileimpl.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6E9064227D5E0F00C3FFC6 /* tileimpl.h */; }; + CE6E9067227D5E0F00C3FFC6 /* tileimpl.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6E9064227D5E0F00C3FFC6 /* tileimpl.h */; }; + CE6E906B227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E9068227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp */; }; + CE6E906C227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E9068227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp */; }; + CE6E906D227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E9068227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp */; }; + CE6E906E227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E9069227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp */; }; + CE6E906F227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E9069227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp */; }; + CE6E9070227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E9069227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp */; }; + CE6E9071227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E906A227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp */; }; + CE6E9072227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E906A227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp */; }; + CE6E9073227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE6E906A227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp */; }; CF047D38109D0E0600FD0754 /* 65c816.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0615A0526CCB900A80003 /* 65c816.h */; }; CF047D3B109D0E0600FD0754 /* bsx.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2F381A09B17E9E0078DCA7 /* bsx.h */; }; CF047D3C109D0E0600FD0754 /* c4.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061600526CCB900A80003 /* c4.h */; }; @@ -728,6 +740,10 @@ BF0B39AD1FA5792F002B04D3 /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = ""; }; BF0B39DE1FA580F9002B04D3 /* msu1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = msu1.cpp; sourceTree = ""; }; BF0B39E21FA58124002B04D3 /* msu1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = msu1.h; sourceTree = ""; }; + CE6E9064227D5E0F00C3FFC6 /* tileimpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tileimpl.h; sourceTree = ""; }; + CE6E9068227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "tileimpl-h2x1.cpp"; sourceTree = ""; }; + CE6E9069227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "tileimpl-n2x1.cpp"; sourceTree = ""; }; + CE6E906A227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "tileimpl-n1x1.cpp"; sourceTree = ""; }; CF047E15109D0E0600FD0754 /* Snes9x (i386).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Snes9x (i386).app"; sourceTree = BUILT_PRODUCTS_DIR; }; CF047E17109D0E0600FD0754 /* Info_i386.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info_i386.plist; sourceTree = ""; }; CF0567660CF98E7E00C7877C /* Snes9x.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Snes9x.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1224,6 +1240,7 @@ EAE061EA0526CCB900A80003 /* srtc.h */, CFA82C3D0F1B43A60089C17F /* srtcemu.h */, EAE061EC0526CCB900A80003 /* tile.h */, + CE6E9064227D5E0F00C3FFC6 /* tileimpl.h */, EA2F380F09B17E070078DCA7 /* bsx.cpp */, EAE0615F0526CCB900A80003 /* c4.cpp */, EAE061610526CCB900A80003 /* c4emu.cpp */, @@ -1269,6 +1286,9 @@ EAE061E90526CCB900A80003 /* srtc.cpp */, CFA82C3E0F1B43A60089C17F /* srtcemu.cpp */, EAE061EB0526CCB900A80003 /* tile.cpp */, + CE6E9068227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp */, + CE6E906A227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp */, + CE6E9069227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp */, BF0B39791FA5792F002B04D3 /* apu */, CF5553B00EA24C36005957E4 /* filter */, EAA7B5D807609F76001BAB8B /* jma */, @@ -1417,6 +1437,7 @@ CF047D51109D0E0600FD0754 /* missing.h in Headers */, CF047D52109D0E0600FD0754 /* movie.h in Headers */, CF047D53109D0E0600FD0754 /* obc1.h in Headers */, + CE6E9066227D5E0F00C3FFC6 /* tileimpl.h in Headers */, CF047D54109D0E0600FD0754 /* pixform.h in Headers */, CF047D55109D0E0600FD0754 /* port.h in Headers */, CF047D56109D0E0600FD0754 /* ppu.h in Headers */, @@ -1603,6 +1624,7 @@ CF0566E30CF98E7E00C7877C /* mac-netplay.h in Headers */, CF0566E40CF98E7E00C7877C /* mac-os.h in Headers */, CF0566E50CF98E7E00C7877C /* mac-prefs.h in Headers */, + CE6E9065227D5E0F00C3FFC6 /* tileimpl.h in Headers */, CF0566E60CF98E7E00C7877C /* mac-quicktime.h in Headers */, BF0B39B81FA5792F002B04D3 /* SPC_DSP.h in Headers */, CF0566E70CF98E7E00C7877C /* mac-render.h in Headers */, @@ -1653,6 +1675,7 @@ CF2F462B1095EE72007D33FA /* missing.h in Headers */, CF2F462C1095EE72007D33FA /* movie.h in Headers */, CF2F462D1095EE72007D33FA /* obc1.h in Headers */, + CE6E9067227D5E0F00C3FFC6 /* tileimpl.h in Headers */, CF2F462E1095EE72007D33FA /* pixform.h in Headers */, CF2F462F1095EE72007D33FA /* port.h in Headers */, CF2F46301095EE72007D33FA /* ppu.h in Headers */, @@ -1981,6 +2004,7 @@ CF047DD5109D0E0600FD0754 /* snapshot.cpp in Sources */, CF047DD8109D0E0600FD0754 /* spc7110.cpp in Sources */, CF047DD9109D0E0600FD0754 /* srtc.cpp in Sources */, + CE6E906C227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp in Sources */, CF047DDA109D0E0600FD0754 /* tile.cpp in Sources */, CF047DDB109D0E0600FD0754 /* 2xsai.cpp in Sources */, CF047DDC109D0E0600FD0754 /* blit.cpp in Sources */, @@ -2013,11 +2037,13 @@ CF047DF3109D0E0600FD0754 /* mac-dialog.cpp in Sources */, CF047DF4109D0E0600FD0754 /* mac-file.cpp in Sources */, CF047DF5109D0E0600FD0754 /* mac-gworld.cpp in Sources */, + CE6E9072227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp in Sources */, CF047DF6109D0E0600FD0754 /* mac-joypad.cpp in Sources */, CF047DF7109D0E0600FD0754 /* mac-keyboard.cpp in Sources */, CF047DF8109D0E0600FD0754 /* mac-multicart.cpp in Sources */, CF047DF9109D0E0600FD0754 /* mac-musicbox.mm in Sources */, CF047DFA109D0E0600FD0754 /* mac-netplay.cpp in Sources */, + CE6E906F227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp in Sources */, CF047DFB109D0E0600FD0754 /* mac-os.mm in Sources */, CF047DFC109D0E0600FD0754 /* mac-prefs.cpp in Sources */, CF047DFD109D0E0600FD0754 /* mac-quicktime.cpp in Sources */, @@ -2037,6 +2063,7 @@ CF0567040CF98E7E00C7877C /* c4.cpp in Sources */, CF0567050CF98E7E00C7877C /* c4emu.cpp in Sources */, CF0567060CF98E7E00C7877C /* cheats.cpp in Sources */, + CE6E906B227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp in Sources */, BF0B39AF1FA5792F002B04D3 /* apu.cpp in Sources */, CF0567070CF98E7E00C7877C /* cheats2.cpp in Sources */, CF0567080CF98E7E00C7877C /* clip.cpp in Sources */, @@ -2055,6 +2082,7 @@ CF5D3E250FAFD35400340007 /* dsp4.cpp in Sources */, CFE7FBB40D2F67BA002F3102 /* fxemu.cpp in Sources */, CF0567120CF98E7E00C7877C /* fxinst.cpp in Sources */, + CE6E9071227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp in Sources */, CF0567130CF98E7E00C7877C /* gfx.cpp in Sources */, CF0567140CF98E7E00C7877C /* globals.cpp in Sources */, CF0567150CF98E7E00C7877C /* loadzip.cpp in Sources */, @@ -2077,6 +2105,7 @@ CF0567270CF98E7E00C7877C /* spc7110.cpp in Sources */, CF0567280CF98E7E00C7877C /* srtc.cpp in Sources */, CF0567290CF98E7E00C7877C /* tile.cpp in Sources */, + CE6E906E227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp in Sources */, CF5553C90EA24C36005957E4 /* 2xsai.cpp in Sources */, CF5553CB0EA24C36005957E4 /* blit.cpp in Sources */, CF5553CD0EA24C36005957E4 /* epx.cpp in Sources */, @@ -2171,6 +2200,7 @@ CF2F46AF1095EE72007D33FA /* snapshot.cpp in Sources */, CF2F46B21095EE72007D33FA /* spc7110.cpp in Sources */, CF2F46B31095EE72007D33FA /* srtc.cpp in Sources */, + CE6E906D227D5E1E00C3FFC6 /* tileimpl-h2x1.cpp in Sources */, CF2F46B41095EE72007D33FA /* tile.cpp in Sources */, CF2F46B51095EE72007D33FA /* 2xsai.cpp in Sources */, CF2F46B61095EE72007D33FA /* blit.cpp in Sources */, @@ -2203,11 +2233,13 @@ CF2F46CD1095EE72007D33FA /* mac-dialog.cpp in Sources */, CF2F46CE1095EE72007D33FA /* mac-file.cpp in Sources */, CF2F46CF1095EE72007D33FA /* mac-gworld.cpp in Sources */, + CE6E9073227D5E1E00C3FFC6 /* tileimpl-n1x1.cpp in Sources */, CF2F46D01095EE72007D33FA /* mac-joypad.cpp in Sources */, CF2F46D11095EE72007D33FA /* mac-keyboard.cpp in Sources */, CF2F46D21095EE72007D33FA /* mac-multicart.cpp in Sources */, CF2F46D31095EE72007D33FA /* mac-musicbox.mm in Sources */, CF2F46D41095EE72007D33FA /* mac-netplay.cpp in Sources */, + CE6E9070227D5E1E00C3FFC6 /* tileimpl-n2x1.cpp in Sources */, CF2F46D51095EE72007D33FA /* mac-os.mm in Sources */, CF2F46D61095EE72007D33FA /* mac-prefs.cpp in Sources */, CF2F46D71095EE72007D33FA /* mac-quicktime.cpp in Sources */, diff --git a/tile.cpp b/tile.cpp index 85bd0f81..4399b693 100644 --- a/tile.cpp +++ b/tile.cpp @@ -4,12 +4,9 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include "snes9x.h" -#include "ppu.h" -#include "tile.h" - -extern struct SLineMatrixData LineMatrixData[240]; +#include "tileimpl.h" +using namespace TileImpl; namespace { @@ -17,97 +14,6 @@ namespace { uint8 hrbit_odd[256]; uint8 hrbit_even[256]; - struct BPProgressive - { - enum { Pitch = 1 }; - static alwaysinline uint32 Get(uint32 StartLine) { return StartLine; } - }; - - // Interlace: Only draw every other line, so we'll redefine bpstart_t and Pitch to do so. - // Otherwise, it's the same as Normal2x1/Hires2x1. - struct BPInterlace - { - enum { Pitch = 2 }; - static alwaysinline uint32 Get(uint32 StartLine) { return StartLine * 2 + BG.InterlaceLine; } - }; - - // The 1x1 pixel plotter, for speedhacking modes. - template - struct Normal1x1Base - { - enum { Pitch = BPSTART::Pitch }; - typedef BPSTART bpstart_t; - - static alwaysinline void Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2) - { - (void) OffsetInLine; - if (Z1 > GFX.DB[Offset + N] && (M)) - { - GFX.S[Offset + N] = MATH::Calc(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + N], GFX.SubZBuffer[Offset + N]); - GFX.DB[Offset + N] = Z2; - } - } - }; - - template - struct Normal1x1 : public Normal1x1Base {}; - - // The 2x1 pixel plotter, for normal rendering when we've used hires/interlace already this frame. - template - struct Normal2x1Base - { - enum { Pitch = BPSTART::Pitch }; - typedef BPSTART bpstart_t; - - static alwaysinline void Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2) - { - (void) OffsetInLine; - if (Z1 > GFX.DB[Offset + 2 * N] && (M)) - { - GFX.S[Offset + 2 * N] = GFX.S[Offset + 2 * N + 1] = MATH::Calc(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); - GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; - } - } - }; - - template - struct Normal2x1 : public Normal2x1Base {}; - template - struct Interlace : public Normal2x1Base {}; - - // Hires pixel plotter, this combines the main and subscreen pixels as appropriate to render hires or pseudo-hires images. - // Use it only on the main screen, subscreen should use Normal2x1 instead. - // Hires math: - // Main pixel is mathed as normal: Main(x, y) * Sub(x, y). - // Sub pixel is mathed somewhat weird: Basically, for Sub(x + 1, y) we apply the same operation we applied to Main(x, y) - // (e.g. no math, add fixed, add1/2 subscreen) using Main(x, y) as the "corresponding subscreen pixel". - // Also, color window clipping clips Sub(x + 1, y) if Main(x, y) is clipped, not Main(x + 1, y). - // We don't know how Sub(0, y) is handled. - template - struct HiresBase - { - enum { Pitch = BPSTART::Pitch }; - typedef BPSTART bpstart_t; - - static alwaysinline void Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2) - { - if (Z1 > GFX.DB[Offset + 2 * N] && (M)) - { - GFX.S[Offset + 2 * N + 1] = MATH::Calc(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); - if ((OffsetInLine + 2 * N ) != (SNES_WIDTH - 1) << 1) - GFX.S[Offset + 2 * N + 2] = MATH::Calc((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N + 2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); - if ((OffsetInLine + 2 * N) == 0 || (OffsetInLine + 2 * N) == GFX.RealPPL) - GFX.S[Offset + 2 * N] = MATH::Calc((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); - GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; - } - } - }; - - template - struct Hires : public HiresBase {}; - template - struct HiresInterlace : public HiresBase {}; - // Here are the tile converters, selected by S9xSelectTileConverter(). // Really, except for the definition of DOBIT and the number of times it is called, they're all the same. @@ -329,719 +235,8 @@ namespace { #undef DOBIT - - class CachedTile - { - public: - CachedTile(uint32 tile) : Tile(tile) {} - - alwaysinline void GetCachedTile() - { - TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); - if (Tile & 0x100) - TileAddr += BG.NameSelect; - TileAddr &= 0xffff; - TileNumber = TileAddr >> BG.TileShift; - if (Tile & H_FLIP) - { - pCache = &BG.BufferFlip[TileNumber << 6]; - if (!BG.BufferedFlip[TileNumber]) - BG.BufferedFlip[TileNumber] = BG.ConvertTileFlip(pCache, TileAddr, Tile & 0x3ff); - } - else - { - pCache = &BG.Buffer[TileNumber << 6]; - if (!BG.Buffered[TileNumber]) - BG.Buffered[TileNumber] = BG.ConvertTile(pCache, TileAddr, Tile & 0x3ff); - } - } - - alwaysinline bool IsBlankTile() const - { - return ((Tile & H_FLIP) ? BG.BufferedFlip[TileNumber] : BG.Buffered[TileNumber]) == BLANK_TILE; - } - - alwaysinline void SelectPalette() const - { - if (BG.DirectColourMode) - { - GFX.RealScreenColors = DirectColourMaps[(Tile >> 10) & 7]; - } - else - GFX.RealScreenColors = &IPPU.ScreenColors[((Tile >> BG.PaletteShift) & BG.PaletteMask) + BG.StartPalette]; - GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; - } - - alwaysinline uint8* Ptr() const - { - return pCache; - } - - private: - uint8 *pCache; - uint32 Tile; - uint32 TileNumber; - uint32 TileAddr; - }; - - struct NOMATH - { - static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) - { - return Main; - } - }; - typedef NOMATH Blend_None; - - template - struct REGMATH - { - static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) - { - return Op::fn(Main, (SD & 0x20) ? Sub : GFX.FixedColour); - } - }; - typedef REGMATH Blend_Add; - typedef REGMATH Blend_Sub; - typedef REGMATH Blend_AddBrightness; - - template - struct MATHF1_2 - { - static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) - { - return GFX.ClipColors ? Op::fn(Main, GFX.FixedColour) : Op::fn1_2(Main, GFX.FixedColour); - } - }; - typedef MATHF1_2 Blend_AddF1_2; - typedef MATHF1_2 Blend_SubF1_2; - - template - struct MATHS1_2 - { - static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) - { - return GFX.ClipColors ? REGMATH::Calc(Main, Sub, SD) : (SD & 0x20) ? Op::fn1_2(Main, Sub) : Op::fn(Main, GFX.FixedColour); - } - }; - typedef MATHS1_2 Blend_AddS1_2; - typedef MATHS1_2 Blend_SubS1_2; - typedef MATHS1_2 Blend_AddS1_2Brightness; - - template< - template class TILE, - template class PIXEL - > - struct Renderers - { - enum { Pitch = PIXEL::Pitch }; - typedef typename TILE< PIXEL >::call_t call_t; - - static call_t Functions[9]; - - }; - template< - template class TILE, - template class PIXEL - > - typename Renderers::call_t Renderers::Functions[9] = - { - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - TILE< PIXEL >::Draw, - }; - - // Basic routine to render an unclipped tile. - // Input parameters: - // bpstart_t = either StartLine or (StartLine * 2 + BG.InterlaceLine), - // so interlace modes can render every other line from the tile. - // Pitch = 1 or 2, again so interlace can count lines properly. - // DRAW_PIXEL(N, M) is a routine to actually draw the pixel. N is the pixel in the row to draw, - // and M is a test which if false means the pixel should be skipped. - // Z1 is the "draw if Z1 > cur_depth". - // Z2 is the "cur_depth = new_depth". OBJ need the two separate. - // Pix is the pixel to draw. - - #define OFFSET_IN_LINE \ - uint32 OffsetInLine = Offset % GFX.RealPPL; - #define DRAW_PIXEL(N, M) PIXEL::Draw(N, M, Offset, OffsetInLine, Pix, Z1, Z2) - #define Z1 GFX.Z1 - #define Z2 GFX.Z2 - - template - struct DrawTile16 - { - typedef void (*call_t)(uint32, uint32, uint32, uint32); - - enum { Pitch = PIXEL::Pitch }; - typedef typename PIXEL::bpstart_t bpstart_t; - - static void Draw(uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) - { - CachedTile cache(Tile); - int32 l; - uint8 *bp, Pix; - - cache.GetCachedTile(); - if (cache.IsBlankTile()) - return; - cache.SelectPalette(); - - if (!(Tile & (V_FLIP | H_FLIP))) - { - bp = cache.Ptr() + bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) - { - for (int x = 0; x < 8; x++) { - Pix = bp[x]; DRAW_PIXEL(x, Pix); - } - } - } - else - if (!(Tile & V_FLIP)) - { - bp = cache.Ptr() + bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) - { - for (int x = 0; x < 8; x++) { - Pix = bp[7 - x]; DRAW_PIXEL(x, Pix); - } - } - } - else - if (!(Tile & H_FLIP)) - { - bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) - { - for (int x = 0; x < 8; x++) { - Pix = bp[x]; DRAW_PIXEL(x, Pix); - } - } - } - else - { - bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) - { - for (int x = 0; x < 8; x++) { - Pix = bp[7 - x]; DRAW_PIXEL(x, Pix); - } - } - } - } - }; - - #undef Z1 - #undef Z2 - - // Basic routine to render a clipped tile. Inputs same as above. - - #define Z1 GFX.Z1 - #define Z2 GFX.Z2 - - template - struct DrawClippedTile16 - { - typedef void (*call_t)(uint32, uint32, uint32, uint32, uint32, uint32); - - enum { Pitch = PIXEL::Pitch }; - typedef typename PIXEL::bpstart_t bpstart_t; - - static void Draw(uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount) - { - CachedTile cache(Tile); - int32 l; - uint8 *bp, Pix, w; - - cache.GetCachedTile(); - if (cache.IsBlankTile()) - return; - cache.SelectPalette(); - - if (!(Tile & (V_FLIP | H_FLIP))) - { - bp = cache.Ptr() + bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) - { - w = Width; - switch (StartPixel) - { - case 0: Pix = bp[0]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ - case 1: Pix = bp[1]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ - case 2: Pix = bp[2]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ - case 3: Pix = bp[3]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ - case 4: Pix = bp[4]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ - case 5: Pix = bp[5]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ - case 6: Pix = bp[6]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ - case 7: Pix = bp[7]; DRAW_PIXEL(7, Pix); break; - } - } - } - else - if (!(Tile & V_FLIP)) - { - bp = cache.Ptr() + bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) - { - w = Width; - switch (StartPixel) - { - case 0: Pix = bp[7]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ - case 1: Pix = bp[6]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ - case 2: Pix = bp[5]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ - case 3: Pix = bp[4]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ - case 4: Pix = bp[3]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ - case 5: Pix = bp[2]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ - case 6: Pix = bp[1]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ - case 7: Pix = bp[0]; DRAW_PIXEL(7, Pix); break; - } - } - } - else - if (!(Tile & H_FLIP)) - { - bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) - { - w = Width; - switch (StartPixel) - { - case 0: Pix = bp[0]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ - case 1: Pix = bp[1]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ - case 2: Pix = bp[2]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ - case 3: Pix = bp[3]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ - case 4: Pix = bp[4]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ - case 5: Pix = bp[5]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ - case 6: Pix = bp[6]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ - case 7: Pix = bp[7]; DRAW_PIXEL(7, Pix); break; - } - } - } - else - { - bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) - { - w = Width; - switch (StartPixel) - { - case 0: Pix = bp[7]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ - case 1: Pix = bp[6]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ - case 2: Pix = bp[5]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ - case 3: Pix = bp[4]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ - case 4: Pix = bp[3]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ - case 5: Pix = bp[2]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ - case 6: Pix = bp[1]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ - case 7: Pix = bp[0]; DRAW_PIXEL(7, Pix); break; - } - } - } - } - }; - - #undef Z1 - #undef Z2 - - // Basic routine to render a single mosaic pixel. - // DRAW_PIXEL, bpstart_t, Z1, Z2 and Pix are the same as above, but Pitch is not used. - - #define Z1 GFX.Z1 - #define Z2 GFX.Z2 - - template - struct DrawMosaicPixel16 - { - typedef void (*call_t)(uint32, uint32, uint32, uint32, uint32, uint32); - - typedef typename PIXEL::bpstart_t bpstart_t; - - static void Draw(uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount) - { - CachedTile cache(Tile); - int32 l, w; - uint8 Pix; - - cache.GetCachedTile(); - if (cache.IsBlankTile()) - return; - cache.SelectPalette(); - - if (Tile & H_FLIP) - StartPixel = 7 - StartPixel; - - if (Tile & V_FLIP) - Pix = cache.Ptr()[56 - bpstart_t::Get(StartLine) + StartPixel]; - else - Pix = cache.Ptr()[bpstart_t::Get(StartLine) + StartPixel]; - - if (Pix) - { - OFFSET_IN_LINE; - for (l = LineCount; l > 0; l--, Offset += GFX.PPL) - { - for (w = Width - 1; w >= 0; w--) - DRAW_PIXEL(w, 1); - } - } - } - }; - - #undef Z1 - #undef Z2 - - // Basic routine to render the backdrop. - // DRAW_PIXEL is the same as above, but since we're just replicating a single pixel there's no need for Pitch or bpstart_t - // (or interlace at all, really). - // The backdrop is always depth = 1, so Z1 = Z2 = 1. And backdrop is always color 0. - - #define Z1 1 - #define Z2 1 - #define Pix 0 - - template - struct DrawBackdrop16 - { - typedef void (*call_t)(uint32 Offset, uint32 Left, uint32 Right); - - static void Draw(uint32 Offset, uint32 Left, uint32 Right) - { - uint32 l, x; - - GFX.RealScreenColors = IPPU.ScreenColors; - GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; - - OFFSET_IN_LINE; - for (l = GFX.StartY; l <= GFX.EndY; l++, Offset += GFX.PPL) - { - for (x = Left; x < Right; x++) - DRAW_PIXEL(x, 1); - } - } - }; - - #undef Pix - #undef Z1 - #undef Z2 - #undef DRAW_PIXEL - - // Basic routine to render a chunk of a Mode 7 BG. - // Mode 7 has no interlace, so bpstart_t and Pitch are unused. - // We get some new parameters, so we can use the same DRAW_TILE to do BG1 or BG2: - // DCMODE tests if Direct Color should apply. - // BG is the BG, so we use the right clip window. - // MASK is 0xff or 0x7f, the 'color' portion of the pixel. - // We define Z1/Z2 to either be constant 5 or to vary depending on the 'priority' portion of the pixel. - - #define CLIP_10_BIT_SIGNED(a) (((a) & 0x2000) ? ((a) | ~0x3ff) : ((a) & 0x3ff)) - - #define DRAW_PIXEL(N, M) PIXEL::Draw(N, M, Offset, OffsetInLine, Pix, OP::Z1(D, b), OP::Z2(D, b)) - - struct DrawMode7BG1_OP - { - enum { - MASK = 0xff, - BG = 0 - }; - static uint8 Z1(int D, uint8 b) { return D + 7; } - static uint8 Z2(int D, uint8 b) { return D + 7; } - static uint8 DCMODE() { return Memory.FillRAM[0x2130] & 1; } - }; - struct DrawMode7BG2_OP - { - enum { - MASK = 0x7f, - BG = 1 - }; - static uint8 Z1(int D, uint8 b) { return D + ((b & 0x80) ? 11 : 3); } - static uint8 Z2(int D, uint8 b) { return D + ((b & 0x80) ? 11 : 3); } - static uint8 DCMODE() { return 0; } - }; - - template - struct DrawTileNormal - { - typedef void (*call_t)(uint32 Left, uint32 Right, int D); - - static void Draw(uint32 Left, uint32 Right, int D) - { - uint8 *VRAM1 = Memory.VRAM + 1; - - if (OP::DCMODE()) - { - GFX.RealScreenColors = DirectColourMaps[0]; - } - else - GFX.RealScreenColors = IPPU.ScreenColors; - - GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; - - int aa, cc; - int startx; - - uint32 Offset = GFX.StartY * GFX.PPL; - struct SLineMatrixData *l = &LineMatrixData[GFX.StartY]; - - OFFSET_IN_LINE; - for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Offset += GFX.PPL, l++) - { - int yy, starty; - - int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; - int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; - - int32 CentreX = ((int32) l->CentreX << 19) >> 19; - int32 CentreY = ((int32) l->CentreY << 19) >> 19; - - if (PPU.Mode7VFlip) - starty = 255 - (int) (Line + 1); - else - starty = Line + 1; - - yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); - - int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); - int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); - - if (PPU.Mode7HFlip) - { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } - else - { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - } - - int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); - int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); - int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); - - uint8 Pix; - - if (!PPU.Mode7Repeat) - { - for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) - { - int X = ((AA + BB) >> 8) & 0x3ff; - int Y = ((CC + DD) >> 8) & 0x3ff; - - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); - uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); - - Pix = b & OP::MASK; DRAW_PIXEL(x, Pix); - } - } - else - { - for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) - { - int X = ((AA + BB) >> 8); - int Y = ((CC + DD) >> 8); - - uint8 b; - - if (((X | Y) & ~0x3ff) == 0) - { - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); - b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); - } - else - if (PPU.Mode7Repeat == 3) - b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); - else - continue; - - Pix = b & OP::MASK; DRAW_PIXEL(x, Pix); - } - } - } - } - }; - - template - struct DrawMode7BG1 : public DrawTileNormal {}; - template - struct DrawMode7BG2 : public DrawTileNormal {}; - - template - struct DrawTileMosaic - { - typedef void (*call_t)(uint32 Left, uint32 Right, int D); - - static void Draw(uint32 Left, uint32 Right, int D) - { - uint8 *VRAM1 = Memory.VRAM + 1; - - if (OP::DCMODE()) - { - GFX.RealScreenColors = DirectColourMaps[0]; - } - else - GFX.RealScreenColors = IPPU.ScreenColors; - - GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; - - int aa, cc; - int startx, StartY = GFX.StartY; - - int HMosaic = 1, VMosaic = 1, MosaicStart = 0; - int32 MLeft = Left, MRight = Right; - - if (PPU.BGMosaic[0]) - { - VMosaic = PPU.Mosaic; - MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % VMosaic; - StartY -= MosaicStart; - } - - if (PPU.BGMosaic[OP::BG]) - { - HMosaic = PPU.Mosaic; - MLeft -= MLeft % HMosaic; - MRight += HMosaic - 1; - MRight -= MRight % HMosaic; - } - - uint32 Offset = StartY * GFX.PPL; - struct SLineMatrixData *l = &LineMatrixData[StartY]; - - OFFSET_IN_LINE; - for (uint32 Line = StartY; Line <= GFX.EndY; Line += VMosaic, Offset += VMosaic * GFX.PPL, l += VMosaic) - { - if (Line + VMosaic > GFX.EndY) - VMosaic = GFX.EndY - Line + 1; - - int yy, starty; - - int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; - int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; - - int32 CentreX = ((int32) l->CentreX << 19) >> 19; - int32 CentreY = ((int32) l->CentreY << 19) >> 19; - - if (PPU.Mode7VFlip) - starty = 255 - (int) (Line + 1); - else - starty = Line + 1; - - yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); - - int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); - int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); - - if (PPU.Mode7HFlip) - { - startx = MRight - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } - else - { - startx = MLeft; - aa = l->MatrixA; - cc = l->MatrixC; - } - - int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); - int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); - int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); - - uint8 Pix; - uint8 ctr = 1; - - if (!PPU.Mode7Repeat) - { - for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) - { - if (--ctr) - continue; - ctr = HMosaic; - - int X = ((AA + BB) >> 8) & 0x3ff; - int Y = ((CC + DD) >> 8) & 0x3ff; - - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); - uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); - - if ((Pix = (b & OP::MASK))) - { - for (int32 h = MosaicStart; h < VMosaic; h++) - { - for (int32 w = x + HMosaic - 1; w >= x; w--) - DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); - } - } - } - } - else - { - for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) - { - if (--ctr) - continue; - ctr = HMosaic; - - int X = ((AA + BB) >> 8); - int Y = ((CC + DD) >> 8); - - uint8 b; - - if (((X | Y) & ~0x3ff) == 0) - { - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); - b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); - } - else - if (PPU.Mode7Repeat == 3) - b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); - else - continue; - - if ((Pix = (b & OP::MASK))) - { - for (int32 h = MosaicStart; h < VMosaic; h++) - { - for (int32 w = x + HMosaic - 1; w >= x; w--) - DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); - } - } - } - } - - MosaicStart = 0; - } - } - }; - - template - struct DrawMode7MosaicBG1 : public DrawTileMosaic {}; - template - struct DrawMode7MosaicBG2 : public DrawTileMosaic {}; - - - #undef DRAW_PIXEL - } // anonymous namespace - void S9xInitTileRenderer (void) { int i; diff --git a/tileimpl-h2x1.cpp b/tileimpl-h2x1.cpp new file mode 100644 index 00000000..d2cf1bf6 --- /dev/null +++ b/tileimpl-h2x1.cpp @@ -0,0 +1,47 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + +#define _TILEIMPL_CPP_ +#include "tileimpl.h" + +namespace TileImpl { + + template + void HiresBase::Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2) + { + if (Z1 > GFX.DB[Offset + 2 * N] && (M)) + { + GFX.S[Offset + 2 * N + 1] = MATH::Calc(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); + if ((OffsetInLine + 2 * N ) != (SNES_WIDTH - 1) << 1) + GFX.S[Offset + 2 * N + 2] = MATH::Calc((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N + 2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); + if ((OffsetInLine + 2 * N) == 0 || (OffsetInLine + 2 * N) == GFX.RealPPL) + GFX.S[Offset + 2 * N] = MATH::Calc((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); + GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; + } + } + + + // hires double width + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + + // hires double width interlace + template struct Renderers; + template struct Renderers; + template struct Renderers; + //template struct Renderers; + //template struct Renderers; + //template struct Renderers; + //template struct Renderers; + //template struct Renderers; + +} // namespace TileImpl diff --git a/tileimpl-n1x1.cpp b/tileimpl-n1x1.cpp new file mode 100644 index 00000000..9a9c900f --- /dev/null +++ b/tileimpl-n1x1.cpp @@ -0,0 +1,34 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + +#define _TILEIMPL_CPP_ +#include "tileimpl.h" + +namespace TileImpl { + + template + void Normal1x1Base::Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2) + { + (void) OffsetInLine; + if (Z1 > GFX.DB[Offset + N] && (M)) + { + GFX.S[Offset + N] = MATH::Calc(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + N], GFX.SubZBuffer[Offset + N]); + GFX.DB[Offset + N] = Z2; + } + } + + + // normal width + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + +} // namespace TileImpl diff --git a/tileimpl-n2x1.cpp b/tileimpl-n2x1.cpp new file mode 100644 index 00000000..cf688f9d --- /dev/null +++ b/tileimpl-n2x1.cpp @@ -0,0 +1,44 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + +#define _TILEIMPL_CPP_ +#include "tileimpl.h" + +namespace TileImpl { + + template + void Normal2x1Base::Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2) + { + (void) OffsetInLine; + if (Z1 > GFX.DB[Offset + 2 * N] && (M)) + { + GFX.S[Offset + 2 * N] = GFX.S[Offset + 2 * N + 1] = MATH::Calc(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); + GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; + } + } + + + // normal double width + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + template struct Renderers; + + // normal double width interlace + template struct Renderers; + template struct Renderers; + template struct Renderers; + //template struct Renderers; + //template struct Renderers; + //template struct Renderers; + //template struct Renderers; + //template struct Renderers; + +} // namespace TileImpl diff --git a/tileimpl.h b/tileimpl.h new file mode 100644 index 00000000..9b7e86d4 --- /dev/null +++ b/tileimpl.h @@ -0,0 +1,801 @@ +/*****************************************************************************\ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + This file is licensed under the Snes9x License. + For further information, consult the LICENSE file in the root directory. +\*****************************************************************************/ + +#ifndef _TILEIMPL_H_ +#define _TILEIMPL_H_ + +#include "snes9x.h" +#include "ppu.h" +#include "tile.h" + +extern struct SLineMatrixData LineMatrixData[240]; + + +namespace TileImpl { + + struct BPProgressive + { + enum { Pitch = 1 }; + static alwaysinline uint32 Get(uint32 StartLine) { return StartLine; } + }; + + // Interlace: Only draw every other line, so we'll redefine bpstart_t and Pitch to do so. + // Otherwise, it's the same as Normal2x1/Hires2x1. + struct BPInterlace + { + enum { Pitch = 2 }; + static alwaysinline uint32 Get(uint32 StartLine) { return StartLine * 2 + BG.InterlaceLine; } + }; + + + // The 1x1 pixel plotter, for speedhacking modes. + template + struct Normal1x1Base + { + enum { Pitch = BPSTART::Pitch }; + typedef BPSTART bpstart_t; + + static void Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2); + }; + + template + struct Normal1x1 : public Normal1x1Base {}; + + + // The 2x1 pixel plotter, for normal rendering when we've used hires/interlace already this frame. + template + struct Normal2x1Base + { + enum { Pitch = BPSTART::Pitch }; + typedef BPSTART bpstart_t; + + static void Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2); + }; + + template + struct Normal2x1 : public Normal2x1Base {}; + template + struct Interlace : public Normal2x1Base {}; + + + // Hires pixel plotter, this combines the main and subscreen pixels as appropriate to render hires or pseudo-hires images. + // Use it only on the main screen, subscreen should use Normal2x1 instead. + // Hires math: + // Main pixel is mathed as normal: Main(x, y) * Sub(x, y). + // Sub pixel is mathed somewhat weird: Basically, for Sub(x + 1, y) we apply the same operation we applied to Main(x, y) + // (e.g. no math, add fixed, add1/2 subscreen) using Main(x, y) as the "corresponding subscreen pixel". + // Also, color window clipping clips Sub(x + 1, y) if Main(x, y) is clipped, not Main(x + 1, y). + // We don't know how Sub(0, y) is handled. + template + struct HiresBase + { + enum { Pitch = BPSTART::Pitch }; + typedef BPSTART bpstart_t; + + static void Draw(uint8 N, uint8 M, uint32 Offset, uint32 OffsetInLine, uint8 Pix, uint8 Z1, uint8 Z2); + }; + + template + struct Hires : public HiresBase {}; + template + struct HiresInterlace : public HiresBase {}; + + + class CachedTile + { + public: + CachedTile(uint32 tile) : Tile(tile) {} + + alwaysinline void GetCachedTile() + { + TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); + if (Tile & 0x100) + TileAddr += BG.NameSelect; + TileAddr &= 0xffff; + TileNumber = TileAddr >> BG.TileShift; + if (Tile & H_FLIP) + { + pCache = &BG.BufferFlip[TileNumber << 6]; + if (!BG.BufferedFlip[TileNumber]) + BG.BufferedFlip[TileNumber] = BG.ConvertTileFlip(pCache, TileAddr, Tile & 0x3ff); + } + else + { + pCache = &BG.Buffer[TileNumber << 6]; + if (!BG.Buffered[TileNumber]) + BG.Buffered[TileNumber] = BG.ConvertTile(pCache, TileAddr, Tile & 0x3ff); + } + } + + alwaysinline bool IsBlankTile() const + { + return ((Tile & H_FLIP) ? BG.BufferedFlip[TileNumber] : BG.Buffered[TileNumber]) == BLANK_TILE; + } + + alwaysinline void SelectPalette() const + { + if (BG.DirectColourMode) + { + GFX.RealScreenColors = DirectColourMaps[(Tile >> 10) & 7]; + } + else + GFX.RealScreenColors = &IPPU.ScreenColors[((Tile >> BG.PaletteShift) & BG.PaletteMask) + BG.StartPalette]; + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; + } + + alwaysinline uint8* Ptr() const + { + return pCache; + } + + private: + uint8 *pCache; + uint32 Tile; + uint32 TileNumber; + uint32 TileAddr; + }; + + + struct NOMATH + { + static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) + { + return Main; + } + }; + typedef NOMATH Blend_None; + + template + struct REGMATH + { + static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) + { + return Op::fn(Main, (SD & 0x20) ? Sub : GFX.FixedColour); + } + }; + typedef REGMATH Blend_Add; + typedef REGMATH Blend_Sub; + typedef REGMATH Blend_AddBrightness; + + template + struct MATHF1_2 + { + static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) + { + return GFX.ClipColors ? Op::fn(Main, GFX.FixedColour) : Op::fn1_2(Main, GFX.FixedColour); + } + }; + typedef MATHF1_2 Blend_AddF1_2; + typedef MATHF1_2 Blend_SubF1_2; + + template + struct MATHS1_2 + { + static alwaysinline uint16 Calc(uint16 Main, uint16 Sub, uint8 SD) + { + return GFX.ClipColors ? REGMATH::Calc(Main, Sub, SD) : (SD & 0x20) ? Op::fn1_2(Main, Sub) : Op::fn(Main, GFX.FixedColour); + } + }; + typedef MATHS1_2 Blend_AddS1_2; + typedef MATHS1_2 Blend_SubS1_2; + typedef MATHS1_2 Blend_AddS1_2Brightness; + + template< + template class TILE, + template class PIXEL + > + struct Renderers + { + enum { Pitch = PIXEL::Pitch }; + typedef typename TILE< PIXEL >::call_t call_t; + + static call_t Functions[9]; + }; + + #ifdef _TILEIMPL_CPP_ + template< + template class TILE, + template class PIXEL + > + typename Renderers::call_t Renderers::Functions[9] = + { + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + TILE< PIXEL >::Draw, + }; + #endif + + // Basic routine to render an unclipped tile. + // Input parameters: + // bpstart_t = either StartLine or (StartLine * 2 + BG.InterlaceLine), + // so interlace modes can render every other line from the tile. + // Pitch = 1 or 2, again so interlace can count lines properly. + // DRAW_PIXEL(N, M) is a routine to actually draw the pixel. N is the pixel in the row to draw, + // and M is a test which if false means the pixel should be skipped. + // Z1 is the "draw if Z1 > cur_depth". + // Z2 is the "cur_depth = new_depth". OBJ need the two separate. + // Pix is the pixel to draw. + + #define OFFSET_IN_LINE \ + uint32 OffsetInLine = Offset % GFX.RealPPL; + #define DRAW_PIXEL(N, M) PIXEL::Draw(N, M, Offset, OffsetInLine, Pix, Z1, Z2) + #define Z1 GFX.Z1 + #define Z2 GFX.Z2 + + template + struct DrawTile16 + { + typedef void (*call_t)(uint32, uint32, uint32, uint32); + + enum { Pitch = PIXEL::Pitch }; + typedef typename PIXEL::bpstart_t bpstart_t; + + static void Draw(uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) + { + CachedTile cache(Tile); + int32 l; + uint8 *bp, Pix; + + cache.GetCachedTile(); + if (cache.IsBlankTile()) + return; + cache.SelectPalette(); + + if (!(Tile & (V_FLIP | H_FLIP))) + { + bp = cache.Ptr() + bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) + { + for (int x = 0; x < 8; x++) { + Pix = bp[x]; DRAW_PIXEL(x, Pix); + } + } + } + else + if (!(Tile & V_FLIP)) + { + bp = cache.Ptr() + bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) + { + for (int x = 0; x < 8; x++) { + Pix = bp[7 - x]; DRAW_PIXEL(x, Pix); + } + } + } + else + if (!(Tile & H_FLIP)) + { + bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) + { + for (int x = 0; x < 8; x++) { + Pix = bp[x]; DRAW_PIXEL(x, Pix); + } + } + } + else + { + bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) + { + for (int x = 0; x < 8; x++) { + Pix = bp[7 - x]; DRAW_PIXEL(x, Pix); + } + } + } + } + }; + + #undef Z1 + #undef Z2 + + // Basic routine to render a clipped tile. Inputs same as above. + + #define Z1 GFX.Z1 + #define Z2 GFX.Z2 + + template + struct DrawClippedTile16 + { + typedef void (*call_t)(uint32, uint32, uint32, uint32, uint32, uint32); + + enum { Pitch = PIXEL::Pitch }; + typedef typename PIXEL::bpstart_t bpstart_t; + + static void Draw(uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount) + { + CachedTile cache(Tile); + int32 l; + uint8 *bp, Pix, w; + + cache.GetCachedTile(); + if (cache.IsBlankTile()) + return; + cache.SelectPalette(); + + if (!(Tile & (V_FLIP | H_FLIP))) + { + bp = cache.Ptr() + bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) + { + w = Width; + switch (StartPixel) + { + case 0: Pix = bp[0]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ + case 1: Pix = bp[1]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ + case 2: Pix = bp[2]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ + case 3: Pix = bp[3]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ + case 4: Pix = bp[4]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ + case 5: Pix = bp[5]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ + case 6: Pix = bp[6]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ + case 7: Pix = bp[7]; DRAW_PIXEL(7, Pix); break; + } + } + } + else + if (!(Tile & V_FLIP)) + { + bp = cache.Ptr() + bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp += 8 * Pitch, Offset += GFX.PPL) + { + w = Width; + switch (StartPixel) + { + case 0: Pix = bp[7]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ + case 1: Pix = bp[6]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ + case 2: Pix = bp[5]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ + case 3: Pix = bp[4]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ + case 4: Pix = bp[3]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ + case 5: Pix = bp[2]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ + case 6: Pix = bp[1]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ + case 7: Pix = bp[0]; DRAW_PIXEL(7, Pix); break; + } + } + } + else + if (!(Tile & H_FLIP)) + { + bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) + { + w = Width; + switch (StartPixel) + { + case 0: Pix = bp[0]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ + case 1: Pix = bp[1]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ + case 2: Pix = bp[2]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ + case 3: Pix = bp[3]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ + case 4: Pix = bp[4]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ + case 5: Pix = bp[5]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ + case 6: Pix = bp[6]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ + case 7: Pix = bp[7]; DRAW_PIXEL(7, Pix); break; + } + } + } + else + { + bp = cache.Ptr() + 56 - bpstart_t::Get(StartLine); + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, bp -= 8 * Pitch, Offset += GFX.PPL) + { + w = Width; + switch (StartPixel) + { + case 0: Pix = bp[7]; DRAW_PIXEL(0, Pix); if (!--w) break; /* Fall through */ + case 1: Pix = bp[6]; DRAW_PIXEL(1, Pix); if (!--w) break; /* Fall through */ + case 2: Pix = bp[5]; DRAW_PIXEL(2, Pix); if (!--w) break; /* Fall through */ + case 3: Pix = bp[4]; DRAW_PIXEL(3, Pix); if (!--w) break; /* Fall through */ + case 4: Pix = bp[3]; DRAW_PIXEL(4, Pix); if (!--w) break; /* Fall through */ + case 5: Pix = bp[2]; DRAW_PIXEL(5, Pix); if (!--w) break; /* Fall through */ + case 6: Pix = bp[1]; DRAW_PIXEL(6, Pix); if (!--w) break; /* Fall through */ + case 7: Pix = bp[0]; DRAW_PIXEL(7, Pix); break; + } + } + } + } + }; + + #undef Z1 + #undef Z2 + + // Basic routine to render a single mosaic pixel. + // DRAW_PIXEL, bpstart_t, Z1, Z2 and Pix are the same as above, but Pitch is not used. + + #define Z1 GFX.Z1 + #define Z2 GFX.Z2 + + template + struct DrawMosaicPixel16 + { + typedef void (*call_t)(uint32, uint32, uint32, uint32, uint32, uint32); + + typedef typename PIXEL::bpstart_t bpstart_t; + + static void Draw(uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount) + { + CachedTile cache(Tile); + int32 l, w; + uint8 Pix; + + cache.GetCachedTile(); + if (cache.IsBlankTile()) + return; + cache.SelectPalette(); + + if (Tile & H_FLIP) + StartPixel = 7 - StartPixel; + + if (Tile & V_FLIP) + Pix = cache.Ptr()[56 - bpstart_t::Get(StartLine) + StartPixel]; + else + Pix = cache.Ptr()[bpstart_t::Get(StartLine) + StartPixel]; + + if (Pix) + { + OFFSET_IN_LINE; + for (l = LineCount; l > 0; l--, Offset += GFX.PPL) + { + for (w = Width - 1; w >= 0; w--) + DRAW_PIXEL(w, 1); + } + } + } + }; + + #undef Z1 + #undef Z2 + + // Basic routine to render the backdrop. + // DRAW_PIXEL is the same as above, but since we're just replicating a single pixel there's no need for Pitch or bpstart_t + // (or interlace at all, really). + // The backdrop is always depth = 1, so Z1 = Z2 = 1. And backdrop is always color 0. + + #define Z1 1 + #define Z2 1 + #define Pix 0 + + template + struct DrawBackdrop16 + { + typedef void (*call_t)(uint32 Offset, uint32 Left, uint32 Right); + + static void Draw(uint32 Offset, uint32 Left, uint32 Right) + { + uint32 l, x; + + GFX.RealScreenColors = IPPU.ScreenColors; + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; + + OFFSET_IN_LINE; + for (l = GFX.StartY; l <= GFX.EndY; l++, Offset += GFX.PPL) + { + for (x = Left; x < Right; x++) + DRAW_PIXEL(x, 1); + } + } + }; + + #undef Pix + #undef Z1 + #undef Z2 + #undef DRAW_PIXEL + + // Basic routine to render a chunk of a Mode 7 BG. + // Mode 7 has no interlace, so bpstart_t and Pitch are unused. + // We get some new parameters, so we can use the same DRAW_TILE to do BG1 or BG2: + // DCMODE tests if Direct Color should apply. + // BG is the BG, so we use the right clip window. + // MASK is 0xff or 0x7f, the 'color' portion of the pixel. + // We define Z1/Z2 to either be constant 5 or to vary depending on the 'priority' portion of the pixel. + + #define CLIP_10_BIT_SIGNED(a) (((a) & 0x2000) ? ((a) | ~0x3ff) : ((a) & 0x3ff)) + + #define DRAW_PIXEL(N, M) PIXEL::Draw(N, M, Offset, OffsetInLine, Pix, OP::Z1(D, b), OP::Z2(D, b)) + + struct DrawMode7BG1_OP + { + enum { + MASK = 0xff, + BG = 0 + }; + static uint8 Z1(int D, uint8 b) { return D + 7; } + static uint8 Z2(int D, uint8 b) { return D + 7; } + static uint8 DCMODE() { return Memory.FillRAM[0x2130] & 1; } + }; + struct DrawMode7BG2_OP + { + enum { + MASK = 0x7f, + BG = 1 + }; + static uint8 Z1(int D, uint8 b) { return D + ((b & 0x80) ? 11 : 3); } + static uint8 Z2(int D, uint8 b) { return D + ((b & 0x80) ? 11 : 3); } + static uint8 DCMODE() { return 0; } + }; + + template + struct DrawTileNormal + { + typedef void (*call_t)(uint32 Left, uint32 Right, int D); + + static void Draw(uint32 Left, uint32 Right, int D) + { + uint8 *VRAM1 = Memory.VRAM + 1; + + if (OP::DCMODE()) + { + GFX.RealScreenColors = DirectColourMaps[0]; + } + else + GFX.RealScreenColors = IPPU.ScreenColors; + + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; + + int aa, cc; + int startx; + + uint32 Offset = GFX.StartY * GFX.PPL; + struct SLineMatrixData *l = &LineMatrixData[GFX.StartY]; + + OFFSET_IN_LINE; + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Offset += GFX.PPL, l++) + { + int yy, starty; + + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; + + int32 CentreX = ((int32) l->CentreX << 19) >> 19; + int32 CentreY = ((int32) l->CentreY << 19) >> 19; + + if (PPU.Mode7VFlip) + starty = 255 - (int) (Line + 1); + else + starty = Line + 1; + + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); + + int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); + int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); + + if (PPU.Mode7HFlip) + { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } + else + { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + } + + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); + int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); + int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); + + uint8 Pix; + + if (!PPU.Mode7Repeat) + { + for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) + { + int X = ((AA + BB) >> 8) & 0x3ff; + int Y = ((CC + DD) >> 8) & 0x3ff; + + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); + + Pix = b & OP::MASK; DRAW_PIXEL(x, Pix); + } + } + else + { + for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) + { + int X = ((AA + BB) >> 8); + int Y = ((CC + DD) >> 8); + + uint8 b; + + if (((X | Y) & ~0x3ff) == 0) + { + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); + } + else + if (PPU.Mode7Repeat == 3) + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); + else + continue; + + Pix = b & OP::MASK; DRAW_PIXEL(x, Pix); + } + } + } + } + }; + + template + struct DrawMode7BG1 : public DrawTileNormal {}; + template + struct DrawMode7BG2 : public DrawTileNormal {}; + + template + struct DrawTileMosaic + { + typedef void (*call_t)(uint32 Left, uint32 Right, int D); + + static void Draw(uint32 Left, uint32 Right, int D) + { + uint8 *VRAM1 = Memory.VRAM + 1; + + if (OP::DCMODE()) + { + GFX.RealScreenColors = DirectColourMaps[0]; + } + else + GFX.RealScreenColors = IPPU.ScreenColors; + + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; + + int aa, cc; + int startx, StartY = GFX.StartY; + + int HMosaic = 1, VMosaic = 1, MosaicStart = 0; + int32 MLeft = Left, MRight = Right; + + if (PPU.BGMosaic[0]) + { + VMosaic = PPU.Mosaic; + MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % VMosaic; + StartY -= MosaicStart; + } + + if (PPU.BGMosaic[OP::BG]) + { + HMosaic = PPU.Mosaic; + MLeft -= MLeft % HMosaic; + MRight += HMosaic - 1; + MRight -= MRight % HMosaic; + } + + uint32 Offset = StartY * GFX.PPL; + struct SLineMatrixData *l = &LineMatrixData[StartY]; + + OFFSET_IN_LINE; + for (uint32 Line = StartY; Line <= GFX.EndY; Line += VMosaic, Offset += VMosaic * GFX.PPL, l += VMosaic) + { + if (Line + VMosaic > GFX.EndY) + VMosaic = GFX.EndY - Line + 1; + + int yy, starty; + + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; + + int32 CentreX = ((int32) l->CentreX << 19) >> 19; + int32 CentreY = ((int32) l->CentreY << 19) >> 19; + + if (PPU.Mode7VFlip) + starty = 255 - (int) (Line + 1); + else + starty = Line + 1; + + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); + + int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); + int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); + + if (PPU.Mode7HFlip) + { + startx = MRight - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } + else + { + startx = MLeft; + aa = l->MatrixA; + cc = l->MatrixC; + } + + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); + int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); + int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); + + uint8 Pix; + uint8 ctr = 1; + + if (!PPU.Mode7Repeat) + { + for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) + { + if (--ctr) + continue; + ctr = HMosaic; + + int X = ((AA + BB) >> 8) & 0x3ff; + int Y = ((CC + DD) >> 8) & 0x3ff; + + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); + + if ((Pix = (b & OP::MASK))) + { + for (int32 h = MosaicStart; h < VMosaic; h++) + { + for (int32 w = x + HMosaic - 1; w >= x; w--) + DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); + } + } + } + } + else + { + for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) + { + if (--ctr) + continue; + ctr = HMosaic; + + int X = ((AA + BB) >> 8); + int Y = ((CC + DD) >> 8); + + uint8 b; + + if (((X | Y) & ~0x3ff) == 0) + { + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); + } + else + if (PPU.Mode7Repeat == 3) + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); + else + continue; + + if ((Pix = (b & OP::MASK))) + { + for (int32 h = MosaicStart; h < VMosaic; h++) + { + for (int32 w = x + HMosaic - 1; w >= x; w--) + DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); + } + } + } + } + + MosaicStart = 0; + } + } + }; + + template + struct DrawMode7MosaicBG1 : public DrawTileMosaic {}; + template + struct DrawMode7MosaicBG2 : public DrawTileMosaic {}; + + + #undef DRAW_PIXEL + +} // namespace TileImpl + +#endif diff --git a/unix/Makefile.in b/unix/Makefile.in index 3092ef1c..fcef9483 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -8,7 +8,7 @@ OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` BUILDDIR = . -OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../msu1.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o ../sha256.o ../bml.o unix.o x11.o +OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../msu1.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../tileimpl-n1x1.o ../tileimpl-n2x1.o ../tileimpl-h2x1.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o ../sha256.o ../bml.o unix.o x11.o DEFS = -DMITSHM ifdef S9XDEBUGGER diff --git a/win32/snes9xw.vcxproj b/win32/snes9xw.vcxproj index d55881e0..6ccecb85 100644 --- a/win32/snes9xw.vcxproj +++ b/win32/snes9xw.vcxproj @@ -423,6 +423,7 @@ + @@ -566,6 +567,9 @@ + + + diff --git a/win32/snes9xw.vcxproj.filters b/win32/snes9xw.vcxproj.filters index e8f062e0..7f233e8b 100644 --- a/win32/snes9xw.vcxproj.filters +++ b/win32/snes9xw.vcxproj.filters @@ -446,6 +446,15 @@ Emu + + Emu + + + Emu + + + Emu + UnZip @@ -816,6 +825,9 @@ Emu + + Emu + GUI\VideoDriver @@ -872,4 +884,4 @@ - \ No newline at end of file +