git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-support/makecom/bin_to_com.c

      1 // This is free and unencumbered software released into the public domain.
      2 // For more information, please refer to <https://unlicense.org>
      3 // bbbbbr 2020
      4 
      5 #include <stdio.h>
      6 #include <string.h>
      7 #include <stdlib.h>
      8 #include <unistd.h>
      9 #include <stdbool.h>
     10 #include <stdint.h>
     11 
     12 #include "common.h"
     13 #include "list.h"
     14 #include "files.h"
     15 #include "noi_file.h"
     16 #include "bin_to_com.h"
     17 
     18 
     19 uint8_t * banks[BANKS_MAX_COUNT] = {NULL};
     20 uint16_t  banks_len[BANKS_MAX_COUNT] = {0};
     21 uint16_t  banks_count = 0;
     22 
     23 
     24 void banks_cleanup(void) {
     25     for (int c = 0; c <= BANKS_MAX_ID; c++) {
     26         if (banks[c] != NULL) {
     27 
     28             free(banks[c]);
     29             banks[c] = NULL;
     30         }
     31     }
     32 }
     33 
     34 
     35 // Allocate memory for banks as banks are requested
     36 // If preceding banks are not yet allocated then do those too
     37 uint8_t * bank_get_ptr(uint16_t bank_num) {
     38 
     39     if (bank_num > BANKS_MAX_ID) {
     40         printf("makecom: ERROR: Requested bank %d is larger than max bank num %d!\n", bank_num, BANKS_MAX_ID);
     41         exit(EXIT_FAILURE);
     42     }
     43 
     44     if (banks[bank_num] == NULL) {
     45 
     46         // Make sure all banks leading up to requested are also allocated
     47         for (int c = 0; c <= bank_num; c++) {
     48             if (banks[c] == NULL) {
     49 
     50                 banks[c] = malloc(BANK_SIZE);
     51 
     52                 if (!banks[c]) {
     53                     printf("makecom: ERROR: Failed to allocate memory for bank %d!\n", c);
     54                     exit(EXIT_FAILURE);
     55                 }
     56 
     57                 // zero out buffer (though unused space will not get written out)
     58                 memset(banks[c], 0x00u, BANK_SIZE);
     59             }
     60         }
     61     }
     62 
     63     return banks[bank_num];
     64 }
     65 
     66 
     67 
     68 // Copy data from source bin file at offset address into requested bank buffer
     69 void copy_to_bank(uint16_t bank_num, uint32_t rom_src_addr, uint32_t bank_out_addr, uint32_t length) {
     70 
     71     // TODO: make sure bin src addr doesn't exceed source file buffer length
     72     if ((rom_src_addr + length) > rom_buf_in_len) {
     73         printf("makecom: ERROR: Can't copy %d bytes from %x for bank %d, would overflow past end of ROM source buffer of size %d!\n", length, rom_src_addr, bank_num, (uint32_t)rom_buf_in_len);
     74         exit(EXIT_FAILURE);
     75     }
     76 
     77     if ((bank_out_addr + length) > BANK_SIZE) {
     78         printf("makecom: ERROR: Can't copy %d bytes to %04x for bank %d, would overflow past end of bank buffer of size %d!\n",length, bank_out_addr, bank_num, BANK_SIZE);
     79         exit(EXIT_FAILURE);
     80     }
     81 
     82     if (bank_num > banks_count)
     83         banks_count = bank_num;
     84 
     85     // Update length of bank data buffers (to allow for truncating output later)
     86     if ((bank_out_addr + length) > banks_len[bank_num])
     87         banks_len[bank_num] = (bank_out_addr + length);
     88 
     89     // printf("* copying... bank:%d from:%x to:%x len:%d\n",
     90     //         bank_num, rom_src_addr, bank_out_addr, length);
     91 
     92     memcpy(bank_get_ptr(bank_num) + bank_out_addr, p_rom_buf_in + rom_src_addr, length);
     93 }
     94 
     95 
     96 void banks_write_out(void) {
     97 
     98     // If any of below fails it will trigger exit() and cleanup() will be called
     99 
    100     // Write first bank out, handled differently than rest
    101     if ((banks[0] != NULL) && (banks_len[0] > 0)) {
    102         // printf("Bank %d: Writing %d bytes to %s\n",0, banks_len[0], filename_out_com);
    103         file_write_from_buffer(filename_out_com, banks[0], banks_len[0]);
    104     } else {
    105         printf("makecom: Error: Bank 0 was empty, no data written\n");
    106         exit;
    107     }
    108 
    109     // Write out remaining banks if applicable
    110     char bank_fname[MAX_STR_LEN] = "";
    111     for (int c = 1; c <= BANKS_MAX_ID; c++) {
    112         if ((banks[c] != NULL) && (banks_len[0] > 0)) {
    113             // Format to 8.3 filename with bank num as zero padded extension
    114             sprintf(bank_fname, "%s.%03d", filename_banks_base, c);
    115             // printf("Bank %d: Writing %d bytes to %s\n",c, banks_len[c], bank_fname);
    116             file_write_from_buffer(bank_fname, banks[c], banks_len[c]);
    117         } else
    118             break; // Exit loop on first unpopulated bank
    119     }
    120 
    121 }
    122 
    123 
    124 
    125 int bin2com(void) {
    126 
    127     symbol_item * symbols = (symbol_item *)symbol_list.p_array;
    128 
    129     for(int c = 0; c < symbol_list.count; c++) {
    130 
    131         // Only process completed symbols (start and length both set, lenth not zero)
    132         if ((symbols[c].addr_start != SYM_VAL_UNSET) &&
    133             (symbols[c].length != SYM_VAL_UNSET) &&
    134             (symbols[c].length > 0)) {
    135 
    136             // If symbol is for a bank > 0
    137             if ((strncmp(symbols[c].name, "_CODE_", (sizeof("_CODE_") - 1)) == 0) && (symbols[c].bank_num > 0)) {
    138                 // Copy data from bank addr in source ROM to start of separate bank buffer
    139                 copy_to_bank(symbols[c].bank_num, symbols[c].src_rom_addr, BANK_START_ADDR, symbols[c].length);
    140             } else {
    141                 // For remaining symbols (assume bank 0), relocate them by -100 when possible (addr -> addr - 100)
    142                 copy_to_bank(BANK_0, symbols[c].addr_start, BANK_0_RELOC_ADDR(symbols[c].addr_start), symbols[c].length);
    143             }
    144         }
    145     }
    146 
    147     // Patch in updated bank / overlay count and bank filename
    148     if ((banks_count > 0) && (overlay_count_addr != SYM_VAL_UNSET) && (overlay_name_addr != SYM_VAL_UNSET)) {
    149 
    150         if (overlay_count_addr > BANK_0_ADDR_OFFSET)
    151             *(banks[0] + (overlay_count_addr - BANK_0_ADDR_OFFSET)) = banks_count;
    152 
    153         if (overlay_name_addr > BANK_0_ADDR_OFFSET)
    154             memcpy(banks[0] + (overlay_name_addr - BANK_0_ADDR_OFFSET), filename_overlay, COM_OVERLAY_NAME_LEN-1);
    155     }
    156 
    157     // No write the data out
    158     banks_write_out();
    159 
    160     return EXIT_SUCCESS;
    161 }
    162 
    163 
    164 

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.