mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-02-20 00:32:21 +01:00
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:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user