diff --git a/Makefile b/Makefile index 4f81fe1b..dbd927c5 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,13 @@ TOPDIR = $(realpath .) SUBDIRS = tools lib system effects intro EXTRA-FILES = tags cscope.out -CLEAN-FILES = bootloader.bin +CLEAN-FILES = bootloader.bin a500rom.bin addchip.bootblock.bin -all: a500rom.bin bootloader.bin build +all: a500rom.bin bootloader.bin addchip.bootblock.bin build -include $(TOPDIR)/build/common.mk +addchip.bootblock.bin: VASMFLAGS += -phxass -cnop=0 -a500rom.bin: ASFLAGS += -phxass -bootloader.bin: ASFLAGS += -phxass +include $(TOPDIR)/build/common.mk FILES := $(shell find include lib system -type f -iname '*.[ch]') diff --git a/addchip.bootblock.asm b/addchip.bootblock.asm new file mode 100644 index 00000000..9abe5444 --- /dev/null +++ b/addchip.bootblock.asm @@ -0,0 +1,163 @@ +; Downloaded from https://github.com/earok/close-and-run-amiga68k + + include 'lvo/exec_lib.i' + include 'lvo/intuition_lib.i' + +Height EQU 50 +zeropage EQU $100 + +RT_INIT EQU $16 +lib_Version EQU $14 +LibList EQU $17a +io_Device EQU $14 +KS20 EQU 36 + + +boot dc.b 'DOS',0 + dc.b 'r05s' ;tagged + dc.l 880 + +start movem.l d2-d5/a2/a5,-(a7) + + moveq #-1,d0 ;disable externals drives + movea.l io_Device(a1),a1 + movea.l $3c(a1),a1 ;the 'old times mod' + lea $34(a1),a1 + move.l d0,(a1)+ ;df1: + move.l d0,(a1)+ ;df2: + move.l d0,(a1) ;and why not.. df3: + + moveq #0,d4 + cmpi.w #KS20,lib_Version(a6) ;fork + shs d4 + + lea zeropage.w,a5 ;a0jmp + move.l a5,d5 + lea a0jmp(pc),a0 + moveq #(endscreen-a0jmp)/4-1,d0 +_l move.l (a0)+,(a5)+ + dbf d0,_l ;at end a5=zerobss + + movea.l LibList(a6),a0 + lea intuitionlib(pc),a1 + jsr _LVOFindName(a6) + move.l d0,(a5)+ ;intuitionbase + beq.b _exit + + lea intuitionlib(pc),a1 + jsr _LVOFindResident(a6) + tst.l d0 ;can be omitted.. + beq.b _exit + + lea wbname(pc),a1 ;'Workbench Screen',0 + moveq #doslib-wbname,d1 ;strlen + bsr.b findstrres + move.l a0,title-(zerobss+4)(a5) + + move.l d4,(a5)+ ;v36? + beq.b notags + moveq #10,d1 ;strlen + clr.b -1(a1,d1.w) ;'Workbench',0 + bsr.b findstrres + move.l a0,pubname-(zerobss+8)(a5) + + +notags lea doslib(pc),a1 + jsr _LVOFindResident(a6) + tst.l d0 + beq.b _exit + movea.l d0,a1 + move.l RT_INIT(a1),(a5) ;dosinit + + tst.l d4 ;v36? + beq.b _done + move.w #Height,_h-(zerobss+8)(a5) ;set height for >=v36 + jsr _LVOCacheClearU(a6) + +_done moveq #-1,d0 +_exit movea.l d5,a0 ;a0jmp + not.l d0 + movem.l (sp)+,d2-d5/a2/a5 + rts + + +;input: d0=resident base +; d1=strlen +; a1=string to search +;output: a0=&str +;used: d2/d3/a2 saved by main, a0 as return code + +findstrres movea.l d0,a0 +_search move.w d1,d2 + subq.w #2,d2 ;-(dbne,+) + movea.l a1,a2 + move.b (a2)+,d3 +_s1 cmp.b (a0)+,d3 + bne.b _s1 +_s2 cmpm.b (a2)+,(a0)+ + dbne d2,_s2 + bne.b _search + suba.l d1,a0 + rts + +wbname dc.b 'Workbench Screen',0 +doslib dc.b 'dos.library',0 +intuitionlib dc.b 'intuition.library',0 + + cnop 0,4 + +fakechecksum dc.l $b99c2e9d + +a0jmp lea zerobss(pc),a5 + movea.l (a5)+,a6 ;intuitionbase + jsr _LVOOpenIntuition(a6) ;KS1.x mandatory (undocumented) + lea wbscreen(pc),a0 + tst.l (a5)+ + bne.b v36 + jsr _LVOOpenScreen(a6) + bra.s dos +v36 lea tagitems(pc),a1 ;Workbench need to be Pub + jsr _LVOOpenScreenTagList(a6) +dos movea.l (a5),a0 ;dosinit + jmp (a0) ;start amigados + cnop 0,4 + +tagitems dc.l $8000002f ;SA_PubName +pubname dc.l 0 ;'Workbench',0 +; dc.l 0 ;TAG_DONE (fixed to wbscreen struct) + ; +wbscreen dc.w 0 ;WORD LeftEdge + dc.w 0 ;WORD TopEdge + dc.w 640 ;WORD Widht +_h dc.w 200 ;WORD Height (KS1.x min height) + dc.w 1 ;WORD Depth + dc.b 0,1 ;UBYTE DetailPen, BlockPen + dc.w $8000 ;UWORD ViewModes -> HIRES + dc.w 1 ;UWORD Type -> WBENCHSCREEN + dc.l 0 ;struct TextAttr *Font, defaults +title dc.l 0 ;UBYTE *DefaultTitle, ROM + dc.l 0 ;struct Gadget *Gadgets, UNUSED + dc.l 0 ;struct BitMap *CustomBitMap, NULL +endscreen ; + ; +zerobss ; ;(fixed to wbscreen struct) +;intuitionbase ;zerobss+0 +; ds.l 1 +;stag ;zerobss+4 +; ds.l 1 +;dosinit ;zerobss+8 +; ds.l 1 +endzero + + cnop 0,16 +ver dc.b '$VER: addchip.bootblock 1.1 (27.07.2017) by ross',0 + + cnop 0,16 +message dc.b ' This code snippet allows you to regain some precious chip ram. ' + cnop 0,16 + dc.b '* Greetings to all Evergreen Amiga Board members! *' + even + + END + +; vim: ft=asm68k:ts=8:sw=8:et diff --git a/build/common.mk b/build/common.mk index 0e71fe0e..8d4f5cb2 100644 --- a/build/common.mk +++ b/build/common.mk @@ -28,14 +28,19 @@ LDSCRIPT := $(TOPDIR)/system/amiga.lds # Don't reload library base for each call CPPFLAGS += -D__CONSTLIBBASEDECL__=const +CPPFLAGS += -DCHIPMEM_KB=$(CHIPMEM) -DFASTMEM_KB=$(FASTMEM) -DLOGOUT=$(LOGOUT) -# Default configuration -FRAMES_PER_ROW ?= 6 +include $(TOPDIR)/config.mk +ifeq ($(UAE), 1) CPPFLAGS += -DUAE +endif + +ifeq ($(AMIGAOS), 1) +CPPFLAGS += -DAMIGAOS +endif -# Pass "VERBOSE=1" at command line to display command being invoked by GNU Make -ifneq ($(VERBOSE), 1) +ifeq ($(VERBOSE), 0) .SILENT: QUIET := --quiet endif diff --git a/build/effect.mk b/build/effect.mk index 8c499737..35830abc 100644 --- a/build/effect.mk +++ b/build/effect.mk @@ -12,9 +12,14 @@ CRT0 = $(TOPDIR)/system/crt0.o MAIN ?= $(TOPDIR)/effects/main.o BOOTLOADER = $(TOPDIR)/bootloader.bin ROMSTARTUP = $(TOPDIR)/a500rom.bin +BOOTBLOCK = $(TOPDIR)/addchip.bootblock.bin -EXTRA-FILES += $(DATA_GEN) $(EFFECT).img $(EFFECT).adf $(EFFECT).rom -CLEAN-FILES += $(DATA_GEN) $(EFFECT).exe $(EFFECT).exe.dbg $(EFFECT).exe.map +EXTRA-FILES += $(DATA_GEN) $(EFFECT).adf +CLEAN-FILES += $(DATA_GEN) $(EFFECT).exe $(EFFECT).exe.dbg $(EFFECT).exe.map + +ifeq ($(AMIGAOS), 0) +EXTRA-FILES += $(EFFECT).img $(EFFECT).rom +endif all: build @@ -66,6 +71,7 @@ data/%.c: data/%.sync @echo "[SYNC] $(DIR)$< -> $(DIR)$@" $(SYNC2C) $(SYNC2C.$*) $< > $@ || (rm -f $@ && exit 1) +ifeq ($(AMIGAOS), 0) %.img: %.exe $(DATA) $(DATA_GEN) @echo "[IMG] $(addprefix $(DIR),$*.exe $(DATA) $(DATA_GEN)) -> $(DIR)$@" $(FSUTIL) create $@ $(filter-out %bootloader.bin,$^) @@ -77,6 +83,14 @@ data/%.c: data/%.sync %.rom: %.img $(ROMSTARTUP) @echo "[ROM] $(DIR)$< -> $(DIR)$@" $(ROMUTIL) $(ROMSTARTUP) $< $@ +else +%.adf: %.exe $(BOOTBLOCK) + @echo "[ADF] $(DIR)$< -> $(DIR)$@" + echo $< > startup-sequence + xdftool $@ format dos + write $< + makedir s + write startup-sequence s + dd if=$(BOOTBLOCK) of=$@ conv=notrunc status=none + rm startup-sequence +endif # Default debugger - can be changed by passing DEBUGGER=xyz to make. DEBUGGER ?= gdb @@ -97,4 +111,4 @@ $(TOPDIR)/gdb-dashboard: make -C $(TOPDIR) gdb-dashboard .PHONY: run debug run-floppy debug-floppy -.PRECIOUS: $(BOOTLOADER) $(EFFECT).img +.PRECIOUS: $(BOOTLOADER) $(BOOTBLOCK) $(EFFECT).img diff --git a/config.mk b/config.mk new file mode 100644 index 00000000..c7efd1c8 --- /dev/null +++ b/config.mk @@ -0,0 +1,29 @@ +# 1 => Use fs-uae dependant features i.e. call-traps (see `include/uae.h`) +# to aid debugging and profiling. This may render executable files +# unusable (most likely crash) on real hardware. +# 0 => Disable use of aforementioned features. Required for a release! +UAE := 1 + +# [only when UAE=0] Redirect diagnostic and log messages to: +# 0 => null output (drop messages) +# 1 => parallel port +# 2 => serial port +LOGOUT := 2 + +# 1 => Make executable files compatible with AmigaOS. Created ADFs will +# be formatted with Old Filesystem (KS1.3) and contain special bootblock +# that maximizes amount of chip memory. Executable file will be started +# automatically facilitating `startup-sequence` feature of AmigaDOS. +# 0 => Executable files must be started from ROM or ADF since they require +# custom environment created by bootstrap code. +AMIGAOS := 0 + +# [only when AMIGAOS=1] Amount of chip and fast (or public) memory +# (in kilobytes!) passed to our custom memory allocator. +# To calculate total memory taken after an executable file +# is loaded into memory please use `m68k-amigaos-objdump` tool. +CHIPMEM := 160 +FASTMEM := 288 + +# Pass "VERBOSE=1" at command line to display command being invoked by GNU Make +VERBOSE ?= 0 diff --git a/include/custom_regdef.h b/include/custom_regdef.h index 8a269424..78cfb3e8 100644 --- a/include/custom_regdef.h +++ b/include/custom_regdef.h @@ -147,6 +147,8 @@ struct Custom { #define intena 0x09a #define intreqr 0x01e #define intreq 0x09c +#define serdatr 0x018 +#define serdat 0x030 #endif diff --git a/include/system/debug.h b/include/system/debug.h index 60df499d..0fc9698e 100644 --- a/include/system/debug.h +++ b/include/system/debug.h @@ -8,10 +8,15 @@ #define Log(...) UaeLog(__VA_ARGS__); #define Panic(...) { UaeLog(__VA_ARGS__); PANIC(); } #else +#if LOGOUT > 0 void Log(const char *format, ...) __attribute__ ((format (printf, 1, 2))); __noreturn void Panic(const char *format, ...) __attribute__ ((format (printf, 1, 2))); +#else +#define Log(...) +#define Panic(...) HALT() +#endif #endif #ifdef _SYSTEM diff --git a/requirements.txt b/requirements.txt index 97629e19..ec7528b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ pycodestyle pygments zopflipy blessings +amitools diff --git a/system/Makefile b/system/Makefile index c0ea24e9..798197d7 100644 --- a/system/Makefile +++ b/system/Makefile @@ -1,7 +1,5 @@ TOPDIR := $(realpath ..) -# AMIGAOS => save & restore AmigaOS context -# (for intros or trackmos that can be launched from AmigaOS) CPPFLAGS += -D_SYSTEM LIBNAME := system @@ -9,7 +7,8 @@ SOURCES := \ amigaos.c \ autoinit.c \ debug.c \ - debug-putchar.S \ + dputchar.S \ + kputchar.S \ effect.c \ loader.c \ profiler.c \ diff --git a/system/amigaos.c b/system/amigaos.c index 18e540b7..385638bf 100644 --- a/system/amigaos.c +++ b/system/amigaos.c @@ -40,8 +40,8 @@ static ExcVecT oldExcVec; static void *oldSysStack; /* Memory for framework allocator. */ -static __aligned(4) __bss_chip char ChipMem[160 * 1024]; -static __aligned(4) char FastMem[288 * 1024]; +static __aligned(4) __bss_chip char ChipMem[CHIPMEM_KB * 1024]; +static __aligned(4) char FastMem[FASTMEM_KB * 1024]; /* Normally BootDataT is provided by the boot loader. Since we were started * from AmigaOS we have to fill this structure and pass it to Loader. */ diff --git a/system/debug-putchar.S b/system/debug-putchar.S deleted file mode 100644 index 4aacd633..00000000 --- a/system/debug-putchar.S +++ /dev/null @@ -1,19 +0,0 @@ -# Reliable transfers may only happen 3 or more E-cycles basis. -# http://lallafa.de/blog/2015/09/amiga-parallel-port-how-fast-can-you-go/ - -#include -#include - -# [a0] ciab, ciaa = ciab + $1001 -ENTRY(DPutChar) -.Loop: btst #CIAB_PRTRBUSY,(a0) /* is printer buffer empty ? */ - jne .Loop - - st.b ciaddrb+0x1001(a0) /* set direction to out */ - move.b d0,ciaprb+0x1001(a0) /* write the data */ - tst.b (a0) /* waste 2 E-cycles */ - tst.b (a0) - rts -END(DPutChar) - -# vim: ft=gas:ts=8:sw=8:noet: diff --git a/system/debug.c b/system/debug.c index f003840a..382a5107 100644 --- a/system/debug.c +++ b/system/debug.c @@ -1,17 +1,33 @@ #include "debug.h" -#ifndef UAE +#if !defined(UAE) && LOGOUT > 0 #include #include + +#if LOGOUT == 1 #include extern void DPutChar(void *ptr, char data); +#define PUTCHAR DPutChar +#define AUXDATA ciab +#endif + +#if LOGOUT == 2 +#include + +extern void KPutChar(void *ptr, char data); + +#define PUTCHAR KPutChar +#define AUXDATA custom +#endif + void Log(const char *format, ...) { va_list args; va_start(args, format); - kvprintf(DPutChar, (void *)ciab, format, args); + kvprintf(PUTCHAR, (void *)AUXDATA, format, args); + va_end(args); } @@ -19,7 +35,7 @@ __noreturn void Panic(const char *format, ...) { va_list args; va_start(args, format); - kvprintf(DPutChar, (void *)ciab, format, args); + kvprintf(PUTCHAR, (void *)AUXDATA, format, args); va_end(args); PANIC(); diff --git a/system/dputchar.S b/system/dputchar.S new file mode 100644 index 00000000..d92d2a4f --- /dev/null +++ b/system/dputchar.S @@ -0,0 +1,36 @@ +# Reliable transfers may only happen 3 or more E-cycles basis. +# http://lallafa.de/blog/2015/09/amiga-parallel-port-how-fast-can-you-go/ + +#include +#include + +/* It's a reimplementation of PRawPutChar in ddebug.lib from NDK3.2 */ + +# [a0.l] ciab, ciaa = ciab + $1001 +# [d0.b] character +ENTRY(DPutChar) + tst.b d0 /* don't send character if it's zero */ + beq.s .Quit + + move.w d0,-(sp) + cmp.b #10,d0 /* send '\r' first if the character is `\n` */ + bne.s .NoNL + moveq #13,d0 + bsr.s .Send + tst.b (a0) /* waste single E-cycle */ +.NoNL: move.w (sp)+,d0 + +.Send: tst.b (a0) /* waste 2 E-cycles */ + tst.b (a0) +.Wait: btst #CIAB_PRTRBUSY,(a0) /* is printer buffer empty ? */ + bne.s .Wait + + st.b ciaddrb+0x1001(a0) /* set direction to out */ + move.b d0,ciaprb+0x1001(a0) /* write the data */ + tst.b (a0) /* waste another 2 E-cycles */ + tst.b (a0) + +.Quit: rts +END(DPutChar) + +# vim: ft=gas:ts=8:sw=8:noet: diff --git a/system/kputchar.S b/system/kputchar.S new file mode 100644 index 00000000..008e398a --- /dev/null +++ b/system/kputchar.S @@ -0,0 +1,27 @@ +#include +#include + +# [a0.l] custom +# [d0.b] character +ENTRY(KPutChar) + tst.b d0 /* don't send character if it's zero */ + beq.s .Quit + + move.w d0,-(sp) + cmp.b #10,d0 /* send '\r' first if the character is `\n` */ + bne.s .NoNL + moveq #13,d0 + bsr.s .Send +.NoNL: move.w (sp)+,d0 + +.Send: move.w #0x100,d1 /* add stop bit */ + move.b d0,d1 + +.Wait: btst.b #5,serdatr(a0) /* loop until transmit buffer empty */ + beq.s .Wait + move.w d1,serdat(a0) /* send the character */ + +.Quit: rts +END(KPutChar) + +# vim: ft=gas:ts=8:sw=8:noet: