summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcamthesaxman <cameronghall@cox.net>2016-07-23 14:18:19 -0500
committerYamaArashi <YamaArashi@users.noreply.github.com>2016-07-23 12:18:19 -0700
commit2b4143ce6891e2c15db4c9188fd80002a0f7e248 (patch)
tree750fd4109b43720a302c944b508342b9f443bed1
parentaae9a50849c7d5a71005062f32545fce0e2ccf55 (diff)
decompile libc (#24)
-rw-r--r--Makefile5
-rw-r--r--ld_script.txt2
-rw-r--r--src/libc.c143
3 files changed, 148 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index aa187456f..90d72096b 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,7 @@ C_SRCS := $(wildcard src/*.c)
C_OBJS := $(C_SRCS:%.c=%.o)
ASM_OBJS := asm/crt0.o asm/rom3.o asm/rom4.o asm/rom_8074BAC.o asm/rom5.o \
- asm/libgcnmultiboot.o asm/m4a_1.o asm/m4a_3.o asm/libagbsyscall.o asm/libc.o
+ asm/libgcnmultiboot.o asm/m4a_1.o asm/m4a_3.o asm/libagbsyscall.o
DATA_ASM_OBJS := data/data1.o data/data2.o data/graphics.o data/sound_data.o \
data/event_scripts.o data/battle_anim_scripts.o
@@ -85,6 +85,9 @@ include misc.mk
%.gbapal: %.pal ; $(GFX) $< $@
%.lz: % ; $(GFX) $< $@
+src/libc_ruby.o src/libc_sapphire.o: CC1 := tools/agbcc/bin/old_agbcc
+src/libc_ruby.o src/libc_sapphire.o: CFLAGS := -O2
+
src/siirtc_ruby.o src/siirtc_sapphire.o: CFLAGS := -mthumb-interwork
src/agb_flash_ruby.o src/agb_flash_sapphire.o: CFLAGS := -O -mthumb-interwork
diff --git a/ld_script.txt b/ld_script.txt
index 89dff1a5d..ed3aa449d 100644
--- a/ld_script.txt
+++ b/ld_script.txt
@@ -109,7 +109,7 @@ SECTIONS {
tools/agbcc/lib/libgcc.a:fp-bit.o(.text);
tools/agbcc/lib/libgcc.a:_lshrdi3.o(.text);
tools/agbcc/lib/libgcc.a:_negdi2.o(.text);
- asm/libc.o(.text);
+ src/libc.o(.text);
} =0
.rodata :
diff --git a/src/libc.c b/src/libc.c
new file mode 100644
index 000000000..e408ba51e
--- /dev/null
+++ b/src/libc.c
@@ -0,0 +1,143 @@
+#include "global.h"
+#include <stddef.h>
+
+#define LBLOCKSIZE (sizeof(long))
+
+// Nonzero if (long)X contains a NULL byte.
+#define CONTAINSNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
+
+// Nonzero if X is not aligned on a "long" boundary.
+#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
+
+void *memcpy(void *dst0, const void *src0, size_t len0)
+{
+ char *dst = dst0;
+ const char *src = src0;
+ long *aligned_dst;
+ const long *aligned_src;
+ unsigned int len = len0;
+
+ // If the size is small, or either src or dst is unaligned,
+ // then go to the byte copy loop. This should be rare.
+ if(len >= 16 && !(UNALIGNED(src) | UNALIGNED(dst)))
+ {
+ aligned_dst = (long *)dst;
+ aligned_src = (long *)src;
+
+ // Copy 4X long words at a time if possible.
+ while(len >= 16)
+ {
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ len -= 16;
+ }
+
+ // Copy one long word at a time if possible
+ while(len >= 4)
+ {
+ *aligned_dst++ = *aligned_src++;
+ len -= 4;
+ }
+
+ dst = (char *)aligned_dst;
+ src = (char *)aligned_src;
+ }
+
+ // Pick up any remaining bytes with a byte copier.
+ while(len--)
+ *dst++ = *src++;
+
+ return dst0;
+}
+
+void *memset(void *m, int c, size_t n)
+{
+ char *s = (char *)m;
+ int count, i;
+ unsigned long buffer;
+ unsigned long *aligned_addr;
+ unsigned char *unaligned_addr;
+
+ // If the size is small or m is unaligned,
+ // then go to the byte copy loop. This should be rare.
+ if(n >= LBLOCKSIZE && !UNALIGNED(m))
+ {
+ // We know that n is large and m is word-aligned.
+ aligned_addr = (unsigned long *)m;
+
+ // Store C into each char sized location in buffer so that
+ // we can set large blocks quickly.
+ c &= 0xFF;
+ if(LBLOCKSIZE == 4)
+ {
+ buffer = (c << 8) | c;
+ buffer |= (buffer << 16);
+ }
+ else
+ {
+ buffer = 0;
+ for(i = 0; i < LBLOCKSIZE; i++)
+ buffer = (buffer << 8) | c;
+ }
+
+ while(n >= LBLOCKSIZE * 4)
+ {
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ n -= LBLOCKSIZE * 4;
+ }
+ while(n >= LBLOCKSIZE)
+ {
+ *aligned_addr++ = buffer;
+ n -= LBLOCKSIZE;
+ }
+
+ s = (char *)aligned_addr;
+ }
+
+ // Pick up the remainder with a bytewise loop.
+ while(n--)
+ *s++ = (char)c;
+
+ return m;
+}
+
+int strcmp(const char *s1, const char *s2)
+{
+ unsigned long *a1;
+ unsigned long *a2;
+
+ // If s1 or s2 are unaligned, then skip this and compare bytes.
+ if(!(UNALIGNED(s1) | UNALIGNED(s2)))
+ {
+ // Compare them a word at a time.
+ a1 = (unsigned long *)s1;
+ a2 = (unsigned long *)s2;
+ while(*a1 == *a2)
+ {
+ // If *a1 == *a2, and we find a null in *a1,
+ // then the strings must be equal, so return zero.
+ if(CONTAINSNULL(*a1))
+ return 0;
+
+ a1++;
+ a2++;
+ }
+
+ s1 = (char *)a1;
+ s2 = (char *)a2;
+ }
+
+ // Check the remaining few bytes.
+ while(*s1 != '\0' && *s1 == *s2)
+ {
+ s1++;
+ s2++;
+ }
+
+ return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+}