ref: 6ffa751090c7c8db55fbf3cb0f7a28e90f558a56
dir: /src/link/output.c/
/* * This file is part of RGBDS. * * Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors. * * SPDX-License-Identifier: MIT */ #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "extern/err.h" #include "link/mylink.h" #include "link/mapfile.h" #include "link/main.h" #include "link/assign.h" char *tzOutname; char *tzOverlayname; int32_t MaxOverlayBank; void writehome(FILE *f, FILE *f_overlay) { const struct sSection *pSect; uint8_t *mem; mem = malloc(MaxAvail[BANK_INDEX_ROM0]); if (!mem) return; if (f_overlay != NULL) { fseek(f_overlay, 0L, SEEK_SET); if (fread(mem, 1, MaxAvail[BANK_INDEX_ROM0], f_overlay) != MaxAvail[BANK_INDEX_ROM0]) { warnx("Failed to read data from overlay file."); } } else { memset(mem, fillchar, MaxAvail[BANK_INDEX_ROM0]); } MapfileInitBank(0); pSect = pSections; while (pSect) { if (pSect->Type == SECT_ROM0) { memcpy(mem + pSect->nOrg, pSect->pData, pSect->nByteSize); MapfileWriteSection(pSect); } pSect = pSect->pNext; } MapfileCloseBank(area_Avail(0)); fwrite(mem, 1, MaxAvail[BANK_INDEX_ROM0], f); free(mem); } void writebank(FILE *f, FILE *f_overlay, int32_t bank) { const struct sSection *pSect; uint8_t *mem; mem = malloc(MaxAvail[bank]); if (!mem) return; if (f_overlay != NULL && bank <= MaxOverlayBank) { fseek(f_overlay, bank * 0x4000, SEEK_SET); if (fread(mem, 1, MaxAvail[bank], f_overlay) != MaxAvail[bank]) warnx("Failed to read data from overlay file."); } else { memset(mem, fillchar, MaxAvail[bank]); } MapfileInitBank(bank); pSect = pSections; while (pSect) { if (pSect->Type == SECT_ROMX && pSect->nBank == bank) { memcpy(mem + pSect->nOrg - 0x4000, pSect->pData, pSect->nByteSize); MapfileWriteSection(pSect); } pSect = pSect->pNext; } MapfileCloseBank(area_Avail(bank)); fwrite(mem, 1, MaxAvail[bank], f); free(mem); } void out_Setname(char *tzOutputfile) { tzOutname = tzOutputfile; } void out_SetOverlayname(char *tzOverlayfile) { tzOverlayname = tzOverlayfile; } void Output(void) { int32_t i; FILE *f; FILE *f_overlay = NULL; /* * Load overlay */ if (tzOverlayname) { f_overlay = fopen(tzOverlayname, "rb"); if (!f_overlay) { errx(1, "Failed to open overlay file %s\n", tzOverlayname); } fseek(f_overlay, 0, SEEK_END); if (ftell(f_overlay) % 0x4000 != 0) errx(1, "Overlay file must be aligned to 0x4000 bytes."); MaxOverlayBank = (ftell(f_overlay) / 0x4000) - 1; if (MaxOverlayBank < 1) errx(1, "Overlay file must be at least 0x8000 bytes."); if (MaxOverlayBank > MaxBankUsed) MaxBankUsed = MaxOverlayBank; } /* * Write ROM. */ f = fopen(tzOutname, "wb"); if (f != NULL) { writehome(f, f_overlay); for (i = 1; i <= MaxBankUsed; i += 1) writebank(f, f_overlay, i); fclose(f); } /* * Close overlay */ if (tzOverlayname) fclose(f_overlay); /* * Add regular sections to map and sym files. */ for (i = BANK_INDEX_WRAM0; i < BANK_INDEX_MAX; i++) { const struct sSection *pSect; MapfileInitBank(i); pSect = pSections; while (pSect) { if (pSect->nBank == i) MapfileWriteSection(pSect); pSect = pSect->pNext; } MapfileCloseBank(area_Avail(i)); } }