--- /dev/null
+*.o
+*.d
+*.swp
+*.elf
+*.bin
+*.adf
+link.map
--- /dev/null
+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
--- /dev/null
+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 = .;
+}
--- /dev/null
+[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
--- /dev/null
+| 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
--- /dev/null
+#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;
+}
--- /dev/null
+#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_ */
--- /dev/null
+#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<NBPL; i++) {
+ bplptr[i] = framebuf + SCANSZ * i;
+ }
+ REG_BPL1MOD = SCANSZ * (NBPL - 1);
+ REG_BPL2MOD = SCANSZ * (NBPL - 1);
+
+ for(i=0; i<32; i++) {
+ REG_COLOR_PTR[i] = 0xf0f;
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef GFX_H_
+#define GFX_H_
+
+#define SCR_W 320
+#define SCR_H 256
+#define SCANSZ (SCR_W / 8)
+#define BPLSZ (SCANSZ * SCR_H)
+#define NBPL 5
+
+#define wait_vpos(x) \
+ asm volatile ( \
+ "0: move.l 0xdff004, %%d0\n\t" \
+ "and.l #0x1ff00, %%d0\n\t" \
+ "cmp.l %0, %%d0\n\t" \
+ "bne 0b\n\t" \
+ :: "i"((x) << 8) : "%d0")
+
+#define wait_vblank() wait_vpos(300)
+
+#define wait_blit() \
+ asm volatile ( \
+ "tst 0xdff002\n\t" \
+ "0: btst #6, 0xdff002\n\t" \
+ "bne 0b\n\t")
+
+unsigned char framebuf[BPLSZ * NBPL];
+unsigned char *bplptr[NBPL];
+
+int init_gfx(void);
+
+#endif /* GFX_H_ */
--- /dev/null
+#ifndef HWREGS_H_
+#define HWREGS_H_
+
+#include "inttypes.h"
+
+#define REG_BASE_ADDR 0xdff000
+
+#define REGN_BLTDDAT 0x000
+#define REGN_DMACONR 0x002
+#define REGN_VPOSR 0x004
+#define REGN_VHPOSR 0x006
+#define REGN_DSKDATR 0x008
+#define REGN_JOY0DAT 0x00a
+#define REGN_JOY1DAT 0x00c
+#define REGN_CLXDAT 0x00e
+#define REGN_ADKCONR 0x010
+#define REGN_POT0DAT 0x012
+#define REGN_POT1DAT 0x014
+#define REGN_POTGOR 0x016
+#define REGN_SERDATR 0x018
+#define REGN_DSKBYTR 0x01a
+#define REGN_INTENAR 0x01c
+#define REGN_INTREQR 0x01e
+#define REGN_DSKPTH 0x020
+#define REGN_DSKPTL 0x022
+#define REGN_DSKLEN 0x024
+#define REGN_DSKDAT 0x026
+#define REGN_REFPTR 0x028
+#define REGN_VPOSW 0x02a
+#define REGN_VHPOSW 0x02c
+#define REGN_COPCON 0x02e
+#define REGN_SERDAT 0x030
+#define REGN_SERPER 0x032
+#define REGN_POTGO 0x034
+#define REGN_JOYTEST 0x036
+#define REGN_STREQU 0x038
+#define REGN_STRVBL 0x03a
+#define REGN_STRHOR 0x03c
+#define REGN_STRLONG 0x03e
+#define REGN_BLTCON0 0x040
+#define REGN_BLTCON1 0x042
+#define REGN_BLTAFWM 0x044
+#define REGN_BLTALWM 0x046
+#define REGN_BLTCPTH 0x048
+#define REGN_BLTCPTL 0x04a
+#define REGN_BLTBPTH 0x04c
+#define REGN_BLTBPTL 0x04e
+#define REGN_BLTAPTH 0x050
+#define REGN_BLTAPTL 0x052
+#define REGN_BLTDPTH 0x054
+#define REGN_BLTDPTL 0x056
+#define REGN_BLTSIZE 0x058
+#define REGN_BLTCON0L 0x05a
+#define REGN_BLTSIZV 0x05c
+#define REGN_BLTSIZH 0x05e
+#define REGN_BLTCMOD 0x060
+#define REGN_BLTBMOD 0x062
+#define REGN_BLTAMOD 0x064
+#define REGN_BLTDMOD 0x066
+#define REGN_BLTCDAT 0x070
+#define REGN_BLTBDAT 0x072
+#define REGN_BLTADAT 0x074
+#define REGN_SPRHDAT 0x078
+#define REGN_DENISEID 0x07c
+#define REGN_DSKSYNC 0x07e
+#define REGN_COP1LCH 0x080
+#define REGN_COP1LCL 0x082
+#define REGN_COP2LCH 0x084
+#define REGN_COP2LCL 0x086
+#define REGN_CMPJMP1 0x088
+#define REGN_CMPJMP2 0x08a
+#define REGN_COPINS 0x08c
+#define REGN_DIWSTART 0x08e
+#define REGN_DIWSTOP 0x090
+#define REGN_DDFSTART 0x092
+#define REGN_DDFSTOP 0x094
+#define REGN_DMACON 0x096
+#define REGN_CLXCON 0x098
+#define REGN_INTENA 0x09a
+#define REGN_INTREQ 0x09c
+#define REGN_ADKCON 0x09e
+
+#define REGN_AUDIO_LCH(c) (REGN_AUDIO0_BASE + (c) * 16 + 0)
+#define REGN_AUDIO_LCL(c) (REGN_AUDIO0_BASE + (c) * 16 + 2)
+#define REGN_AUDIO_LEN(c) (REGN_AUDIO0_BASE + (c) * 16 + 4)
+#define REGN_AUDIO_PER(c) (REGN_AUDIO0_BASE + (c) * 16 + 6)
+#define REGN_AUDIO_VOL(c) (REGN_AUDIO0_BASE + (c) * 16 + 8)
+#define REGN_AUDIO_DAT(c) (REGN_AUDIO0_BASE + (c) * 16 + 10)
+
+#define REGN_AUDIO0_BASE 0x0a0
+#define REGN_AUD0LCH (REGN_AUDIO0_BASE + 0)
+#define REGN_AUD0LCL (REGN_AUDIO0_BASE + 2)
+#define REGN_AUD0LEN (REGN_AUDIO0_BASE + 4)
+#define REGN_AUD0PER (REGN_AUDIO0_BASE + 6)
+#define REGN_AUD0VOL (REGN_AUDIO0_BASE + 8)
+#define REGN_AUD0DAT (REGN_AUDIO0_BASE + 10)
+#define REGN_AUDIO1_BASE 0x0b0
+#define REGN_AUD1LCH (REGN_AUDIO1_BASE + 0)
+#define REGN_AUD1LCL (REGN_AUDIO1_BASE + 2)
+#define REGN_AUD1LEN (REGN_AUDIO1_BASE + 4)
+#define REGN_AUD1PER (REGN_AUDIO1_BASE + 6)
+#define REGN_AUD1VOL (REGN_AUDIO1_BASE + 8)
+#define REGN_AUD1DAT (REGN_AUDIO1_BASE + 10)
+#define REGN_AUDIO2_BASE 0x0c0
+#define REGN_AUD2LCH (REGN_AUDIO2_BASE + 0)
+#define REGN_AUD2LCL (REGN_AUDIO2_BASE + 2)
+#define REGN_AUD2LEN (REGN_AUDIO2_BASE + 4)
+#define REGN_AUD2PER (REGN_AUDIO2_BASE + 6)
+#define REGN_AUD2VOL (REGN_AUDIO2_BASE + 8)
+#define REGN_AUD2DAT (REGN_AUDIO2_BASE + 10)
+#define REGN_AUDIO3_BASE 0x0d0
+#define REGN_AUD3LCH (REGN_AUDIO3_BASE + 0)
+#define REGN_AUD3LCL (REGN_AUDIO3_BASE + 2)
+#define REGN_AUD3LEN (REGN_AUDIO3_BASE + 4)
+#define REGN_AUD3PER (REGN_AUDIO3_BASE + 6)
+#define REGN_AUD3VOL (REGN_AUDIO3_BASE + 8)
+#define REGN_AUD3DAT (REGN_AUDIO3_BASE + 10)
+
+#define REGN_BPL1PTH 0x0e0
+#define REGN_BPL1PTL 0x0e2
+#define REGN_BPL2PTH 0x0e4
+#define REGN_BPL2PTL 0x0e6
+#define REGN_BPL3PTH 0x0e8
+#define REGN_BPL3PTL 0x0ea
+#define REGN_BPL4PTH 0x0ec
+#define REGN_BPL4PTL 0x0ee
+#define REGN_BPL5PTH 0x0f0
+#define REGN_BPL5PTL 0x0f2
+#define REGN_BPL6PTH 0x0f4
+#define REGN_BPL6PTL 0x0f6
+#define REGN_BPLCON0 0x100
+#define REGN_BPLCON1 0x102
+#define REGN_BPLCON2 0x104
+#define REGN_BPLCON3 0x106
+#define REGN_BPL1MOD 0x108
+#define REGN_BPL2MOD 0x10a
+#define REGN_BPL1DAT 0x110
+#define REGN_BPL2DAT 0x112
+#define REGN_BPL3DAT 0x114
+#define REGN_BPL4DAT 0x116
+#define REGN_BPL5DAT 0x118
+#define REGN_BPL6DAT 0x11a
+
+#define REGN_SPR0PTH 0x120
+#define REGN_SPR0PTL 0x122
+#define REGN_SPR1PTH 0x124
+#define REGN_SPR1PTL 0x126
+#define REGN_SPR2PTH 0x128
+#define REGN_SPR2PTL 0x12a
+#define REGN_SPR3PTH 0x12c
+#define REGN_SPR3PTL 0x12e
+#define REGN_SPR4PTH 0x130
+#define REGN_SPR4PTL 0x132
+#define REGN_SPR5PTH 0x134
+#define REGN_SPR5PTL 0x136
+#define REGN_SPR6PTH 0x138
+#define REGN_SPR6PTL 0x13a
+#define REGN_SPR7PTH 0x13c
+#define REGN_SPR7PTL 0x13e
+
+#define REGN_SPRITE_POS(s) (REGN_SPRITE0_BASE + (s) * 8 + 0)
+#define REGN_SPRITE_CTL(s) (REGN_SPRITE0_BASE + (s) * 8 + 2)
+#define REGN_SPRITE_DATA(s) (REGN_SPRITE0_BASE + (s) * 8 + 4)
+#define REGN_SPRITE_DATB(s) (REGN_SPRITE0_BASE + (s) * 8 + 6)
+
+#define REGN_SPRITE0_BASE 0x140
+#define REGN_SPR0POS REGN_SPRITE_POS(0)
+#define REGN_SPR0CTL REGN_SPRITE_CTL(0)
+#define REGN_SPR0DATA REGN_SPRITE_DATA(0)
+#define REGN_SPR0DATB REGN_SPRITE_DATB(0)
+#define REGN_SPRITE1_BASE 0x148
+#define REGN_SPR1POS REGN_SPRITE_POS(1)
+#define REGN_SPR1CTL REGN_SPRITE_CTL(1)
+#define REGN_SPR1DATA REGN_SPRITE_DATA(1)
+#define REGN_SPR1DATB REGN_SPRITE_DATB(1)
+#define REGN_SPRITE2_BASE 0x150
+#define REGN_SPR2POS REGN_SPRITE_POS(2)
+#define REGN_SPR2CTL REGN_SPRITE_CTL(2)
+#define REGN_SPR2DATA REGN_SPRITE_DATA(2)
+#define REGN_SPR2DATB REGN_SPRITE_DATB(2)
+#define REGN_SPRITE3_BASE 0x158
+#define REGN_SPR3POS REGN_SPRITE_POS(3)
+#define REGN_SPR3CTL REGN_SPRITE_CTL(3)
+#define REGN_SPR3DATA REGN_SPRITE_DATA(3)
+#define REGN_SPR3DATB REGN_SPRITE_DATB(3)
+#define REGN_SPRITE4_BASE 0x160
+#define REGN_SPR4POS REGN_SPRITE_POS(4)
+#define REGN_SPR4CTL REGN_SPRITE_CTL(4)
+#define REGN_SPR4DATA REGN_SPRITE_DATA(4)
+#define REGN_SPR4DATB REGN_SPRITE_DATB(4)
+#define REGN_SPRITE5_BASE 0x168
+#define REGN_SPR5POS REGN_SPRITE_POS(5)
+#define REGN_SPR5CTL REGN_SPRITE_CTL(5)
+#define REGN_SPR5DATA REGN_SPRITE_DATA(5)
+#define REGN_SPR5DATB REGN_SPRITE_DATB(5)
+#define REGN_SPRITE6_BASE 0x170
+#define REGN_SPR6POS REGN_SPRITE_POS(6)
+#define REGN_SPR6CTL REGN_SPRITE_CTL(6)
+#define REGN_SPR6DATA REGN_SPRITE_DATA(6)
+#define REGN_SPR6DATB REGN_SPRITE_DATB(6)
+#define REGN_SPRITE7_BASE 0x178
+#define REGN_SPR7POS REGN_SPRITE_POS(7)
+#define REGN_SPR7CTL REGN_SPRITE_CTL(7)
+#define REGN_SPR7DATA REGN_SPRITE_DATA(7)
+#define REGN_SPR7DATB REGN_SPRITE_DATB(7)
+
+#define REGN_COLOR_BASE 0x180
+#define REGN_COLOR(idx) (REGN_COLOR_BASE + (idx) * 2)
+
+#define REGN_COLOR0 REGN_COLOR(0)
+#define REGN_COLOR1 REGN_COLOR(1)
+#define REGN_COLOR2 REGN_COLOR(2)
+#define REGN_COLOR3 REGN_COLOR(3)
+#define REGN_COLOR4 REGN_COLOR(4)
+#define REGN_COLOR5 REGN_COLOR(5)
+#define REGN_COLOR6 REGN_COLOR(6)
+#define REGN_COLOR7 REGN_COLOR(7)
+#define REGN_COLOR8 REGN_COLOR(8)
+#define REGN_COLOR9 REGN_COLOR(9)
+#define REGN_COLOR10 REGN_COLOR(10)
+#define REGN_COLOR11 REGN_COLOR(11)
+#define REGN_COLOR12 REGN_COLOR(12)
+#define REGN_COLOR13 REGN_COLOR(13)
+#define REGN_COLOR14 REGN_COLOR(14)
+#define REGN_COLOR15 REGN_COLOR(15)
+#define REGN_COLOR16 REGN_COLOR(16)
+#define REGN_COLOR17 REGN_COLOR(17)
+#define REGN_COLOR18 REGN_COLOR(18)
+#define REGN_COLOR19 REGN_COLOR(19)
+#define REGN_COLOR20 REGN_COLOR(20)
+#define REGN_COLOR21 REGN_COLOR(21)
+#define REGN_COLOR22 REGN_COLOR(22)
+#define REGN_COLOR23 REGN_COLOR(23)
+#define REGN_COLOR24 REGN_COLOR(24)
+#define REGN_COLOR25 REGN_COLOR(25)
+#define REGN_COLOR26 REGN_COLOR(26)
+#define REGN_COLOR27 REGN_COLOR(27)
+#define REGN_COLOR28 REGN_COLOR(28)
+#define REGN_COLOR29 REGN_COLOR(29)
+#define REGN_COLOR30 REGN_COLOR(30)
+#define REGN_COLOR31 REGN_COLOR(31)
+
+#define REGN_HTOTAL 0x1c0
+#define REGN_HSSTOP 0x1c2
+#define REGN_HBSTART 0x1c4
+#define REGN_HBSTOP 0x1c6
+#define REGN_VTOTAL 0x1c8
+#define REGN_VSSTOP 0x1ca
+#define REGN_VBSTART 0x1cc
+#define REGN_VBSTOP 0x1ce
+#define REGN_BEAMCON0 0x1dc
+#define REGN_HSSTART 0x1de
+#define REGN_VSSTART 0x1e0
+#define REGN_HCENTER 0x1e2
+#define REGN_DIWHIGH 0x1e4
+
+#define REGN_COP1LCH 0x080
+#define REGN_COP1LCL 0x082
+#define REGN_COP2LCH 0x084
+#define REGN_COP2LCL 0x086
+#define REGN_COPJMP1 0x088
+#define REGN_COPJMP2 0x08a
+
+#define REG(r) (*(volatile uint16_t*)(REG_BASE_ADDR | (r)))
+
+#define REG_CIAA_PORTA *(volatile uint8_t*)0xbfe001
+
+#define REG_INTENA REG(REGN_INTENA)
+#define REG_INTENAR REG(REGN_INTENAR)
+#define REG_INTREQ REG(REGN_INTREQ)
+#define REG_INTREQR REG(REGN_INTREQR)
+#define REG_ADKCON REG(REGN_ADKCON)
+#define REG_ADKCONR REG(REGN_ADKCONR)
+#define REG_DMACON REG(REGN_DMACON)
+#define REG_DMACONR REG(REGN_DMACONR)
+#define REG_BPLCON0 REG(REGN_BPLCON0)
+#define REG_BPLCON1 REG(REGN_BPLCON1)
+#define REG_BPLCON2 REG(REGN_BPLCON2)
+#define REG_BPL1PTH REG(REGN_BPL1PTH)
+#define REG_BPL2PTH REG(REGN_BPL2PTH)
+#define REG_BPL3PTH REG(REGN_BPL3PTH)
+#define REG_BPL4PTH REG(REGN_BPL4PTH)
+#define REG_BPL5PTH REG(REGN_BPL5PTH)
+#define REG_BPL6PTH REG(REGN_BPL6PTH)
+#define REG_BPL1PTL REG(REGN_BPL1PTL)
+#define REG_BPL2PTL REG(REGN_BPL2PTL)
+#define REG_BPL3PTL REG(REGN_BPL3PTL)
+#define REG_BPL4PTL REG(REGN_BPL4PTL)
+#define REG_BPL5PTL REG(REGN_BPL5PTL)
+#define REG_BPL6PTL REG(REGN_BPL6PTL)
+#define REG32_BPL1PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL1PTH)
+#define REG32_BPL2PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL2PTH)
+#define REG32_BPL3PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL3PTH)
+#define REG32_BPL4PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL4PTH)
+#define REG32_BPL5PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL5PTH)
+#define REG32_BPL6PT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BPL6PTH)
+#define REG_BPL1MOD REG(REGN_BPL1MOD)
+#define REG_BPL2MOD REG(REGN_BPL2MOD)
+#define REG_DIWSTART REG(REGN_DIWSTART)
+#define REG_DIWSTOP REG(REGN_DIWSTOP)
+#define REG_DDFSTART REG(REGN_DDFSTART)
+#define REG_DDFSTOP REG(REGN_DDFSTOP)
+#define REG_VPOS REG(REGN_VPOS)
+#define REG_VPOSR REG(REGN_VPOSR)
+#define REG_VHPOS REG(REGN_VHPOS)
+#define REG_VHPOSR REG(REGN_VHPOSR)
+#define REG32_VPOSR *(volatile uint32_t*)(REG_BASE_ADDR | REGN_VPOSR)
+
+#define REG_COLOR_PTR ((volatile uint16_t*)(REG_BASE_ADDR | REGN_COLOR0))
+#define REG_COLOR0 REG(REGN_COLOR0)
+#define REG_COLOR1 REG(REGN_COLOR1)
+#define REG_COLOR2 REG(REGN_COLOR2)
+#define REG_COLOR3 REG(REGN_COLOR3)
+#define REG_COLOR4 REG(REGN_COLOR4)
+#define REG_COLOR5 REG(REGN_COLOR5)
+#define REG_COLOR6 REG(REGN_COLOR6)
+#define REG_COLOR7 REG(REGN_COLOR7)
+#define REG_COLOR8 REG(REGN_COLOR8)
+#define REG_COLOR9 REG(REGN_COLOR9)
+#define REG_COLOR10 REG(REGN_COLOR10)
+#define REG_COLOR11 REG(REGN_COLOR11)
+#define REG_COLOR12 REG(REGN_COLOR12)
+#define REG_COLOR13 REG(REGN_COLOR13)
+#define REG_COLOR14 REG(REGN_COLOR14)
+#define REG_COLOR15 REG(REGN_COLOR15)
+#define REG_COLOR16 REG(REGN_COLOR16)
+#define REG_COLOR17 REG(REGN_COLOR17)
+#define REG_COLOR18 REG(REGN_COLOR18)
+#define REG_COLOR19 REG(REGN_COLOR19)
+#define REG_COLOR20 REG(REGN_COLOR20)
+#define REG_COLOR21 REG(REGN_COLOR21)
+#define REG_COLOR22 REG(REGN_COLOR22)
+#define REG_COLOR23 REG(REGN_COLOR23)
+#define REG_COLOR24 REG(REGN_COLOR24)
+#define REG_COLOR25 REG(REGN_COLOR25)
+#define REG_COLOR26 REG(REGN_COLOR26)
+#define REG_COLOR27 REG(REGN_COLOR27)
+#define REG_COLOR28 REG(REGN_COLOR28)
+#define REG_COLOR29 REG(REGN_COLOR29)
+#define REG_COLOR30 REG(REGN_COLOR30)
+#define REG_COLOR31 REG(REGN_COLOR31)
+
+#define REG32_COP1LC *(volatile uint32_t*)(REG_BASE_ADDR | REGN_COP1LCH)
+#define REG32_COP2LC *(volatile uint32_t*)(REG_BASE_ADDR | REGN_COP2LCH)
+#define REG_COPJMP1 REG(REGN_COPJMP1)
+#define REG_COPJMP2 REG(REGN_COPJMP2)
+
+#define REG_BLTCON0 REG(REGN_BLTCON0)
+#define REG_BLTCON1 REG(REGN_BLTCON1)
+#define REG32_BLTCON *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BLTCON0)
+#define REG_BLTAFWM REG(REGN_BLTAFWM)
+#define REG_BLTALWM REG(REGN_BLTALWM)
+#define REG32_BLTAFLWM *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BLTAFWM)
+#define REG_BLTCPTH REG(REGN_BLTCPTH)
+#define REG_BLTCPTL REG(REGN_BLTCPTL)
+#define REG32_BLTCPT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BLTCPTH)
+#define REG_BLTBPTH REG(REGN_BLTBPTH)
+#define REG_BLTBPTL REG(REGN_BLTBPTL)
+#define REG32_BLTBPT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BLTBPTH)
+#define REG_BLTAPTH REG(REGN_BLTAPTH)
+#define REG_BLTAPTL REG(REGN_BLTAPTL)
+#define REG32_BLTAPT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BLTAPTH)
+#define REG_BLTDPTH REG(REGN_BLTDPTH)
+#define REG_BLTDPTL REG(REGN_BLTDPTL)
+#define REG32_BLTDPT *(volatile uint32_t*)(REG_BASE_ADDR | REGN_BLTDPTH)
+#define REG_BLTSIZE REG(REGN_BLTSIZE)
+#define REG_BLTCMOD REG(REGN_BLTCMOD)
+#define REG_BLTBMOD REG(REGN_BLTBMOD)
+#define REG_BLTAMOD REG(REGN_BLTAMOD)
+#define REG_BLTDMOD REG(REGN_BLTDMOD)
+#define REG_BLTCDAT REG(REGN_BLTCDAT)
+#define REG_BLTBDAT REG(REGN_BLTBDAT)
+#define REG_BLTADAT REG(REGN_BLTADAT)
+
+#define REG_SERPER REG(REGN_SERPER)
+#define REG_SERDATR REG(REGN_SERDATR)
+#define REG_SERDAT REG(REGN_SERDAT)
+
+/* ------ bits ------- */
+#define SETBITS(x) ((x) | 0x8000)
+#define CLRBITS(x) (x)
+
+/* interrupt numbers */
+enum {
+ INTR_TBE,
+ INTR_DSKBLK,
+ INTR_SOFT,
+ INTR_PORTS,
+ INTR_COPPER,
+ INTR_VERTB,
+ INTR_BLITTER,
+ INTR_AUDIO0,
+ INTR_AUDIO1,
+ INTR_AUDIO2,
+ INTR_AUDIO3,
+ INTR_RBF,
+ INTR_DSKSYN,
+ INTR_EXTER
+};
+
+/* interrupt enable flags */
+enum {
+ INTEN_TBE = 0x0001,
+ INTEN_DSKBLK = 0x0002,
+ INTEN_SOFT = 0x0004,
+ INTEN_PORTS = 0x0008,
+ INTEN_COPPER = 0x0010,
+ INTEN_VERTB = 0x0020,
+ INTEN_BLITTER = 0x0040,
+ INTEN_AUDIO0 = 0x0080,
+ INTEN_AUDIO1 = 0x0100,
+ INTEN_AUDIO2 = 0x0200,
+ INTEN_AUDIO3 = 0x0400,
+ INTEN_RBF = 0x0800,
+ INTEN_DSKSYN = 0x1000,
+ INTEN_EXTER = 0x2000,
+ INTEN_MASTER = 0x4000,
+
+ INTEN_ALL = 0x7fff
+};
+
+/* DMA control flags */
+enum {
+ DMA_AUD0 = 0x0001,
+ DMA_AUD1 = 0x0002,
+ DMA_AUD2 = 0x0004,
+ DMA_AUD3 = 0x0008,
+ DMA_AUDIO = 0x000f, /* all the above */
+ DMA_DISK = 0x0010,
+ DMA_SPRITE = 0x0020,
+ DMA_BLITTER = 0x0040,
+ DMA_COPPER = 0x0080,
+ DMA_BPL = 0x0100,
+ DMA_MASTER = 0x0200,
+
+ DMA_ALL = 0x01ff
+};
+
+/* Bitplane control */
+enum {
+ BPLCON0_ERSY = 0x0002,
+ BPLCON0_LACE = 0x0004,
+ BPLCON0_LPEN = 0x0008,
+ BPLCON0_GAUD = 0x0100,
+ BPLCON0_COLOR = 0x0200,
+ BPLCON0_DBLPF = 0x0400,
+ BPLCON0_HOMOD = 0x0800,
+ BPLCON0_BPU0 = 0x1000,
+ BPLCON0_BPU1 = 0x2000,
+ BPLCON0_BPU2 = 0x4000,
+ BPLCON0_HIRES = 0x8000
+};
+
+#define BPLCON0_COUNT(x) ((x) << 12)
+
+/* blitter control */
+enum {
+ BLTCON0_USED = 0x0100,
+ BLTCON0_USEC = 0x0200,
+ BLTCON0_USEB = 0x0400,
+ BLTCON0_USEA = 0x0800
+};
+
+enum {
+ BLTCON1_LINE = 0x0001,
+ BLTCON1_DECR = 0x0002,
+ BLTCON1_FCI = 0x0004,
+ BLTCON1_IFE = 0x0008,
+ BLTCON1_EFE = 0x0010,
+ BLTCON1_DOFF = 0x0080
+};
+
+#define BLTCON0_LF(x) (x)
+#define BLTCON0_ASH(x) ((x) << 12)
+#define BLTCON1_BSH(x) ((x) << 12)
+
+enum {
+ BLTCON_LINE = 0x00000001,
+ BLTCON_DECR = 0x00000002,
+ BLTCON_FCI = 0x00000004,
+ BLTCON_IFE = 0x00000008,
+ BLTCON_EFE = 0x00000010,
+ BLTCON_DOFF = 0x00000080,
+ BLTCON_USED = 0x01000000,
+ BLTCON_USEC = 0x02000000,
+ BLTCON_USEB = 0x04000000,
+ BLTCON_USEA = 0x08000000
+};
+
+#define BLTCON_LF(x) ((uint32_t)(x) << 16)
+#define BLTCON_ASH(x) ((uint32_t)(x) << 28)
+#define BLTCON_BSH(x) ((uint32_t)(x) << 12)
+
+#define BLTSIZE_XWORDS(x) ((uint16_t)(x) & 0x7f)
+#define BLTSIZE_X(x) BLTSIZE_XWORDS((x) / 16)
+#define BLTSIZE_Y(x) ((uint16_t)(x) << 6)
+#define BLTSIZE(x, y) (BLTSIZE_X(x) | BLTSIZE_Y(y))
+
+
+#define CIAA_PA_FIR0 0x40
+#define CIAA_PA_FIR1 0x80
+
+enum {
+ SERDATR_STOP8 = 0x0100,
+ SERDATR_STOP9 = 0x0200,
+ SERDATR_RXD = 0x0800,
+ SERDATR_TSRE = 0x1000,
+ SERDATR_TBE = 0x2000,
+ SERDATR_RBF = 0x4000,
+ SERDATR_OVRUN = 0x8000
+};
+
+#define ADKCON_UARTBRK 0x0800
+
+#endif /* HWREGS_H_ */
--- /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
+#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)
+{
+ 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<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 % 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;
+}
+
--- /dev/null
+#ifndef AMIGA_LIBC_STDLIB_H_
+#define AMIGA_LIBC_STDLIB_H_
+
+#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);
+}
--- /dev/null
+#ifndef AMIGA_LIBC_STRING_H_
+#define AMIGA_LIBC_STRING_H_
+
+#include <stdlib.h>
+
+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_ */
--- /dev/null
+#include <string.h>
+#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<NBPL; i++) {
+ uint32_t addr = (intptr_t)bplptr[i];
+ int reg = REGN_BPL1PTH + i * 4;
+ add_copper(COPPER_MOVE(reg, addr >> 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;
+}
--- /dev/null
+#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++);
+ }
+}
--- /dev/null
+#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_ */
--- /dev/null
+| 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
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "game.h"
+#include "gfx.h"
+
+int game_init(void)
+{
+ printf("hello world\n");
+
+ return 0;
+}
+
+void game_draw(void)
+{
+}
--- /dev/null
+#ifndef GAME_H_
+#define GAME_H_
+
+int game_init(void);
+void game_draw(void);
+
+#endif /* GAME_H_ */
--- /dev/null
+#!/usr/bin/python
+# mk_adf.py <bootblock> <payload> <output_adf>
+#
+# Stuff a given bootblock and payload into an output ADF image.
+#
+# Written & released by Keir Fraser <keir.xen@gmail.com>
+#
+# This is free and unencumbered software released into the public domain.
+# See the file COPYING for more details, or visit <http://unlicense.org>.
+
+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)