Real-match ov86 by defining .itcm section properties; add asmdiff

This commit is contained in:
PikalaxALT 2022-11-28 18:09:15 -05:00
parent 488f1a6d6e
commit a33633c089
7 changed files with 292 additions and 3 deletions

View File

@ -1,7 +1,7 @@
.include "macros/function.inc"
.include "global.inc"
.section .itcm
.section .itcm,4,1,4
arm_func_start sub_01FF8000
sub_01FF8000: ; 0x01FF8000

View File

@ -3435,7 +3435,7 @@ ov86_0223CD00: ; 0x0223CD00
ldr r2, [r3, r2]
mov r0, #3
add r1, #0x14
.byte 0xBB, 0xF5, 0x4C, 0xEC
bl sub_01FF85B8
ldr r0, _0223CD30 ; =0x04000448
mov r1, #1
str r1, [r0, #0]
@ -4063,7 +4063,7 @@ ov86_0223D220: ; 0x0223D220
ldr r2, [r4, r2]
mov r0, #3
add r1, r4, r1
.byte 0xBB, 0xF5, 0xBA, 0xE9
bl sub_01FF85B8
ldr r0, _0223D260 ; =0x04000448
mov r1, #1
str r1, [r0, #0]

4
tools/asmdiff/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.bins/
.files/
ntrextractfile
ntruncompbw

17
tools/asmdiff/Makefile Normal file
View File

@ -0,0 +1,17 @@
CC := gcc
CFLAGS := -O2 -g -Wno-unused-result
ifneq ($(DEBUG),1)
CFLAGS += -DNDEBUG
endif
programs := ntrextractfile ntruncompbw
all: $(programs)
@:
clean:
$(RM) $(programs)
%: %.c
$(CC) $(CFLAGS) -o $@ $<

View File

@ -0,0 +1,8 @@
import sys
with open(sys.argv[1], 'rb') as fp:
data = fp.read()
x = data.find(b'\x21\x06\xc0\xde')
if x != -1:
x -= 28
print(x)

View File

@ -0,0 +1,153 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#ifndef NDEBUG
#ifdef _MSC_VER
#define debug_printf(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
#define debug_printf(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#endif //_MSC_VER
#else
#define debug_printf(fmt, ...) ((void)0)
#endif //NDEBUG
#define FIND_FAIL (-1u)
struct NtrDirHeader {
unsigned offset;
unsigned short first_file;
unsigned short count_or_parent;
};
static char FILEBUF[BUFSIZ];
unsigned find_file(struct NtrDirHeader * fnt, const char * cfilename) {
unsigned file_id = fnt->first_file;
char * filename = strdup(cfilename);
char * tokenizer = filename;
int found = 0;
char * tree = (char *)fnt + fnt->offset;
char * token;
while ((token = strtok(tokenizer, "/")) != NULL) {
tokenizer = NULL;
debug_printf("TOKEN: %s\n", token);
long toklen = strlen(token);
while (*tree) {
char flag = *tree++;
#ifndef NDEBUG
char *entname = malloc((flag & 0x7F) + 1);
*stpncpy(entname, tree, flag & 0x7F) = 0;
debug_printf("testing entry %s...", entname);
free(entname);
#endif //NDEBUG
if ((toklen != (flag & 0x7F)) || strncmp(tree, token, toklen) != 0) {
debug_printf("no; is %s\n", (flag & 0x80) ? "dir" : "file");
// Next entry
tree += (flag & 0x7F);
if (flag & 0x80) {
tree += 2; // skip dir id
}
else {
file_id++;
}
}
else {
debug_printf("yes; is %s\n", (flag & 0x80) ? "dir" : "file");
tree += (flag & 0x7F);
if (flag & 0x80) {
// navigate to next dir
unsigned short dir_id = (unsigned char) tree[0] | ((unsigned char) tree[1] << 8);
file_id = fnt[dir_id & 0xFFF].first_file;
tree = (char *)fnt + fnt[dir_id & 0xFFF].offset;
break;
}
else {
found = 1;
token = strtok(NULL, "/");
goto done;
}
}
}
}
done:
free(filename);
if (!found || token != NULL) {
file_id = FIND_FAIL;
}
return file_id;
}
int main(int argc, char ** argv) {
if (argc < 3) {
fprintf(stderr, "missing required argument: %s\n", (argc == 1) ? "BASEROM" : "FILENAME");
return 1;
}
FILE *baserom = fopen(argv[1], "rb");
if (baserom == NULL) {
fprintf(stderr, "unable to open ROM %s for reading\n", argv[1]);
return 1;
}
debug_printf("opened baserom\n");
// fnt offset, fnt size, fat offset, fat size
unsigned offsets[4];
fseek(baserom, 64, SEEK_SET);
if (fread(offsets, 4, 4, baserom) != 4) {
fprintf(stderr, "failed to read from baserom\n");
fclose(baserom);
return 1;
}
debug_printf("read offsets\n");
// read fnt
struct NtrDirHeader *fnt = malloc(offsets[1]);
if (fnt == NULL) {
fprintf(stderr, "unable to allocate FNT buffer\n");
fclose(baserom);
return 1;
}
fseek(baserom, offsets[0], SEEK_SET);
if (fread(fnt, 1, offsets[1], baserom) != offsets[1]) {
fprintf(stderr, "unable to read FNT\n");
free(fnt);
fclose(baserom);
return 1;
}
debug_printf("read fnt\n");
unsigned file_id = find_file(fnt, argv[2]);
free(fnt);
if (file_id == FIND_FAIL) {
fprintf(stderr, "file not found");
fclose(baserom);
return 1;
}
debug_printf("found file with id %u\n", file_id);
// Extract the file to stdout
if (8 * file_id >= offsets[3]) {
fprintf(stderr, "nitrofs lookup failed");
fclose(baserom);
return 1;
}
FILE *out = fdopen(dup(fileno(stdout)), "wb");
fseek(baserom, offsets[2] + 8 * file_id, SEEK_SET);
fread(offsets, 4, 2, baserom);
fseek(baserom, offsets[0], SEEK_SET);
while (offsets[1] - offsets[0] > BUFSIZ) {
fread(FILEBUF, 1, BUFSIZ, baserom);
fwrite(FILEBUF, 1, BUFSIZ, out);
offsets[0] += BUFSIZ;
}
fread(FILEBUF, 1, offsets[1] - offsets[0], baserom);
fwrite(FILEBUF, 1, offsets[1] - offsets[0], out);
fclose(out);
fclose(baserom);
return 0;
}

107
tools/asmdiff/ntruncompbw.c Normal file
View File

@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
static inline uint32_t READ32(const unsigned char * ptr)
{
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
}
static uint32_t MIi_UncompressBackwards(unsigned char ** out_p, size_t compsize)
{
unsigned char * out = *out_p;
// Read the pointer to the end of the compressed image
uint8_t * endptr = out + compsize - 8;
uint32_t size = READ32(endptr);
uint32_t offset = READ32(endptr + 4);
out = realloc(out, compsize + offset);
if (out == NULL)
return -1u;
endptr = out + compsize;
uint8_t * dest_p = endptr + offset;
uint8_t * end = endptr - ((uint8_t)(size >> 24));
uint8_t * start = endptr - (size & ~0xFF000000);
while (end > start) {
uint8_t r5 = *--end;
for (int i = 0; i < 8; i++) {
if ((r5 & 0x80) == 0)
*--dest_p = *--end;
else {
int ip = *--end;
int r7 = *--end;
r7 = ((r7 | (ip << 8)) & ~0xF000) + 2;
ip += 0x20;
while (ip >= 0) {
dest_p[-1] = dest_p[r7];
dest_p--;
ip -= 0x10;
}
}
if (end <= start)
break;
r5 <<= 1;
}
}
*out_p = out;
return compsize + offset;
}
int main(int argc, char ** argv)
{
if (argc < 4) {
fprintf(stderr, "usage: %s FILE VMA END\n\ninsufficient arguments\n", argv[0]);
return 1;
}
char * infname = argv[1];
uint32_t vma = strtoul(argv[2], NULL, 0);
uint32_t end = strtoul(argv[3], NULL, 0);
if (end == 0) {
fprintf(stderr, "compressed size is 0, no action taken\n");
return 0;
}
FILE * infile = fopen(infname, "r+b");
if (infile == NULL) {
fclose(infile);
fprintf(stderr, "unable to open file %s for reading\n", infname);
return 1;
}
fseek(infile, 0, SEEK_END);
long infsize = ftell(infile);
fseek(infile, 0, SEEK_SET);
if (infsize != end - vma) {
fclose(infile);
fprintf(stderr, "compressed size does not match file size, I am cowardly doing nothing\n");
return 0;
}
unsigned char * inbuf = malloc(infsize);
if (inbuf == NULL) {
fclose(infile);
fprintf(stderr, "error: malloc(%d)\n", (int)infsize);
return 1;
}
if (fread(inbuf, 1, infsize, infile) != infsize) {
fclose(infile);
free(inbuf);
fprintf(stderr, "error reading from %s\n", infname);
return 1;
}
uint32_t outsize = MIi_UncompressBackwards(&inbuf, end - vma);
if (outsize == -1u) {
fclose(infile);
fprintf(stderr, "fatal error reallocating for decompression\n");
return 1;
}
fseek(infile, 0, SEEK_SET);
if (fwrite(inbuf, 1, outsize, infile) != outsize) {
fclose(infile);
free(inbuf);
fprintf(stderr, "error writing back to %s\n", infname);
return 1;
}
fclose(infile);
free(inbuf);
return 0;
}