--- /dev/null
+name = testrom
+src = $(wildcard *.asm)
+obj = $(src:.asm=.o)
+bin = $(name).bin
+rom = $(name).rom
+tap = $(name).tap
+
+AS = vasmz80_oldstyle
+ASFLAGS = -Fvobj
+LD = vlink
+LDFLAGS = -b rawbin1
+
+.PHONY: tap
+tap: $(tap)
+
+.PHONY: rom
+rom: $(rom)
+
+$(bin): $(obj)
+ $(LD) -o $@ $(LDFLAGS) -Ttext 28000 $(obj)
+
+$(rom): $(obj)
+ $(LD) -o $@ $(LDFLAGS) -Ttext 0 $(obj)
+
+$(tap): $(bin)
+ appmake +zx -o $@ --org 28000 --blockname $(name) -b $<
+
+%.o: %.asm
+ $(AS) -o $@ $(ASFLAGS) $< >/dev/null
+
+.PHONY: clean
+clean:
+ rm -f $(bin) $(rom) $(tap) $(obj)
+
+.PHONY: run
+run: $(tap)
+ fuse-sdl $(tap)
+
+.PHONY: program
+program: $(rom)
+ minipro -p 'AT28C16 @DIP24' -s -w $<
--- /dev/null
+; vi:filetype=z80:
+fb_addr equ $4000
+attr_addr equ $5800
+ula_port equ $fe
+
+main:
+ call init
+ ld c, 16
+ ld b, 12
+ call calc_cell_addr
+ ld a, 'F'
+ call putchar
+ inc de
+ ld a, 'O'
+ call putchar
+ inc de
+ ld a, 'O'
+ call putchar
+
+.looptop:
+ jr .looptop
+
+init:
+ ; setup attributes
+ ld hl, attr_addr
+ ld a, $47
+ ld b, 24
+.attry: ld c, 32
+.attrx: ld (hl), a
+ inc hl
+ dec c
+ jr nz, .attrx
+ dec b
+ jr nz, .attry
+
+ ; clear screen
+ ld hl, fb_addr
+ xor a
+ ld b, 192
+.clry: ld c, 32
+.clrx: ld (hl), a
+ inc hl
+ dec c
+ jr nz, .clrx
+ dec b
+ jr nz, .clry
+
+ ; set border
+ out (ula_port), a
+
+ ret
+
+; expects X -> c, Y -> b, returns in de
+calc_cell_addr:
+ push af
+ sla b
+ sla b ; change from blocks to pixels
+ sla b
+ ; construct low address byte -> e
+ ld a, b ; start with Y
+ sla a
+ sla a
+ and $e0 ; keep top 3 bits
+ ld e, a ; move into e
+ ld a, c ; a <- X
+ and $1f ; keep low 5 bits
+ or e ; combine with Y bits
+ ld e, a ; move the result back to e
+ ; construct high address byte -> d
+ ld a, b ; start with Y again
+ sra a
+ sra a
+ sra a
+ and $18 ; keep bits 3 and 4
+ ld d, a ; keep it in d
+ ld a, b ; grap Y one more time
+ and $7 ; keep low 3 bits of Y in a
+ or d ; combine with Y6-Y7
+ ld bc, fb_addr
+ or b ; combine with high byte of fb address
+ ld d, a ; move result back to d
+ pop af
+ ret
+
+
+ ; de: dest
+ ; a: char
+putchar:
+ sub 'A'
+ ret c
+ cp 27
+ ret nc
+ push de
+ sla a
+ sla a
+ sla a
+ ld h, 0
+ ld l, a
+ ld bc, glyph_a
+ add hl, bc
+ ld c, 8
+.chartop:
+ ld a, (hl)
+ ld (de), a
+ inc d
+ inc hl
+ dec c
+ jr nz, .chartop
+ pop de
+ ret
+
+ include glyphs.inc