1
0
vt100-games/cpmtris/cpmtris.z
2019-10-24 11:48:18 +02:00

1380 lines
17 KiB
Plaintext

;Cpmtris v1.0 - a tetris clone for Z80-based CP/M machines.
;Copyright (C) 1996 Russell Marks. See 'README' for license details.
;conversion of my OPL tetris for the psion series 3 via my ZX81 tetris
; (both also free and available on request)
org 0100h
jp indirect
defb 0
;cpmtris is, in this version, patched to run on a 8 MHz
;80x24 VT100 machine
;104h - number of columns
; must have at least 50 columns
; you don't really need to set this; it isn't used for anything.
cols: defb 80
;105h - number of lines
; must have at least 10 lines
lines: defb 24
;106h - 10*Mhz of your Z80.
; e.g. on a 3.5MHz Spectrum +3 it would be 35.
; most CP/M machines have speeds around the 3 to 4 MHz mark,
; so if you don't know the speed of your box just use 35.
mhz10: defb 80
;107h - terminal type
;you can roll your own terminal routines, but there's hard-coded
;support for a few terminals which saves you the effort. they are:
; type 1 - VT100
; type 2 - VT52, PCW, Spectrum +3, etc.
; type 3 - ZCN
; type 4 - VC404 (volker-craig)
;set this to zero if you're writing your own clear screen and cursor
;move routines.
;note that the terminal type does not influence the number of lines,
;columns and the 'mhz10' setting - all those must still be set (above).
termtype: defb 1
;108h-10fh - reserved (currently unused)
defb 0,0,0,0,0,0,0,0
;the routines below are allowed to corrupt af/bc/de/hl,
; but other registers must remain intact. You can use these routines
; from them:
;the routine at 180h prints the num. in de in decimal, preserving all regs.
;the routine at 183h prints the char in a, preserving all regs.
;110h - clear screen
;this example is for a VT100.
hackcls:
ld de,mcls
ld c,9
jp 5
mcls: defb 27,'[H',27,'[J$'
defb 0
;120h - move to (x,y), where (0,0) is top-left
;entry: (b,c)=(x,y)
;this example is for a VT100.
hackmove:
ld a,27
call 0183h
ld a,'['
call 0183h
ld e,c
inc e
ld d,0
call 0180h
ld a,';'
call 0183h
ld e,b
inc e
;d still 0
call 0180h
ld a,'H'
jp 0183h
;140h - extra patch space, in case the above isn't enough
;all the space up to 17fh is usable
defb 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
;180h - print de as decimal number (for VT100 cursor move)
;saves af/bc/de/hl
jp dispdec2
;183h - print char in a
;saves all regs
jp putchar
;we jump to here first, so that the 1st jump always stays the same
; no matter what hacking is done in future, and any binary patches
; made by overwriting the first record still work.
indirect:
jp main
dispdec2:
push af
push bc
push de
push hl
call dispdec
pop hl
pop de
pop bc
pop af
ret
;the shapes
shps:
defb 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0
defb 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0
defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
defb 1,0,0,0,0,1,1,0,1,0,0,0,0,1,1,0
defb 1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0
defb 0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
defb 0,1,0,0,1,1,0,0,0,1,0,0,1,1,0,0
defb 1,1,0,0,0,1,1,0,1,1,0,0,0,1,1,0
defb 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
defb 0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0
defb 1,1,1,1,0,1,0,0,1,1,1,1,0,1,0,0
defb 0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0
defb 0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0
defb 0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0
defb 1,1,1,0,0,1,1,0,1,1,1,0,1,1,0,0
defb 0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0
defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
defb 0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,0
defb 0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0
defb 0,1,0,0,0,0,0,0,1,1,0,0,0,0,1,0
defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
defb 1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0
defb 0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0
defb 0,1,0,0,1,0,0,0,0,1,1,0,0,0,0,0
defb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;map of the 10x21 screen (and some spare)
scrn:
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
defw 0,0,0,0,0, 0,0,0,0,0
mtitle: defb 'Cpmtris by RJM 96',0
mkeys1: defb 'K - left, L - right',0
mkeys2: defb 'S - rotate, D - drop',0
mgamovr: defb '*** GAME OVER! ***',0
mlines: defb 'Lines: 0',0
mprskey: defb 'Again? (y/n)',0
mbotline: defb '--==--==--==--==--==',0
ybot equ 20 ;bottom of scrn
timout equ 20 ;timeout in frames before block drops one place
shp: defb 0 ;current shape
frm: defb 0 ;current frame (rotation)
xy:
y: defb 0
x: defb 0
timc: defb 0
tmp: defb 0
linesdun: defw 0
xstatpos: defb 30
;terminal-related stuff
compact: defb 0 ;if 1 use doubled-up pixels (" '.:")
pause: defw 0
;for ZCN we make a new font which is basically a copy of ZCN's but
;with some UDGs on the end.
zcnfont equ 0eac0h
newzcnfont equ 08000h
zcnchars: defb 128,129,130,131
zcncdat:
defb 000h,022h,000h,000h,022h,000h
defb 000h,022h,000h,077h,0ffh,0ffh
defb 077h,0ffh,0ffh,000h,022h,000h
defb 077h,0ffh,0ffh,077h,0ffh,0ffh
main:
;if on ZCN, we'll be using the 'compact' 2-pixel-per-char mode.
;since we can (admittedly fairly kludgely) hack up a few udgs, do
;that. (looks a lot nicer.)
ld a,(066h)
cp 0f7h
call z,zcninit
call srand
call chkargs
call playgame
jr main
chkargs:
ld a,(05dh)
cp 32
ret z
;set terminal type if 0<=a<=3
sub 48
ret c
cp 5
ret nc
ld (termtype),a
cp 3
jr z,carg1
;set to 24 lines if termtype specified and not ZCN type
ld a,24
ld (lines),a
carg1:
ld a,(06dh)
cp 32
ret z
;set mhz10
ld hl,06dh
call atoi
ld a,l
ld (mhz10),a
ret
ld d,h
ld e,l
call dispdec
ld a,' '
call putchar
ld a,'$'
ld (070h),a
ld de,06dh
ld c,9
call 5
jp 0
playgame:
ld a,(lines)
cp 20
jr nc,notcpt
ld a,1
ld (compact),a
notcpt:
;work out frame pause
ld a,(mhz10)
ld h,0
ld l,a
ld de,72
call multiply
ld (pause),hl
call cls
;show title/keys
ld a,(xstatpos)
ld b,a
ld c,0
ld hl,mtitle
call mvaddstr
ld a,(lines)
cp 20
jr c,nokeyhlp
ld a,(xstatpos)
ld b,a
ld c,18
ld hl,mkeys1
call mvaddstr
ld a,(xstatpos)
ld b,a
ld c,20
ld hl,mkeys2
call mvaddstr
nokeyhlp:
call initscr
ld hl,0
ld (linesdun),hl
ld a,(xstatpos)
ld b,a
ld c,7
ld hl,mlines
call mvaddstr
blklp:
;gen new blk
ld hl,7
call rand
ld a,l
ld (shp),a
call rand16
ld a,l
and 3
ld (frm),a
xor a
ld (y),a
ld a,4
ld (x),a
ld a,timout
ld (timc),a
;if hit now, game over
ld bc,(xy)
ld a,(frm)
call hitshp
jp c,endgam
ld a,1
call drawshp
;frame loop
hitlp:
call inkey
cp 'k' ;left (k)
jr nz,skip1
xor a
call drawshp
ld bc,(xy)
dec b
ld a,(frm)
call hitshp
jr c,skip0a
ld a,(x)
dec a
ld (x),a
skip0a:
ld a,1
call drawshp
jp skipn
skip1:
cp 'l' ;right (l)
jr nz,skip2
xor a
call drawshp
ld bc,(xy)
inc b
ld a,(frm)
call hitshp
jr c,skip1a
ld a,(x)
inc a
ld (x),a
skip1a:
ld a,1
call drawshp
jp skipn
skip2:
cp 's' ;rot (s)
jr nz,skip3
ld a,(frm)
inc a
and 3
ld (tmp),a
xor a
call drawshp
ld bc,(xy)
ld a,(tmp)
call hitshp
jr c,skip2a
ld a,(tmp)
ld (frm),a
skip2a:
ld a,1
call drawshp
jp skipn
skip3:
cp 'd' ;drop (d)
jr nz,skip4
xor a
call drawshp
droplp:
ld bc,(xy)
inc c
ld a,(frm)
call hitshp
jr c,skip3a
ld a,(y)
inc a
ld (y),a
jr droplp
skip3a:
ld a,1
call drawshp
jr endhit
skip4:
cp 27
jp z,abortgam
ld a,(timc)
dec a
ld (timc),a
jr nz,skipn
xor a
call drawshp
ld bc,(xy)
inc c
ld a,(frm)
call hitshp
jr nc,skip5
ld a,1
call drawshp
jr endhit
skip5:
ld a,(y)
inc a
ld (y),a
ld a,timout
ld (timc),a
ld a,1
call drawshp
skipn:
;pause between frames
ld bc,(pause)
pauselp:
dec bc
ld a,b
or c
jr nz,pauselp
jp hitlp
endhit:
call dolines
ld a,(xstatpos)
add a,7
ld b,a
ld c,7
call move
ld de,(linesdun)
call dispdec
jp blklp
endgam:
;draw last hit block.
;this is messy, but if you get a 1x4 block it looks
;incredibly unfair otherwise.
ld a,1
call drawshp
abortgam:
ld a,(xstatpos)
ld b,a
ld c,5
ld hl,mgamovr
call mvaddstr
ld a,(lines)
ld e,a
ld a,15
cp e
jr c,agam1
ld a,3
agam1:
ld c,a
dec c
ld a,(xstatpos)
ld b,a
ld hl,mprskey
call mvaddstr
call stashcur
;wait for no key
mpklp:
call inkey
and a
jr nz,mpklp
;wait for key
mpklp2:
call inkey
and a
jr z,mpklp2
;if key was y, ret
cp 'y'
ret z
;if key wasn't n, repeat
cp 'n'
jr nz,mpklp2
;otherwise, quit...
bombout:
call cls
jp 0
;draw/undraw blk on 10x20 scrn
;entry: (b,c)=(x,y), a=1 to draw, 0 to undraw
drawblk:
;do scrn()
ld h,0
ld l,c
call mul10
ld d,0
ld e,b
add hl,de
ld de,scrn
add hl,de
ld (hl),a
ld e,a
ld a,(compact)
and a
ld a,e
jr nz,compblk
;actually draw
push af
rlc b
call move
pop af
and a
jr z,dblkskip
;think hard before changing these, they're also used by the
; scrolling stuff. at the very least, it's important to
; preserve the z flag.
dblkon:
ld a,'['
call putchar
ld a,']'
call putchar
ret
dblkoff:
dblkskip:
ld a,' '
call putchar
ld a,' '
call putchar
ret
;multiply hl by 10
mul10:
push de
add hl,hl ;*2
ld d,h
ld e,l
add hl,hl ;*4
add hl,hl ;*8
add hl,de ;*10
pop de
ret
;this draws a 'compact' block, which can be used on a machine
;with less than 20 lines. It makes the play area only 10x10 onscreen.
;this is really intended to support ZCN boxes, but should work
;for other things too.
;it's called from drawblk when needed.
;entry: hl points to byte set in scrn, (b,c)=(x,y).
cbchars: defb ' .',39,':' ;i.e. " .':"
compblk:
;scrn() has already been done, we just have to draw/undraw.
and a
rr c
rl e
;so c=y/2 and bit 0 of e=y&1
push de
push hl
call move
pop hl
pop de
;work out what the char there should be, from looking at scrn().
;build up the 0-3 offset in cbchars in d.
ld a,(hl)
rra
rl d
ld bc,10
bit 0,e
jr z,cblkskip
ld bc,-10
cblkskip:
add hl,bc
ld a,(hl)
rra
rl d
;if y&1=1, bits 0 and 1 of d are the wrong way round.
;fix that here.
bit 0,e
jr z,cblk2
rr d
rr b ;bit 0 -> b
rr d
rr c ;bit 1 -> c
rl b
rl d ;b -> bit 1
rl c
rl d ;c -> bit 0
cblk2:
;get correct char and print it.
ld a,d
and 3
ld h,0
ld l,a
ld de,cbchars
add hl,de
ld a,(hl)
jp putchar
;draw shape
;entry: a=1 to draw, 0 to undraw
dsasav: defb 0
drawshp:
ld (dsasav),a
;let hl=offset in shp()
ld a,(frm)
ld h,0
ld l,a
add hl,hl
add hl,hl
ld de,shps
add hl,de
ex de,hl
ld a,(shp)
ld h,0
ld l,a
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,de
ld de,(xy)
ld c,4
dsylp:
ld a,(x)
ld d,a
ld b,4
dsxlp:
ld a,(hl)
and a
jr z,dsskip
push bc
push de
push hl
ld b,d
ld c,e
ld a,(dsasav)
call drawblk
pop hl
pop de
pop bc
dsskip:
inc hl
inc d
djnz dsxlp
push de
ld de,12
add hl,de
pop de
inc e
dec c
jr nz,dsylp
ld a,(dsasav)
and a
ret z
;if we're drawing rather than undrawing, move cursor out of the way
;FALLS THROUGH
;move cursor to safe pos out of the way
stashcur:
ld b,22
ld c,0
call move
ret
;entry: (b,c)=(x,y), a=frm
hsxy:
hsy: defb 0
hsx: defb 0
hitshp:
ld (hsxy),bc
;let hl=offset in shp()
ld h,0
ld l,a
add hl,hl
add hl,hl
ld de,shps
add hl,de
ex de,hl
ld a,(shp)
ld h,0
ld l,a
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,de
ld de,(hsxy)
ld c,4
hsylp:
ld a,(hsx)
ld d,a
ld b,4
hsxlp:
ld a,(hl)
and a
jr z,hsskip
;if <0 or >9, always hit
ld a,d
cp 10
ccf
ret c
;now proper check
push de
push hl
ld h,0
ld l,e
call mul10
ld e,d
ld d,0
add hl,de
ld de,scrn
add hl,de
ld a,(hl)
pop hl
pop de
and a
scf
ret nz
hsskip:
inc hl
inc d
djnz hsxlp
push de
ld de,12
add hl,de
pop de
inc e
dec c
jr nz,hsylp
and a
ret
initscr:
ld hl,scrn
ld de,scrn+1
ld bc,210
ld (hl),0
ldir
ld hl,ybot
call mul10
ld de,scrn
add hl,de
ld d,h
ld e,l
inc de
ld bc,9
ld (hl),1
ldir
;draw blank play area if needed
ld a,(compact)
and a
jr z,iscrncmp
ld c,10
iscrylp:
ld b,10
iscrxlp:
push bc
dec b
dec c
call move
ld a,(cbchars)
call putchar
pop bc
djnz iscrxlp
dec c
jr nz,iscrylp
iscrncmp:
;only draw bottom line if (lines)>=ybot+1 (21)
ld a,(lines)
ld c,ybot
inc c
cp c
ret c
dec c
ld b,0
ld hl,mbotline
call mvaddstr
ret
dolines:
ld c,ybot-1
dlylp:
;e used as total
ld e,0
ld b,10
dlxlp:
push de
ld h,0
ld l,c
call mul10
ld de,scrn
add hl,de
ld d,0
ld e,b
dec e
add hl,de
pop de
ld a,(hl)
add a,e
ld e,a
djnz dlxlp
ld a,e
and a
ret z
cp 10
jr nz,dlskip
push bc
call scrlscr
pop bc
inc c
dlskip:
dec c
jr nz,dlylp
ret
;scroll up from line c
scrlscr:
dec c
ssylp:
push bc
;copy scrn() array line
ld h,0
ld l,c
call mul10
ld de,scrn
add hl,de
push hl
ld de,10
add hl,de
pop de
ex de,hl
ld bc,10
ldir
pop bc
push bc
;copy to screen
;right now, hl points to scrn() data for this line,
; and c+1 is the line to draw it on.
inc c
push bc
push hl
ld a,(compact)
and a
call z,move
pop hl
pop bc
ld b,10
ssxlp:
ld a,(compact)
and a
jr nz,ssskip1
;normal
ld a,(hl)
and a
call nz,dblkon
call z,dblkoff
jr ssskip2
ssskip1:
;compact
push bc
ld a,10
sub b
ld b,a
push hl
call compblk
pop hl
pop bc
ssskip2:
inc hl
djnz ssxlp
pop bc
dec c
jr nz,ssylp
ld hl,(linesdun)
inc hl
ld (linesdun),hl
ret
;move to (b,c) and display asciiz at hl
mvaddstr:
push hl
call move
pop hl
mvaslp:
ld a,(hl)
and a
ret z
call putchar
inc hl
jr mvaslp
;get non-blocking input.
;returns a=char or 0 if none pressed
inkey:
call kbhit
ld a,0
ret nc
jp getch
;the built-in terminal support
cls:
ld a,(termtype)
and a
jp z,hackcls
cp 1
jr nz,cls2
;VT100
ld de,mclsvt100
ld c,9
jp 5
mclsvt100: defb 27,'[H',27,'[J$'
cls2:
cp 2
jr nz,cls3
;VT52
ld de,mclsvt52
ld c,9
jp 5
mclsvt52: defb 27,'H',27,'J$'
cls3:
cp 3
jr nz,cls4
;ZCN
ld a,1
jp putchar
cls4:
cp 4
ret nz
;VC404
ld a,24
jp putchar
move:
ld a,(termtype)
and a
jp z,hackmove
cp 1
jr nz,move2
;VT100
ld a,27
call putchar
ld a,'['
call putchar
ld e,c
inc e
ld d,0
call dispdec2
ld a,';'
call putchar
ld e,b
inc e
;d still 0
call dispdec2
ld a,'H'
jp putchar
move2:
cp 2
jr nz,move3
;VT52
ld a,27
call putchar
ld a,'Y'
call putchar
ld a,32
add a,c
call putchar
ld a,32
add a,b
jp putchar
move3:
cp 3
jr nz,move4
;ZCN
ld a,16
call putchar
ld a,32
add a,c
call putchar
ld a,32
add a,b
jp putchar
move4:
cp 4
ret nz
;VC404
ld a,16
call putchar
ld a,32
add a,c
call putchar
ld a,32
add a,b
jp putchar
zcninit:
;we know it's ZCN, so set termtype etc.
ld a,3
ld (termtype),a
ld a,120
ld (cols),a
ld a,10
ld (lines),a
ld a,46
ld (mhz10),a
ld hl,zcnchars
ld de,cbchars
ld bc,4
ldir
ld hl,zcnfont
ld de,newzcnfont
ld bc,96*6
ldir
ld hl,zcncdat
ld bc,4*6
ldir
;enable the new font
ld de,newzcnfont-192
ld c,142
call 5
;might as well turn off the cursor, too.
ld a,4
call putchar
ret
;stuff from ZX81 version of zcnlib's maths.z
;this doesn't require undocumented Z80 ops, which are causing
;probs on the 'cpm' CP/M emulator I'm testing this on.
;ZX81-friendly (non-ix-using) version; probably slower, but at least
; it works :-)
;divide
;gives z1=x/y and z2=x mod y
;entry: hl=x, de=y
;exit: hl=z1 (result), de=z2 (remainder)
;af/bc corrupt
dividey: defw 0
divide:
ld b,h
ld c,l
;see if we're trying to divide by zero
ld a,d
or e
ret z
ld (dividey),de
ld de,0
ld hl,0
ld a,16
dvlp:
push af
and a
rl l
rl h
and a
rl e
rl d
bit 7,b
jr z,dvs1
ld a,1
or l
ld l,a
dvs1:
push hl
and a
push de
ld de,(dividey)
sbc hl,de
pop de
jp m,dvs2
;nasty! fiddle the stack
ex (sp),hl
ld a,1
or e
ld e,a
dvs2:
pop hl
and a
rl c
rl b
pop af
dec a
jr nz,dvlp
;finally! got the results.
ex de,hl
;exit: hl=result, de=remainder
ret
;this from zcnlib's maths.z
;this does z=x*y
;entry: hl=x, de=y
;exit: hl=z
;af/bc/de corrupt
multiply:
ld b,h
ld c,l
ld hl,0
ld a,16
mulp:
and a
rr d
rr e
jr nc,musp
add hl,bc
musp:
and a
rl c
rl b
dec a
jr nz,mulp
ret
numtmp: defb '0000000000000000$' ;16 zeroes and '$'
;convert number in de to ascii in internal buffer
;entry: de=number
;exit: de=addr of number in internal buffer, '$' terminated
itoa:
ld b,10
;FALLS THROUGH
;call here for routine with functionality as above but with b=base
;convert number in de to ascii, in given base (unsigned)
;entry: de=number, b=base (from 2 to 36)
;exit: af/bc/de/hl corrupt
itoabase:
ld hl,numtmp+16
ld a,'$'
ld (hl),a
dispnlp:
push bc
push hl
ex de,hl
ld e,b
ld d,0
call divide
ld a,e
add a,48
cp 58
jr c,dispn1
add a,7 ;compensate for >=10
dispn1:
ex de,hl ;so de now is result of division
pop hl
pop bc
dec hl
ld (hl),a
ld a,d
or e
jp nz,dispnlp
ex de,hl
ret
;display number in de, in decimal
dispdec:
call itoa
ld c,9
jp 5
;like C func. entry: hl=addr of number, exit: hl=actual number
atoi:
ld b,10
;FALLS THROUGH
;convert number of specified base as ASCII at hl to number.
;the ASCII number should be terminated by a non-digit in this base.
;supports bases from 2 to 36
;entry: hl=address of first digit of ASCII number,
; b=base (e.g. 10 for decimal)
;exit: hl=number
atoibase:
ld de,0 ;total of number so far.
atoilp:
ld a,(hl)
;uppercase it
call atoiislw
jr nc,atoi0
res 5,a
atoi0:
sub 48
jr c,atoidone ;if not digit, end
cp 10
jr c,atoi0a
sub 7 ;compensate if we're using letters
atoi0a:
cp b
jr nc,atoidone ;if not digit, end
;otherwise, multiply our running total by base and add this.
push hl
push bc
push af
ld l,b
ld h,0
call multiply
pop af
ld e,a
ld d,0
add hl,de
ex de,hl
pop bc
pop hl
inc hl
jr atoilp
atoidone:
;got number in de - put it in hl.
ex de,hl
ret
atoiislw:
cp 'a'
ccf
ret nc
cp '{'
ret