Initial attempt to bootstrap Travis CI

This commit is contained in:
PikalaxALT
2019-06-23 19:29:44 -04:00
parent 64498f4107
commit 8e7a1dac01
8 changed files with 378 additions and 3 deletions
+35
View File
@@ -0,0 +1,35 @@
language: generic
dist: trusty
sudo: false
addons:
apt:
packages:
- gcc-multilib
- linux-libc-dev
- zlib-dev
cache:
apt: true
install:
- pushd $HOME
- travis_retry git clone https://github.com/luckytyphlosion/agbcc.git -b new_layout_with_libs
- cd agbcc && make && make install prefix=$TRAVIS_BUILD_DIR
- popd
matrix:
include:
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env: _="Build"
script:
- head -c 16777216 /dev/zero > tmp.bin
- make ips_patch -C tools/br_ips
- tools/br_ips/ips_patch tmp.bin baserom.ips baserom.gba
- rm tmp.bin
- make tools CXX=g++-7
- make -j2 compare
after_success:
- .travis/calcrom/webhook.sh pokefirered
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash -ex
# Only run this script if it's the master branch build.
if [[ "$TRAVIS_BRANCH" != "master" || "$TRAVIS_PULL_REQUEST" != "false" ]]; then
exit 0
fi
build_name=$1
map_file=$build_name.map
if [ ! -f $map_file ]; then
echo "$map_file does not exist!"
exit 1
fi
output=$(perl $(dirname "$0")/calcrom.pl $build_name.map | sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g')
curl -d "{\"username\": \"$CALCROM_DISCORD_WEBHOOK_USERNAME\", \"avatar_url\": \"$CALCROM_DISCORD_WEBHOOK_AVATAR_URL\", \"content\":\"\`\`\`$build_name progress:\\n$output\`\`\`\"}" -H "Content-Type: application/json" -X POST $CALCROM_DISCORD_WEBHOOK_URL
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -665,7 +665,7 @@ gUnknown_843EE64:: @ 843EE64
.asciz "SEARCH"
.align 2
.incbin "baserom.gba", 0x43EEC0, 0x43F004-0x43EEC0
.incbin "baserom.gba", 0x43EEC0, 0x144
gUnknown_843F004:: @ 843F004
.incbin "baserom.gba", 0x43F004, 0x100
+1 -2
View File
@@ -16412,5 +16412,4 @@ gUnknown_8EAFFC0:: @ 8EAFFC0
gUnknown_8EB0ADC:: @ 8EB0ADC
.incbin "baserom.gba", 0xEB0ADC, 0x44
gUnknown_8EB0B20:: @ 8EB0B20
.incbin "baserom.gba", 0xEB0B20
@ EOF
+13
View File
@@ -0,0 +1,13 @@
CC := gcc
CFLAGS := -O3
all: br_ips ips_patch
clean:
rm -f br_ips ips_patch br_ips.exe ips_patch.exe
br_ips: br_ips.c
$(CC) $(CFLAGS) -o $@ $^
ips_patch: ips_patch.c
$(CC) $(CFLAGS) -o $@ $^
+249
View File
@@ -0,0 +1,249 @@
#define _POSIX_C_SOURCE 200808L // Don't use GNU getline
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifdef _MSC_VER
#define FATAL_ERROR(format, ...) \
do { \
fprintf(stderr, format, __VA_ARGS__); \
exit(1); \
} while (0)
#else
#define FATAL_ERROR(format, ...) \
do { \
fprintf(stderr, format, ##__VA_ARGS__); \
exit(1); \
} while (0)
#endif // _MSC_VER
#ifndef _SSIZE_T
#define _SSIZE_T
typedef int ssize_t;
#endif // _SSIZE_T
static const char SPLASH[] = "IPS patch creator for undisassembled data\n"
"Created by PikalaxALT on 23 June 2019 All Rights Reserved\n";
struct Baserom {
uint32_t offset;
size_t size;
};
static ssize_t getline(char ** lineptr, size_t * n, FILE * stream) {
ssize_t i = 0;
int c;
size_t size = *n;
char * buf = *lineptr;
if (size == 0) {
size = BUFSIZ;
buf = realloc(buf, BUFSIZ);
}
if (buf == NULL) return -1;
do {
if (feof(stream)) return -1;
c = getc(stream);
buf[i++] = c;
if (i == size) {
size <<= 1;
buf = realloc(buf, size);
if (buf == NULL) return -1;
}
} while (c != '\n');
*lineptr = buf;
*n = size;
return i;
}
static void getIncbinsFromFile(struct Baserom ** incbins, size_t * num, size_t * maxnum, const char * fname, char ** strbuf, size_t * buffersize) {
FILE * file = fopen(fname, "r");
if (file == NULL) FATAL_ERROR("unable to open file \"%s\" for reading\n", fname);
struct Baserom * data = *incbins;
size_t nincbins = *num;
size_t maxnincbins = *maxnum;
int line_n = 0;
while (getline(strbuf, buffersize, file) > 0) {
line_n++;
char * nl_p = strchr(*strbuf, '\n');
if (nl_p != NULL) *nl_p = 0;
char * include = strstr(*strbuf, ".include");
if (include != NULL) {
char incfname[128];
include = strchr(include, '"');
if (include == NULL) FATAL_ERROR("%s:%d: malformed include\n", fname, line_n);
include++;
char * endq_p = strchr(include, '"');
if (endq_p == NULL) FATAL_ERROR("%s:%d: malformed include\n", fname, line_n);
*endq_p = 0;
strcpy(incfname, include);
getIncbinsFromFile(&data, &nincbins, &maxnincbins, incfname, strbuf, buffersize);
continue;
}
char * line = strstr(*strbuf, ".incbin");
if (line == NULL) continue;
line = strstr(line + sizeof(".incbin"), "\"baserom.gba\",");
if (line == NULL) continue;
line += sizeof("\"baserom.gba\",") - 1;
uint32_t incbinOffset;
do {
if (*line == 0) FATAL_ERROR("%s:%d: malformed incbin\n", fname, line_n);
incbinOffset = strtoul(line, &line, 0);
line++;
} while (incbinOffset == 0);
ssize_t incbinSize;
do {
if (*line == 0) FATAL_ERROR("%s:%d: malformed incbin\n", fname, line_n);
incbinSize = strtoul(line, &line, 0);
line++;
} while (incbinSize == 0);
if (incbinOffset >= 0x01000000) FATAL_ERROR("%s:%d: offset exceeds encodable limit\n", fname, line_n);
if (incbinOffset == 0x454F46) { // "EOF"
incbinOffset--;
incbinSize++;
}
if (incbinOffset + incbinSize >= 0xFFFFFF + 0xFFFF) FATAL_ERROR("%s:%d: size exceeds encodable limit\n", fname, line_n);
do {
size_t trueSize = incbinSize <= 0xFFFF ? incbinSize : 0xFFFF;
if (nincbins >= maxnincbins) {
maxnincbins <<= 1;
data = realloc(data, maxnincbins * sizeof(struct Baserom));
if (data == NULL) FATAL_ERROR("unable to reallocate incbins buffer\n");
}
// fprintf(stderr, "DEBUG: %s:%d: 0x%x, 0x%lx\n", fname, line_n, incbinOffset, trueSize);
data[nincbins].offset = incbinOffset;
data[nincbins].size = trueSize;
incbinOffset += trueSize;
incbinSize -= trueSize;
if (incbinOffset == 0x454F46) {
incbinOffset--;
data[nincbins].size--;
incbinSize++;
}
nincbins++;
} while (incbinSize > 0);
}
if (!feof(file)) FATAL_ERROR("getline\n");
fclose(file);
*incbins = data;
*num = nincbins;
*maxnum = maxnincbins;
}
static struct Baserom * getAllIncbins(FILE * ld_script, size_t * num_p) {
char * line = NULL;
size_t linesiz = 0;
char fname_buf[128];
size_t maxnum = 256;
size_t num = 0;
struct Baserom * incbins = malloc(256 * sizeof(struct Baserom));
if (incbins == NULL) FATAL_ERROR("failed to allocate incbins buffer\n");
while (getline(&line, &linesiz, ld_script) > 0) {
char * endptr;
if ((endptr = strstr(line, ".o(.rodata);")) == NULL
&& (endptr = strstr(line, ".o(script_data);")) == NULL
&& (endptr = strstr(line, ".o(gfx_data);")) == NULL) continue;
char * startptr = line;
while (isspace(*startptr)) startptr++;
if (strstr(startptr, ".a:") != NULL) continue; // no incbins in libs
if (strstr(startptr, "src/") == startptr) continue; // no incbins in src/
endptr[1] = 's';
endptr[2] = 0;
strcpy(fname_buf, startptr);
getIncbinsFromFile(&incbins, &num, &maxnum, fname_buf, &line, &linesiz);
}
if (!feof(ld_script)) FATAL_ERROR("getline\n");
free(line);
*num_p = num;
return incbins;
}
static int cmp_baserom(const void * a, const void * b) {
const struct Baserom * aa = (const struct Baserom *)a;
const struct Baserom * bb = (const struct Baserom *)b;
return (aa->offset > bb->offset) - (aa->offset < bb->offset);
}
static void collapseIncbins(struct Baserom * incbins, size_t * num_p) {
size_t num = *num_p;
qsort(incbins, num, sizeof(struct Baserom), cmp_baserom);
for (int i = 0; i < num - 1; i++) {
while (incbins[i].offset + incbins[i].size == incbins[i + 1].offset) {
if (incbins[i].size == 0xFFFF) break;
while (incbins[i].size == 0) {
for (int j = i; j < num - 1; j++) incbins[j] = incbins[j + 1];
num--;
if (i == num - 1) break;
}
if (i == num - 1) break;
incbins[i].size += incbins[i + 1].size;
if (incbins[i].size > 0xFFFF) {
incbins[i + 1].size = incbins[i].size - 0xFFFF;
incbins[i].size = 0xFFFF;
incbins[i + 1].offset = incbins[i].offset + 0xFFFF;
if (incbins[i + 1].offset == 0x454F46) {
incbins[i].size--;
incbins[i + 1].offset--;
incbins[i + 1].size++;
}
break;
} else {
for (int j = i + 1; j < num - 1; j++) incbins[j] = incbins[j + 1];
num--;
if (i == num - 1) break;
}
}
}
*num_p = num;
}
static void writePatch(const char * filename, const struct Baserom * incbins, size_t num, FILE * rom) {
FILE * file = fopen(filename, "wb");
if (file == NULL) FATAL_ERROR("unable to open file \"%s\" for writing\n", filename);
char * readbuf = malloc(0x10000);
if (readbuf == NULL) FATAL_ERROR("failed to allocate write buffer\n");
fwrite("PATCH", 1, 5, file); // magic
for (int i = 0; i < num; i++) {
uint32_t offset = incbins[i].offset;
putc(offset >> 16, file);
putc(offset >> 8, file);
putc(offset >> 0, file);
size_t size = incbins[i].size;
putc(size >> 8, file);
putc(size >> 0, file);
if (fseek(rom, offset, SEEK_SET)) FATAL_ERROR("seek\n");
if (fread(readbuf, 1, size, rom) != size) FATAL_ERROR("read\n");
if (fwrite(readbuf, 1, size, file) != size) FATAL_ERROR("write\n");
printf("DEBUG: 0x%x, 0x%lx\n", offset, size);
}
free(readbuf);
fwrite("EOF", 1, 3, file);
fclose(file);
}
int main() {
puts(SPLASH);
FILE * rom = fopen("baserom.gba", "rb");
if (rom == NULL) FATAL_ERROR("unable to open \"baserom.gba\" for reading\n");
FILE * ld_script = fopen("ld_script.txt", "r");
if (ld_script == NULL) FATAL_ERROR("unable to open \"ld_script.txt\" for reading\n");
size_t num = 0;
struct Baserom * incbins = getAllIncbins(ld_script, &num);
fclose(ld_script);
if (num == 0) {
puts("No baserom.gba incbins found!\n");
} else {
collapseIncbins(incbins, &num);
writePatch("baserom.ips", incbins, num, rom);
}
fclose(rom);
free(incbins);
puts("IPS file created at baserom.ips\n");
return 0;
}
+63
View File
@@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#ifdef _MSC_VER
#define FATAL_ERROR(format, ...) \
do { \
fprintf(stderr, format, __VA_ARGS__); \
exit(1); \
} while (0)
#else
#define FATAL_ERROR(format, ...) \
do { \
fprintf(stderr, format, ##__VA_ARGS__); \
exit(1); \
} while (0)
#endif // _MSC_VER
static const char SPLASH[] = "Small IPS patch utility\n"
"Created by PikalaxALT on 23 June 2019 All Rights Reserved\n";
int main(int argc, char ** argv) {
puts(SPLASH);
if (argc != 4) FATAL_ERROR("usage: %s ROM PATCH OUT\n", argv[0]);
FILE * rom = fopen(argv[1], "rb");
if (rom == NULL) FATAL_ERROR("failed to open file \"%s\" for reading\n", argv[1]);
FILE * patch = fopen(argv[2], "rb");
if (patch == NULL) FATAL_ERROR("failed to open file \"%s\" for reading\n", argv[2]);
FILE * out = fopen(argv[3], "wb");
if (patch == NULL) FATAL_ERROR("failed to open file \"%s\" for writing\n", argv[3]);
char magic[5];
if (fread(magic, 1, 5, patch) != 5) FATAL_ERROR("read magic\n");
if (memcmp(magic, "PATCH", 5) != 0) FATAL_ERROR("malformed IPS patch\n");
fseek(rom, 0, SEEK_END);
size_t romsize = ftell(rom);
fseek(rom, 0, SEEK_SET);
char * buffer = malloc(romsize);
if (buffer == NULL) FATAL_ERROR("failed to allocate dest buffer\n");
if (fread(buffer, 1, romsize, rom) != romsize) FATAL_ERROR("read ROM\n");
fclose(rom);
while (1) {
uint32_t offset;
size_t size;
offset = (unsigned char)getc(patch) << 16;
offset |= (unsigned char)getc(patch) << 8;
offset |= (unsigned char)getc(patch);
if (offset == 0x454F46) break;
size = (unsigned char)getc(patch) << 8;
size |= (unsigned char)getc(patch);
if (fread(buffer + offset, 1, size, patch) != size) FATAL_ERROR("read segment\n");
}
fclose(patch);
fwrite(buffer, 1, romsize, out);
fclose(out);
free(buffer);
return 0;
}