ref: 88b66f2941ccb25d83c346f10c86d2a2eb5c9eeb
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));
}
}