|
|
|
@ -1,6 +1,9 @@ |
|
|
|
|
#define OLC_PGE_APPLICATION |
|
|
|
|
#include "olcPixelGameEngine.h" |
|
|
|
|
|
|
|
|
|
#include <ranges> |
|
|
|
|
|
|
|
|
|
using namespace olc; |
|
|
|
|
|
|
|
|
|
struct Rom{ |
|
|
|
|
const static uint16_t MIN_INDEX{}; |
|
|
|
@ -18,6 +21,23 @@ struct Rom{ |
|
|
|
|
UNKNOWN_2, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static uint32_t snesToHex(uint32_t addr,bool header=true){ |
|
|
|
|
uint32_t newAddr{addr}; |
|
|
|
|
if(newAddr>=0x400000&&newAddr<0x600000);//NO-OP
|
|
|
|
|
else if(newAddr>=0xC00000&&newAddr<0x1000000)newAddr-=0xC00000; |
|
|
|
|
else throw std::out_of_range{std::format("SNES address out of range: {}",newAddr)}; |
|
|
|
|
|
|
|
|
|
if(header)newAddr+=0x200; |
|
|
|
|
return newAddr-0xA0200; |
|
|
|
|
} |
|
|
|
|
static uint32_t hexToSnes(uint32_t addr,bool header=true){ |
|
|
|
|
uint32_t newAddr{addr}; |
|
|
|
|
if(header)newAddr-=0x200; |
|
|
|
|
if(newAddr>=0&&newAddr<0x400000)return newAddr+0xC00000; |
|
|
|
|
else if(newAddr>=0x400000&&newAddr<0x600000)return newAddr; |
|
|
|
|
else throw std::out_of_range{std::format("File offset out of range: {}",newAddr)}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct DataBlock{ |
|
|
|
|
uint32_t addr,ptr; |
|
|
|
|
std::string_view data; |
|
|
|
@ -66,17 +86,41 @@ struct Rom{ |
|
|
|
|
return (data[13]<<24)+(data[14]<<16)+(data[15]<<8)+data[16]; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
struct BackgroundPalette{ |
|
|
|
|
std::vector<Pixel>colors; |
|
|
|
|
byte bpp; |
|
|
|
|
uint32_t addr; |
|
|
|
|
BackgroundPalette(std::string_view data,uint16_t index,byte bpp) |
|
|
|
|
:bpp(bpp){ |
|
|
|
|
DataBlock pointer{data,0xDAD9U+index*4U}; |
|
|
|
|
uint32_t addr=snesToHex(pointer.readInt32()); |
|
|
|
|
DataBlock dataBlock{data,addr}; |
|
|
|
|
this->addr=addr; |
|
|
|
|
if(bpp!=2&&bpp!=4)throw std::invalid_argument{std::format("Palette Error: Incorrect color depth specified. Must be 2 or 4, provided {}",bpp)}; |
|
|
|
|
for(uint8_t i:std::views::iota(0,pow(2,bpp))){ |
|
|
|
|
uint16_t clr16{dataBlock.readShort()}; |
|
|
|
|
uint8_t b{((clr16>>10)&31)*8U}; |
|
|
|
|
uint8_t g{((clr16>>5)&31)*8U}; |
|
|
|
|
uint8_t r{(clr16&31)*8U}; |
|
|
|
|
colors.emplace_back(r,g,b); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
std::string data; |
|
|
|
|
std::vector<BattleBackground>backgrounds; |
|
|
|
|
std::vector<BackgroundPalette>palettes; |
|
|
|
|
Rom(){ |
|
|
|
|
std::ifstream dataStream{"truncated_backgrounds.dat",std::ios_base::binary}; |
|
|
|
|
while(dataStream.good())data+=dataStream.get(); |
|
|
|
|
|
|
|
|
|
for(uint16_t i=0;i<=MAX_INDEX;i++){ |
|
|
|
|
for(uint16_t i:std::views::iota(0U,MAX_INDEX+1U)){ |
|
|
|
|
backgrounds.emplace_back(data,i); |
|
|
|
|
paletteBits[backgrounds.back().paletteInd]=backgrounds.back().bbp; |
|
|
|
|
graphicsBits[backgrounds.back().graphicsInd]=backgrounds.back().bbp; |
|
|
|
|
} |
|
|
|
|
for(uint16_t i:std::views::iota(0U,paletteBits.size())){ |
|
|
|
|
palettes.emplace_back(data,i,paletteBits[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -100,9 +144,20 @@ public: |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int yOffset{0}; |
|
|
|
|
|
|
|
|
|
bool OnUserUpdate(float fElapsedTime) override |
|
|
|
|
{ |
|
|
|
|
if(GetMouseWheel()<0)yOffset-=32; |
|
|
|
|
if(GetMouseWheel()>0)yOffset+=32; |
|
|
|
|
|
|
|
|
|
for(uint8_t row=0;Rom::BackgroundPalette&palette:rom.palettes){ |
|
|
|
|
for(uint8_t index=0;Pixel&col:palette.colors){ |
|
|
|
|
FillRectDecal(vf2d{index*8.f+8,row*8.f+yOffset},{8,8},col); |
|
|
|
|
index++; |
|
|
|
|
} |
|
|
|
|
row++; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|