From: John Tsiombikas Date: Sat, 23 Jan 2021 17:38:52 +0000 (+0200) Subject: brought the code over from the amiga test X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=lugburz;a=commitdiff_plain;h=515574f76f8442b756fbbf87b41e340d6a78bc42 brought the code over from the amiga test --- 515574f76f8442b756fbbf87b41e340d6a78bc42 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a73195 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +*.d +*.swp +*.elf +*.bin +*.adf +link.map diff --git a/Makefile.amiga b/Makefile.amiga new file mode 100644 index 0000000..cff0ffb --- /dev/null +++ b/Makefile.amiga @@ -0,0 +1,57 @@ +src = $(wildcard src/*.c) \ + $(wildcard src/amiga/*.c) \ + $(wildcard src/amiga/libc/*.c) +asrc = $(wildcard src/*.s) \ + $(wildcard src/amiga/*.s) \ + $(wildcard src/amiga/libc/*.s) +obj = $(src:.c=.o) $(asrc:.s=.o) +dep = $(src:.c=.d) + +name = lugburz +elf = $(name).elf +bin = $(name).bin +adf = $(name).adf +bootblock = boot.bin + +tool_prefix = m68k-elf- + +CC = $(tool_prefix)gcc +AS = $(tool_prefix)as +LD = $(tool_prefix)gcc +OBJCOPY = $(tool_prefix)objcopy + +inc = -Isrc -Isrc/amiga -Isrc/amiga/libc + +ASFLAGS = -m68000 +CFLAGS = -m68000 -ffreestanding -nostdinc -fno-builtin -pedantic -Wall -Os $(inc) +LDFLAGS = -T amiga.ld -Wl,-print-gc-sections -Wl,-Map,link.map -ffreestanding \ + -nostdlib -lgcc + +$(adf): $(bin) $(bootblock) + tools/mk_adf.py $(bootblock) $(bin) $@ + +$(bin): $(elf) + $(OBJCOPY) -O binary $< $@ + +$(elf): $(obj) + $(LD) -o $@ $(obj) $(LDFLAGS) + +$(bootblock): src/amiga/boot/boot.o + $(OBJCOPY) -O binary $< $@ + +-include $(dep) + +%.d: %.c + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +.PHONY: clean +clean: + rm -f $(obj) src/amiga/boot/boot.o $(bin) $(elf) + +.PHONY: cleandep +cleandep: + rm -f $(dep) + +.PHONY: run +run: + fs-uae diff --git a/amiga.ld b/amiga.ld new file mode 100644 index 0000000..2183783 --- /dev/null +++ b/amiga.ld @@ -0,0 +1,25 @@ +OUTPUT_ARCH(m68k) + +PROVIDE (_stacktop = 0x80000); + +SECTIONS { + /* bootblock will load us at 10000h */ + . = 0x10000; + + .startup : { * (.startup); } + .text : { * (.text); } + .rodata : { * (.rodata); } + .data : { * (.data); } + + .dummy ALIGN(4): { LONG(42); } + + .bss ALIGN(4): { + _bss_start = .; + * (.bss); + . = ALIGN(4); + _bss_end = .; + } + _bss_size = SIZEOF(.bss); + + _mem_start = .; +} diff --git a/fs-uae.conf b/fs-uae.conf new file mode 100644 index 0000000..b57374e --- /dev/null +++ b/fs-uae.conf @@ -0,0 +1,19 @@ +[config] +keep_aspect = 1 +floppies_dir = $HOME/amiga/disks +floppy_overlays_dir = $HOME/amiga/disks +kickstarts_dir = $HOME/amiga/rom +logs_dir = $HOME/amiga/logs +screenshots_output_dir = . +floppy_drive_speed = 0 +floppy_drive_volume = 0 +kickstart_file = $HOME/amiga/rom/kickstart-1.3.rom +console_debugger = 1 +warp_mode = 1 +chip_memory = 512 +fast_memory = 0 +slow_memory = 0 +initial_grab_input = 0 +serial_port = /tmp/uaetty + +floppy_drive_0 = lugburz.adf diff --git a/src/amiga/boot/boot.s b/src/amiga/boot/boot.s new file mode 100644 index 0000000..4f1ccb7 --- /dev/null +++ b/src/amiga/boot/boot.s @@ -0,0 +1,20 @@ +| vi:filetype=gas68k: + .equ CMD_READ, 2 + .equ EXEC_DO_IO, -0x1c8 + .equ LOADADDR, 0x10000 + +start: +| starting with trackdisk device I/O request pointer in a1 +| load the program at 0x100 and jump there +| program length is patched by mk_adf just before start + move.l -6(%pc), %d0 | get program size + move.w #0x080, 0xdff180 + move.l %d0, 0x24(%a1) | I/O length + move.l #LOADADDR, 0x28(%a1) | I/O data pointer + move.l #512, 0x2c(%a1) | I/O offset (skip first sector) + move.w #CMD_READ, 0x1c(%a1) | I/O command + jsr EXEC_DO_IO(%a6) + move.w #0xf0f, 0xdff180 + + jmp LOADADDR + .align 4 diff --git a/src/amiga/copper.c b/src/amiga/copper.c new file mode 100644 index 0000000..bee6a8a --- /dev/null +++ b/src/amiga/copper.c @@ -0,0 +1,77 @@ +#include "copper.h" +#include "hwregs.h" + +uint32_t *copperlist, *copperlist_end; +static uint32_t *copmem, *curlist; +static int mode, copmem_size; + +extern uint32_t **_mem_start; + +int init_copper(uint32_t *cmem, int maxlist, int nlists) +{ + /* allocate and set new copper lists */ + if(maxlist <= 0) maxlist = 256; + mode = nlists >= COPPER_DOUBLE ? COPPER_DOUBLE : COPPER_SINGLE; + + copmem_size = maxlist * 4 * mode; + copmem = cmem ? cmem : *_mem_start; + + curlist = copperlist = copmem; + *curlist = COPPER_END; + + if(mode == COPPER_DOUBLE) { + copperlist = curlist + maxlist; + *copperlist = COPPER_END; + } + copperlist_end = copperlist; + + REG32_COP1LC = (uint32_t)curlist; + REG_COPJMP1 = 0; /* causes copper to read COP1LC */ + return 0; +} + +void cleanup_copper(void) +{ +} + +void enable_copper(void) +{ + REG_DMACON = SETBITS(DMA_COPPER); +} + +void disable_copper(void) +{ + REG_DMACON = CLRBITS(DMA_COPPER); +} + +void clear_copper(void) +{ + copperlist_end = copperlist; + *copperlist_end = COPPER_END; +} + +void add_copper(uint32_t cmd) +{ + *copperlist_end++ = cmd; +} + +void sort_copper(void) +{ + /* TODO */ +} + +void swap_copper(void) +{ + if(mode == COPPER_DOUBLE) { + uint32_t *tmpptr; + tmpptr = curlist; + curlist = copperlist; + copperlist = copperlist_end = tmpptr; + + REG32_COP1LC = (uint32_t)curlist; + REG_COPJMP1 = 0; + } else { + copperlist_end = curlist; + } + *copperlist_end = COPPER_END; +} diff --git a/src/amiga/copper.h b/src/amiga/copper.h new file mode 100644 index 0000000..29be226 --- /dev/null +++ b/src/amiga/copper.h @@ -0,0 +1,39 @@ +#ifndef COPPER_H_ +#define COPPER_H_ + +#include "inttypes.h" + +#define COPPER_MOVE(reg, data) (((uint32_t)(reg) << 16) | ((uint32_t)(data) & 0xffff)) +#define COPPER_WAIT(x, y) \ + (0x0001fffe | ((uint32_t)((x) + 0x81) << 16) | ((uint32_t)((y) + 0x2c) << 24)) +#define COPPER_WAIT_OVERSCAN(x, y) \ + (0x0001fffe | ((uint32_t)(x) << 16) | ((uint32_t)(y) << 24)) +#define COPPER_VWAIT(s) (0x0001ff00 | ((uint32_t)((s) + 0x2c) << 24)) +#define COPPER_VWAIT_OVERSCAN(s) \ + (0x0001ff00 | ((uint32_t)(s) << 24)) +#define COPPER_OVERFLOW 0xffdffffe +#define COPPER_END 0xfffffffe + +extern uint32_t *copperlist, *copperlist_end; + +enum { + COPPER_SINGLE = 1, + COPPER_DOUBLE = 2 +}; + +int init_copper(uint32_t *cmem, int maxlist, int nlists); +void cleanup_copper(void); + +/* enables copper DMA */ +void enable_copper(void); +/* disables copper DMA */ +void disable_copper(void); + +void clear_copper(void); +void add_copper(uint32_t cmd); +void sort_copper(void); /* TODO */ + +void swap_copper(void); + + +#endif /* COPPER_H_ */ diff --git a/src/amiga/gfx.c b/src/amiga/gfx.c new file mode 100644 index 0000000..b18e027 --- /dev/null +++ b/src/amiga/gfx.c @@ -0,0 +1,26 @@ +#include "gfx.h" +#include "hwregs.h" + +int init_gfx(void) +{ + int i; + + REG_BPLCON0 = BPLCON0_COUNT(NBPL) | BPLCON0_COLOR; + REG_BPLCON1 = 0; + REG_DIWSTART = 0x2c81; + REG_DIWSTOP = 0x2cc1; + REG_DDFSTART = 0x38; + REG_DDFSTOP = 0xd0; + + for(i=0; i= '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/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..c404a52 --- /dev/null +++ b/src/amiga/libc/stdio.c @@ -0,0 +1,265 @@ +#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) +{ + if(c == '\n') { + ser_putchar('\r'); + } + 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..9b8dcc4 --- /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 % base; + *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a'); + val /= base; + } + + 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 new file mode 100644 index 0000000..ea0a6dc --- /dev/null +++ b/src/amiga/libc/stdlib.h @@ -0,0 +1,16 @@ +#ifndef AMIGA_LIBC_STDLIB_H_ +#define AMIGA_LIBC_STDLIB_H_ + +#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 new file mode 100644 index 0000000..e1a1182 --- /dev/null +++ b/src/amiga/libc/string.h @@ -0,0 +1,20 @@ +#ifndef AMIGA_LIBC_STRING_H_ +#define AMIGA_LIBC_STRING_H_ + +#include + +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/amiga/main.c b/src/amiga/main.c new file mode 100644 index 0000000..7585bf0 --- /dev/null +++ b/src/amiga/main.c @@ -0,0 +1,53 @@ +#include +#include "hwregs.h" +#include "copper.h" +#include "gfx.h" +#include "game.h" +#include "serial.h" + +static uint32_t coplist[128]; + +int main(void) +{ + int i; + + REG_INTENA = SETBITS(INTEN_VERTB | INTEN_MASTER); + REG_DMACON = CLRBITS(DMA_ALL); + + ser_init(38400); + ser_print("lugburz amiga starting up...\n"); + + init_gfx(); + + REG_COLOR0 = 0x111; + REG_COLOR1 = 0x23c; + REG_COLOR2 = 0xc32; + REG_COLOR3 = 0x22c; + REG_COLOR4 = 0xcc2; + + wait_vblank(); + + init_copper(coplist, 32, COPPER_SINGLE); + for(i=0; i> 16)); + add_copper(COPPER_MOVE(reg + 2, addr)); + } + add_copper(COPPER_VWAIT(50)); + add_copper(COPPER_MOVE(REGN_COLOR0, 0xf00)); + add_copper(COPPER_VWAIT(60)); + add_copper(COPPER_MOVE(REGN_COLOR0, 0x111)); + *copperlist_end = COPPER_END; + + game_init(); + + wait_vblank(); + REG_DMACON = SETBITS(DMA_BPL | DMA_COPPER | DMA_MASTER); + + for(;;) { + wait_vblank(); + game_draw(); + } + return 0; +} diff --git a/src/amiga/serial.c b/src/amiga/serial.c new file mode 100644 index 0000000..dae3a12 --- /dev/null +++ b/src/amiga/serial.c @@ -0,0 +1,48 @@ +#include "hwregs.h" +#include "serial.h" + +#define CLK 3546895 +#define BVAL(b) (CLK / (b) - 1) + +static inline uint16_t baudval(int baud) +{ + switch(baud) { + case 110: return BVAL(110); + case 300: return BVAL(300); + case 600: return BVAL(600); + case 1200: return BVAL(1200); + case 2400: return BVAL(2400); + case 4800: return BVAL(4800); + case 9600: return BVAL(9600); + case 14400: return BVAL(14400); + case 19200: return BVAL(19200); + case 38400: return BVAL(38400); + case 57600: return BVAL(57600); + case 115200: return BVAL(115200); + default: + break; + } + return BVAL(baud); +} + +void ser_init(int baud) +{ + REG_SERPER = baudval(baud) & 0x7fff; +} + +/* +void ser_putchar(int c) +{ + REG_SERDAT = ((uint16_t)c & 0xff) | 0x100; +} +*/ + +void ser_print(const char *s) +{ + while(*s) { + if(*s == '\n') { + ser_putchar('\r'); + } + ser_putchar(*s++); + } +} diff --git a/src/amiga/serial.h b/src/amiga/serial.h new file mode 100644 index 0000000..e460c98 --- /dev/null +++ b/src/amiga/serial.h @@ -0,0 +1,21 @@ +#ifndef SERIAL_H_ +#define SERIAL_H_ + +#include "hwregs.h" + +/* dff030 is REG_SERDAT + * dff018 is REG_SERDATR + * bit 13 of SERDATR is TBE (transmit buffer empty) + */ +#define ser_putchar(c) \ + asm volatile( \ + "or.w #0x100, %0\n\t" \ + "0: btst #13, 0xdff018\n\t" \ + "beq 0b\n\t" \ + "move.w %0, 0xdff030\n\t" \ + :: "d"((int16_t)c)) + +void ser_init(int baud); +void ser_print(const char *s); + +#endif /* SERIAL_H_ */ diff --git a/src/amiga/startup.s b/src/amiga/startup.s new file mode 100644 index 0000000..745cf67 --- /dev/null +++ b/src/amiga/startup.s @@ -0,0 +1,30 @@ +| vi:filetype=gas68k: + .global halt_cpu + .extern main + + .section .startup,"a" + + | enter supervisor mode (assumes VBR=0) + move.l #super, 0x80 + trap #0 +super: + ori.w #0x0300, %sr | disable interrupts + + | zero the .bss section + move.l #_bss_start, %a0 + move.l #_bss_end, %a1 + cmp.l %a0, %a1 + beq.s 1f | skip zeroing if the section is empty +0: clr.b (%a0)+ + cmp.l %a0, %a1 + bne.s 0b +1: + | setup the stack + move.l #_stacktop, %sp + andi.w #0xf8ff, %sr | enable interrupts + + jsr main +0: bra.b 0b + +halt_cpu: + stop #0x2700 diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..e5b6912 --- /dev/null +++ b/src/game.c @@ -0,0 +1,15 @@ +#include +#include +#include "game.h" +#include "gfx.h" + +int game_init(void) +{ + printf("hello world\n"); + + return 0; +} + +void game_draw(void) +{ +} diff --git a/src/game.h b/src/game.h new file mode 100644 index 0000000..69c14e8 --- /dev/null +++ b/src/game.h @@ -0,0 +1,7 @@ +#ifndef GAME_H_ +#define GAME_H_ + +int game_init(void); +void game_draw(void); + +#endif /* GAME_H_ */ diff --git a/tools/mk_adf.py b/tools/mk_adf.py new file mode 100755 index 0000000..64b0d94 --- /dev/null +++ b/tools/mk_adf.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# mk_adf.py +# +# Stuff a given bootblock and payload into an output ADF image. +# +# Written & released by Keir Fraser +# +# This is free and unencumbered software released into the public domain. +# See the file COPYING for more details, or visit . + +import struct, sys + +# Amiga bootblock checksum +def checksum(bb, sum=0): + while len(bb): + x, bb = struct.unpack(">L",bb[:4]), bb[4:] + sum += x[0] + if sum >= (1<<32): + sum -= (1<<32)-1 + return sum + +def main(argv): + bb_f = open(argv[1], "rb") + pl_f = open(argv[2], "rb") + out_f = open(argv[3], "wb") + bb_dat = bb_f.read() + pl_dat = pl_f.read() + + # Construct bootblock header. We will splice in the checksum later. + header = struct.pack(">ccccLLLL", + 'D', 'O', 'S', '\0', # Bootblock signature + 0, # Checksum (placeholder) + 880, # Root block + 0x60060000, # BRA.B +6 + (len(pl_dat) + 511) & ~511) # Payload length, padded + + + # Compute checksum over header, bootblock, and first 512 bytes of payload. + sum = checksum(pl_dat[:512], checksum(bb_dat, checksum(header))) + sum ^= 0xFFFFFFFF + # Splice the computed checksum into the header + header = header[:4] + struct.pack(">L", sum) + header[8:] + # Write out the header and bootblock code + out_f.write(header) + out_f.write(bb_dat) + # Pad bootblock to 512 bytes + for x in xrange((512-len(bb_dat)-len(header))/4): + out_f.write(struct.pack(">L", 0)) + # Write the payload from sector 1 onwards + out_f.write(pl_dat) + # Pad the ADF image to 880kB + for x in xrange((901120-len(pl_dat)-512)/4): + out_f.write(struct.pack(">L", 0)) + +if __name__ == "__main__": + main(sys.argv)