Palette reading and rendering implemented.

master
sigonasr2 5 months ago
parent 11ac0ee4d2
commit 759fcd26e1
  1. 57
      EarthboundBattleBackgrounds/EarthboundBattleBackgrounds/main.cpp
  2. BIN
      EarthboundBattleBackgrounds/x64/Debug/EarthboundBattleBackgrounds.exe
  3. BIN
      EarthboundBattleBackgrounds/x64/Debug/EarthboundBattleBackgrounds.pdb

@ -1,6 +1,9 @@
#define OLC_PGE_APPLICATION #define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h" #include "olcPixelGameEngine.h"
#include <ranges>
using namespace olc;
struct Rom{ struct Rom{
const static uint16_t MIN_INDEX{}; const static uint16_t MIN_INDEX{};
@ -18,6 +21,23 @@ struct Rom{
UNKNOWN_2, 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{ struct DataBlock{
uint32_t addr,ptr; uint32_t addr,ptr;
std::string_view data; std::string_view data;
@ -66,17 +86,41 @@ struct Rom{
return (data[13]<<24)+(data[14]<<16)+(data[15]<<8)+data[16]; 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::string data;
std::vector<BattleBackground>backgrounds; std::vector<BattleBackground>backgrounds;
std::vector<BackgroundPalette>palettes;
Rom(){ Rom(){
std::ifstream dataStream{"truncated_backgrounds.dat",std::ios_base::binary}; std::ifstream dataStream{"truncated_backgrounds.dat",std::ios_base::binary};
while(dataStream.good())data+=dataStream.get(); 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); backgrounds.emplace_back(data,i);
paletteBits[backgrounds.back().paletteInd]=backgrounds.back().bbp; paletteBits[backgrounds.back().paletteInd]=backgrounds.back().bbp;
graphicsBits[backgrounds.back().graphicsInd]=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; return true;
} }
int yOffset{0};
bool OnUserUpdate(float fElapsedTime) override 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; return true;
} }
}; };

Loading…
Cancel
Save