romusage: upgrade from 1.2.8 to 1.3.0

# Version 1.3.0
- `-b:HEXVAL:[...]` Set hex bytes treated as Empty in ROM files (.gb/etc) (default `FF`(255), ex use 255 AND 0: `-b:FF:00`
- Improve error messaging
- Allow filename at any location in option arguments

# Version 1.2.9
- `-nMEM` Hide memory regions with case sensitive substring (ex hide all RAM: `-nMEM:RAM`)
This commit is contained in:
bbbbbr
2024-10-11 23:50:59 -07:00
parent 1c1c8f9b47
commit fc8cd5b9ca
14 changed files with 301 additions and 95 deletions

View File

@@ -37,25 +37,25 @@
// ===== Game Boy =====
// ROM
const bank_item ROM_0 = {"ROM_0", 0x0000, 0x3FFF, BANKED_NO, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_NO};
const bank_item ROM_X_banked = {"ROM_", 0x4000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_1, BANK_MERGED_NO};
const bank_item ROM_0 = {"ROM_0", 0x0000, 0x3FFF, BANKED_NO, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_NO, HIDDEN_NO};
const bank_item ROM_X_banked = {"ROM_", 0x4000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_1, BANK_MERGED_NO, HIDDEN_NO};
// Merged version
const bank_item ROM_nonbanked = {"ROM", 0x0000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_YES};
const bank_item ROM_nonbanked = {"ROM", 0x0000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_YES, HIDDEN_NO};
// VRAM
const bank_item VRAM = {"VRAM_", 0x8000, 0x9FFF, BANKED_YES, 0x9FFF, 0,0,0, BANK_MEM_TYPE_VRAM, BANK_STARTNUM_0, BANK_MERGED_NO};
const bank_item VRAM = {"VRAM_", 0x8000, 0x9FFF, BANKED_YES, 0x9FFF, 0,0,0, BANK_MEM_TYPE_VRAM, BANK_STARTNUM_0, BANK_MERGED_NO, HIDDEN_NO};
// SRAM
const bank_item SRAM = {"SRAM_", 0xA000, 0xBFFF, BANKED_YES, 0xBFFF, 0,0,0, BANK_MEM_TYPE_SRAM, BANK_STARTNUM_0, BANK_MERGED_NO};
const bank_item SRAM = {"SRAM_", 0xA000, 0xBFFF, BANKED_YES, 0xBFFF, 0,0,0, BANK_MEM_TYPE_SRAM, BANK_STARTNUM_0, BANK_MERGED_NO, HIDDEN_NO};
// WRAM
const bank_item WRAM_0 = {"WRAM_LO", 0xC000, 0xCFFF, BANKED_NO, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_0, BANK_MERGED_NO};
const bank_item WRAM_X_banked = {"WRAM_HI_",0xD000, 0xDFFF, BANKED_YES, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_1, BANK_MERGED_NO};
const bank_item WRAM_0 = {"WRAM_LO", 0xC000, 0xCFFF, BANKED_NO, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_0, BANK_MERGED_NO, HIDDEN_NO};
const bank_item WRAM_X_banked = {"WRAM_HI_",0xD000, 0xDFFF, BANKED_YES, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_1, BANK_MERGED_NO, HIDDEN_NO};
// Merged version
const bank_item WRAM_nonbanked = {"WRAM", 0xC000, 0xDFFF, BANKED_YES, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_0, BANK_MERGED_YES};
const bank_item WRAM_nonbanked = {"WRAM", 0xC000, 0xDFFF, BANKED_YES, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_0, BANK_MERGED_YES, HIDDEN_NO};
// HRAM
const bank_item HRAM = {"HRAM", 0xFF80, 0xFFFE, BANKED_NO, 0xFFFE, 0,0,0, BANK_MEM_TYPE_HRAM, BANK_STARTNUM_0, BANK_MERGED_NO};
const bank_item HRAM = {"HRAM", 0xFF80, 0xFFFE, BANKED_NO, 0xFFFE, 0,0,0, BANK_MEM_TYPE_HRAM, BANK_STARTNUM_0, BANK_MERGED_NO, HIDDEN_NO};
// ===== Game Gear =====
@@ -66,15 +66,15 @@ const bank_item HRAM = {"HRAM", 0xFF80, 0xFFFE, BANKED_NO, 0xFFFE,
// _LIT_<N> is at base address 0x8000 (assets)
// _DATA_N is also at base address 0x8000 (RAM)
const bank_item smsgg_ROM_0 = {"ROM_0", 0x0000, 0x3FFF, BANKED_NO, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_NO};
const bank_item smsgg_ROM_X_banked = {"ROM_", 0x4000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_1, BANK_MERGED_NO};
const bank_item smsgg_ROM_0 = {"ROM_0", 0x0000, 0x3FFF, BANKED_NO, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_NO, HIDDEN_NO};
const bank_item smsgg_ROM_X_banked = {"ROM_", 0x4000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_1, BANK_MERGED_NO, HIDDEN_NO};
// Merged version
const bank_item smsgg_ROM_nonbanked = {"ROM", 0x0000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_YES};
const bank_item smsgg_ROM_nonbanked = {"ROM", 0x0000, 0x7FFF, BANKED_YES, 0x7FFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_0, BANK_MERGED_YES, HIDDEN_NO};
const bank_item smsgg_LIT_X_banked = {"LIT_", 0x8000, 0xBFFF, BANKED_YES, 0xBFFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_1, BANK_MERGED_NO};
const bank_item smsgg_LIT_X_banked = {"LIT_", 0x8000, 0xBFFF, BANKED_YES, 0xBFFF, 0,0,0, BANK_MEM_TYPE_ROM, BANK_STARTNUM_1, BANK_MERGED_NO, HIDDEN_NO};
// Data can also be in the 0x8000 region.. requires some special handling in banks_check()
const bank_item smsgg_DATA_X_banked = {"DATA_", 0x8000, 0xBFFF, BANKED_YES, 0xBFFF, 0,0,0, BANK_MEM_TYPE_SRAM, BANK_STARTNUM_1, BANK_MERGED_NO};
const bank_item smsgg_RAM_nonbanked = {"RAM", 0xC000, 0xDFFF, BANKED_YES, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_0, BANK_MERGED_YES};
const bank_item smsgg_DATA_X_banked = {"DATA_", 0x8000, 0xBFFF, BANKED_YES, 0xBFFF, 0,0,0, BANK_MEM_TYPE_SRAM, BANK_STARTNUM_1, BANK_MERGED_NO, HIDDEN_NO};
const bank_item smsgg_RAM_nonbanked = {"RAM", 0xC000, 0xDFFF, BANKED_YES, 0xDFFF, 0,0,0, BANK_MEM_TYPE_WRAM, BANK_STARTNUM_0, BANK_MERGED_YES, HIDDEN_NO};
static int bank_template_add(int idx, bank_item * p_bank_templates, const bank_item * p_bank) {

View File

@@ -657,6 +657,16 @@ static void bank_fill_area_gaps_with_unknown(void) {
}
// Check if a bank name matches any substrings on the hide list
static bool bank_name_check_hidden(char * str_bank_name) {
for (int c = 0; c < banks_hide_count; c++) {
if (strstr(str_bank_name, banks_hide_list[c])) return true;
}
return false;
}
// Print banks to output
void banklist_finalize_and_show(void) {
@@ -672,6 +682,7 @@ void banklist_finalize_and_show(void) {
for (c = 0; c < bank_list.count; c++) {
// Sort areas in bank and calculate usage
banks[c].size_used = bank_areas_calc_used(&banks[c], banks[c].start, banks[c].end);
banks[c].hidden = bank_name_check_hidden(banks[c].name);
if (get_option_area_sort() == OPT_AREA_SORT_SIZE_DESC)
qsort (banks[c].area_list.p_array, banks[c].area_list.count, sizeof(area_item), area_item_compare_size_desc);
@@ -725,7 +736,7 @@ void bank_areas_split_to_buckets(bank_item * p_bank, uint32_t range_start, uint3
bank_item bank_copy = *p_bank;
bank_copy.area_list.p_array = (void *)malloc(bank_copy.area_list.size * bank_copy.area_list.typesize);
if (!bank_copy.area_list.p_array) {
log_error("ERROR: Failed to reallocate memory for list!\n");
log_error("Error: Failed to reallocate memory for list!\n");
exit(EXIT_FAILURE);
}
// Copy main list of areas to copy of bank for modification

View File

@@ -39,6 +39,9 @@
#define BANK_MERGED_NO false
#define BANK_MERGED_YES true
#define HIDDEN_NO false
#define HIDDEN_YES true
#define MINIGRAPH_SIZE (2 * 14) // Number of characters wide (inside edge brackets)
#define LARGEGRAPH_BYTES_PER_CHAR 16
@@ -79,6 +82,7 @@ typedef struct bank_item {
int base_bank_num;
bool is_merged_bank;
// End of templating vars
bool hidden;
// TODO: track overflow bytes and report them in graph
list_type area_list;

View File

@@ -254,12 +254,15 @@ void banklist_printall(list_type * p_bank_list) {
// Print all banks
for (c = 0; c < p_bank_list->count; c++) {
bank_print_info(&banks[c]);
fprintf(stdout,"\n");
if (!banks[c].hidden) {
bank_print_info(&banks[c]);
fprintf(stdout,"\n");
if (get_option_area_sort() != OPT_AREA_SORT_HIDE) // This is a hack-workaround, TODO:fixme
if (banks_display_areas)
bank_print_area(&banks[c]);
if (get_option_area_sort() != OPT_AREA_SORT_HIDE) { // This is a hack-workaround, TODO:fixme
if (banks_display_areas)
bank_print_area(&banks[c]);
}
}
} // End: Print all banks loop
@@ -333,10 +336,12 @@ void banklist_printall_json(list_type * p_bank_list) {
// Print each bank as an array object item
for (c = 0; c < p_bank_list->count; c++) {
// Comma separator between array items
if (c > 0) fprintf(stdout," ,\n");
if (!banks[c].hidden) {
// Comma separator between array items
if (c > 0) fprintf(stdout," ,\n");
bank_print_info_json(&banks[c]);
bank_print_info_json(&banks[c]);
}
}
// JSON array footer

View File

@@ -10,6 +10,7 @@
#include <stdint.h>
#include "common.h"
#include "logging.h"
#include "list.h"
#include "banks.h"
#include "cdb_file.h"
@@ -288,7 +289,10 @@ int cdb_file_process_symbols(char * filename_in) {
cdb_symbollist_add_all_to_banks();
} // end: if valid file
else return (false);
else {
log_error("Error: Failed to open input file %s\n", filename_in);
return false;
}
return true;
}

View File

@@ -3,12 +3,14 @@
// bbbbbr 2020
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "common.h"
#include "logging.h"
#include "rom_file.h"
bool banks_display_areas = false;
bool banks_display_headers = false;
@@ -38,6 +40,8 @@ bool option_percentage_based_color = false;
uint32_t option_area_hide_size = OPT_AREA_HIDE_SIZE_DEFAULT;
bool exit_error = false;
int banks_hide_count = 0;
char banks_hide_list[BANKS_HIDE_SZ][DEFAULT_STR_LEN];
// Turn on/off display of areas within bank
@@ -151,7 +155,7 @@ void set_option_area_hide_size(uint32_t value) {
// -sP:DEFAULT:ROM:VRAM:SRAM:WRAM:HRAM
//
// Custom color scheme for output
bool option_set_displayed_bank_range(char * arg_str) {
bool set_option_displayed_bank_range(char * arg_str) {
#define MAX_SPLIT_WORDS 4
#define EXPECTED_COLS 3
@@ -223,6 +227,54 @@ bool get_option_display_asciistyle(void) {
}
// Add a substring for hiding banks
bool set_option_banks_hide_add(char * str_bank_hide_substring) {
if (banks_hide_count < BANKS_HIDE_SZ) {
snprintf(banks_hide_list[banks_hide_count], (DEFAULT_STR_LEN - 1), "%s", str_bank_hide_substring);
banks_hide_count++;
return true;
} else
log_error("Error: no bank hide string slots available\n");
return false;
}
// Set hex bytes treated as Empty in ROM files (.gb/etc) -b:HEXVAL:HEXVAL...
// -b:FF
// Value passed in has "-e" stripped off the front
bool set_option_binary_rom_empty_values(char * arg_str) {
#define MAX_ROMFILE_ENTRIES 256
#define MIN_EXPECTED_ENTRIES 1
char entries_found;
char * p_str;
char * p_words[MAX_ROMFILE_ENTRIES];
// Clear existing defaults
romfile_empty_value_table_clear();
// Split string into words separated by : chars
entries_found = 0;
p_str = strtok(arg_str,":");
while (p_str != NULL)
{
p_words[entries_found++] = p_str;
p_str = strtok(NULL, "-:");
if (entries_found >= MAX_ROMFILE_ENTRIES) break;
}
for (int c = 0; c < entries_found; c++)
romfile_empty_value_table_add_entry( (uint8_t)strtol(p_words[c], NULL, 16) );
if (entries_found >= MIN_EXPECTED_ENTRIES)
return true;
else
return false; // Signal failure
}
void set_exit_error(void) {

View File

@@ -38,6 +38,9 @@
#define OPT_PLAT_GAMEBOY 0u
#define OPT_PLAT_SMS_GG_GBDK 1u // GBDK specific layout of sms/gg
#define BANKS_HIDE_SZ 30 // How many hide substrings to support
#define BANKS_HIDE_MAX (BANKS_HIDE_SZ - 1)
extern bool banks_display_areas;
extern bool banks_display_headers;
@@ -64,6 +67,9 @@ extern unsigned int option_merged_banks;
extern uint32_t option_area_hide_size;
extern bool exit_error;
extern int banks_hide_count;
extern char banks_hide_list[BANKS_HIDE_SZ][DEFAULT_STR_LEN];
void set_option_all_areas_exclusive(bool value);
void set_option_quiet_mode(bool value);
@@ -81,9 +87,11 @@ void set_option_show_compact(bool value);
void set_option_show_json(bool value);
void set_option_summarized(bool value);
bool option_set_displayed_bank_range(char * arg_str);
bool set_option_displayed_bank_range(char * arg_str);
void set_option_merged_banks(unsigned int value);
bool set_option_banks_hide_add(char * str_bank_hide_substring);
bool set_option_binary_rom_empty_values(char * arg_str);
int get_option_input_source(void);
int get_option_area_sort(void);
@@ -99,4 +107,5 @@ uint32_t round_up_power_of_2(uint32_t val);
uint32_t min(uint32_t a, uint32_t b);
uint32_t max(uint32_t a, uint32_t b);
#endif // _COMMON_H

View File

@@ -229,7 +229,6 @@ void area_convert_and_add(area_item area) {
int ihx_file_process_areas(char * filename_in) {
int ret = true; // default to success
char cols;
char strline_in[MAX_STR_LEN] = "";
FILE * ihx_file = fopen(filename_in, "r");
@@ -301,9 +300,11 @@ int ihx_file_process_areas(char * filename_in) {
fclose(ihx_file);
} // end: if valid file
else
ret = false;
else {
log_error("Error: Failed to open input file %s\n", filename_in);
return false;
}
return ret;
return true;
}

View File

@@ -21,7 +21,7 @@ void list_init(list_type * p_list, size_t array_typesize) {
p_list->p_array = (void *)malloc(p_list->size * p_list->typesize);
if (!p_list->p_array) {
log_error("ERROR: Failed to allocate memory for list!\n");
log_error("Error: Failed to allocate memory for list!\n");
exit(EXIT_FAILURE);
}
}
@@ -54,7 +54,7 @@ void list_additem(list_type * p_list, void * p_newitem) {
p_list->p_array = (void *)realloc(p_list->p_array, p_list->size * p_list->typesize);
// If realloc failed, free original buffer before quitting
if (!p_list->p_array) {
log_error("ERROR: Failed to reallocate memory for list!\n");
log_error("Error: Failed to reallocate memory for list!\n");
if (tmp_list) {
free(tmp_list);
tmp_list = NULL;

View File

@@ -10,6 +10,7 @@
#include <stdint.h>
#include "common.h"
#include "logging.h"
#include "banks.h"
#include "map_file.h"
@@ -141,7 +142,10 @@ int map_file_process_areas(char * filename_in) {
fclose(map_file);
} // end: if valid file
else return (false);
else {
log_error("Error: Failed to open input file %s\n", filename_in);
return false;
}
return true;
}

View File

@@ -10,6 +10,7 @@
#include <stdint.h>
#include "common.h"
#include "logging.h"
#include "list.h"
#include "banks.h"
#include "noi_file.h"
@@ -172,7 +173,10 @@ int noi_file_process_areas(char * filename_in) {
noi_arealist_add_all_to_banks();
} // end: if valid file
else return (false);
else {
log_error("Error: Failed to open input file %s\n", filename_in);
return false;
}
return true;
}

View File

@@ -17,8 +17,15 @@
#define ADDR_UNSET 0xFFFFFFFF
#define EMPTY_CONSECUTIVE_THRESHOLD 16
#define EMPTY_VAL 0xFF
#define EMPTY_RUN_TOO_SHORT(length, threshold) ((length > 0) && (length < threshold))
#define EMPTY_VALUE_MAX_COUNT 256
#define EMPTY_DEFAULT_CONSECUTIVE_THRESHOLD 17
#define EMPTY_0x00_CONSECUTIVE_THRESHOLD 128 // Larger threshold for 0x00 empty values due to possible sparse arrays
bool empty_values[EMPTY_VALUE_MAX_COUNT];
uint32_t empty_consecutive_thresholds[EMPTY_VALUE_MAX_COUNT];
#define BANK_SIZE 0x4000
#define BANK_ADDR_MASK 0x00003FFF
#define BANK_NUM_MASK 0xFFFFC000
@@ -27,6 +34,36 @@
#define ROM_ADDR_TO_BANKED(addr) ((addr & BANK_ADDR_MASK) | ((addr & BANK_NUM_MASK) << BANK_NUM_UPSHIFT))
// Clear the empty values table to all values disabled
// should be called to remove defaults
void romfile_empty_value_table_clear(void) {
for (int c = 0; c < EMPTY_VALUE_MAX_COUNT; c++)
empty_values[c] = false;
}
// Set a byte value in the empty values table to true, range is 0-255 (byte)
void romfile_empty_value_table_add_entry(uint8_t value) {
empty_values[value] = true;
}
// Call this before processing option arguments
void romfile_init_defaults(void) {
// Default is: only value considered empty is 0xFF
romfile_empty_value_table_clear();
empty_values[0xFF] = true;
// "Empty" 0x00 byte values use a longer run length threshold than other values due to possible sparse arrays
for (int c = 0; c < EMPTY_VALUE_MAX_COUNT; c++) {
empty_consecutive_thresholds[c] = EMPTY_DEFAULT_CONSECUTIVE_THRESHOLD;
}
empty_consecutive_thresholds[0x00] = EMPTY_0x00_CONSECUTIVE_THRESHOLD;
}
// Read from a file into a buffer (will allocate needed memory)
// Returns NULL if reading file didn't succeed
uint8_t * file_read_into_buffer(char * filename, uint32_t *ret_size) {
@@ -50,25 +87,23 @@ uint8_t * file_read_into_buffer(char * filename, uint32_t *ret_size) {
}
// Read was successful, set return size
*ret_size = fsize;
} else log_error("ERROR: Failed to allocate memory to read file %s\n", filename);
} else log_error("Error: Failed to allocate memory to read file %s\n", filename);
} else log_error("ERROR: Failed to read size of file %s\n", filename);
} else log_error("Error: Failed to read size of file %s\n", filename);
fclose(file_in);
} else log_error("ERROR: Failed to open input file %s\n", filename);
} else log_error("Error: Failed to open input file %s\n", filename);
return filedata;
}
// Calculate a range, adjust it's bank num and add try adding to banks if valid
static void rom_add_range(area_item range, uint32_t cur_idx, uint32_t empty_run, bool romsize_32K_or_less) {
static void rom_add_range(area_item range, bool romsize_32K_or_less) {
// If active range ended, add to areas
if (range.start != ADDR_UNSET) {
// Range ended, add to areas
range.end = cur_idx - empty_run;
// Don't try to virtual translate address for binary ROM
// files 32K or smaller, most likely they're unbanked.
if (!romsize_32K_or_less) {
@@ -101,9 +136,11 @@ int rom_file_process(char * filename_in) {
uint8_t * p_buf = NULL;
uint32_t buf_idx = 0;
uint32_t buf_length = 0;
uint32_t empty_run = 0;
uint32_t empty_run_length;
uint32_t empty_run_length_threshold;
uint8_t empty_run_value;
uint32_t bank_bytes = 0;
area_item rom_range;
area_item used_rom_range;
bool romsize_32K_or_less;
set_option_input_source(OPT_INPUT_SRC_ROM);
@@ -112,50 +149,91 @@ int rom_file_process(char * filename_in) {
p_buf = file_read_into_buffer(filename_in, &buf_length);
romsize_32K_or_less = (buf_length <= 0x8000);
rom_range.name[0] = '\0'; // Rom file ranges don't have names, set string to empty
rom_range.start = ADDR_UNSET;
used_rom_range.name[0] = '\0'; // Rom file ranges don't have names, set string to empty
if (p_buf) {
// Loop through all ROM bytes
while (buf_idx < buf_length) {
// This is looking for "Used" ranges broken up by non-"Empty" ranges
//
// Process each bank (0x4000 bytes in a row) separately
// and close out any ranges that might span between them
if (buf_length > BANK_SIZE) bank_bytes = BANK_SIZE;
else bank_bytes = buf_length;
// Reset range state values for each bank pass
used_rom_range.start = ADDR_UNSET;
empty_run_length = 0;
while (bank_bytes) {
// Split buffer up into runs of non-zero bytes
// with a threshold of N zero bytes in a row to split them
if (p_buf[buf_idx] != EMPTY_VAL) {
if (rom_range.start == ADDR_UNSET)
rom_range.start = buf_idx;
empty_run = 0;
} else {
empty_run++;
// Split buffer up into potential runs of "Used" bytes with a
// threshold of N non-empty same value bytes in a row to split them up
// Handle current run/range if present and over threshold.
// Otherwise ignore the "empty" vals since it may be data of that value
if ((empty_run > EMPTY_CONSECUTIVE_THRESHOLD) &&
(rom_range.start != ADDR_UNSET)) {
uint8_t cur_byte_value = p_buf[buf_idx];
// Add range then flag as cleared and prep for a new range
rom_add_range(rom_range, buf_idx, empty_run, romsize_32K_or_less);
rom_range.start = ADDR_UNSET;
// Continue an existing run if the value matches the current runs value (0x00 or 0xFF)
if ((empty_run_length > 0) && (cur_byte_value == empty_run_value)) {
empty_run_length++;
// If the current "Empty" range is over the threshold it means
// any existing "Used" data range needs to be closed out and submitted.
//
// Otherwise the "Empty" values may be part of data and can be ignored
if ((empty_run_length >= empty_run_length_threshold) &&
(used_rom_range.start != ADDR_UNSET)) {
// Add range and back-calculate last "Used" range address using start of "empty" address
used_rom_range.end = buf_idx - empty_run_length;
rom_add_range(used_rom_range, romsize_32K_or_less);
// Clear as ready for new range
used_rom_range.start = ADDR_UNSET;
}
}
else {
// Close out pending failed (too short) "Empty" run
if (EMPTY_RUN_TOO_SHORT(empty_run_length, empty_run_length_threshold)) {
// If no range started, then convert it to a "Used" range since the bytes aren't actually empty
if (used_rom_range.start == ADDR_UNSET) used_rom_range.start = buf_idx - empty_run_length;
}
// Start a potential "Empty" new run
if (empty_values[cur_byte_value] == true) {
empty_run_length = 1;
empty_run_value = cur_byte_value;
// "Empty" 0x00 byte values use a longer run length threshold due to possible sparse arrays
empty_run_length_threshold = empty_consecutive_thresholds[cur_byte_value];
}
// Not "Empty", so reset "Empty" length
else {
empty_run_length = 0;
// Start a potential "Used" (non-empty) data range if one isn't active.
if (used_rom_range.start == ADDR_UNSET) used_rom_range.start = buf_idx;
}
}
buf_idx++;
bank_bytes--;
} // end: while still _bank_ bytes to process
// Close out a remaining run if one exists (at last byte which is -1 of current)
// Flag as cleared and prep for a new range
rom_add_range(rom_range, buf_idx - 1, empty_run, romsize_32K_or_less);
rom_range.start = ADDR_UNSET;
// End of Bank Cleanup
// Potentially Empty bytes at the end of a bank that don't meet threshold... might be empty?
//
// // Convert "Empty" run to "Used" if it didn't cross the "Empty" threshold
// if (EMPTY_RUN_TOO_SHORT(empty_run_length, empty_run_length_threshold)) {
// if (used_rom_range.start == ADDR_UNSET) used_rom_range.start = buf_idx - empty_run_length;
// }
// Close pending "Used" run if needed (at last byte which is -1 of current)
if (used_rom_range.start != ADDR_UNSET) {
used_rom_range.end = (buf_idx - 1);
rom_add_range(used_rom_range, romsize_32K_or_less);
}
} // End main buffer loop
@@ -165,7 +243,10 @@ int rom_file_process(char * filename_in) {
}
} // end: if valid file
else return (false);
else {
log_error("Error: Failed to open input file %s\n", filename_in);
return false;
}
return true;
}

View File

@@ -3,3 +3,6 @@
// bbbbbr 2020
int rom_file_process(char * filename_in);
void romfile_empty_value_table_clear(void);
void romfile_empty_value_table_add_entry(uint8_t value);
void romfile_init_defaults(void);

View File

@@ -19,10 +19,15 @@
#include "cdb_file.h"
#include "rom_file.h"
#define VERSION "version 1.2.8"
#define VERSION "version 1.3.0"
enum {
HELP_FULL = 0,
HELP_BRIEF
};
void static display_cdb_warning(void);
void static display_help(void);
void static display_help(int mode);
int handle_args(int argc, char * argv[]);
static bool matches_extension(char *, char *);
static void init(void);
@@ -42,7 +47,7 @@ static void display_cdb_warning() {
" ************************ NOTICE ************************ \n");
}
static void display_help(void) {
static void display_help(int mode) {
fprintf(stdout,
"romusage input_file.[map|noi|ihx|cdb|.gb[c]|.pocket|.duck|.gg|.sms] [options]\n"
VERSION", by bbbbbr\n"
@@ -60,6 +65,7 @@ static void display_help(void) {
"\n"
"-m : Manually specify an Area -m:NAME:HEXADDR:HEXLENGTH\n"
"-e : Manually specify an Area that should not overlap -e:NAME:HEXADDR:HEXLENGTH\n"
"-b : Set hex bytes treated as Empty in ROM files (.gb/etc) -b:HEXVAL[...] (default FF)\n"
"-E : All areas are exclusive (except HEADERs), warn for any overlaps\n"
"-q : Quiet, no output except warnings and errors\n"
"-Q : Suppress output of warnings and errors\n"
@@ -73,11 +79,15 @@ static void display_help(void) {
"-smROM : Show Merged ROM_0 and ROM_1 output (i.e. bare 32K ROM)\n"
"-smWRAM : Show Merged WRAM_0 and WRAM_1 output (i.e DMG/MGB not CGB)\n"
" -sm* compatible with banked ROM_x or WRAM_x when used with -B\n"
"-sJ : Show JSON output. Some options not applicable. When used, -Q recommended\n"
"-nB : Hide warning banner (for .cdb output)\n"
"-nA : Hide areas (shown by default in .cdb output)\n"
"-z : Hide areas smaller than SIZE -z:DECSIZE\n"
"\n"
"-sJ : Show JSON output. Some options not applicable. When used, -Q recommended\n"
"-nB : Hide warning banner (for .cdb output)\n"
"-nA : Hide areas (shown by default in .cdb output)\n"
"-z : Hide areas smaller than SIZE -z:DECSIZE\n"
"-nMEM : Hide banks matching case sensitive substring (ex hide all RAM: -nMEM:RAM)\n"
"\n");
if (mode == HELP_FULL) {
fprintf(stdout,
"Use: Read a .map, .noi, .cdb or .ihx file to display area sizes\n"
"Example 1: \"romusage build/MyProject.map\"\n"
"Example 2: \"romusage build/MyProject.noi -a -e:STACK:DEFF:100 -e:SHADOW_OAM:C000:A0\"\n"
@@ -85,6 +95,7 @@ static void display_help(void) {
"Example 4: \"romusage build/MyProject.map -q -R\"\n"
"Example 5: \"romusage build/MyProject.noi -sR -sP:90:32:90:35:33:36\"\n"
"Example 6: \"romusage build/MyProject.map -sRp -g -B -F:255:15 -smROM -smWRAM\"\n"
"Example 7: \"romusage build/MyProject.gb -g -b:FF:00\"\n"
"\n"
"Notes:\n"
" * GBDK / RGBDS map file format detection is automatic.\n"
@@ -97,6 +108,7 @@ static void display_help(void) {
" so bank totals may be incorrect/missing.\n"
" * GB/GBC/ROM files are just guessing, no promises.\n"
);
}
}
@@ -114,19 +126,15 @@ int handle_args(int argc, char * argv[]) {
int i;
if( argc < 2 ) {
display_help();
display_help(HELP_FULL);
return false;
}
// Copy input filename (if not preceded with option dash)
if (argv[1][0] != '-')
snprintf(filename_in, sizeof(filename_in), "%s", argv[1]);
// Start at first optional argument, argc is zero based
for (i = 1; i <= (argc -1); i++ ) {
for (i = 0; i <= (argc -1); i++ ) {
if (strstr(argv[i], "-h") == argv[i]) {
display_help();
display_help(HELP_FULL);
show_help_and_exit = true;
return true; // Don't parse further input when -h is used
} else if (strstr(argv[i], "-a") == argv[i]) {
@@ -144,8 +152,8 @@ int handle_args(int argc, char * argv[]) {
}
} else if (strstr(argv[i], "-sP") == argv[i]) {
if (!set_option_custom_bank_colors(argv[i])) {
fprintf(stdout,"malformed custom color palette: %s\n\n", argv[i]);
display_help();
log_error("Malformed -sP custom color palette: %s\n\n", argv[i]);
// display_help();
return false;
}
} else if (strstr(argv[i], "-sH") == argv[i]) {
@@ -178,9 +186,15 @@ int handle_args(int argc, char * argv[]) {
} else if (strstr(argv[i], "-B") == argv[i]) {
set_option_summarized(true);
} else if (strstr(argv[i], "-F") == argv[i]) {
if (!option_set_displayed_bank_range(argv[i])) {
fprintf(stdout,"Malformed -F forced display max bank range\n\n");
display_help();
if (!set_option_displayed_bank_range(argv[i])) {
log_error("Malformed -F forced display max bank range\n\n");
// display_help();
return false;
}
} else if (strstr(argv[i], "-b") == argv[i]) {
if (!set_option_binary_rom_empty_values(argv[i] + strlen("-b"))) {
log_error("Malformed or no entries found -b set hex values treated as empty for ROM files: %s\n\n", argv[i]);
return false;
}
@@ -199,19 +213,31 @@ int handle_args(int argc, char * argv[]) {
} else if (strstr(argv[i], "-z:") == argv[i]) {
set_option_area_hide_size( strtol(argv[i] + 3, NULL, 10));
} else if (strstr(argv[i], "-nMEM:") == argv[i]) {
if (!set_option_banks_hide_add(argv[i] + strlen("-nMEM:"))) {
log_error("Adding memory region to hide failed: %s\n\n", argv[i]);
// display_help();
return false;
}
} else if ((strstr(argv[i], "-m") == argv[i]) ||
(strstr(argv[i], "-e") == argv[i])) {
if (!area_manual_queue(argv[i])) {
fprintf(stdout,"Malformed manual area argument: %s\n\n", argv[i]);
display_help();
log_error("Malformed -m or -e manual area argument: %s\n\n", argv[i]);
// display_help();
return false;
}
} else if (argv[i][0] == '-') {
fprintf(stdout,"Unknown argument: %s\n\n", argv[i]);
display_help();
log_error("Error: Unknown argument: %s\n\n", argv[i]);
display_help(HELP_BRIEF);
return false;
}
// Copy input filename (if not preceded with option dash)
else if (argv[i][0] != '-') {
snprintf(filename_in, sizeof(filename_in), "%s", argv[i]);
}
}
return true;
@@ -235,6 +261,7 @@ static void init(void) {
cdb_init();
noi_init();
banks_init();
romfile_init_defaults();
}
@@ -305,13 +332,14 @@ int main( int argc, char *argv[] ) {
if (!get_option_hide_banners()) display_cdb_warning();
ret = EXIT_SUCCESS; // Exit with success
}
} else {
log_error("Error: Incompatible file extension\n");
}
}
}
if (ret == EXIT_FAILURE)
printf("Problem with filename or unable to open file! %s\n", filename_in);
// if (ret == EXIT_FAILURE)
// printf("Problem with filename or unable to open file! %s\n", filename_in);
// Override exit code if was set during processing
if (get_exit_error())