summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/compilers.md63
-rw-r--r--src/code/z_actor.c2
-rw-r--r--src/code/z_kanfont.c2
-rw-r--r--src/code/z_sram.c2
4 files changed, 66 insertions, 3 deletions
diff --git a/docs/compilers.md b/docs/compilers.md
new file mode 100644
index 000000000..120aaf43c
--- /dev/null
+++ b/docs/compilers.md
@@ -0,0 +1,63 @@
+# Compilers
+
+Ocarina of Time was written mostly in C, compiled to MIPS machine code. For the
+N64 and GameCube versions, all code was compiled with the IDO compiler. For the
+iQue Player versions, some of the code (namely libultra, and some game files
+such as those related to Chinese text) was compiled with the EGCS compiler instead.
+
+## IDO
+
+Ocarina of Time was originally developed on
+[Silicon Graphics "Indy"](https://en.wikipedia.org/wiki/SGI_Indy) workstations,
+and IDO (IRIS Development Option) was the C compiler toolchain that shipped with
+these. Two different versions of IDO were used for Ocarina of Time: IDO 5.3 was
+used for some libraries (namely libultra, libleo, and the JPEG library) while
+IDO 7.1 was used for the other libraries and all of the "main" game code.
+
+These Silicon Graphics workstations ran the MIPS-based IRIX operating system, so
+the original compiler binaries can't run on modern systems. Originally this
+project used [qemu-irix](https://github.com/n64decomp/qemu-irix) (now
+unmaintained) to run emulate IRIX on modern systems, but nowadays we use the
+more lightweight
+[ido-static-recomp](https://github.com/decompals/ido-static-recomp) instead.
+
+## EGCS
+
+[EGCS (Experimental/Enhanced GNU Compiler System)](https://en.wikipedia.org/wiki/GNU_Compiler_Collection#EGCS_fork)
+was a fork of the GCC compiler. The Linux-based iQue SDK included a patched
+version of EGCS release 1.1.2. The original compiler can still run on modern Linux
+systems, but we use a
+[modified version](https://github.com/decompals/mips-gcc-egcs-2.91.66)
+that includes Mac support and a few other minor improvements (such as anonymous
+struct/union support).
+
+This version of the EGCS compiler has a bug where code that indexes into an array member can
+fail to compile if the array member is at a large (>= 0x8000) offset in a struct. For
+example, when run on the source code
+
+```c
+struct Foo {
+ char a[0x8000];
+ int b[1];
+};
+
+int test(struct Foo* foo, int i) {
+ return foo->b[i];
+}
+```
+
+the compiler errors with
+
+```
+Compiler error: src.c: In function `test':
+src.c:8: internal error--unrecognizable insn:
+(insn 20 18 22 (set (reg:SI 85)
+ (plus:SI (reg:SI 81)
+ (const_int 32768))) -1 (nil)
+ (nil))
+../../gcc/toplev.c:1367: Internal compiler error in function fatal_insn
+```
+
+In some recompiled files, the game developers had to modify the code to work
+around this bug, for example by storing a pointer to the array in a temporary
+variable before indexing into it.
diff --git a/src/code/z_actor.c b/src/code/z_actor.c
index 0626f05de..37a370557 100644
--- a/src/code/z_actor.c
+++ b/src/code/z_actor.c
@@ -2570,7 +2570,7 @@ void Actor_Draw(PlayState* play, Actor* actor) {
gSPSegment(POLY_OPA_DISP++, 0x06, play->objectCtx.slots[actor->objectSlot].segment);
gSPSegment(POLY_XLU_DISP++, 0x06, play->objectCtx.slots[actor->objectSlot].segment);
#else
- // Workaround for EGCS bug
+ // Workaround for EGCS internal compiler error (see docs/compilers.md)
slots = play->objectCtx.slots;
gSPSegment(POLY_OPA_DISP++, 0x06, slots[actor->objectSlot].segment);
gSPSegment(POLY_XLU_DISP++, 0x06, slots[actor->objectSlot].segment);
diff --git a/src/code/z_kanfont.c b/src/code/z_kanfont.c
index 985e2d52f..fa038276f 100644
--- a/src/code/z_kanfont.c
+++ b/src/code/z_kanfont.c
@@ -119,7 +119,7 @@ void Font_LoadOrderedFont(Font* font) {
PRINTF("msg_data=%x, msg_data0=%x jj=%x\n", font->msgOffset, font->msgLength, len);
- // Workaround for EGCS bug
+ // Workaround for EGCS internal compiler error (see docs/compilers.md)
msgBufWide = font->msgBufWide;
fontBufIndex = 0;
for (codePointIndex = 0; msgBufWide[codePointIndex] != MESSAGE_WIDE_END; codePointIndex++) {
diff --git a/src/code/z_sram.c b/src/code/z_sram.c
index d7d453c9a..0531e2995 100644
--- a/src/code/z_sram.c
+++ b/src/code/z_sram.c
@@ -853,7 +853,7 @@ void Sram_InitSave(FileSelectState* fileSelect, SramContext* sramCtx) {
#if !PLATFORM_IQUE
gSaveContext.save.info.playerData.playerName[offset] = fileSelect->fileNames[fileSelect->buttonIndex][offset];
#else
- // Workaround for EGCS bug
+ // Workaround for EGCS internal compiler error (see docs/compilers.md)
u8* fileName = fileSelect->fileNames[fileSelect->buttonIndex];
gSaveContext.save.info.playerData.playerName[offset] = fileName[offset];