1380 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			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
 | 
