mirror of
https://github.com/risingPhil/libpokemegb.git
synced 2026-09-07 16:36:55 -05:00
Create dedicated Gen2ReproSaveManager class.
This one allows you to read save data from the rom. But it doesn't let you write to them. That will have to be implemented in PokeMe64, because it needs transfer pak writes to specific MBC registers
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "gen1/Gen1GameReader.h"
|
||||
#include "gen2/Gen2GameReader.h"
|
||||
#include "gen2/Gen2ReproSaveManager.h"
|
||||
#include "RomReader.h"
|
||||
#include "SaveManager.h"
|
||||
#include "utils.h"
|
||||
@@ -39,6 +40,7 @@ int main(int argc, char** argv)
|
||||
|
||||
GameboyCartridgeHeader cartridgeHeader;
|
||||
BufferBasedRomReader romReader(romBuffer, romFileSize);
|
||||
Gen2ReproSaveManager saveManager(romReader, Gen2ReproType::ALIEXPRESS_TYPE1, false);
|
||||
|
||||
readGameboyCartridgeHeader(romReader, cartridgeHeader);
|
||||
|
||||
@@ -63,11 +65,19 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t savBankBuffer[GB_SRAM_BANK_SIZE];
|
||||
|
||||
for(uint8_t i=0; i < 4; ++i)
|
||||
{
|
||||
saveManager.read(savBankBuffer, GB_SRAM_BANK_SIZE);
|
||||
fwrite(savBankBuffer, sizeof(uint8_t), GB_SRAM_BANK_SIZE, outFile);
|
||||
}
|
||||
#if 0
|
||||
|
||||
// So, turns out that these reproductions dedicate an entire rom bank
|
||||
// for every SRAM bank.
|
||||
// As a matter of fact, each SRAM bank is located at an offset of 0x2000 within
|
||||
// said rom bank.
|
||||
uint8_t savBankBuffer[GB_SRAM_BANK_SIZE];
|
||||
const uint8_t* cur = romBuffer + GEN2_REPRO_SAVE_OFFSET_IN_ROM;
|
||||
const uint8_t* const end = cur + (GB_ROM_BANK_SIZE * 4);
|
||||
while(cur < end)
|
||||
@@ -76,6 +86,7 @@ int main(int argc, char** argv)
|
||||
fwrite(savBankBuffer, sizeof(uint8_t), GB_SRAM_BANK_SIZE, outFile);
|
||||
cur += GB_ROM_BANK_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
fclose(outFile);
|
||||
|
||||
|
||||
89
include/gen2/Gen2ReproSaveManager.h
Normal file
89
include/gen2/Gen2ReproSaveManager.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef _GEN2REPROSAVEMANAGER_H
|
||||
#define _GEN2REPROSAVEMANAGER_H
|
||||
|
||||
#include "RomReader.h"
|
||||
#include "SaveManager.h"
|
||||
|
||||
enum class Gen2ReproType
|
||||
{
|
||||
INVALID,
|
||||
ALIEXPRESS_TYPE1
|
||||
};
|
||||
|
||||
typedef struct Gen2ReproSRAMRomOffsetMetadata
|
||||
{
|
||||
// A list of rom offsets for each SRAM bank
|
||||
struct {
|
||||
uint8_t romBankIndex;
|
||||
uint16_t romBankOffset;
|
||||
} sramBankOffsets[4];
|
||||
} Gen2ReproSRAMRomOffsetMetadata;
|
||||
|
||||
/**
|
||||
* @brief This class provides a way to read save data from a reproduction cart
|
||||
* Reproduction carts save their data inside the rom data.
|
||||
*/
|
||||
class Gen2ReproSaveManager : public BaseSaveManager
|
||||
{
|
||||
public:
|
||||
Gen2ReproSaveManager(IRomReader& romReader, Gen2ReproType reproType, bool writeEnabled);
|
||||
virtual ~Gen2ReproSaveManager();
|
||||
|
||||
/**
|
||||
* @brief This function reads a byte, returns it and advances the internal pointer by 1 byte
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
bool readByte(uint8_t& outByte) override;
|
||||
void writeByte(uint8_t byte) override;
|
||||
|
||||
/**
|
||||
* @brief This function reads multiple bytes into the specified output buffer
|
||||
* @note: bytesToRead should be <= 0x2000 (SRAM bank size)
|
||||
*
|
||||
* @return whether the operation was successful
|
||||
*/
|
||||
bool read(uint8_t* outBuffer, uint32_t bytesToRead) override;
|
||||
void write(const uint8_t* buffer, uint32_t bytesToWrite) override;
|
||||
|
||||
/**
|
||||
* @brief This function reads the current byte without advancing the internal pointer by 1 byte
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t peek() override;
|
||||
|
||||
/**
|
||||
* @brief This function advances the internal pointer by the specified numBytes.
|
||||
* This can be considered a relative seek
|
||||
*
|
||||
*/
|
||||
bool advance(uint32_t numBytes = 1) override;
|
||||
|
||||
/**
|
||||
* @brief This function rewinds the internal pointer with the specified numBytes
|
||||
* This can be considered a backward relative seek
|
||||
*/
|
||||
bool rewind(uint32_t numBytes = 1) override;
|
||||
|
||||
/**
|
||||
* @brief This function seeks to the specified absolute SRAM offset
|
||||
*
|
||||
* @param absoluteOffset
|
||||
*/
|
||||
bool seek(uint32_t absoluteOffset) override;
|
||||
|
||||
/**
|
||||
* @brief Returns the index of the current bank
|
||||
*/
|
||||
uint8_t getCurrentBankIndex() const override;
|
||||
protected:
|
||||
private:
|
||||
IRomReader& romReader_;
|
||||
Gen2ReproType reproType_;
|
||||
const Gen2ReproSRAMRomOffsetMetadata* reproRomOffsetMeta_;
|
||||
uint32_t absoluteOffset_;
|
||||
bool writeEnabled_;
|
||||
};
|
||||
|
||||
#endif
|
||||
124
src/gen2/Gen2ReproSaveManager.cpp
Normal file
124
src/gen2/Gen2ReproSaveManager.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "gen2/Gen2ReproSaveManager.h"
|
||||
|
||||
static const Gen2ReproSRAMRomOffsetMetadata aliexpressReproRomOffsets = {
|
||||
.sramBankOffsets = {
|
||||
{
|
||||
.romBankIndex = 0x74,
|
||||
.romBankOffset = 0x6000
|
||||
},
|
||||
{
|
||||
.romBankIndex = 0x75,
|
||||
.romBankOffset = 0x6000
|
||||
},
|
||||
{
|
||||
.romBankIndex = 0x76,
|
||||
.romBankOffset = 0x6000
|
||||
},
|
||||
{
|
||||
.romBankIndex = 0x77,
|
||||
.romBankOffset = 0x6000
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static uint8_t calculateBankIndex(uint32_t absoluteSRAMOffset)
|
||||
{
|
||||
return (absoluteSRAMOffset / 0x2000);
|
||||
}
|
||||
|
||||
static const Gen2ReproSRAMRomOffsetMetadata* getReproSaveRomOffsets(Gen2ReproType reproType)
|
||||
{
|
||||
switch(reproType)
|
||||
{
|
||||
case Gen2ReproType::ALIEXPRESS_TYPE1:
|
||||
return &aliexpressReproRomOffsets;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Gen2ReproSaveManager::Gen2ReproSaveManager(IRomReader& romReader, Gen2ReproType reproType, bool writeEnabled)
|
||||
: romReader_(romReader)
|
||||
, reproType_(reproType)
|
||||
, reproRomOffsetMeta_(getReproSaveRomOffsets(reproType))
|
||||
, absoluteOffset_(0)
|
||||
, writeEnabled_(writeEnabled)
|
||||
{
|
||||
seek(0);
|
||||
}
|
||||
|
||||
Gen2ReproSaveManager::~Gen2ReproSaveManager()
|
||||
{
|
||||
}
|
||||
|
||||
bool Gen2ReproSaveManager::readByte(uint8_t& outByte)
|
||||
{
|
||||
return read(&outByte, 1);
|
||||
}
|
||||
|
||||
void Gen2ReproSaveManager::writeByte(uint8_t byte)
|
||||
{
|
||||
write(&byte, 1);
|
||||
}
|
||||
|
||||
bool Gen2ReproSaveManager::read(uint8_t* outBuffer, uint32_t bytesToRead)
|
||||
{
|
||||
bool ret = romReader_.read(outBuffer, bytesToRead);
|
||||
if(!ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret &= advance(bytesToRead);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Gen2ReproSaveManager::write(const uint8_t* buffer, uint32_t bytesToWrite)
|
||||
{
|
||||
(void)buffer;
|
||||
(void)bytesToWrite;
|
||||
if(!writeEnabled_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO:
|
||||
}
|
||||
|
||||
uint8_t Gen2ReproSaveManager::peek()
|
||||
{
|
||||
return romReader_.peek();
|
||||
}
|
||||
|
||||
bool Gen2ReproSaveManager::advance(uint32_t numBytes)
|
||||
{
|
||||
absoluteOffset_ += numBytes;
|
||||
return seek(absoluteOffset_);
|
||||
}
|
||||
|
||||
bool Gen2ReproSaveManager::rewind(uint32_t numBytes)
|
||||
{
|
||||
absoluteOffset_ -= numBytes;
|
||||
return seek(absoluteOffset_);
|
||||
}
|
||||
|
||||
bool Gen2ReproSaveManager::seek(uint32_t absoluteOffset)
|
||||
{
|
||||
const uint8_t bankIndex = calculateBankIndex(absoluteOffset);
|
||||
|
||||
if(!reproRomOffsetMeta_ || bankIndex > 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
absoluteOffset_ = absoluteOffset;
|
||||
|
||||
const uint16_t localOffset = absoluteOffset % 0x2000;
|
||||
return romReader_.seekToRomPointer(reproRomOffsetMeta_->sramBankOffsets[bankIndex].romBankOffset + localOffset, reproRomOffsetMeta_->sramBankOffsets[bankIndex].romBankIndex);
|
||||
}
|
||||
|
||||
uint8_t Gen2ReproSaveManager::getCurrentBankIndex() const
|
||||
{
|
||||
return calculateBankIndex(absoluteOffset_);
|
||||
}
|
||||
Reference in New Issue
Block a user