mirror of
https://github.com/risingPhil/libpokemegb.git
synced 2026-03-21 17:44:24 -05:00
Support reading and writing the trainers' money from the save file.
It was implemented to be used for the Pokéshop idea for PokeMe64
This commit is contained in:
parent
8bb1f6a7d3
commit
54d9caa6c2
116
Makefile
116
Makefile
|
|
@ -1,58 +1,58 @@
|
||||||
# # Compiler flags
|
# # Compiler flags
|
||||||
CXXFLAGS := -std=c++11 -fno-rtti -fno-exceptions -fno-unwind-tables -Wall -Wextra -I $(CURDIR) -I $(CURDIR)/include -g -Os
|
CXXFLAGS := -std=c++11 -fno-rtti -fno-exceptions -fno-unwind-tables -Wall -Wextra -I $(CURDIR) -I $(CURDIR)/include -g -Os
|
||||||
|
|
||||||
# Source files directory
|
# Source files directory
|
||||||
SRC_DIR := src
|
SRC_DIR := src
|
||||||
# Build directory
|
# Build directory
|
||||||
BUILD_DIR := build
|
BUILD_DIR := build
|
||||||
|
|
||||||
# Source files (add more as needed)
|
# Source files (add more as needed)
|
||||||
SRCS := $(shell find $(SRC_DIR) -type f -name '*.cpp')
|
SRCS := $(shell find $(SRC_DIR) -type f -name '*.cpp')
|
||||||
# Object files
|
# Object files
|
||||||
OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCS))
|
OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCS))
|
||||||
|
|
||||||
PNG_SUPPORT ?= 1
|
PNG_SUPPORT ?= 1
|
||||||
|
|
||||||
# Add PNG support flag if PNG_SUPPORT is set to 1
|
# Add PNG support flag if PNG_SUPPORT is set to 1
|
||||||
ifeq ($(PNG_SUPPORT),1)
|
ifeq ($(PNG_SUPPORT),1)
|
||||||
CXXFLAGS += -DPNG_SUPPORT
|
CXXFLAGS += -DPNG_SUPPORT
|
||||||
MAKEOVERRIDES := PNG_SUPPORT=1
|
MAKEOVERRIDES := PNG_SUPPORT=1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Ensure necessary directories exist
|
# Ensure necessary directories exist
|
||||||
# This function ensures the directory for the target exists
|
# This function ensures the directory for the target exists
|
||||||
define make_directory
|
define make_directory
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# Target executable
|
# Target executable
|
||||||
TARGET := libpokemegb.a
|
TARGET := libpokemegb.a
|
||||||
|
|
||||||
# Phony targets
|
# Phony targets
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
# Default target
|
# Default target
|
||||||
all: $(TARGET) examples
|
all: $(TARGET) examples
|
||||||
|
|
||||||
examples: $(TARGET)
|
examples: $(TARGET)
|
||||||
$(MAKE) -C examples $(MAKECMDGOALS) $(MAKEOVERRIDES)
|
$(MAKE) -C examples $(MAKECMDGOALS) $(MAKEOVERRIDES)
|
||||||
|
|
||||||
# Rule to build the target executable
|
# Rule to build the target executable
|
||||||
$(TARGET): $(OBJS)
|
$(TARGET): $(OBJS)
|
||||||
@echo "Creating static library $(TARGET)"
|
@echo "Creating static library $(TARGET)"
|
||||||
ar rcs $@ $(OBJS)
|
ar rcs $@ $(OBJS)
|
||||||
ranlib $(TARGET)
|
ranlib $(TARGET)
|
||||||
|
|
||||||
# Rule to compile source files
|
# Rule to compile source files
|
||||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp | $(BUILD_DIR) $(C_FILE)
|
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp | $(BUILD_DIR) $(C_FILE)
|
||||||
$(make_directory)
|
$(make_directory)
|
||||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
# Create the build directory if it doesn't exist
|
# Create the build directory if it doesn't exist
|
||||||
$(BUILD_DIR):
|
$(BUILD_DIR):
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
# Clean rule
|
# Clean rule
|
||||||
clean:
|
clean:
|
||||||
make -C examples clean $(MAKEOVERRIDES)
|
make -C examples clean $(MAKEOVERRIDES)
|
||||||
rm -rf $(BUILD_DIR) $(TARGET)
|
rm -rf $(BUILD_DIR) $(TARGET)
|
||||||
|
|
|
||||||
|
|
@ -1,73 +1,79 @@
|
||||||
#include "gen1/Gen1GameReader.h"
|
#include "gen1/Gen1GameReader.h"
|
||||||
#include "gen2/Gen2GameReader.h"
|
#include "gen2/Gen2GameReader.h"
|
||||||
#include "RomReader.h"
|
#include "RomReader.h"
|
||||||
#include "SaveManager.h"
|
#include "SaveManager.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
static void print_usage()
|
static void print_usage()
|
||||||
{
|
{
|
||||||
printf("Usage: checkSave <path/to/rom.gbc> <path/to/file.sav>\n");
|
printf("Usage: checkSave <path/to/rom.gbc> <path/to/file.sav>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if(argc != 3)
|
if(argc != 3)
|
||||||
{
|
{
|
||||||
print_usage();
|
print_usage();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
uint8_t* romBuffer;
|
uint8_t* romBuffer;
|
||||||
uint8_t* savBuffer;
|
uint8_t* savBuffer;
|
||||||
uint32_t romFileSize;
|
uint32_t romFileSize;
|
||||||
uint32_t savFileSize;
|
uint32_t savFileSize;
|
||||||
|
|
||||||
printf("rom: %s, save: %s\n", argv[1], argv[2]);
|
printf("rom: %s, save: %s\n", argv[1], argv[2]);
|
||||||
|
|
||||||
romBuffer = readFileIntoBuffer(argv[1], romFileSize);
|
romBuffer = readFileIntoBuffer(argv[1], romFileSize);
|
||||||
if(!romBuffer)
|
if(!romBuffer)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ERROR: Couldn't read file %s\n", argv[1]);
|
fprintf(stderr, "ERROR: Couldn't read file %s\n", argv[1]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
savBuffer = readFileIntoBuffer(argv[2], savFileSize);
|
savBuffer = readFileIntoBuffer(argv[2], savFileSize);
|
||||||
if(!savBuffer)
|
if(!savBuffer)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ERROR: Couldn't read file %s\n", argv[2]);
|
fprintf(stderr, "ERROR: Couldn't read file %s\n", argv[2]);
|
||||||
free(romBuffer);
|
free(romBuffer);
|
||||||
romBuffer = nullptr;
|
romBuffer = nullptr;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameboyCartridgeHeader cartridgeHeader;
|
GameboyCartridgeHeader cartridgeHeader;
|
||||||
BufferBasedRomReader romReader(romBuffer, romFileSize);
|
BufferBasedRomReader romReader(romBuffer, romFileSize);
|
||||||
BufferBasedSaveManager saveManager(savBuffer, savFileSize);
|
BufferBasedSaveManager saveManager(savBuffer, savFileSize);
|
||||||
|
|
||||||
readGameboyCartridgeHeader(romReader, cartridgeHeader);
|
readGameboyCartridgeHeader(romReader, cartridgeHeader);
|
||||||
|
|
||||||
// check if we're dealing with gen 1
|
// check if we're dealing with gen 1
|
||||||
const Gen1GameType gen1Type = gen1_determineGameType(cartridgeHeader);
|
const Gen1GameType gen1Type = gen1_determineGameType(cartridgeHeader);
|
||||||
const Gen2GameType gen2Type = gen2_determineGameType(cartridgeHeader);
|
const Gen2GameType gen2Type = gen2_determineGameType(cartridgeHeader);
|
||||||
if (gen1Type != Gen1GameType::INVALID)
|
if (gen1Type != Gen1GameType::INVALID)
|
||||||
{
|
{
|
||||||
Gen1GameReader gameReader(romReader, saveManager, gen1Type);
|
Gen1GameReader gameReader(romReader, saveManager, gen1Type);
|
||||||
printf("%s", (gameReader.isMainChecksumValid()) ? "Game save valid!\n" : "Game save NOT valid!\n");
|
printf("%s", (gameReader.isMainChecksumValid()) ? "Game save valid!\n" : "Game save NOT valid!\n");
|
||||||
}
|
printf("OT: %u\n", gameReader.getTrainerID());
|
||||||
else if (gen2Type != Gen2GameType::INVALID)
|
printf("Name: %s\n", gameReader.getTrainerName());
|
||||||
{
|
printf("Money: %u\n", gameReader.getTrainerMoney());
|
||||||
Gen2GameReader gameReader(romReader, saveManager, gen2Type);
|
}
|
||||||
printf("%s", (gameReader.isMainChecksumValid()) ? "Main save valid!\n" : "Main save NOT valid!\n");
|
else if (gen2Type != Gen2GameType::INVALID)
|
||||||
printf("%s", (gameReader.isBackupChecksumValid()) ? "Backup save valid!\n" : "Backup save NOT valid!\n");
|
{
|
||||||
}
|
Gen2GameReader gameReader(romReader, saveManager, gen2Type);
|
||||||
|
printf("%s", (gameReader.isMainChecksumValid()) ? "Main save valid!\n" : "Main save NOT valid!\n");
|
||||||
free(romBuffer);
|
printf("%s", (gameReader.isBackupChecksumValid()) ? "Backup save valid!\n" : "Backup save NOT valid!\n");
|
||||||
romBuffer = 0;
|
printf("OT: %u\n", gameReader.getTrainerID());
|
||||||
|
printf("Name: %s\n", gameReader.getTrainerName());
|
||||||
free(savBuffer);
|
printf("Money: %u\n", gameReader.getTrainerMoney());
|
||||||
savBuffer = 0;
|
}
|
||||||
|
|
||||||
return 0;
|
free(romBuffer);
|
||||||
|
romBuffer = 0;
|
||||||
|
|
||||||
|
free(savBuffer);
|
||||||
|
savBuffer = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1,204 +1,215 @@
|
||||||
#ifndef GEN1GAMEREADER_H
|
#ifndef GEN1GAMEREADER_H
|
||||||
#define GEN1GAMEREADER_H
|
#define GEN1GAMEREADER_H
|
||||||
|
|
||||||
#include "gen1/Gen1SpriteDecoder.h"
|
#include "gen1/Gen1SpriteDecoder.h"
|
||||||
#include "gen1/Gen1IconDecoder.h"
|
#include "gen1/Gen1IconDecoder.h"
|
||||||
#include "gen1/Gen1PlayerPokemonStorage.h"
|
#include "gen1/Gen1PlayerPokemonStorage.h"
|
||||||
#include "gen1/Gen1DistributionPokemon.h"
|
#include "gen1/Gen1DistributionPokemon.h"
|
||||||
#include "gen1/Gen1Localization.h"
|
#include "gen1/Gen1Localization.h"
|
||||||
#include "gen1/Gen1Maps.h"
|
#include "gen1/Gen1Maps.h"
|
||||||
|
|
||||||
class IRomReader;
|
class IRomReader;
|
||||||
class ISaveManager;
|
class ISaveManager;
|
||||||
|
|
||||||
class Gen1GameReader
|
class Gen1GameReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Gen1GameReader(IRomReader& romReader, ISaveManager& saveManager, Gen1GameType gameType, Gen1LocalizationLanguage language = Gen1LocalizationLanguage::MAX);
|
Gen1GameReader(IRomReader& romReader, ISaveManager& saveManager, Gen1GameType gameType, Gen1LocalizationLanguage language = Gen1LocalizationLanguage::MAX);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves the current game cartridges'/roms' language
|
* @brief Retrieves the current game cartridges'/roms' language
|
||||||
*/
|
*/
|
||||||
Gen1LocalizationLanguage getGameLanguage() const;
|
Gen1LocalizationLanguage getGameLanguage() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the name of a pokémon based on an index number
|
* @brief get the name of a pokémon based on an index number
|
||||||
* Note: you don't own the returned pointer. The data will get overwritten on the next call to this function,
|
* Note: you don't own the returned pointer. The data will get overwritten on the next call to this function,
|
||||||
* so make sure to strdup() it if you need to store it for later
|
* so make sure to strdup() it if you need to store it for later
|
||||||
*
|
*
|
||||||
* @return const char*
|
* @return const char*
|
||||||
*/
|
*/
|
||||||
const char* getPokemonName(uint8_t index) const;
|
const char* getPokemonName(uint8_t index) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the pokedex number of a pokemon at the given internal index
|
* @brief Gets the pokedex number of a pokemon at the given internal index
|
||||||
*/
|
*/
|
||||||
uint8_t getPokemonNumber(uint8_t index) const;
|
uint8_t getPokemonNumber(uint8_t index) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function returns the Gen1PokemonIconType for a pokemon at the given index
|
* @brief This function returns the Gen1PokemonIconType for a pokemon at the given index
|
||||||
*/
|
*/
|
||||||
Gen1PokemonIconType getPokemonIconType(uint8_t index) const;
|
Gen1PokemonIconType getPokemonIconType(uint8_t index) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief With this function, you can check if the index is valid and not referring to missingno
|
* @brief With this function, you can check if the index is valid and not referring to missingno
|
||||||
*/
|
*/
|
||||||
bool isValidIndex(uint8_t index) const;
|
bool isValidIndex(uint8_t index) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads the pokemon stats at the given index
|
* @brief This function reads the pokemon stats at the given index
|
||||||
*
|
*
|
||||||
* @return whether or not this operation was successful
|
* @return whether or not this operation was successful
|
||||||
*/
|
*/
|
||||||
bool readPokemonStatsForIndex(uint8_t index, Gen1PokeStats& stats) const;
|
bool readPokemonStatsForIndex(uint8_t index, Gen1PokeStats& stats) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the index of the color palette based on the pokedex number of a certain pokemon
|
* @brief Get the index of the color palette based on the pokedex number of a certain pokemon
|
||||||
*/
|
*/
|
||||||
uint8_t getColorPaletteIndexByPokemonNumber(uint8_t pokeNumber);
|
uint8_t getColorPaletteIndexByPokemonNumber(uint8_t pokeNumber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads the color palette with the given ID into outColorPalette
|
* @brief This function reads the color palette with the given ID into outColorPalette
|
||||||
* outColorPalette should be a pointer to an uint16_t array with 4 elements
|
* outColorPalette should be a pointer to an uint16_t array with 4 elements
|
||||||
*
|
*
|
||||||
* Based on: https://bulbapedia.bulbagarden.net/wiki/List_of_color_palettes_by_index_number_(Generation_I)
|
* Based on: https://bulbapedia.bulbagarden.net/wiki/List_of_color_palettes_by_index_number_(Generation_I)
|
||||||
*
|
*
|
||||||
* @param outColorPalette
|
* @param outColorPalette
|
||||||
*/
|
*/
|
||||||
void readColorPalette(uint8_t paletteId, uint16_t* outColorPalette);
|
void readColorPalette(uint8_t paletteId, uint16_t* outColorPalette);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the trainer name from the save file
|
* @brief Get the trainer name from the save file
|
||||||
* Note: the resulting const char* does not need to be free'd.
|
* Note: the resulting const char* does not need to be free'd.
|
||||||
* However, it needs to be either used rightaway or strdup()'d, because the data will get overwritten on the next call to this function.
|
* However, it needs to be either used rightaway or strdup()'d, because the data will get overwritten on the next call to this function.
|
||||||
*/
|
*/
|
||||||
const char* getTrainerName() const;
|
const char* getTrainerName() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the rival name from the save file
|
* @brief Get the rival name from the save file
|
||||||
* Note: the resulting const char* does not need to be free'd.
|
* Note: the resulting const char* does not need to be free'd.
|
||||||
* However, it needs to be either used rightaway or strdup()'d, because the data will get overwritten on the next call to this function.
|
* However, it needs to be either used rightaway or strdup()'d, because the data will get overwritten on the next call to this function.
|
||||||
*/
|
*/
|
||||||
const char* getRivalName() const;
|
const char* getRivalName() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the player ID from the save file
|
* @brief Get the player ID from the save file
|
||||||
*/
|
*/
|
||||||
uint16_t getTrainerID() const;
|
uint16_t getTrainerID() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the current map the player is in.
|
* @brief This function retrieves the amount of pokédollars the trainer currently has
|
||||||
*/
|
*/
|
||||||
Gen1Maps getCurrentMap() const;
|
uint32_t getTrainerMoney() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a Gen1Party instance, which can be used to retrieve the information about the pokemon currently in the trainers' party
|
* @brief Sets the amount of pokédollars the trainer currently has
|
||||||
*/
|
* NOTE: the value is capped to 16777215 as this is the maximum value that can be represented by 3 bytes
|
||||||
Gen1Party getParty();
|
*/
|
||||||
|
void setTrainerMoney(uint32_t amount);
|
||||||
/**
|
|
||||||
* @brief Returns a Gen1Box instance, which can be used to retrieve information about the pokemon currently in the Trainers' PC box at the specified index
|
/**
|
||||||
*/
|
* Retrieves the current map the player is in.
|
||||||
Gen1Box getBox(uint8_t boxIndex);
|
*/
|
||||||
|
Gen1Maps getCurrentMap() const;
|
||||||
/**
|
|
||||||
* @brief Returns the 0-based index of the currently selected PC box for pokemon
|
/**
|
||||||
*/
|
* @brief Returns a Gen1Party instance, which can be used to retrieve the information about the pokemon currently in the trainers' party
|
||||||
uint8_t getCurrentBoxIndex();
|
*/
|
||||||
|
Gen1Party getParty();
|
||||||
/**
|
|
||||||
* @brief This function returns whether the pokemon with the given pokedexNumber has been SEEN/OWNED.
|
/**
|
||||||
*/
|
* @brief Returns a Gen1Box instance, which can be used to retrieve information about the pokemon currently in the Trainers' PC box at the specified index
|
||||||
bool getPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber) const;
|
*/
|
||||||
|
Gen1Box getBox(uint8_t boxIndex);
|
||||||
/**
|
|
||||||
* @brief This function sets the pokedex flag for the given pokedexNumber
|
/**
|
||||||
*/
|
* @brief Returns the 0-based index of the currently selected PC box for pokemon
|
||||||
void setPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber) const;
|
*/
|
||||||
|
uint8_t getCurrentBoxIndex();
|
||||||
/**
|
|
||||||
* @brief This function returns the counter value of the given dex flag
|
/**
|
||||||
*/
|
* @brief This function returns whether the pokemon with the given pokedexNumber has been SEEN/OWNED.
|
||||||
uint8_t getPokedexCounter(PokedexFlag dexFlag) const;
|
*/
|
||||||
|
bool getPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber) const;
|
||||||
/**
|
|
||||||
* @brief This function decodes a sprite at the given bank and pointer.
|
/**
|
||||||
* Returns a pointer to a buffer containing the decoded gameboy sprite in gameboy sprite format.
|
* @brief This function sets the pokedex flag for the given pokedexNumber
|
||||||
* The size of the returned buffer is SPRITE_BITPLANE_BUFFER_SIZE_IN_BYTES * 2
|
*/
|
||||||
*
|
void setPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber) const;
|
||||||
* WARNING: this function returns a pointer to an internal buffer of the Gen1SpriteDecoder. It will get overwritten on the next call to this function.
|
|
||||||
* If you want to keep the content around for longer, make a copy of this data.
|
/**
|
||||||
*/
|
* @brief This function returns the counter value of the given dex flag
|
||||||
uint8_t* decodeSprite(uint8_t bankIndex, uint16_t pointer);
|
*/
|
||||||
|
uint8_t getPokedexCounter(PokedexFlag dexFlag) const;
|
||||||
/**
|
|
||||||
* @brief This function decodes the given pokemon icon and returns an internal buffer
|
/**
|
||||||
* Note that this returns a 16x16 buffer in gameboy format with tiles in vertical order.
|
* @brief This function decodes a sprite at the given bank and pointer.
|
||||||
* You need to feed it to an instance of SpriteRenderer to convert it to a useful format
|
* Returns a pointer to a buffer containing the decoded gameboy sprite in gameboy sprite format.
|
||||||
*
|
* The size of the returned buffer is SPRITE_BITPLANE_BUFFER_SIZE_IN_BYTES * 2
|
||||||
* WARNING: this function returns a buffer to an internal buffer of Gen1IconDecoder. That means it will get overwritten on the next call to this function.
|
*
|
||||||
* If you want to keep the content around for longer, make a copy of this data
|
* WARNING: this function returns a pointer to an internal buffer of the Gen1SpriteDecoder. It will get overwritten on the next call to this function.
|
||||||
*/
|
* If you want to keep the content around for longer, make a copy of this data.
|
||||||
uint8_t* decodePokemonIcon(Gen1PokemonIconType iconType, bool firstFrame = true);
|
*/
|
||||||
|
uint8_t* decodeSprite(uint8_t bankIndex, uint16_t pointer);
|
||||||
/**
|
|
||||||
* @brief Adds a pokemon to the save. Tries to add it to the party first. If there's no more room there, it tries to add it to the
|
/**
|
||||||
* first ingame PC box with open slots
|
* @brief This function decodes the given pokemon icon and returns an internal buffer
|
||||||
*
|
* Note that this returns a 16x16 buffer in gameboy format with tiles in vertical order.
|
||||||
* @param originalTrainerID optional parameter. If not specified (=null), the original trainer id string will be set to the players'
|
* You need to feed it to an instance of SpriteRenderer to convert it to a useful format
|
||||||
* @param nickname optional parameter. If not specified (= null), the pokemon species name will be used instead.
|
*
|
||||||
*
|
* WARNING: this function returns a buffer to an internal buffer of Gen1IconDecoder. That means it will get overwritten on the next call to this function.
|
||||||
* @return
|
* If you want to keep the content around for longer, make a copy of this data
|
||||||
* 0xFF - Could not add pokemon (probably no space left)
|
*/
|
||||||
* 0xFE - Added to players' party
|
uint8_t* decodePokemonIcon(Gen1PokemonIconType iconType, bool firstFrame = true);
|
||||||
* 0x0 - 0xB - Added to box at index <value>
|
|
||||||
*/
|
/**
|
||||||
uint8_t addPokemon(Gen1TrainerPokemon& poke, const char* originalTrainerID = 0, const char* nickname = 0);
|
* @brief Adds a pokemon to the save. Tries to add it to the party first. If there's no more room there, it tries to add it to the
|
||||||
|
* first ingame PC box with open slots
|
||||||
/**
|
*
|
||||||
* @brief Adds a distribution pokemon to the save. Tries to add it to the party first. If there's no more room there, it tries to add it to the
|
* @param originalTrainerID optional parameter. If not specified (=null), the original trainer id string will be set to the players'
|
||||||
* first ingame PC box with open slots
|
* @param nickname optional parameter. If not specified (= null), the pokemon species name will be used instead.
|
||||||
*
|
*
|
||||||
* @param nickname optional parameter. If not specified (= null), the pokemon species name will be used instead.
|
* @return
|
||||||
*
|
* 0xFF - Could not add pokemon (probably no space left)
|
||||||
* @return
|
* 0xFE - Added to players' party
|
||||||
* 0xFF - Could not add pokemon (probably no space left)
|
* 0x0 - 0xB - Added to box at index <value>
|
||||||
* 0xFE - Added to players' party
|
*/
|
||||||
* 0x0 - 0xB - Added to box at index <value>
|
uint8_t addPokemon(Gen1TrainerPokemon& poke, const char* originalTrainerID = 0, const char* nickname = 0);
|
||||||
*/
|
|
||||||
uint8_t addDistributionPokemon(const Gen1DistributionPokemon& distributionPoke, const char* nickname = 0);
|
/**
|
||||||
|
* @brief Adds a distribution pokemon to the save. Tries to add it to the party first. If there's no more room there, it tries to add it to the
|
||||||
/**
|
* first ingame PC box with open slots
|
||||||
* @brief This function checks whether the main checksum of bank 1 is valid
|
*
|
||||||
*/
|
* @param nickname optional parameter. If not specified (= null), the pokemon species name will be used instead.
|
||||||
bool isMainChecksumValid();
|
*
|
||||||
|
* @return
|
||||||
/**
|
* 0xFF - Could not add pokemon (probably no space left)
|
||||||
* @brief Updates the main data checksum in bank 1
|
* 0xFE - Added to players' party
|
||||||
*/
|
* 0x0 - 0xB - Added to box at index <value>
|
||||||
void updateMainChecksum();
|
*/
|
||||||
/**
|
uint8_t addDistributionPokemon(const Gen1DistributionPokemon& distributionPoke, const char* nickname = 0);
|
||||||
* @brief Checks whether the whole bank checksum of the given memory bank is valid.
|
|
||||||
* As you may or may not know, bank 2 and bank 3 contain the PC Pokemon boxes of the player
|
/**
|
||||||
* These memory banks have 2 types of checksums: a whole memory bank checksum (which is this one)
|
* @brief This function checks whether the main checksum of bank 1 is valid
|
||||||
* And a checksum per box. (which will be dealt with in the Gen1Box class)
|
*/
|
||||||
*
|
bool isMainChecksumValid();
|
||||||
* So yeah, this function is about the whole memory bank checksums in memory bank 2 and 3
|
|
||||||
*/
|
/**
|
||||||
bool isWholeBoxBankValid(uint8_t bankIndex);
|
* @brief Updates the main data checksum in bank 1
|
||||||
|
*/
|
||||||
/**
|
void updateMainChecksum();
|
||||||
* @brief This function updates the checksum value of the whole box bank (bank 2 or 3)
|
/**
|
||||||
*/
|
* @brief Checks whether the whole bank checksum of the given memory bank is valid.
|
||||||
void updateWholeBoxBankChecksum(uint8_t bankIndex);
|
* As you may or may not know, bank 2 and bank 3 contain the PC Pokemon boxes of the player
|
||||||
protected:
|
* These memory banks have 2 types of checksums: a whole memory bank checksum (which is this one)
|
||||||
private:
|
* And a checksum per box. (which will be dealt with in the Gen1Box class)
|
||||||
IRomReader& romReader_;
|
*
|
||||||
ISaveManager& saveManager_;
|
* So yeah, this function is about the whole memory bank checksums in memory bank 2 and 3
|
||||||
Gen1SpriteDecoder spriteDecoder_;
|
*/
|
||||||
Gen1IconDecoder iconDecoder_;
|
bool isWholeBoxBankValid(uint8_t bankIndex);
|
||||||
Gen1GameType gameType_;
|
|
||||||
Gen1LocalizationLanguage localization_;
|
/**
|
||||||
};
|
* @brief This function updates the checksum value of the whole box bank (bank 2 or 3)
|
||||||
|
*/
|
||||||
|
void updateWholeBoxBankChecksum(uint8_t bankIndex);
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
IRomReader& romReader_;
|
||||||
|
ISaveManager& saveManager_;
|
||||||
|
Gen1SpriteDecoder spriteDecoder_;
|
||||||
|
Gen1IconDecoder iconDecoder_;
|
||||||
|
Gen1GameType gameType_;
|
||||||
|
Gen1LocalizationLanguage localization_;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,90 +1,91 @@
|
||||||
#ifndef _GEN1LOCALIZATION_H
|
#ifndef _GEN1LOCALIZATION_H
|
||||||
#define _GEN1LOCALIZATION_H
|
#define _GEN1LOCALIZATION_H
|
||||||
|
|
||||||
#include "gen1/Gen1Common.h"
|
#include "gen1/Gen1Common.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This enum defines the supported localization languages for gen 1.
|
* @brief This enum defines the supported localization languages for gen 1.
|
||||||
* MAX is invalid. It is defined to be used in a for loop if needed.
|
* MAX is invalid. It is defined to be used in a for loop if needed.
|
||||||
* It can also be used as an invalid value to force Gen1GameReader to identify
|
* It can also be used as an invalid value to force Gen1GameReader to identify
|
||||||
* the localization language
|
* the localization language
|
||||||
*/
|
*/
|
||||||
enum class Gen1LocalizationLanguage
|
enum class Gen1LocalizationLanguage
|
||||||
{
|
{
|
||||||
ENGLISH,
|
ENGLISH,
|
||||||
FRENCH,
|
FRENCH,
|
||||||
SPANISH,
|
SPANISH,
|
||||||
GERMAN,
|
GERMAN,
|
||||||
ITALIAN,
|
ITALIAN,
|
||||||
JAPANESE,
|
JAPANESE,
|
||||||
MAX
|
MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Different pokémon localizations unfortunately also store data at different locations in the rom.
|
* @brief Different pokémon localizations unfortunately also store data at different locations in the rom.
|
||||||
* This is because stuff shifts around because of the different text.
|
* This is because stuff shifts around because of the different text.
|
||||||
*
|
*
|
||||||
* So to deal with different localizations of the same game, we need to keep track of the various rom offsets we need
|
* So to deal with different localizations of the same game, we need to keep track of the various rom offsets we need
|
||||||
* for each of them.
|
* for each of them.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct Gen1LocalizationRomOffsets
|
typedef struct Gen1LocalizationRomOffsets
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @brief The rom offset at which the species structs can be found containing the base stats
|
* @brief The rom offset at which the species structs can be found containing the base stats
|
||||||
* of the various pokémon. https://bulbapedia.bulbagarden.net/wiki/Pok%C3%A9mon_species_data_structure_(Generation_I)
|
* of the various pokémon. https://bulbapedia.bulbagarden.net/wiki/Pok%C3%A9mon_species_data_structure_(Generation_I)
|
||||||
*/
|
*/
|
||||||
uint32_t stats;
|
uint32_t stats;
|
||||||
/**
|
/**
|
||||||
* @brief For some reason, in the Pokémon Blue and Red versions, the mew species(stats) struct is stored separately.
|
* @brief For some reason, in the Pokémon Blue and Red versions, the mew species(stats) struct is stored separately.
|
||||||
* This does not apply to Pokémon Yellow
|
* This does not apply to Pokémon Yellow
|
||||||
*/
|
*/
|
||||||
uint32_t statsMew;
|
uint32_t statsMew;
|
||||||
/**
|
/**
|
||||||
* @brief This is the rom offset at which the pokedex numbers of pokémon are stored in pokemon index order
|
* @brief This is the rom offset at which the pokedex numbers of pokémon are stored in pokemon index order
|
||||||
*/
|
*/
|
||||||
uint32_t numbers;
|
uint32_t numbers;
|
||||||
/**
|
/**
|
||||||
* @brief This is the rom offset at which we can find the encoded pokémon names.
|
* @brief This is the rom offset at which we can find the encoded pokémon names.
|
||||||
* These can be decoded with gen1_decodePokeText()
|
* These can be decoded with gen1_decodePokeText()
|
||||||
*/
|
*/
|
||||||
uint32_t names;
|
uint32_t names;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the rom offset at which we can find the party menu icon type for each pokémon in pokedex number order.
|
* @brief This is the rom offset at which we can find the party menu icon type for each pokémon in pokedex number order.
|
||||||
*/
|
*/
|
||||||
uint32_t iconTypes;
|
uint32_t iconTypes;
|
||||||
/**
|
/**
|
||||||
* @brief This is the rom offset at which we can find the MonPartySpritePointers pointer table
|
* @brief This is the rom offset at which we can find the MonPartySpritePointers pointer table
|
||||||
* This defines where the icon sprites are stored in the rom (and the number of tiles)
|
* This defines where the icon sprites are stored in the rom (and the number of tiles)
|
||||||
*
|
*
|
||||||
* see https://github.com/pret/pokered/blob/master/data/icon_pointers.asm
|
* see https://github.com/pret/pokered/blob/master/data/icon_pointers.asm
|
||||||
*/
|
*/
|
||||||
uint32_t icons;
|
uint32_t icons;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the rom offset at which a palette index is stored for each pokémon in pokedex number order.
|
* @brief This is the rom offset at which a palette index is stored for each pokémon in pokedex number order.
|
||||||
*/
|
*/
|
||||||
uint32_t paletteIndices;
|
uint32_t paletteIndices;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the rom offset at which each pokémon sprite color palette is stored in palette index order
|
* @brief This is the rom offset at which each pokémon sprite color palette is stored in palette index order
|
||||||
*/
|
*/
|
||||||
uint32_t palettes;
|
uint32_t palettes;
|
||||||
} Gen1LocalizationRomOffsets;
|
} Gen1LocalizationRomOffsets;
|
||||||
|
|
||||||
typedef struct Gen1LocalizationSRAMOffsets
|
typedef struct Gen1LocalizationSRAMOffsets
|
||||||
{
|
{
|
||||||
uint32_t trainerID;
|
uint32_t trainerID;
|
||||||
uint32_t currentMap;
|
uint32_t trainerMoney;
|
||||||
uint32_t dexSeen;
|
uint32_t currentMap;
|
||||||
uint32_t dexOwned;
|
uint32_t dexSeen;
|
||||||
uint32_t rivalName;
|
uint32_t dexOwned;
|
||||||
uint32_t party;
|
uint32_t rivalName;
|
||||||
uint32_t currentBoxIndex;
|
uint32_t party;
|
||||||
uint32_t checksum;
|
uint32_t currentBoxIndex;
|
||||||
} Gen1LocalizationSRAMOffsets;
|
uint32_t checksum;
|
||||||
|
} Gen1LocalizationSRAMOffsets;
|
||||||
const Gen1LocalizationRomOffsets& gen1_getRomOffsets(Gen1GameType gameType, Gen1LocalizationLanguage language);
|
|
||||||
const Gen1LocalizationSRAMOffsets& gen1_getSRAMOffsets(Gen1LocalizationLanguage language);
|
const Gen1LocalizationRomOffsets& gen1_getRomOffsets(Gen1GameType gameType, Gen1LocalizationLanguage language);
|
||||||
|
const Gen1LocalizationSRAMOffsets& gen1_getSRAMOffsets(Gen1LocalizationLanguage language);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -131,6 +131,18 @@ public:
|
||||||
*/
|
*/
|
||||||
const char *getTrainerName() const;
|
const char *getTrainerName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function retrieves the amount of pokédollars the trainer currently has
|
||||||
|
*/
|
||||||
|
uint32_t getTrainerMoney() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the amount of pokédollars the trainer currently has
|
||||||
|
* NOTE: the value is capped to 16777215 as this is the maximum value that can be represented by 3 bytes
|
||||||
|
*/
|
||||||
|
void setTrainerMoney(uint32_t amount);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the rival name from the save file
|
* @brief Get the rival name from the save file
|
||||||
* Note: the resulting const char* does not need to be free'd.
|
* Note: the resulting const char* does not need to be free'd.
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ typedef struct Gen2LocalizationSRAMOffsets
|
||||||
uint32_t currentBox;
|
uint32_t currentBox;
|
||||||
uint32_t dexSeen;
|
uint32_t dexSeen;
|
||||||
uint32_t dexOwned;
|
uint32_t dexOwned;
|
||||||
|
uint32_t trainerMoney;
|
||||||
uint32_t party;
|
uint32_t party;
|
||||||
uint32_t eventFlags;
|
uint32_t eventFlags;
|
||||||
uint32_t mainChecksum;
|
uint32_t mainChecksum;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,197 +1,199 @@
|
||||||
#include "gen1/Gen1Localization.h"
|
#include "gen1/Gen1Localization.h"
|
||||||
|
|
||||||
static const Gen1LocalizationRomOffsets g1_localizationROMOffsetsRGB[] = {
|
static const Gen1LocalizationRomOffsets g1_localizationROMOffsetsRGB[] = {
|
||||||
// English
|
// English
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x425B,
|
.statsMew = 0x425B,
|
||||||
.numbers = 0x41024,
|
.numbers = 0x41024,
|
||||||
.names = 0x1c21e,
|
.names = 0x1c21e,
|
||||||
.iconTypes = 0x7190D,
|
.iconTypes = 0x7190D,
|
||||||
.icons = 0x717C0,
|
.icons = 0x717C0,
|
||||||
.paletteIndices = 0x725C9,
|
.paletteIndices = 0x725C9,
|
||||||
.palettes = 0x72660
|
.palettes = 0x72660
|
||||||
},
|
},
|
||||||
// French
|
// French
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x425B,
|
.statsMew = 0x425B,
|
||||||
.numbers = 0x40FAA,
|
.numbers = 0x40FAA,
|
||||||
.names = 0x1C21E,
|
.names = 0x1C21E,
|
||||||
.iconTypes = 0x718DE,
|
.iconTypes = 0x718DE,
|
||||||
.icons = 0x71791,
|
.icons = 0x71791,
|
||||||
.paletteIndices = 0x7259A,
|
.paletteIndices = 0x7259A,
|
||||||
.palettes = 0x72631
|
.palettes = 0x72631
|
||||||
},
|
},
|
||||||
// Spanish
|
// Spanish
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x425B,
|
.statsMew = 0x425B,
|
||||||
.numbers = 0x40FB4,
|
.numbers = 0x40FB4,
|
||||||
.names = 0x1C21E,
|
.names = 0x1C21E,
|
||||||
.iconTypes = 0x718FD,
|
.iconTypes = 0x718FD,
|
||||||
.icons = 0x717B0,
|
.icons = 0x717B0,
|
||||||
.paletteIndices = 0x725B9,
|
.paletteIndices = 0x725B9,
|
||||||
.palettes = 0x72650
|
.palettes = 0x72650
|
||||||
},
|
},
|
||||||
// German
|
// German
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x425B,
|
.statsMew = 0x425B,
|
||||||
.numbers = 0x40F96,
|
.numbers = 0x40F96,
|
||||||
.names = 0x1C21E,
|
.names = 0x1C21E,
|
||||||
.iconTypes = 0x718E7,
|
.iconTypes = 0x718E7,
|
||||||
.icons = 0x7179A,
|
.icons = 0x7179A,
|
||||||
.paletteIndices = 0x725A3,
|
.paletteIndices = 0x725A3,
|
||||||
.palettes = 0x7263A
|
.palettes = 0x7263A
|
||||||
},
|
},
|
||||||
// Italian
|
// Italian
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x425B,
|
.statsMew = 0x425B,
|
||||||
.numbers = 0x40FB6,
|
.numbers = 0x40FB6,
|
||||||
.names = 0x1C21E,
|
.names = 0x1C21E,
|
||||||
.iconTypes = 0x7194D,
|
.iconTypes = 0x7194D,
|
||||||
.icons = 0x71800,
|
.icons = 0x71800,
|
||||||
.paletteIndices = 0x72609,
|
.paletteIndices = 0x72609,
|
||||||
.palettes = 0x726A0
|
.palettes = 0x726A0
|
||||||
},
|
},
|
||||||
// Japanese
|
// Japanese
|
||||||
{
|
{
|
||||||
.stats = 0x38000,
|
.stats = 0x38000,
|
||||||
.statsMew = 0x4200,
|
.statsMew = 0x4200,
|
||||||
.numbers = 0x4279A,
|
.numbers = 0x4279A,
|
||||||
.names = 0x39068,
|
.names = 0x39068,
|
||||||
.iconTypes = 0x71DD1,
|
.iconTypes = 0x71DD1,
|
||||||
.icons = 0x71C84,
|
.icons = 0x71C84,
|
||||||
.paletteIndices = 0x72A1F,
|
.paletteIndices = 0x72A1F,
|
||||||
.palettes = 0x72AB6
|
.palettes = 0x72AB6
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Gen1LocalizationRomOffsets g1_localizationROMOffsetsBlueJpn = {
|
static const Gen1LocalizationRomOffsets g1_localizationROMOffsetsBlueJpn = {
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x425B,
|
.statsMew = 0x425B,
|
||||||
.numbers = 0x42784,
|
.numbers = 0x42784,
|
||||||
.names = 0x39446,
|
.names = 0x39446,
|
||||||
.iconTypes = 0x71DC1,
|
.iconTypes = 0x71DC1,
|
||||||
.icons = 0x71C74,
|
.icons = 0x71C74,
|
||||||
.paletteIndices = 0x72A0E,
|
.paletteIndices = 0x72A0E,
|
||||||
.palettes = 0x72AA5
|
.palettes = 0x72AA5
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Gen1LocalizationRomOffsets g1_localizationROMOffsetsY[] = {
|
static const Gen1LocalizationRomOffsets g1_localizationROMOffsetsY[] = {
|
||||||
// English
|
// English
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
||||||
.numbers = 0x410B1,
|
.numbers = 0x410B1,
|
||||||
.names = 0xE8000,
|
.names = 0xE8000,
|
||||||
.iconTypes = 0x719BA,
|
.iconTypes = 0x719BA,
|
||||||
.icons = 0x7184D,
|
.icons = 0x7184D,
|
||||||
.paletteIndices = 0x72922,
|
.paletteIndices = 0x72922,
|
||||||
.palettes = 0x72AF9
|
.palettes = 0x72AF9
|
||||||
},
|
},
|
||||||
// French
|
// French
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
||||||
.numbers = 0x41036,
|
.numbers = 0x41036,
|
||||||
.names = 0xE8000,
|
.names = 0xE8000,
|
||||||
.iconTypes = 0x7198B,
|
.iconTypes = 0x7198B,
|
||||||
.icons = 0x7181E,
|
.icons = 0x7181E,
|
||||||
.paletteIndices = 0x728F3,
|
.paletteIndices = 0x728F3,
|
||||||
.palettes = 0x72ACA
|
.palettes = 0x72ACA
|
||||||
},
|
},
|
||||||
// Spanish
|
// Spanish
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
||||||
.numbers = 0x41041,
|
.numbers = 0x41041,
|
||||||
.names = 0xE8000,
|
.names = 0xE8000,
|
||||||
.iconTypes = 0x719AA,
|
.iconTypes = 0x719AA,
|
||||||
.icons = 0x7183D,
|
.icons = 0x7183D,
|
||||||
.paletteIndices = 0x72912,
|
.paletteIndices = 0x72912,
|
||||||
.palettes = 0x72AE9
|
.palettes = 0x72AE9
|
||||||
},
|
},
|
||||||
// German
|
// German
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
||||||
.numbers = 0x41023,
|
.numbers = 0x41023,
|
||||||
.names = 0xE8000,
|
.names = 0xE8000,
|
||||||
.iconTypes = 0x71999,
|
.iconTypes = 0x71999,
|
||||||
.icons = 0x7182c,
|
.icons = 0x7182c,
|
||||||
.paletteIndices = 0x72901,
|
.paletteIndices = 0x72901,
|
||||||
.palettes = 0x72AD8
|
.palettes = 0x72AD8
|
||||||
},
|
},
|
||||||
// Italian
|
// Italian
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
||||||
.numbers = 0x41043,
|
.numbers = 0x41043,
|
||||||
.names = 0xE8000,
|
.names = 0xE8000,
|
||||||
.iconTypes = 0x719FA,
|
.iconTypes = 0x719FA,
|
||||||
.icons = 0x7188D,
|
.icons = 0x7188D,
|
||||||
.paletteIndices = 0x72962,
|
.paletteIndices = 0x72962,
|
||||||
.palettes = 0x72B39
|
.palettes = 0x72B39
|
||||||
},
|
},
|
||||||
// Japanese
|
// Japanese
|
||||||
{
|
{
|
||||||
.stats = 0x383DE,
|
.stats = 0x383DE,
|
||||||
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
.statsMew = 0x0, // IRRELEVANT because mew is included in the stats list for Yellow
|
||||||
.numbers = 0x4282D,
|
.numbers = 0x4282D,
|
||||||
.names = 0x39462,
|
.names = 0x39462,
|
||||||
.iconTypes = 0x71911,
|
.iconTypes = 0x71911,
|
||||||
.icons = 0x717A4,
|
.icons = 0x717A4,
|
||||||
.paletteIndices = 0x72650,
|
.paletteIndices = 0x72650,
|
||||||
.palettes = 0x726E7
|
.palettes = 0x726E7
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Gen1LocalizationSRAMOffsets g1_sRAMOffsetsInternational = {
|
static const Gen1LocalizationSRAMOffsets g1_sRAMOffsetsInternational = {
|
||||||
.trainerID = 0x2605,
|
.trainerID = 0x2605,
|
||||||
.currentMap = 0x260A,
|
.trainerMoney = 0x25F3,
|
||||||
.dexSeen = 0x25B6,
|
.currentMap = 0x260A,
|
||||||
.dexOwned = 0x25A3,
|
.dexSeen = 0x25B6,
|
||||||
.rivalName = 0x25F6,
|
.dexOwned = 0x25A3,
|
||||||
.party = 0x2F2C,
|
.rivalName = 0x25F6,
|
||||||
.currentBoxIndex = 0x284C,
|
.party = 0x2F2C,
|
||||||
.checksum = 0x3523
|
.currentBoxIndex = 0x284C,
|
||||||
};
|
.checksum = 0x3523
|
||||||
|
};
|
||||||
static const Gen1LocalizationSRAMOffsets g1_sRAMOffsetsJapan = {
|
|
||||||
.trainerID = 0x25FB,
|
static const Gen1LocalizationSRAMOffsets g1_sRAMOffsetsJapan = {
|
||||||
.currentMap = 0x2600,
|
.trainerID = 0x25FB,
|
||||||
.dexSeen = 0x25B1,
|
.trainerMoney = 0x25EE,
|
||||||
.dexOwned = 0x259E,
|
.currentMap = 0x2600,
|
||||||
.rivalName = 0x25F1,
|
.dexSeen = 0x25B1,
|
||||||
.party = 0x2ED5,
|
.dexOwned = 0x259E,
|
||||||
.currentBoxIndex = 0x2842,
|
.rivalName = 0x25F1,
|
||||||
.checksum = 0x3594
|
.party = 0x2ED5,
|
||||||
};
|
.currentBoxIndex = 0x2842,
|
||||||
|
.checksum = 0x3594
|
||||||
const Gen1LocalizationRomOffsets& gen1_getRomOffsets(Gen1GameType gameType, Gen1LocalizationLanguage language)
|
};
|
||||||
{
|
|
||||||
if(language == Gen1LocalizationLanguage::JAPANESE && gameType == Gen1GameType::BLUE)
|
const Gen1LocalizationRomOffsets& gen1_getRomOffsets(Gen1GameType gameType, Gen1LocalizationLanguage language)
|
||||||
{
|
{
|
||||||
return g1_localizationROMOffsetsBlueJpn;
|
if(language == Gen1LocalizationLanguage::JAPANESE && gameType == Gen1GameType::BLUE)
|
||||||
}
|
{
|
||||||
else
|
return g1_localizationROMOffsetsBlueJpn;
|
||||||
{
|
}
|
||||||
switch(gameType)
|
else
|
||||||
{
|
{
|
||||||
case Gen1GameType::RED:
|
switch(gameType)
|
||||||
case Gen1GameType::BLUE:
|
{
|
||||||
case Gen1GameType::GREEN:
|
case Gen1GameType::RED:
|
||||||
return g1_localizationROMOffsetsRGB[(uint8_t)language];
|
case Gen1GameType::BLUE:
|
||||||
default:
|
case Gen1GameType::GREEN:
|
||||||
return g1_localizationROMOffsetsY[(uint8_t)language];
|
return g1_localizationROMOffsetsRGB[(uint8_t)language];
|
||||||
}
|
default:
|
||||||
}
|
return g1_localizationROMOffsetsY[(uint8_t)language];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const Gen1LocalizationSRAMOffsets& gen1_getSRAMOffsets(Gen1LocalizationLanguage language)
|
}
|
||||||
{
|
|
||||||
return (language != Gen1LocalizationLanguage::JAPANESE) ? g1_sRAMOffsetsInternational : g1_sRAMOffsetsJapan;
|
const Gen1LocalizationSRAMOffsets& gen1_getSRAMOffsets(Gen1LocalizationLanguage language)
|
||||||
|
{
|
||||||
|
return (language != Gen1LocalizationLanguage::JAPANESE) ? g1_sRAMOffsetsInternational : g1_sRAMOffsetsJapan;
|
||||||
}
|
}
|
||||||
|
|
@ -642,6 +642,24 @@ const char *Gen2GameReader::getTrainerName() const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Gen2GameReader::getTrainerMoney() const
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
const uint32_t savOffset = gen2_getSRAMOffsets(gameType_, localization_).trainerMoney;
|
||||||
|
|
||||||
|
saveManager_.seek(savOffset);
|
||||||
|
saveManager_.readUint24(result, Endianness::BIG);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gen2GameReader::setTrainerMoney(uint32_t amount)
|
||||||
|
{
|
||||||
|
const uint32_t savOffset = gen2_getSRAMOffsets(gameType_, localization_).trainerMoney;
|
||||||
|
|
||||||
|
saveManager_.seek(savOffset);
|
||||||
|
saveManager_.writeUint24(amount, Endianness::BIG);
|
||||||
|
}
|
||||||
|
|
||||||
const char *Gen2GameReader::getRivalName() const
|
const char *Gen2GameReader::getRivalName() const
|
||||||
{
|
{
|
||||||
static char result[20];
|
static char result[20];
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,7 @@ static const Gen2LocalizationSRAMOffsets g2_dummySRAMOffsets = {
|
||||||
.currentBox = 0,
|
.currentBox = 0,
|
||||||
.dexSeen = 0,
|
.dexSeen = 0,
|
||||||
.dexOwned = 0,
|
.dexOwned = 0,
|
||||||
|
.trainerMoney = 0,
|
||||||
.party = 0,
|
.party = 0,
|
||||||
.eventFlags = 0,
|
.eventFlags = 0,
|
||||||
.mainChecksum = 0,
|
.mainChecksum = 0,
|
||||||
|
|
@ -243,6 +244,7 @@ static const Gen2LocalizationSRAMOffsets g2_internationalSRAMOffsetsGS = {
|
||||||
.currentBox = 0x2D6C,
|
.currentBox = 0x2D6C,
|
||||||
.dexSeen = 0x2A6C,
|
.dexSeen = 0x2A6C,
|
||||||
.dexOwned = 0x2A4C,
|
.dexOwned = 0x2A4C,
|
||||||
|
.trainerMoney = 0x23DB,
|
||||||
.party = 0x288A,
|
.party = 0x288A,
|
||||||
.eventFlags = 0x261F,
|
.eventFlags = 0x261F,
|
||||||
.mainChecksum = 0x2D69,
|
.mainChecksum = 0x2D69,
|
||||||
|
|
@ -264,6 +266,7 @@ static const Gen2LocalizationSRAMOffsets g2_internationalSRAMOffsetsC = {
|
||||||
.currentBox = 0x2D10,
|
.currentBox = 0x2D10,
|
||||||
.dexSeen = 0x2A47,
|
.dexSeen = 0x2A47,
|
||||||
.dexOwned = 0x2A27,
|
.dexOwned = 0x2A27,
|
||||||
|
.trainerMoney = 0x23DC,
|
||||||
.party = 0x2865,
|
.party = 0x2865,
|
||||||
.eventFlags = 0x2600,
|
.eventFlags = 0x2600,
|
||||||
.mainChecksum = 0x2D0D,
|
.mainChecksum = 0x2D0D,
|
||||||
|
|
@ -297,6 +300,7 @@ static const Gen2LocalizationSRAMOffsets g2_localizationSRAMOffsetsGS[] = {
|
||||||
.currentBox = 0x2DAE,
|
.currentBox = 0x2DAE,
|
||||||
.dexSeen = 0x2AAE,
|
.dexSeen = 0x2AAE,
|
||||||
.dexOwned = 0x2A8E,
|
.dexOwned = 0x2A8E,
|
||||||
|
.trainerMoney = 0x23D3,
|
||||||
.party = 0x28CC,
|
.party = 0x28CC,
|
||||||
.eventFlags = 0x25F7,
|
.eventFlags = 0x25F7,
|
||||||
.mainChecksum = 0x2DAB,
|
.mainChecksum = 0x2DAB,
|
||||||
|
|
@ -318,6 +322,7 @@ static const Gen2LocalizationSRAMOffsets g2_localizationSRAMOffsetsGS[] = {
|
||||||
.currentBox = 0x2D10,
|
.currentBox = 0x2D10,
|
||||||
.dexSeen = 0x29EE,
|
.dexSeen = 0x29EE,
|
||||||
.dexOwned = 0x29CE,
|
.dexOwned = 0x29CE,
|
||||||
|
.trainerMoney = 0x23BC,
|
||||||
.party = 0x283E,
|
.party = 0x283E,
|
||||||
.eventFlags = 0x2600,
|
.eventFlags = 0x2600,
|
||||||
.mainChecksum = 0x2D0D,
|
.mainChecksum = 0x2D0D,
|
||||||
|
|
@ -354,6 +359,7 @@ static const Gen2LocalizationSRAMOffsets g2_localizationSRAMOffsetsC[] = {
|
||||||
.currentBox = 0x2D10,
|
.currentBox = 0x2D10,
|
||||||
.dexSeen = 0x29CA,
|
.dexSeen = 0x29CA,
|
||||||
.dexOwned = 0x29AA,
|
.dexOwned = 0x29AA,
|
||||||
|
.trainerMoney = 0x23BE,
|
||||||
.party = 0x281A,
|
.party = 0x281A,
|
||||||
.eventFlags = 0x25E2,
|
.eventFlags = 0x25E2,
|
||||||
.mainChecksum = 0x2D0D,
|
.mainChecksum = 0x2D0D,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user