From 08dc7cfecb35a6893f7f8d96196859593272da3b Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 4 Aug 2018 04:47:34 +0300 Subject: [PATCH] libc for the amiga version --- Makefile.amiga | 3 +- src/amiga/libc/ctype.c | 56 ++++++++++ src/amiga/libc/ctype.h | 17 +++ src/amiga/libc/inttypes.h | 17 +++ src/amiga/libc/libc_asm.s | 24 ----- src/amiga/libc/stdarg.h | 10 ++ src/amiga/libc/stdint.h | 6 ++ src/amiga/libc/stdio.c | 262 +++++++++++++++++++++++++++++++++++++++++++++ src/amiga/libc/stdio.h | 21 ++++ src/amiga/libc/stdlib.c | 119 ++++++++++++++++++++ src/amiga/libc/stdlib.h | 12 ++- src/amiga/libc/string.c | 116 ++++++++++++++++++++ src/amiga/libc/string.h | 13 ++- src/game.c | 3 + 14 files changed, 652 insertions(+), 27 deletions(-) create mode 100644 src/amiga/libc/ctype.c create mode 100644 src/amiga/libc/ctype.h create mode 100644 src/amiga/libc/inttypes.h delete mode 100644 src/amiga/libc/libc_asm.s create mode 100644 src/amiga/libc/stdarg.h create mode 100644 src/amiga/libc/stdint.h create mode 100644 src/amiga/libc/stdio.c create mode 100644 src/amiga/libc/stdio.h create mode 100644 src/amiga/libc/stdlib.c create mode 100644 src/amiga/libc/string.c diff --git a/Makefile.amiga b/Makefile.amiga index c6fbfbd..7d9a255 100644 --- a/Makefile.amiga +++ b/Makefile.amiga @@ -1,5 +1,6 @@ src = $(wildcard src/*.c) \ - $(wildcard src/amiga/*.c) + $(wildcard src/amiga/*.c) \ + $(wildcard src/amiga/libc/*.c) asrc = $(wildcard src/*.s) \ $(wildcard src/amiga/*.s) \ $(wildcard src/amiga/libc/*.s) diff --git a/src/amiga/libc/ctype.c b/src/amiga/libc/ctype.c new file mode 100644 index 0000000..9676441 --- /dev/null +++ b/src/amiga/libc/ctype.c @@ -0,0 +1,56 @@ +#include "ctype.h" + +int isalnum(int c) +{ + return isalpha(c) || isdigit(c); +} + +int isalpha(int c) +{ + return isupper(c) || islower(c); +} + +int isblank(int c) +{ + return c == ' ' || c == '\t'; +} + +int isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +int isupper(int c) +{ + return c >= 'A' && c <= 'Z'; +} + +int islower(int c) +{ + return c >= 'a' && c <= 'z'; +} + +int isgraph(int c) +{ + return c > ' ' && c <= '~'; +} + +int isprint(int c) +{ + return isgraph(c) || c == ' '; +} + +int isspace(int c) +{ + return isblank(c) || c == '\f' || c == '\n' || c == '\r' || c == '\v'; +} + +int toupper(int c) +{ + return islower(c) ? (c + ('A' - 'a')) : c; +} + +int tolower(int c) +{ + return isupper(c) ? (c + ('A' - 'a')) : c; +} diff --git a/src/amiga/libc/ctype.h b/src/amiga/libc/ctype.h new file mode 100644 index 0000000..5b010d4 --- /dev/null +++ b/src/amiga/libc/ctype.h @@ -0,0 +1,17 @@ +#ifndef CTYPE_H_ +#define CTYPE_H_ + +int isalnum(int c); +int isalpha(int c); +#define isascii(c) ((c) < 128) +int isblank(int c); +int isdigit(int c); +int isupper(int c); +int islower(int c); +int isprint(int c); +int isspace(int c); + +int toupper(int c); +int tolower(int c); + +#endif /* CTYPE_H_ */ diff --git a/src/amiga/libc/inttypes.h b/src/amiga/libc/inttypes.h new file mode 100644 index 0000000..1edfed1 --- /dev/null +++ b/src/amiga/libc/inttypes.h @@ -0,0 +1,17 @@ +#ifndef AMIGA_LIBC_INTTYPES_H_ +#define AMIGA_LIBC_INTTYPES_H_ + +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; + +#endif /* AMIGA_LIBC_INTTYPES_H_ */ diff --git a/src/amiga/libc/libc_asm.s b/src/amiga/libc/libc_asm.s deleted file mode 100644 index 095c8df..0000000 --- a/src/amiga/libc/libc_asm.s +++ /dev/null @@ -1,24 +0,0 @@ -| vi:filetype=gas68k: - .text - - | optimize: transfer words at a time - .global memcpy -memcpy: - move.l 4(%sp), %a0 - move.l 8(%sp), %a1 - move.l 12(%sp), %d0 - sub.l #1, %d0 -0: move.b (%a1)+, (%a0)+ - dbra %d0, 0b - rts - - | optimize: same as above - .global memset -memset: - move.l 4(%sp), %a0 - move.l 8(%sp), %d1 - move.l 12(%sp), %d0 - sub.l #1, %d0 -0: move.b %d1, (%a0)+ - dbra %d0, 0b - rts diff --git a/src/amiga/libc/stdarg.h b/src/amiga/libc/stdarg.h new file mode 100644 index 0000000..696aab2 --- /dev/null +++ b/src/amiga/libc/stdarg.h @@ -0,0 +1,10 @@ +#ifndef STDARG_H_ +#define STDARG_H_ + +typedef __builtin_va_list va_list; + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) + +#endif /* STDARG_H_ */ diff --git a/src/amiga/libc/stdint.h b/src/amiga/libc/stdint.h new file mode 100644 index 0000000..775c434 --- /dev/null +++ b/src/amiga/libc/stdint.h @@ -0,0 +1,6 @@ +#ifndef AMIGA_LIBC_STDINT_H_ +#define AMIGA_LIBC_STDINT_H_ + +#include + +#endif /* AMIGA_LIBC_STDINT_H_ */ diff --git a/src/amiga/libc/stdio.c b/src/amiga/libc/stdio.c new file mode 100644 index 0000000..45e8aec --- /dev/null +++ b/src/amiga/libc/stdio.c @@ -0,0 +1,262 @@ +#include +#include +#include +#include "serial.h" + +static void bwrite(char *buf, size_t buf_sz, char *str, int sz); +static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap); + +int putchar(int c) +{ + ser_putchar(c); + return c; +} + +int puts(const char *s) +{ + while(*s) { + putchar(*s++); + } + putchar('\n'); + return 0; +} + +/* -- printf and friends -- */ + +static char *convc = "dioxXucsfeEgGpn%"; + +#define IS_CONV(c) strchr(convc, c) + +int printf(const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = intern_printf(0, 0, fmt, ap); + va_end(ap); + return res; +} + +int vprintf(const char *fmt, va_list ap) +{ + return intern_printf(0, 0, fmt, ap); +} + +int sprintf(char *buf, const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = intern_printf(buf, 0, fmt, ap); + va_end(ap); + return res; +} + +int vsprintf(char *buf, const char *fmt, va_list ap) +{ + return intern_printf(buf, 0, fmt, ap); +} + +int snprintf(char *buf, size_t sz, const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = intern_printf(buf, sz, fmt, ap); + va_end(ap); + return res; +} + +int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap) +{ + return intern_printf(buf, sz, fmt, ap); +} + + +/* intern_printf provides all the functionality needed by all the printf + * variants. + * - buf: optional buffer onto which the formatted results are written. If null + * then the output goes to the terminal through putchar calls. This is used + * by the (v)sprintf variants which write to an array of char. + * - sz: optional maximum size of the output, 0 means unlimited. This is used + * by the (v)snprintf variants to avoid buffer overflows. + * The rest are obvious, format string and variable argument list. + */ + +#define BUF(x) ((x) ? (x) + cnum : (x)) +#define SZ(x) ((x) ? (x) - cnum : (x)) + +static int intern_printf(char *buf, size_t sz, const char *fmt, va_list ap) +{ + char conv_buf[32]; + char *str; + int i, slen; + const char *fstart = 0; + + /* state */ + int cnum = 0; + int base = 10; + int alt = 0; + int fwidth = 0; + int padc = ' '; + int sign = 0; + int left_align = 0; /* not implemented yet */ + int hex_caps = 0; + int unsig = 0; + + while(*fmt) { + if(*fmt == '%') { + fstart = fmt++; + continue; + } + + if(fstart) { + if(IS_CONV(*fmt)) { + switch(*fmt) { + case 'X': + hex_caps = 1; + + case 'x': + case 'p': + base = 16; + + if(alt) { + bwrite(BUF(buf), SZ(sz), "0x", 2); + } + + case 'u': + unsig = 1; + + if(0) { + case 'o': + base = 8; + + if(alt) { + bwrite(BUF(buf), SZ(sz), "0", 1); + } + } + + case 'd': + case 'i': + if(unsig) { + utoa(va_arg(ap, unsigned int), conv_buf, base); + } else { + itoa(va_arg(ap, int), conv_buf, base); + } + if(hex_caps) { + for(i=0; conv_buf[i]; i++) { + conv_buf[i] = toupper(conv_buf[i]); + } + } + + slen = strlen(conv_buf); + for(i=slen; i +#include + +int putchar(int c); +int getchar(void); + +int puts(const char *s); + +int printf(const char *fmt, ...); +int vprintf(const char *fmt, va_list ap); + +int sprintf(char *buf, const char *fmt, ...); +int vsprintf(char *buf, const char *fmt, va_list ap); + +int snprintf(char *buf, size_t sz, const char *fmt, ...); +int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap); + +#endif /* STDIO_H_ */ diff --git a/src/amiga/libc/stdlib.c b/src/amiga/libc/stdlib.c new file mode 100644 index 0000000..6496c8d --- /dev/null +++ b/src/amiga/libc/stdlib.c @@ -0,0 +1,119 @@ +#include +#include + +int atoi(const char *str) +{ + return strtol(str, 0, 10); +} + +long atol(const char *str) +{ + return strtol(str, 0, 10); +} + +long strtol(const char *str, char **endp, int base) +{ + long acc = 0; + int sign = 1; + + while(isspace(*str)) str++; + + if(base == 0) { + if(str[0] == '0') { + if(str[1] == 'x' || str[1] == 'X') { + base = 16; + } else { + base = 8; + } + } else { + base = 10; + } + } + + if(*str == '+') { + str++; + } else if(*str == '-') { + sign = -1; + str++; + } + + while(*str) { + long val; + char c = tolower(*str); + + if(isdigit(c)) { + val = *str - '0'; + } else if(c >= 'a' || c <= 'f') { + val = 10 + c - 'a'; + } + if(val >= base) { + break; + } + + acc = acc * base + val; + str++; + } + + if(endp) { + *endp = (char*)str; + } + + return sign > 0 ? acc : -acc; +} + +void itoa(int val, char *buf, int base) +{ + static char rbuf[16]; + char *ptr = rbuf; + int neg = 0; + + if(val < 0) { + neg = 1; + val = -val; + } + + if(val == 0) { + *ptr++ = '0'; + } + + while(val) { + int digit = val % 10; + *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a'); + val /= 10; + } + + if(neg) { + *ptr++ = '-'; + } + + ptr--; + + while(ptr >= rbuf) { + *buf++ = *ptr--; + } + *buf = 0; +} + +void utoa(unsigned int val, char *buf, int base) +{ + static char rbuf[16]; + char *ptr = rbuf; + + if(val == 0) { + *ptr++ = '0'; + } + + while(val) { + unsigned int digit = val % base; + *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a'); + val /= base; + } + + ptr--; + + while(ptr >= rbuf) { + *buf++ = *ptr--; + } + *buf = 0; +} + diff --git a/src/amiga/libc/stdlib.h b/src/amiga/libc/stdlib.h index e0a11dc..ea0a6dc 100644 --- a/src/amiga/libc/stdlib.h +++ b/src/amiga/libc/stdlib.h @@ -1,6 +1,16 @@ #ifndef AMIGA_LIBC_STDLIB_H_ #define AMIGA_LIBC_STDLIB_H_ -typedef long size_t; +#include + +typedef int32_t ssize_t; +typedef uint32_t size_t; + +int atoi(const char *str); +long atol(const char *str); +long strtol(const char *str, char **endp, int base); + +void itoa(int val, char *buf, int base); +void utoa(unsigned int val, char *buf, int base); #endif /* AMIGA_LIBC_STDLIB_H_ */ diff --git a/src/amiga/libc/string.c b/src/amiga/libc/string.c new file mode 100644 index 0000000..9260cca --- /dev/null +++ b/src/amiga/libc/string.c @@ -0,0 +1,116 @@ +#include +#include + +void memset(void *s, int c, size_t n) +{ + char *ptr = s; + while(n--) { + *ptr++ = c; + } +} + +void *memcpy(void *dest, const void *src, size_t n) +{ + char *dptr = dest; + const char *sptr = src; + + while(n--) { + *dptr++ = *sptr++; + } + return dest; +} + +void *memmove(void *dest, const void *src, size_t n) +{ + int i; + char *dptr; + const char *sptr; + + if(dest <= src) { + /* forward copy */ + dptr = dest; + sptr = src; + for(i=0; i= s) { + if(*ptr == c) { + return (char*)ptr; + } + } + return 0; +} + +char *strstr(const char *str, const char *substr) +{ + while(*str) { + const char *s1 = str; + const char *s2 = substr; + + while(*s1 && *s1 == *s2) { + s1++; + s2++; + } + if(!*s2) { + return (char*)str; + } + str++; + } + return 0; +} + +int strcmp(const char *s1, const char *s2) +{ + while(*s1 && *s1 == *s2) { + s1++; + s2++; + } + return *s1 - *s2; +} + +int strcasecmp(const char *s1, const char *s2) +{ + while(*s1 && tolower(*s1) == tolower(*s2)) { + s1++; + s2++; + } + return tolower(*s1) - tolower(*s2); +} diff --git a/src/amiga/libc/string.h b/src/amiga/libc/string.h index a2e4c74..e1a1182 100644 --- a/src/amiga/libc/string.h +++ b/src/amiga/libc/string.h @@ -3,7 +3,18 @@ #include -void memcpy(void *dest, const void *src, size_t n); void memset(void *dest, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); + +size_t strlen(const char *s); + +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); + +char *strstr(const char *str, const char *substr); + +int strcmp(const char *s1, const char *s2); +int strcasecmp(const char *s1, const char *s2); #endif /* AMIGA_LIBC_STRING_H_ */ diff --git a/src/game.c b/src/game.c index 89b4e5a..87edac7 100644 --- a/src/game.c +++ b/src/game.c @@ -1,3 +1,4 @@ +#include #include #include "game.h" #include "gfx.h" @@ -21,6 +22,8 @@ int game_init(void) { int i; + printf("hello world\n"); + REG_COLOR0 = 0x221; REG_COLOR1 = 0x222; REG_COLOR2 = 0x332; -- 1.7.10.4