diff --git a/src/boot/boot_io.h b/src/boot/boot_io.h index eb9f5cc6..ccda89da 100644 --- a/src/boot/boot_io.h +++ b/src/boot/boot_io.h @@ -69,7 +69,7 @@ typedef struct { io32_t DMA_BUSY; /**< DMA Busy Register. */ io32_t SEMAPHORE; /**< Semaphore Register. */ io32_t __reserved[0xFFF8]; - io32_t PC; + io32_t PC; /**< Program Counter Register. */ } sp_regs_t; /** @@ -123,16 +123,20 @@ typedef struct { #define SP_SR_CLR_SIG7 (1 << 23) #define SP_SR_SET_SIG7 (1 << 24) -/** @brief DPC Registers Structure. */ +/** + * @brief DPC Registers Structure. + * + * This structure represents the registers for the DPC (Display Processor). + */ typedef struct { - io32_t START; - io32_t END; - io32_t CURRENT; - io32_t SR; - io32_t CLOCK; - io32_t BUF_BUSY; - io32_t PIPE_BUSY; - io32_t TMEM; + io32_t START; /**< Start Register. */ + io32_t END; /**< End Register. */ + io32_t CURRENT; /**< Current Register. */ + io32_t SR; /**< Status Register. */ + io32_t CLOCK; /**< Clock Register. */ + io32_t BUF_BUSY; /**< Buffer Busy Register. */ + io32_t PIPE_BUSY; /**< Pipe Busy Register. */ + io32_t TMEM; /**< TMEM Register. */ } dpc_regs_t; #define DPC_BASE (0x04100000UL) @@ -160,36 +164,26 @@ typedef struct { #define DPC_SR_CLR_CMD_CTR (1 << 8) #define DPC_SR_CLR_CLOCK_CTR (1 << 9) -/** @brief Video Interface Registers Structure. */ +/** + * @brief Video Interface Registers Structure. + * + * This structure represents the registers for the Video Interface (VI). + */ typedef struct { - /** @brief The Control Register. */ - io32_t CR; - /** @brief The Memory Address. */ - io32_t MADDR; - /** @brief The Horizontal Width. */ - io32_t H_WIDTH; - /** @brief The Virtical Interupt. */ - io32_t V_INTR; - /** @brief The Current Line. */ - io32_t CURR_LINE; - /** @brief The Timings. */ - io32_t TIMING; - /** @brief The Virtical Sync. */ - io32_t V_SYNC; - /** @brief The Horizontal Sync. */ - io32_t H_SYNC; - /** @brief The Horizontal Sync Leap. */ - io32_t H_SYNC_LEAP; - /** @brief The Horizontal Limits. */ - io32_t H_LIMITS; - /** @brief The Virtical Limits. */ - io32_t V_LIMITS; - /** @brief The Colour Burst. */ - io32_t COLOR_BURST; - /** @brief The Horizontal Scale. */ - io32_t H_SCALE; - /** @brief The Virtical Scale. */ - io32_t V_SCALE; + io32_t CR; /**< Control Register. */ + io32_t MADDR; /**< Memory Address. */ + io32_t H_WIDTH; /**< Horizontal Width. */ + io32_t V_INTR; /**< Vertical Interrupt. */ + io32_t CURR_LINE; /**< Current Line. */ + io32_t TIMING; /**< Timings. */ + io32_t V_SYNC; /**< Vertical Sync. */ + io32_t H_SYNC; /**< Horizontal Sync. */ + io32_t H_SYNC_LEAP; /**< Horizontal Sync Leap. */ + io32_t H_LIMITS; /**< Horizontal Limits. */ + io32_t V_LIMITS; /**< Vertical Limits. */ + io32_t COLOR_BURST; /**< Color Burst. */ + io32_t H_SCALE; /**< Horizontal Scale. */ + io32_t V_SCALE; /**< Vertical Scale. */ } vi_regs_t; #define VI_BASE (0x04400000UL) @@ -211,20 +205,18 @@ typedef struct { #define VI_CURR_LINE_FIELD (1 << 0) -/** @brief Audio Interface Registers Structure. */ +/** + * @brief Audio Interface Registers Structure. + * + * This structure represents the registers for the Audio Interface (AI). + */ typedef struct { - /** @brief The Memory Address. */ - io32_t MADDR; - /** @brief The Length of bytes. */ - io32_t LEN; - /** @brief The Control Register. */ - io32_t CR; - /** @brief The Status Register. */ - io32_t SR; - /** @brief The DAC rate. */ - io32_t DACRATE; - /** @brief The bit rate. */ - io32_t BITRATE; + io32_t MADDR; /**< Memory Address. */ + io32_t LEN; /**< Length of bytes. */ + io32_t CR; /**< Control Register. */ + io32_t SR; /**< Status Register. */ + io32_t DACRATE; /**< DAC rate. */ + io32_t BITRATE; /**< Bit rate. */ } ai_regs_t; #define AI_BASE (0x04500000UL) @@ -234,29 +226,23 @@ typedef struct { #define AI_SR_FIFO_FULL (1 << 31) #define AI_CR_DMA_ON (1 << 0) -/** @brief Peripheral Interface Register Structure. */ +/** + * @brief Peripheral Interface Register Structure. + * + * This structure represents the registers for the Peripheral Interface (PI). + */ typedef struct { - /** @brief The Memory Address. */ - io32_t MADDR; - /** @brief The Cart Address. */ - io32_t PADDR; - /** @brief The Read Length. */ - io32_t RDMA; - /** @brief The Write Length. */ - io32_t WDMA; - /** @brief The Status Register. */ - io32_t SR; - /** @brief The Domain 2 Registers. */ + io32_t MADDR; /**< Memory Address. */ + io32_t PADDR; /**< Cart Address. */ + io32_t RDMA; /**< Read Length. */ + io32_t WDMA; /**< Write Length. */ + io32_t SR; /**< Status Register. */ struct { - /** @brief The Latch Value. */ - io32_t LAT; - /** @brief The Pulse Width Value. */ - io32_t PWD; - /** @brief The Page Size Value. */ - io32_t PGS; - /** @brief The Release Value. */ - io32_t RLS; - } DOM[2]; + io32_t LAT; /**< Latch Value. */ + io32_t PWD; /**< Pulse Width Value. */ + io32_t PGS; /**< Page Size Value. */ + io32_t RLS; /**< Release Value. */ + } DOM[2]; /**< Domain 2 Registers. */ } pi_regs_t; #define PI_BASE (0x04600000UL) @@ -274,12 +260,24 @@ typedef struct { #define ROM_CART_BASE (0x10000000UL) #define ROM_CART ((io32_t *) ROM_CART_BASE) +/** + * @brief Read a value from a CPU IO address. + * + * @param address The address to read from. + * @return uint32_t The value read from the address. + */ static inline uint32_t cpu_io_read (io32_t *address) { io32_t *uncached = UNCACHED(address); uint32_t value = *uncached; return value; } +/** + * @brief Write a value to a CPU IO address. + * + * @param address The address to write to. + * @param value The value to write. + */ static inline void cpu_io_write (io32_t *address, uint32_t value) { io32_t *uncached = UNCACHED(address); *uncached = value; diff --git a/src/menu/cart_load.c b/src/menu/cart_load.c index fa72f09c..0158b61d 100644 --- a/src/menu/cart_load.c +++ b/src/menu/cart_load.c @@ -1,7 +1,11 @@ +/** + * @file cart_load.c + * @brief Cart loading functions + * @ingroup menu + */ + #include - #include - #include "cart_load.h" #include "path.h" #include "utils/fs.h" @@ -17,13 +21,23 @@ #define EMU_LOCATION "/menu/emulators" #endif - +/** + * @brief Check if the 64DD is connected. + * + * @return true if the 64DD is connected, false otherwise. + */ static bool is_64dd_connected (void) { bool is_64dd_io_present = ((io_read(0x05000540) & 0x0000FFFF) == 0x0000); bool is_64dd_ipl_present = (io_read(0x06001010) == 0x2129FFF8); return (is_64dd_io_present || is_64dd_ipl_present); } +/** + * @brief Create the saves subdirectory. + * + * @param path Pointer to the path structure. + * @return true if an error occurred, false otherwise. + */ static bool create_saves_subdirectory (path_t *path) { path_t *save_folder_path = path_clone(path); path_pop(save_folder_path); @@ -33,6 +47,12 @@ static bool create_saves_subdirectory (path_t *path) { return error; } +/** + * @brief Convert the ROM save type to the flashcart save type. + * + * @param save_type The ROM save type. + * @return flashcart_save_type_t The flashcart save type. + */ static flashcart_save_type_t convert_save_type (rom_save_type_t save_type) { switch (save_type) { case SAVE_TYPE_EEPROM_4KBIT: return FLASHCART_SAVE_TYPE_EEPROM_4KBIT; @@ -46,19 +66,24 @@ static flashcart_save_type_t convert_save_type (rom_save_type_t save_type) { } } - +/** + * @brief Convert the cart load error code to a human-readable message. + * + * @param err The cart load error code. + * @return char* The error message. + */ char *cart_load_convert_error_message (cart_load_err_t err) { switch (err) { case CART_LOAD_OK: return "Cart load OK"; - case CART_LOAD_ERR_ROM_LOAD_FAIL: return "Error occured during ROM loading"; - case CART_LOAD_ERR_SAVE_LOAD_FAIL: return "Error occured during save loading"; + case CART_LOAD_ERR_ROM_LOAD_FAIL: return "Error occurred during ROM loading"; + case CART_LOAD_ERR_SAVE_LOAD_FAIL: return "Error occurred during save loading"; case CART_LOAD_ERR_64DD_PRESENT: return "64DD accessory is connected to the N64"; case CART_LOAD_ERR_64DD_IPL_NOT_FOUND: return "Required 64DD IPL file was not found"; - case CART_LOAD_ERR_64DD_IPL_LOAD_FAIL: return "Error occured during 64DD IPL loading"; - case CART_LOAD_ERR_64DD_DISK_LOAD_FAIL: return "Error occured during 64DD disk loading"; + case CART_LOAD_ERR_64DD_IPL_LOAD_FAIL: return "Error occurred during 64DD IPL loading"; + case CART_LOAD_ERR_64DD_DISK_LOAD_FAIL: return "Error occurred during 64DD disk loading"; case CART_LOAD_ERR_EMU_NOT_FOUND: return "Required emulator file was not found"; - case CART_LOAD_ERR_EMU_LOAD_FAIL: return "Error occured during emulator ROM loading"; - case CART_LOAD_ERR_EMU_ROM_LOAD_FAIL: return "Error occured during emulated ROM loading"; + case CART_LOAD_ERR_EMU_LOAD_FAIL: return "Error occurred during emulator ROM loading"; + case CART_LOAD_ERR_EMU_ROM_LOAD_FAIL: return "Error occurred during emulated ROM loading"; case CART_LOAD_ERR_CREATE_SAVES_SUBDIR_FAIL: return "Couldn't create saves subdirectory"; case CART_LOAD_ERR_EXP_PAK_NOT_FOUND: return "Mandatory Expansion Pak accessory was not found"; case CART_LOAD_ERR_FUNCTION_NOT_SUPPORTED: return "Your flashcart doesn't support required functionality"; @@ -66,6 +91,13 @@ char *cart_load_convert_error_message (cart_load_err_t err) { } } +/** + * @brief Load an N64 ROM and its save file. + * + * @param menu Pointer to the menu structure. + * @param progress Progress callback function. + * @return cart_load_err_t Error code. + */ cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, flashcart_progress_callback_t progress) { path_t *path = path_clone(menu->load.rom_path); @@ -98,6 +130,13 @@ cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, flashcart_progress_cal return CART_LOAD_OK; } +/** + * @brief Load the 64DD IPL and disk. + * + * @param menu Pointer to the menu structure. + * @param progress Progress callback function. + * @return cart_load_err_t Error code. + */ cart_load_err_t cart_load_64dd_ipl_and_disk (menu_t *menu, flashcart_progress_callback_t progress) { if (!flashcart_has_feature(FLASHCART_FEATURE_64DD)) { return CART_LOAD_ERR_FUNCTION_NOT_SUPPORTED; @@ -152,6 +191,14 @@ cart_load_err_t cart_load_64dd_ipl_and_disk (menu_t *menu, flashcart_progress_ca return CART_LOAD_OK; } +/** + * @brief Load an emulator and its ROM. + * + * @param menu Pointer to the menu structure. + * @param emu_type The type of emulator to load. + * @param progress Progress callback function. + * @return cart_load_err_t Error code. + */ cart_load_err_t cart_load_emulator (menu_t *menu, cart_load_emu_type_t emu_type, flashcart_progress_callback_t progress) { path_t *path = path_init(menu->storage_prefix, EMU_LOCATION); diff --git a/src/menu/disk_info.c b/src/menu/disk_info.c index 5c2c7388..2affc184 100644 --- a/src/menu/disk_info.c +++ b/src/menu/disk_info.c @@ -1,3 +1,9 @@ +/** + * @file disk_info.c + * @brief Disk Information component implementation + * @ingroup menu + */ + #include #include #include @@ -6,7 +12,6 @@ #include "disk_info.h" #include "utils/fs.h" - #define SECTORS_PER_BLOCK (85) #define DISK_ZONES (16) #define DISK_BAD_TRACKS_PER_ZONE (12) @@ -27,7 +32,6 @@ #define GET_U32(b) (((b)[0] << 24) | ((b)[1] << 16) | ((b)[2] << 8) | (b)[3]) - static const int tracks_per_zone[DISK_ZONES] = { 158, 158, 149, 149, 149, 149, 149, 114, 158, 158, 149, 149, 149, 149, 149, 114 }; @@ -38,7 +42,14 @@ static const int disk_id_lbas[DISK_ID_LBA_COUNT] = { 15, 14 }; - +/** + * @brief Load a system area LBA from the disk. + * + * @param f File pointer to the disk image. + * @param lba Logical block address to load. + * @param buffer Buffer to store the loaded data. + * @return true if an error occurred, false otherwise. + */ static bool load_system_area_lba (FILE *f, int lba, uint8_t *buffer) { if (lba >= SYSTEM_AREA_LBA_COUNT) { return true; @@ -52,6 +63,13 @@ static bool load_system_area_lba (FILE *f, int lba, uint8_t *buffer) { return false; } +/** + * @brief Verify the integrity of a system area LBA. + * + * @param buffer Buffer containing the LBA data. + * @param sector_length Length of each sector in the LBA. + * @return true if the LBA is valid, false otherwise. + */ static bool verify_system_area_lba (uint8_t *buffer, int sector_length) { for (int sector = 1; sector < SECTORS_PER_BLOCK; sector++) { for (int i = 0; i < sector_length; i++) { @@ -63,6 +81,12 @@ static bool verify_system_area_lba (uint8_t *buffer, int sector_length) { return true; } +/** + * @brief Verify the integrity of a system data LBA. + * + * @param buffer Buffer containing the LBA data. + * @return true if the LBA is valid, false otherwise. + */ static bool verify_system_data_lba (uint8_t *buffer) { return ( (buffer[4] == 0x10) && @@ -72,6 +96,13 @@ static bool verify_system_data_lba (uint8_t *buffer) { ); } +/** + * @brief Set the defect tracks for the disk. + * + * @param buffer Buffer containing the defect track data. + * @param disk_info Pointer to the disk information structure. + * @return true if the defect tracks were set successfully, false otherwise. + */ static bool set_defect_tracks (uint8_t *buffer, disk_info_t *disk_info) { for (int head_zone = 0; head_zone < DISK_ZONES; head_zone++) { uint8_t start = ((head_zone == 0) ? 0 : buffer[7 + head_zone]); @@ -90,6 +121,11 @@ static bool set_defect_tracks (uint8_t *buffer, disk_info_t *disk_info) { return true; } +/** + * @brief Update the bad system area LBAs for the disk. + * + * @param disk_info Pointer to the disk information structure. + */ static void update_bad_system_area_lbas (disk_info_t *disk_info) { if (disk_info->region == DISK_REGION_DEVELOPMENT) { disk_info->bad_system_area_lbas[0] = true; @@ -109,6 +145,13 @@ static void update_bad_system_area_lbas (disk_info_t *disk_info) { } } +/** + * @brief Load and verify the system data LBA from the disk. + * + * @param f File pointer to the disk image. + * @param disk_info Pointer to the disk information structure. + * @return disk_err_t Error code. + */ static disk_err_t load_and_verify_system_data_lba (FILE *f, disk_info_t *disk_info) { uint8_t buffer[SYSTEM_AREA_LBA_LENGTH]; int sector_length; @@ -151,6 +194,13 @@ static disk_err_t load_and_verify_system_data_lba (FILE *f, disk_info_t *disk_in return valid_system_data_lba_found ? DISK_OK : DISK_ERR_INVALID; } +/** + * @brief Load and verify the disk ID LBA from the disk. + * + * @param f File pointer to the disk image. + * @param disk_info Pointer to the disk information structure. + * @return disk_err_t Error code. + */ static disk_err_t load_and_verify_disk_id_lba (FILE *f, disk_info_t *disk_info) { uint8_t buffer[SYSTEM_AREA_LBA_LENGTH]; @@ -175,7 +225,13 @@ static disk_err_t load_and_verify_disk_id_lba (FILE *f, disk_info_t *disk_info) return valid_disk_id_lba_found ? DISK_OK : DISK_ERR_INVALID; } - +/** + * @brief Load the disk information from the specified path. + * + * @param path Pointer to the path structure. + * @param disk_info Pointer to the disk information structure. + * @return disk_err_t Error code. + */ disk_err_t disk_info_load (path_t *path, disk_info_t *disk_info) { FILE *f; disk_err_t err; diff --git a/src/menu/path.c b/src/menu/path.c index 580aec06..086b10e0 100644 --- a/src/menu/path.c +++ b/src/menu/path.c @@ -1,14 +1,24 @@ +/** + * @file path.c + * @brief Path manipulation functions + * @ingroup menu + */ + #include #include #include #include "path.h" - #define PATH_CAPACITY_INITIAL 255 #define PATH_CAPACITY_ALIGNMENT 32 - +/** + * @brief Resize the path buffer to accommodate the specified minimum length. + * + * @param path Pointer to the path structure. + * @param min_length Minimum length to accommodate. + */ static void path_resize (path_t *path, size_t min_length) { path->capacity = min_length > PATH_CAPACITY_INITIAL ? min_length : PATH_CAPACITY_INITIAL; size_t alignment = path->capacity % PATH_CAPACITY_ALIGNMENT; @@ -19,6 +29,12 @@ static void path_resize (path_t *path, size_t min_length) { assert(path->buffer != NULL); } +/** + * @brief Create a new path structure. + * + * @param string Initial path string. + * @return path_t* Pointer to the created path structure. + */ path_t *path_create (const char *string) { if (string == NULL) { string = ""; @@ -32,6 +48,12 @@ path_t *path_create (const char *string) { return path; } +/** + * @brief Append a string to the path. + * + * @param path Pointer to the path structure. + * @param string String to append. + */ static void path_append (path_t *path, char *string) { size_t buffer_length = strlen(path->buffer); size_t string_length = strlen(string); @@ -42,7 +64,13 @@ static void path_append (path_t *path, char *string) { strcat(path->buffer, string); } - +/** + * @brief Initialize a new path structure with a prefix and an initial string. + * + * @param prefix Path prefix. + * @param string Initial path string. + * @return path_t* Pointer to the initialized path structure. + */ path_t *path_init (const char *prefix, char *string) { path_t *path = path_create(prefix); size_t prefix_length = strlen(prefix); @@ -56,6 +84,11 @@ path_t *path_init (const char *prefix, char *string) { return path; } +/** + * @brief Free the memory allocated for the path structure. + * + * @param path Pointer to the path structure. + */ void path_free (path_t *path) { if (path != NULL) { free(path->buffer); @@ -63,31 +96,67 @@ void path_free (path_t *path) { } } +/** + * @brief Clone the path structure. + * + * @param path Pointer to the path structure to clone. + * @return path_t* Pointer to the cloned path structure. + */ path_t *path_clone (path_t *path) { path_t *cloned = path_create(path->buffer); cloned->root = cloned->buffer + (path->root - path->buffer); return cloned; } +/** + * @brief Clone the path structure and push a string to the cloned path. + * + * @param path Pointer to the path structure to clone. + * @param string String to push to the cloned path. + * @return path_t* Pointer to the cloned and modified path structure. + */ path_t *path_clone_push (path_t *path, char *string) { path_t *cloned = path_clone(path); path_push(cloned, string); return cloned; } +/** + * @brief Get the current path string. + * + * @param path Pointer to the path structure. + * @return char* Pointer to the current path string. + */ char *path_get (path_t *path) { return path->buffer; } +/** + * @brief Get the last component of the path. + * + * @param path Pointer to the path structure. + * @return char* Pointer to the last component of the path. + */ char *path_last_get (path_t *path) { char *last_slash = strrchr(path->root, '/'); return (last_slash == NULL) ? path->root : (last_slash + 1); } +/** + * @brief Check if the path is the root path. + * + * @param path Pointer to the path structure. + * @return true if the path is the root path, false otherwise. + */ bool path_is_root (path_t *path) { return (strcmp(path->root, "/") == 0); } +/** + * @brief Pop the last component from the path. + * + * @param path Pointer to the path structure. + */ void path_pop (path_t *path) { if (path_is_root(path)) { return; @@ -100,6 +169,12 @@ void path_pop (path_t *path) { } } +/** + * @brief Push a string to the path. + * + * @param path Pointer to the path structure. + * @param string String to push to the path. + */ void path_push (path_t *path, char *string) { if (path->buffer[strlen(path->buffer) - 1] != '/') { path_append(path, "/"); @@ -110,6 +185,12 @@ void path_push (path_t *path, char *string) { path_append(path, string); } +/** + * @brief Push a subdirectory to the path. + * + * @param path Pointer to the path structure. + * @param string Subdirectory string to push to the path. + */ void path_push_subdir (path_t *path, char *string) { char *file = path_last_get(path); char *tmp = alloca(strlen(file) + 1); @@ -119,6 +200,12 @@ void path_push_subdir (path_t *path, char *string) { path_push(path, tmp); } +/** + * @brief Get the file extension from the path. + * + * @param path Pointer to the path structure. + * @return char* Pointer to the file extension. + */ char *path_ext_get (path_t *path) { char *buffer = path_last_get(path); char *last_dot = strrchr(buffer, '.'); @@ -128,6 +215,11 @@ char *path_ext_get (path_t *path) { return NULL; } +/** + * @brief Remove the file extension from the path. + * + * @param path Pointer to the path structure. + */ void path_ext_remove (path_t *path) { char *buffer = path_last_get(path); char *last_dot = strrchr(buffer, '.'); @@ -136,12 +228,24 @@ void path_ext_remove (path_t *path) { } } +/** + * @brief Replace the file extension in the path. + * + * @param path Pointer to the path structure. + * @param ext New file extension. + */ void path_ext_replace (path_t *path, char *ext) { path_ext_remove(path); path_append(path, "."); path_append(path, ext); } +/** + * @brief Check if the path has a value. + * + * @param path Pointer to the path structure. + * @return true if the path has a value, false otherwise. + */ bool path_has_value(path_t *path) { if(path != NULL) { if(strlen(path->buffer) > 0) { @@ -151,6 +255,13 @@ bool path_has_value(path_t *path) { return false; } +/** + * @brief Check if two paths match. + * + * @param left Pointer to the first path structure. + * @param right Pointer to the second path structure. + * @return true if the paths match, false otherwise. + */ bool path_are_match(path_t *left, path_t *right) { if(!path_has_value(left) && !path_has_value(right)) { return true; diff --git a/src/menu/rom_info.c b/src/menu/rom_info.c index fc2d5bfd..3ab16284 100644 --- a/src/menu/rom_info.c +++ b/src/menu/rom_info.c @@ -1,3 +1,10 @@ +/** + * @file rom_info.c + * @brief ROM Information component implementation + * @ingroup menu + */ + + #include #include #include @@ -47,92 +54,46 @@ typedef struct __attribute__((packed)) { /** @brief ROM Information Match Type Enumeration. */ typedef enum { - // Check only game code - MATCH_TYPE_ID, - - // Check game code and region - MATCH_TYPE_ID_REGION, - - // Check game code, region and version - MATCH_TYPE_ID_REGION_VERSION, - - // Check game check code - MATCH_TYPE_CHECK_CODE, - - // Check for homebrew header ID - MATCH_TYPE_HOMEBREW_HEADER, - - // List end marker - MATCH_TYPE_END + MATCH_TYPE_ID, /**< Check only game code */ + MATCH_TYPE_ID_REGION, /**< Check game code and region */ + MATCH_TYPE_ID_REGION_VERSION, /**< Check game code, region and version */ + MATCH_TYPE_CHECK_CODE, /**< Check game check code */ + MATCH_TYPE_HOMEBREW_HEADER, /**< Check for homebrew header ID */ + MATCH_TYPE_END /**< List end marker */ } match_type_t; +/** @brief ROM Features Enumeration. */ typedef enum { - // No features supported - FEAT_NONE = 0, - - // Controller Pak - FEAT_CPAK = (1 << 0), - - // Rumble Pak - FEAT_RPAK = (1 << 1), - - // Transfer Pak - FEAT_TPAK = (1 << 2), - - // Voice Recognition Unit - FEAT_VRU = (1 << 3), - - // Real Time Clock - FEAT_RTC = (1 << 4), - - // Expansion Pak (for games that will not work without it inserted into the console) - FEAT_EXP_PAK_REQUIRED = (1 << 5), - - // Expansion Pak (for games with game play enhancements) - FEAT_EXP_PAK_RECOMMENDED = (1 << 6), - - // Expansion Pak (for games with visual (or other) enhancements) - FEAT_EXP_PAK_ENHANCED = (1 << 7), - - // No Expansion Pak (for games "broken" with it inserted into the console) - FEAT_EXP_PAK_BROKEN = (1 << 8), - - // 64DD disk to ROM conversion - FEAT_64DD_CONVERSION = (1 << 9), - - // Combo ROM + Disk games - FEAT_64DD_ENHANCED = (1 << 10), + FEAT_NONE = 0, /**< No features supported */ + FEAT_CPAK = (1 << 0), /**< Controller Pak */ + FEAT_RPAK = (1 << 1), /**< Rumble Pak */ + FEAT_TPAK = (1 << 2), /**< Transfer Pak */ + FEAT_VRU = (1 << 3), /**< Voice Recognition Unit */ + FEAT_RTC = (1 << 4), /**< Real Time Clock */ + FEAT_EXP_PAK_REQUIRED = (1 << 5), /**< Expansion Pak required */ + FEAT_EXP_PAK_RECOMMENDED = (1 << 6), /**< Expansion Pak recommended */ + FEAT_EXP_PAK_ENHANCED = (1 << 7), /**< Expansion Pak enhanced */ + FEAT_EXP_PAK_BROKEN = (1 << 8), /**< Expansion Pak broken */ + FEAT_64DD_CONVERSION = (1 << 9), /**< 64DD disk to ROM conversion */ + FEAT_64DD_ENHANCED = (1 << 10) /**< Combo ROM + Disk games */ } feat_t; +/** @brief ROM Match Structure. */ typedef struct { - // Which fields to check - match_type_t type; - - // Fields to check for matching + match_type_t type; /**< Match type */ union { struct { - // Game code (with media type and optional region) or unique ID - const char *id; - - // Game version - uint8_t version; + const char *id; /**< Game code or unique ID */ + uint8_t version; /**< Game version */ }; - - // Game check code - uint64_t check_code; + uint64_t check_code; /**< Game check code */ } fields; - - // Matched game metadata struct { - // Save type (only cartridge save types) - rom_save_type_t save; - - // Supported features - feat_t feat; + rom_save_type_t save; /**< Save type */ + feat_t feat; /**< Supported features */ } data; } match_t; - #define MATCH_ID(i, s, f) { .type = MATCH_TYPE_ID, .fields = { .id = i }, .data = { .save = s, .feat = f } } #define MATCH_ID_REGION(i, s, f) { .type = MATCH_TYPE_ID_REGION, .fields = { .id = i }, .data = { .save = s, .feat = f } } #define MATCH_ID_REGION_VERSION(i, v, s, f) { .type = MATCH_TYPE_ID_REGION_VERSION, .fields = { .id = i, .version = v }, .data = { .save = s, .feat = f } }