/* goombasav.h - functions to handle Goomba / Goomba Color SRAM last updated July 3, 2014 Copyright (C) 2014 libertyernie This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . https://github.com/libertyernie/goombasav When compiling in Visual Studio, set all goombasav files to compile as C++ code (Properties -> C/C++ -> Advanced -> Compile As.) */ #ifndef __GOOMBASAV_H #define __GOOMBASAV_H #include #define GOOMBA_COLOR_SRAM_SIZE 65536 #define GOOMBA_COLOR_AVAILABLE_SIZE 57344 #define GOOMBA_STATEID 0x57a731d8 #define GOOMBA_STATESAVE 0 #define GOOMBA_SRAMSAVE 1 #define GOOMBA_CONFIGSAVE 2 #define GOOMBA_PALETTE 5 typedef uint32_t goomba_size_t; // want a consistent size for printf. This is an alias for uint32_t, but this makes it clear that we're counting the size of something. /* 16-bit and 32-bit values in the stateheader are stored as little endian (native to the GBA's ARM chip as well as x86 processors.) Use this function after getting or before setting a value if your code might run on a big-endian processor (e.g. PowerPC.) */ uint16_t little_endian_conv_16(uint16_t value); /* 16-bit and 32-bit values in the stateheader are stored as little endian (native to the GBA's ARM chip as well as x86 processors.) Use this function after getting or before setting a value if your code might run on a big-endian processor (e.g. PowerPC.) */ uint32_t little_endian_conv_32(uint32_t value); typedef struct { //(modified stateheader) uint16_t size; uint16_t type; //=CONFIGSAVE char bordercolor; char palettebank; char misc; char reserved3; uint32_t sram_checksum; //checksum of rom using SRAM e000-ffff uint32_t zero; //=0 char reserved4[32]; //="CFG" } configdata; typedef struct { uint16_t size; //header+data uint16_t type; //=STATESAVE or SRAMSAVE uint32_t uncompressed_size; uint32_t framecount; uint32_t checksum; char title[32]; } stateheader; typedef struct { const char* sleep; const char* autoload_state; const char* gamma; } configdata_misc_strings; /** * Returns the last error encountered by goombasav (for functions that return * NULL on error.) This string is stored statically by goombasav and its * contents may change over time. */ const char* goomba_last_error(); /** * Set the string buffer used by goomba_last_error to a custom value. If the * input string is too long, the resulting goomba_last_error string will be * truncated. * Returns the number of bytes copied to the buffer (at present, the maximum * is 255.) */ size_t goomba_set_last_error(const char* msg); /** * Gets a struct containing pointers to three static strings (which do not * need to be deallocated.) */ configdata_misc_strings configdata_get_misc(char misc); /** * Returns a multi-line description string that includes all parameters of the * given stateheader or configdata structure. * This string is stored in a static character buffer, and subsequent calls to * stateheader_str or stateheader_summary_str will overwrite this buffer. */ const char* stateheader_str(const stateheader* sh); /** * Returns a one-line summary string displaying the size and title of the * stateheader or configdata structure. * This string is stored in a static character buffer, and subsequent calls to * stateheader_str or stateheader_summary_str will overwrite this buffer. */ const char* stateheader_summary_str(const stateheader* sh); int stateheader_plausible(const stateheader* sh); /** * When given a pointer to a stateheader, returns a pointer to where the next * stateheader will be located (if any). Use stateheader_plausible to * determine if there really is a header at this location. * * If stateheader_plausible determines that the input is not a valid * stateheader, NULL will be returned. */ stateheader* stateheader_advance(const stateheader* sh); /** * Scans for valid stateheaders and allocates an array to store them. The array * will have a capacity of 64, and any difference between that * and the number of headers found will be filled with NULL entries. The last * entry (array[63]) is guaranteed to be NULL. * NOTE: the gba_data parameter can point to a valid header, or to a sequence * equal to GOOMBA_STATEID immediately before a valid header. */ stateheader** stateheader_scan(const void* gba_data); /** * Returns the stateheader in gba_data with the title field = gbc_title, * or NULL if there is none. Only the first 15 bytes of gbc_title will be * used in the comparison. */ stateheader* stateheader_for(const void* gba_data, const char* gbc_title_ptr); /** * Returns true if the given data starts with GOOMBA_STATEID (little endian.) */ int goomba_is_sram(const void* data); /** * Makes a hash of the compressed data that comes after the given header, * using output_bytes bytes. A three-byte hash can be displayed as a color to * give visual feedback of a change in the data. The maximum of output_bytes is * sizeof(int). */ uint64_t goomba_compressed_data_checksum(const stateheader* sh, int output_bytes); /** * If there is save data in 0xe000-0xffff (as signaled by the configdata), * this function compresses it to where it's supposed to go. In the event that * the data passed in is already clean, the same pointer will be returned. * NULL will be returned if an error occurs. * * The given pointer must be at least GOOMBA_COLOR_SRAM_SIZE bytes in length. * If it is longer, any information after GOOMBA_COLOR_SRAM_SIZE bytes will be * ignored. */ char* goomba_cleanup(const void* gba_data_param); /** * Allocates memory to store the uncompressed GB/GBC save file extracted from * the Goomba Color save file stored in header_ptr, or returns NULL if the * decompression failed. */ void* goomba_extract(const void* gba_data, const stateheader* header_ptr, goomba_size_t* size_output); /** * Copies data from the source (which must point to a valid stateheader or * configdata) to dest, up to and including the first 48 bytes that do not * constitute a valid header. */ char* goomba_new_sav(const void* gba_data, const void* gba_header, const void* gbc_sram, goomba_size_t gbc_length); #endif