Experiments with the Spectrum ROM Font

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
MatGubbins
Dynamite Dan
Posts: 1239
Joined: Mon Nov 13, 2017 11:45 am
Location: Kent, UK

Re: Experiments with the Spectrum ROM Font

Post by MatGubbins »

That is a great routine Tom.
User avatar
g0blinish
Manic Miner
Posts: 287
Joined: Sun Jun 17, 2018 2:54 pm

Re: Experiments with the Spectrum ROM Font

Post by g0blinish »

Code: Select all

_loop:	
	ld a,(hl) ; get text -> A=0x41
	or a;sub 0x20
	ret z;ret c
	push hl
	add a,a ; x2
	ld l,a
	ld h,0
	add hl,hl ; x4
	add hl,hl ; x8
	ld bc,0x3C00	; rom font-32*8

User avatar
g0blinish
Manic Miner
Posts: 287
Joined: Sun Jun 17, 2018 2:54 pm

Re: Experiments with the Spectrum ROM Font

Post by g0blinish »

one optimisation:

Code: Select all

;works if A=0..127
 ld l,a
 add hl,hl
 ld h,$1E
 add hl,hl
 add hl,hl
User avatar
Cosmium
Microbot
Posts: 156
Joined: Tue Dec 04, 2018 10:20 pm
Location: USA

Re: Experiments with the Spectrum ROM Font

Post by Cosmium »

Very nice!

Like the clean look and the way it's all procedurally generated from the ROM without needing a new character set in RAM.
User avatar
TomD
Manic Miner
Posts: 377
Joined: Tue Nov 13, 2018 9:47 am
Location: Leeds UK
Contact:

Re: Experiments with the Spectrum ROM Font

Post by TomD »

g0blinish wrote: Sat May 14, 2022 1:49 pm one optimisation:

Code: Select all

;works if A=0..127
 ld l,a
 add hl,hl
 ld h,$1E
 add hl,hl
 add hl,hl
Couldn't get this to work, first thought the ld h,$1e was in the wrong place as it is half $3c so 2 adds after it would make by x4, but even moving it after the second add hl,hl didn't fix it. Wondering if I've missed something?
Retro enthusiast and author of Flynn's Adventure in Bombland, The Order of Mazes & Maze Death Rally-X. Check them out at http://tomdalby.com
User avatar
Joefish
Rick Dangerous
Posts: 2058
Joined: Tue Nov 14, 2017 10:26 am

Re: Experiments with the Spectrum ROM Font

Post by Joefish »

I like the look. Can you explain the algorithm? Is there some sort of clever adaptive function going on, rather than simply expanding a specific list of rows within each character?
User avatar
g0blinish
Manic Miner
Posts: 287
Joined: Sun Jun 17, 2018 2:54 pm

Re: Experiments with the Spectrum ROM Font

Post by g0blinish »

Cosmium wrote: Sat May 14, 2022 9:41 pm Very nice!

Like the clean look and the way it's all procedurally generated from the ROM without needing a new character set in RAM.
my mistake: ld h,$0F
User avatar
TomD
Manic Miner
Posts: 377
Joined: Tue Nov 13, 2018 9:47 am
Location: Leeds UK
Contact:

Re: Experiments with the Spectrum ROM Font

Post by TomD »

Joefish wrote: Mon May 16, 2022 12:03 pm I like the look. Can you explain the algorithm? Is there some sort of clever adaptive function going on, rather than simply expanding a specific list of rows within each character?
As it is doubling on the y-axis the algorithm plots the first byte as per the ROM, and then for the 2nd line (the double one) it checks the current byte against the next. It creates a simple weighting for the current byte which penalises continuous bits. This has the effect that horizontal lines carry a large penalty which favours the single bits which usually represent the vertical parts of the font.
Retro enthusiast and author of Flynn's Adventure in Bombland, The Order of Mazes & Maze Death Rally-X. Check them out at http://tomdalby.com
User avatar
TomD
Manic Miner
Posts: 377
Joined: Tue Nov 13, 2018 9:47 am
Location: Leeds UK
Contact:

Re: Experiments with the Spectrum ROM Font

Post by TomD »

g0blinish wrote: Mon May 16, 2022 12:26 pm
Cosmium wrote: Sat May 14, 2022 9:41 pm Very nice!

Like the clean look and the way it's all procedurally generated from the ROM without needing a new character set in RAM.
my mistake: ld h,$0F
Nice, down to 84bytes now (added an extra 2bytes to check for moving into next 3rd of screen so the text can be plotted on any char line now)

Code: Select all

_main:
	ld hl,_txt
	ld de,18432+(3*32) ; start pos
_loop:	
	ld a,(hl) ; get text -> A=0x41
	or a
	ret z
	push hl
	add a,a ; x2
	ld l,a
	ld h,0x0f
	add hl,hl ; x4
	add hl,hl ; x8
; plot font
	push de
	ld b,8
	ld c,b	; c=8
_pltloop:
	ld a,(hl)
	inc hl
	ld (de),a
	inc d
; what to plot on 2nd line
	push bc
	push de
	push hl
	ld d,a
	ld b,c	; b=8
	ld e,(hl)	
	xor a
	ld c,a
	ld l,a
_testloop:
	rrc d
	jr nc,_testloop100
	inc l	; penalty for continuous bits +1	
	add a,l
	jr _testloop110
_testloop100:
	ld l,0	; reset cumulative counter
_testloop110:
	rrc e
	jr nc,_testloop120
	inc c
_testloop120:
	djnz _testloop
	pop hl
	cp c
	ld a,d
	jr z,_plotc
	jr c,_plotc	
	ld a,(hl)
_plotc:
	pop de
	pop bc
	ld (de),a
	inc d
; over char line?
	ld a,d
	and %00000111
	jr nz,_inchar
	ld a,e
	add a,32
	ld e,a
	jr c,_inchar
	ld a,d
	sub c	; sub 8
	ld d,a
_inchar:
	djnz _pltloop
; onto next
	pop de
	pop hl
	inc hl
	inc e
	jr _loop	
;	
_txt:
	defb "Loading ",0x22,"ChuckieEgg",0x22," Please Wait",0
Retro enthusiast and author of Flynn's Adventure in Bombland, The Order of Mazes & Maze Death Rally-X. Check them out at http://tomdalby.com
User avatar
g0blinish
Manic Miner
Posts: 287
Joined: Sun Jun 17, 2018 2:54 pm

Re: Experiments with the Spectrum ROM Font

Post by g0blinish »

TomD wrote: Mon May 16, 2022 1:43 pm Nice, down to 84bytes now (added an extra 2bytes to check for moving into next 3rd of screen so the text can be plotted on any char line now)
-1 byte: add a,a instead or a
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Experiments with the Spectrum ROM Font

Post by Kweepa »

TomD wrote: Mon May 16, 2022 1:38 pm
Joefish wrote: Mon May 16, 2022 12:03 pm I like the look. Can you explain the algorithm? Is there some sort of clever adaptive function going on, rather than simply expanding a specific list of rows within each character?
As it is doubling on the y-axis the algorithm plots the first byte as per the ROM, and then for the 2nd line (the double one) it checks the current byte against the next. It creates a simple weighting for the current byte which penalises continuous bits. This has the effect that horizontal lines carry a large penalty which favours the single bits which usually represent the vertical parts of the font.
I was able to repro this in basic (on a BBC micro as the Spectrum doesn't have bitwise operations) here:


Essentially:

Code: Select all

loop over lines
   if it's the first non-empty line
      print a blank line
   else
      either print the last line again if this line has three pixels in a row, or print the current line
   endif
   print the current line
User avatar
TomD
Manic Miner
Posts: 377
Joined: Tue Nov 13, 2018 9:47 am
Location: Leeds UK
Contact:

Re: Experiments with the Spectrum ROM Font

Post by TomD »

Kweepa wrote: Mon May 16, 2022 6:05 pm
TomD wrote: Mon May 16, 2022 1:38 pm

As it is doubling on the y-axis the algorithm plots the first byte as per the ROM, and then for the 2nd line (the double one) it checks the current byte against the next. It creates a simple weighting for the current byte which penalises continuous bits. This has the effect that horizontal lines carry a large penalty which favours the single bits which usually represent the vertical parts of the font.
I was able to repro this in basic (on a BBC micro as the Spectrum doesn't have bitwise operations) here:


Essentially:

Code: Select all

loop over lines
   if it's the first non-empty line
      print a blank line
   else
      either print the last line again if this line has three pixels in a row, or print the current line
   endif
   print the current line
Looks good, BBC Basic is amazingly powerful. Been looking at getting this working in Spectrum Basic via a FN() call but proving a challenge :-)
Retro enthusiast and author of Flynn's Adventure in Bombland, The Order of Mazes & Maze Death Rally-X. Check them out at http://tomdalby.com
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Experiments with the Spectrum ROM Font

Post by Kweepa »

Super slow but:

Code: Select all

10 LET a$="Loading "+CHR$ 34+"ChuckieEgg"+CHR$ 34+" Please Wait"
20 FOR i=1 TO LEN a$: LET q=15360+8* CODE a$(i): LET e=0: LET t=0: FOR k=0 TO 1: LET q=q+4*k: FOR b=0 TO 3: LET d=PEEK (q+b): LET n=0: LET m=d: FOR f=0 TO 5: IF m>=192 THEN LET n=1: LET f=5
30 IF m>=128 THEN LET m=m-128
40 LET m=m+m: NEXT f: IF n=0 THEN LET e=t*d
50 LET r=USR "a"+b+b: POKE r,e: POKE r+1,d: LET e=d: IF e>0 THEN LET t=1
60 NEXT b: PRINT AT 5+k,i-1;"\a": NEXT k: NEXT i
highrise
Manic Miner
Posts: 300
Joined: Fri Mar 20, 2020 11:29 pm

Re: Experiments with the Spectrum ROM Font

Post by highrise »

This got me quite intrigued as to how maybe the algorithm could be tweaked. I thought about this simple formula:

look at the current byte of the char, and check for two contiguous bits. If this occurs, then don't repeat for the second line, but instead grab the next byte down.

the char routine looks like this:

charloop:
ld a,(hl) ; value
ld c,a ; keep for later
ld (de),a ; write
call linedown
ld a,c
call bitcounter
cp 2
jr nz,secondline
inc hl
ld c,(hl) ; get next line down instead
dec hl
secondline:
ld a,c
ld (de),a
call linedown
inc hl ; next byte
djnz charloop

Line down is a typical one pixel down routine:

linedown:
inc d ; one line down
ld a,d
and 7
ret nz
ld a,e ; else add 32
add a,32
ld e,a
ret c
ld a,d ; else sub 8 from h
sub 8
ld d,a
ret

and finally, to check for two contiguous bits, which I think can be improved. It returns a value in c of 0,1 or 2.

bitcounter:
push bc
ld bc,$800 ; 8 lines, bit counter at zero
bitcount:
rrca ; check for carry
jr nc,skipbit ; no carry
; carried so increase c
inc c
bit 1,c ; hit 2 bits?
jr nz,done ; yes, return
jr nextbit ; else carry on but don't reset c
skipbit: ld c,0 ; reset counter at no carry
nextbit:
djnz bitcount
done: ld a,c
pop bc
ret

it's not quite right but could perhaps be improved on.


Image
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Experiments with the Spectrum ROM Font

Post by Kweepa »

Slightly faster BASIC version (with a lookup table for consecutive bits):

Code: Select all

10 LET a$="Loading "+CHR$ 34+"ChuckieEgg"+CHR$ 34+" Please Wait"
20 DIM n(256): FOR i=1 TO 21: READ x: FOR j=0 TO 2+(i<14): LET n(x+j)=1: NEXT j: NEXT i: DATA 1,9,17,33,41,65,73,81,129,137,145,161,169,5,21,37,69,85,133,149,165
30 LET u=USR "a": FOR i=1 TO LEN a$: LET q=15360+8* CODE a$(i): LET e=0: LET t=0: FOR k=0 TO 1: FOR b=0 TO 3: LET d=PEEK (q+b): LET n=n(d+1)
40 IF n=1 THEN LET e=t*d
50 LET r=u+b+b: POKE r,e: POKE r+1,d: LET e=d: IF e>0 THEN LET t=1
60 NEXT b: PRINT AT 5+k,i-1;"\a": LET q=q+4: NEXT k: NEXT i
Still way too slow for anything but a crap game competition entry...
highrise
Manic Miner
Posts: 300
Joined: Fri Mar 20, 2020 11:29 pm

Re: Experiments with the Spectrum ROM Font

Post by highrise »

I made a few changes and with a bit of help this routine is a bit smaller (70 bytes I think). It seems that it's really only necessary to detect two bits next to each other.

Code: Select all

		device zxspectrum48
	org $c000

drawtext:
		ld hl,text
		ld de,18432+(3*32) ; start pos		
textloop:
		ld a,(hl)
		and a
		ret z
		push hl ; store text address
		ld bc,$3C00 ; rom font
		ld h,c
		add a,a
		ld l,a
		add hl,hl
		add hl,hl
		add hl,bc
		; keep screen address
		push de
		ld b,8
charloop:
		ld a,(hl) ; value
		ld c,a ; keep for later
		;look for 2 contiguous bits
bitloop:
		cp #C0
		jr nc,twobits
		add a,a
		jr nz,bitloop
		scf
		jr secondline
twobits: ; found two bits together, display previous line
		dec hl
		ld c,(hl) ; get next line above instead
		inc hl
secondline:
		ld a,c
		ld (de),a ; write
		call linedown
		ld a,(hl)
		ld (de),a
		call linedown
linedone:
		inc hl ; next byte
		djnz charloop
		pop de
		inc de
		pop hl
		inc hl
		jr textloop		
linedown:
		inc d		 ; one line down
		ld a,d
		and 7
	    ret nz
		ld a,e				   ; else add 32
	    add a,32
	    ld e,a
	    ret c
		ld a,d				 ; else sub 8 from h
		sub 8
		ld d,a
		ret
			
text:
	defb "Loading ",0x22,"ChuckieEgg",0x22," Please Wait",0
		savetap "bitfont.tap",drawtext
Image
highrise
Manic Miner
Posts: 300
Joined: Fri Mar 20, 2020 11:29 pm

Re: Experiments with the Spectrum ROM Font

Post by highrise »

by the way, if you want to know if a number has two contiguous bits in BASIC, I think something like this will work. Apologies as I haven't written anything in BASIC for a very long time.

LET A=PEEK(charaddr)
LET B=0
FOR I=1 to 7
IF A>191 THEN LET B=1
LET A=A+A
if A>255 THEN LET A=A-256
NEXT I

what this does is check for a number > 191, which means the last two bits of A are set. It then shifts A to the left by doubling it and removing the carry. If there are two bits next to each other then sooner or later the number will be greater than 191.

...I think!
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Experiments with the Spectrum ROM Font

Post by Kweepa »

That is almost exactly what I did in the super slow version :)
Post Reply