mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-24 00:02:43 +02:00
Introduce mkrom
This commit is contained in:
1 parent
39a92c5970
commit
91ae15a32d
22 files changed
+2836
-707
No files matched your search
@@ -0,0 +1,153 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mkrom.h"
|
||||
|
||||
extern struct state state;
|
||||
|
||||
static void copy(char *segname, uint8_t *payload, size_t len, char *constname)
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
char zipsegname[32];
|
||||
uint32_t allocation;
|
||||
|
||||
snprintf(zipsegname, sizeof(zipsegname), "%szip", segname);
|
||||
|
||||
map_get_segment_rompos(zipsegname, &start, &end);
|
||||
|
||||
allocation = end - start;
|
||||
|
||||
if (len > allocation) {
|
||||
fprintf(stderr, "The %s segment is too big after compression to fit the allocation of 0x%x.\n", segname, allocation);
|
||||
fprintf(stderr, "In ld/pd.ld, increase the value of %s to 0x%x or higher.\n", constname, len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(&state.rom[start], payload, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* To pack the data segment, zip it in full and copy it to the datazip segment.
|
||||
*/
|
||||
void pack_data(void)
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
size_t ziplen;
|
||||
|
||||
map_get_segment_rompos("data", &start, &end);
|
||||
|
||||
uint8_t *buffer = malloc(end - start);
|
||||
|
||||
rarezip(buffer, &ziplen, &state.rom[start], end - start, 0);
|
||||
|
||||
copy("data", buffer, ziplen, "ROMALLOCATION_DATA");
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* On the ROM, the gamezips segment exists with its offset table and zip data.
|
||||
* Then after that comes a copy of the gamezips segment but with the offset
|
||||
* table cleared. The second segment is garbage data.
|
||||
*
|
||||
* mkrom has already built the gamezips segment but with a zeroed table.
|
||||
* The real table is pointed to by state.gametable.
|
||||
*
|
||||
* So we have to copy the gamezips segment twice, then paste the gametable
|
||||
* segment over the start of the first one.
|
||||
*/
|
||||
void pack_game(void)
|
||||
{
|
||||
uint32_t gamezipstart;
|
||||
uint32_t gamezipend;
|
||||
size_t truncatedlen;
|
||||
|
||||
// Copy the gamezips segment
|
||||
copy("game", state.gamezips, state.gamezipslen, "ROMALLOCATION_GAME");
|
||||
|
||||
// Paste over the offset table
|
||||
map_get_segment_rompos("gamezip", &gamezipstart, &gamezipend);
|
||||
|
||||
memcpy(&state.rom[gamezipstart], state.gametable, state.gametablelen);
|
||||
|
||||
// Paste the second segment, truncating it to fit the allocation
|
||||
truncatedlen = gamezipend - gamezipstart - state.gamezipslen;
|
||||
|
||||
if (truncatedlen > state.gamezipslen) {
|
||||
truncatedlen = state.gamezipslen;
|
||||
}
|
||||
|
||||
memcpy(&state.rom[gamezipstart + state.gamezipslen], state.gamezips, truncatedlen);
|
||||
|
||||
// The final two bytes from the real segment are duplicated into
|
||||
// the first two bytes of the second segment's offset table
|
||||
state.rom[gamezipstart + state.gamezipslen + 0] = state.rom[gamezipstart + state.gamezipslen - 2];
|
||||
state.rom[gamezipstart + state.gamezipslen + 1] = state.rom[gamezipstart + state.gamezipslen - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* The lib segment is zipped from 0x2000 onwards.
|
||||
*
|
||||
* It's placed twice in a row in the ROM within its allocation, where the second
|
||||
* one is truncated and unused.
|
||||
*/
|
||||
void pack_lib(void)
|
||||
{
|
||||
uint32_t libzipstart;
|
||||
uint32_t libzipend;
|
||||
uint32_t libstart;
|
||||
uint32_t libend;
|
||||
size_t ziplen;
|
||||
size_t seglen;
|
||||
size_t truncatedlen;
|
||||
|
||||
map_get_segment_rompos("lib", &libstart, &libend);
|
||||
|
||||
uint8_t *buffer = malloc(libend - libstart);
|
||||
|
||||
// Read the first 0x2000 into a buffer
|
||||
memcpy(buffer, &state.rom[libstart], 0x2000);
|
||||
|
||||
// Compress the remainder from ROM, appending to the buffer
|
||||
rarezip(&buffer[0x2000], &ziplen, &state.rom[libstart + 0x2000], libend - libstart - 0x2000, 0);
|
||||
seglen = ziplen + 0x2000;
|
||||
|
||||
// Copy the buffer to its real spot in the ROM
|
||||
copy("lib", buffer, seglen, "ROMALLOCATION_LIB");
|
||||
|
||||
// Copy it truncated to its fake spot
|
||||
map_get_segment_rompos("libzip", &libzipstart, &libzipend);
|
||||
|
||||
truncatedlen = libzipend - libzipstart - seglen;
|
||||
|
||||
if (truncatedlen > seglen) {
|
||||
truncatedlen = seglen;
|
||||
}
|
||||
|
||||
memcpy(state.rom + libzipstart + seglen, buffer, truncatedlen);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill from the end of the last segment to the end of the ROM with 0xff.
|
||||
*/
|
||||
void pack_fill(void)
|
||||
{
|
||||
uint32_t offset;
|
||||
|
||||
map_get_segment_rompos("accessingpak", NULL, &offset);
|
||||
|
||||
if (offset == 0) {
|
||||
// We're probably building ntsc-beta, which doesn't have the
|
||||
// accessingpak segment.
|
||||
map_get_segment_rompos("copyright", NULL, &offset);
|
||||
}
|
||||
|
||||
while (offset < 1024 * 1024 * 32) {
|
||||
state.rom[offset] = 0xff;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user