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)
--- /dev/null
+#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;
+}
--- /dev/null
+#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_ */
--- /dev/null
+#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_ */
+++ /dev/null
-| 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
--- /dev/null
+#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_ */
--- /dev/null
+#ifndef AMIGA_LIBC_STDINT_H_
+#define AMIGA_LIBC_STDINT_H_
+
+#include <inttypes.h>
+
+#endif /* AMIGA_LIBC_STDINT_H_ */
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#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<fwidth; i++) {
+ bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
+ cnum++;
+ }
+
+ bwrite(BUF(buf), SZ(sz), conv_buf, strlen(conv_buf));
+ cnum += slen;
+ break;
+
+ case 'c':
+ {
+ char c = va_arg(ap, int);
+ bwrite(BUF(buf), SZ(sz), &c, 1);
+ cnum++;
+ }
+ break;
+
+ case 's':
+ str = va_arg(ap, char*);
+ slen = strlen(str);
+
+ for(i=slen; i<fwidth; i++) {
+ bwrite(BUF(buf), SZ(sz), (char*)&padc, 1);
+ cnum++;
+ }
+ bwrite(BUF(buf), SZ(sz), str, slen);
+ cnum += slen;
+ break;
+
+ case 'n':
+ *va_arg(ap, int*) = cnum;
+ break;
+
+ default:
+ break;
+ }
+
+ /* restore default conversion state */
+ base = 10;
+ alt = 0;
+ fwidth = 0;
+ padc = ' ';
+ hex_caps = 0;
+
+ fstart = 0;
+ fmt++;
+ } else {
+ switch(*fmt) {
+ case '#':
+ alt = 1;
+ break;
+
+ case '+':
+ sign = 1;
+ break;
+
+ case '-':
+ left_align = 1;
+ break;
+
+ case 'l':
+ case 'L':
+ break;
+
+ case '0':
+ padc = '0';
+ break;
+
+ default:
+ if(isdigit(*fmt)) {
+ const char *fw = fmt;
+ while(*fmt && isdigit(*fmt)) fmt++;
+
+ fwidth = atoi(fw);
+ continue;
+ }
+ }
+ fmt++;
+ }
+ } else {
+ bwrite(BUF(buf), SZ(sz), (char*)fmt++, 1);
+ cnum++;
+ }
+ }
+
+ return 0;
+}
+
+
+/* bwrite is called by intern_printf to transparently handle writing into a
+ * buffer (if buf is non-null) or to the terminal (if buf is null).
+ */
+static void bwrite(char *buf, size_t buf_sz, char *str, int sz)
+{
+ if(buf) {
+ if(buf_sz && buf_sz <= sz) sz = buf_sz - 1;
+ memcpy(buf, str, sz);
+
+ buf[sz] = 0;
+ } else {
+ int i;
+ for(i=0; i<sz; i++) {
+ putchar(*str++);
+ }
+ }
+}
+
--- /dev/null
+#ifndef STDIO_H_
+#define STDIO_H_
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+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_ */
--- /dev/null
+#include <stdlib.h>
+#include <ctype.h>
+
+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;
+}
+
#ifndef AMIGA_LIBC_STDLIB_H_
#define AMIGA_LIBC_STDLIB_H_
-typedef long size_t;
+#include <stdint.h>
+
+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_ */
--- /dev/null
+#include <string.h>
+#include <ctype.h>
+
+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<n; i++) {
+ *dptr++ = *sptr++;
+ }
+ } else {
+ /* backwards copy */
+ dptr = (char*)dest + n - 1;
+ sptr = (char*)src + n - 1;
+ for(i=0; i<n; i++) {
+ *dptr-- = *sptr--;
+ }
+ }
+
+ return dest;
+}
+
+size_t strlen(const char *s)
+{
+ size_t len = 0;
+ while(*s++) len++;
+ return len;
+}
+
+char *strchr(const char *s, int c)
+{
+ while(*s) {
+ if(*s == c) {
+ return (char*)s;
+ }
+ s++;
+ }
+ return 0;
+}
+
+char *strrchr(const char *s, int c)
+{
+ const char *ptr = s;
+
+ /* find the end */
+ while(*ptr) ptr++;
+
+ /* go back checking for c */
+ while(--ptr >= 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);
+}
#include <stdlib.h>
-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_ */
+#include <stdio.h>
#include <string.h>
#include "game.h"
#include "gfx.h"
{
int i;
+ printf("hello world\n");
+
REG_COLOR0 = 0x221;
REG_COLOR1 = 0x222;
REG_COLOR2 = 0x332;