mirror of
https://github.com/gbdev/rgbds.git
synced 2025-12-02 07:47:49 +00:00
Previously, the output file was opened before trying to open the overlay. Because of this, rgblink generated an empty output file if the overlay couldn't be opened. Now the overlay is opened (and checked) before the output file, so the output file is only generated if the overlay is found. Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
175 lines
3.2 KiB
C
175 lines
3.2 KiB
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));
|
|
}
|
|
}
|