home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
KAYPRO
/
TOON12.LBR
/
TOON12.AQM
/
TOON12.ASM
Wrap
Assembly Source File
|
2000-06-30
|
13KB
|
531 lines
; TOON12.ASM
;A screen dump program: puts a watchdog between
;the conin jmp and CONIN itself, which simply passes
;along normal chars, but writes the screen to disk
;when it detects ^_. The screen is written by
;bank-switching to video memory through rdvid,
;which alters the bank switch bit from the system
;port to read bank 1 memory (video memory + prom)
;directly. If TOON, the carTOON file for screens,
;already exists, the new screen is added on the end.
;
;In version 1.1, the sub-CCP address in high memory
;where TOON goes is hard coded, but the BDOS jump
;is altered by TOON to point to TOON's lowest addr.
;The TOON watchdog's first location is then a jump
;to the original entry point in the BDOS. Therefore,
;load TOON first, and later programs can adjust
;their use of the TPA using the altered BDOS addr.
;
;Version 1.2 adds the deletion of space chars in
;the 80th column to clean up display on 80 char
;screens, and other minor changes.
; v1.2
;(c)June, 1985
;Mike Yarus * 2231 16th Street * Boulder, CO 80302
;
;TOON.ASM, TOON.COM, and TOON.DOC are released into
;the public domain, and may be used freely for any
;non-commercial purpose. They may not be sold or
;used to enhance the value of another product
;without the permission of the author.
;
;
bdos equ 0005h
wmboot equ 0000h
cr equ 0Dh
lf equ 0Ah
eof equ 1Ah
;
;the following equate is for the conin bios addr
;and the original bdos jump address
;
;a dummy address (= 0000)
dmmy$ad equ wmboot ;to hold a place for real
;address written at run time
;
;equates for the move into high memory
;
offs equ 280h ;distance below ccp to load
ccp equ 0E400h ;bios-1600h=ccp start, std 64k
newstrt equ ccp-offs;new start, offs-et below ccp
;
org 0100h
;
;get the bdos address and store it at bottom of dump
;
lhld 0006h ;load bdos jmp addr
shld bds$trgt+1 ;store at new site
lxi h,newstrt ;get bottom of dump
shld 0006h ;redirect bdos jmp to dump
;
;get the address of the bios
;
lhld 0001h ;load bios + 3
dcx h
dcx h
dcx h ;hl -> bios address
shld bios ;store start of bios jumps
;
;find the phrase "Warm Boot"
;
lxi d,0004h ;offset to warm boot address
dad d ;hl points to warmst addr
call getwd ;warmst routine addr -> hl
;
mvi c,'W' ;search for 'W'
call find0 ;begin at warmbt routine
;
lxi d,newmsg;address in hl from find
call fill0 ;overwrite "Warm Boot"
;
;redirect the conin jump in the bios
;
lhld bios ;load addr of bios
lxi d,000ah ;offset to conin addr addr
dad d ;addr of conin routine addr
shld cinadd ;store it, must overwrite
call getwd ;conin address into hl
shld conin ;store address of conin routine
;
lhld cinadd ;addr of conin addr
lxi d,dump ;addr of dump in de
call putwd ;alter conout addr to dump addr
;
;write in the calculated address of the conin routine
;
lhld conin ;load conin addr
xchg ;conin addr-> de
lxi h,cin$trgt+1 ;addr for call to conin
call putwd ;write addr in de to hl
;
jmp launch0 ;move the business end under ccp
;
;fills memory at h with string stored at d, term by $
;used to fill open memory at fixed, dedicated location
;
fill0 mvi c,'$'
ldax d ;get char into a
cmp c ;is the new char the end char?
rz ;if so, have done string
mov m,a ;if not, store next char
;
inx d
inx h ;increment both string counters
jmp fill0
;
;find the character in c after the address supplied in h
;returns the address of the char in h
;
find0 mov a,m ;get char in a
cmp c ;is it the target char?
rz ;char found, address in h
inx h ;inc address and
jmp find0 ;get the next char
;
;get word at addr in hl into hl: orig addr + 1 -> de
;
getwd mov a,m ;get low order byte
mov e,a ;move to e
inx h ;reset for high order byte
mov a,m ;get it in a
mov d,a ;put high order byte in d
xchg ;exchange number and address
ret
;
;put word in de to address in hl
;
putwd mov a,e ;lsb to a
mov m,a ;lsb to address in hl
inx h ;address for msb
mov a,d ;msb to a
mov m,a ;msb to address
ret
;
;the routine to move the code below it to high memory
;
launch0 lxi b,endmv-begin+1 ;bytes to move
lxi d,begin ;start addr for move
lxi h,newstrt ;new start after move
;
launch ldax d ;get a char from lo mem
mov m,a ;put char in high mem
inx d ;increment lo addr
inx h ;increment hi mem addr
dcx b ;decrement # bytes to move
;
mov a,b ;test if b&c = 0
ora c ;a&c = 0?
jnz launch ;no, get another byte
;
ret ;done, back to cpm
;
newmsg db 'Toon = ^_$'
bios ds 2 ;addr of bios jump table
cinadd ds 2 ;addr of conout jmp addr
conin ds 2 ;addr of the conout routine
;
;***************** all below is moved *****************
begin equ $
;
distnce equ newstrt-begin ;hi mem addr - lo mem
;
;redirect the bdos jmp to its original address
;
bds$trgt
jmp dmmy$ad ;bdos addr at run time
;
;and now, the dump routine,...
;
dump equ $+distnce ;<<< entry, high mem
cin$trgt ;conin address target
call dmmy$ad ;addr put in at run time
mvi c,1fh ;ctrl underline, ^_
cmp c ;compare to char in c
jz dmpfl ;if ^_, go to routine
ret ;otherwise just return
;
;open a file, put something in it after the end of the
;last entry, then close it, OK?
;
;row and col must be initialized for each screen written
;
dmpfl equ $+distnce
mvi a,1
sta col ;col = 1
sta row ;row = 1
;
;set up a local stack
;
lxi h,0 ;clear hl
dad sp ;sp -> hl
shld cpmstk ;store original stack pointer
lxi sp,locstk ;new top of stack
;
;define new dma
;
mvi c,1ah
lxi d,dma ;use the equate
call bdos
;
;initialize address for next write to dma
;
lxi h,dma ;start of dma
shld dmaddr ;start at first addr in dma
;
;prepare the filename in the FCB
;
lxi h,fcb+1 ;destination, for fill
lxi d,flnm ;string address, for fill
call fill ;put filename in fcb
;
;open or make file, go to end of a previous file
;
openf equ $+distnce
mvi c,0fh ;open file
lxi d,fcb
call bdos ;A = 0,1,2,3, or ffh
cpi 0ffh
jnz empty ;is a file, test & find end
makef equ $+distnce ;req'd for era'd Toon
lxi d,filler ;string of 0's
lxi h,fcb+0Ch ;put them after fname
call fill ;zero the fcb
;
mvi c,16h ;make file via bdos
lxi d,fcb
call bdos
jmp scrloop ;skip search to end of file
;
;find end record of file
;
fend equ $+distnce
mvi c,14h ;read sequential
lxi d,fcb
call bdos ;a=0 if read successful
ori 0
jz fend ;not at end, read again
;
;reset the record number, delete the ^Z at eof
;
deleof equ $+distnce
lda fcb+20h ;the current record number
dcr a ;back to last record
sta fcb+20h ;put decremented cr back
call rdseq ;last rec-> dma: advances rec #!
lda fcb+20h ;the current record number
dcr a ;back to last record
sta fcb+20h ;decremented cr, can rewrite
;
;find the eof and overwrite it
;
mvi c,1ah ;eof in c
lxi h,dma ;address for search
call find ;returns addr of char in c in h
shld dmaddr ;store active address in dma
jmp scrloop ;append new text to end of file
;
;measure out a screenfull, write byte by byte from video
;
scrloop equ $+distnce
;
lda col ;get col, set up to read video
mov c,a ;col into c
mvi b,0 ;zero out b
push b ;onto stack
lda row ;get row
mov c,a ;row into c
mvi b,0 ;zero b
push b ;onto stack
call rdvid ;return onto stack, get char!
;
;process the char from video memory, returned in c
;
lhld dmaddr
call dmaout ;char in c, dmaddr in hl
lda col ;get current column
inr a ;increment col, note col -> 81
sta col ;restore col
mvi d,81 ;test, last col?
cmp d ;compare to col
jnz scrloop ;if 80th not written, next col
;
lda row ;row -> a
mov d,a ;row -> d
lda col ;col -> a
add d ;col + row in a
cpi 105 ;done? col + row = 105
jz endf ;yes, done with screen
;
inr d ;no, increment row
mov a,d ;row + 1 -> a
sta row ;restore row
call eoln ;put in crlf
mvi a,1
sta col ;col -> 1 for new row
jmp scrloop ;fill next col
;
;read the next record
;
rdseq equ $+distnce
mvi c,14h ;read sequential
lxi d,fcb
call bdos
ret ;done, go back
;
;write the dma to current record
;
wrtseq equ $+distnce
mvi c,15h ;write sequential
lxi d,fcb
call bdos
ret ;end
;
;close file
;
clsfl equ $+distnce
mvi c,10h ;close file
lxi d,fcb
call bdos
ret ;done
;
;test to see if ex=rc=0, eg, empty Toon
;
empty equ $+distnce ;test for empty Toon
;and delete, if so
lda fcb+0Fh ;load the # rec in extent
mov b,a ;curr record to b
lda fcb+0Ch ;locd curr extent to a
ora b ;rec & extent 0?
jnz fend ;not empty, find end
;
;erase file
;
erafl equ $+distnce ;erase empty file
mvi c,13h ;bdos erase file
lxi d,fcb
call bdos
jmp makef ;now make new file
;
;fills memory at h with string stored at d, term by $
;used to fill open memory at fixed, dedicated location
;
fill equ $+distnce
mvi c,'$'
ldax d ;get char into a
cmp c ;is the new char the end char?
rz ;if so, have done string
mov m,a ;if not, store next char
;
inx d
inx h ;increment both string counters
jmp fill
;
;find the character in c after the address supplied in h
;returns the address of the char in h
;
find equ $+distnce
mov a,m ;get char in a
cmp c ;is it the target char?
rz ;char found, address in h
inx h ;inc address and
jmp find ;get the next char
;
;write to dma from c, which has char
;dmaddr is in hl
;
dmaout equ $+distnce
call ckdma ;decides to write when dma full
mov m,c ;byte -> dma
call incr ;increment dmaddr
ret ;done
;
;dma full? yes->reset and restart dma
;gets and returns current char in c, dmaddr in hl
;
ckdma equ $+distnce
lxi d,dma+80h ;get dma end+1
mov a,e ;lsb of dma end in a
cmp l ;at end of dma?
rnz ;ret if not done yet
;
push b ;save char
call wrtseq ;full dma, write it
pop b ;get char back
lxi h,dma ;reset dmaddr
shld dmaddr ;store dmaddr
ret ;done
;
;increment the address for current write to dma
;
incr equ $+distnce
lhld dmaddr ;load next write addr
inx h ;+ 1
shld dmaddr ;restore incr addr
ret ;done
;
;writes crlf after every 80 screen chars
;deletes blank at eoln to make 79 char lines
;in order to inprove screen appearance
;
eoln equ $+distnce
lhld dmaddr ;get next location
dcx h ;last written char
mov a,m ;get the char
cpi 20h ;was it a blank?
jnz eoln1 ;no, terminate line
shld dmaddr ;yes, update address
jmp eoln2 ;cr & lf
;
eoln1 equ $+distnce
inx h ;skip non-blank
eoln2 equ $+distnce
mvi c,cr
call dmaout ;check address in hl
mvi c,lf
call dmaout ;check address in hl
ret
;
;puts in last section of file, eof,...Note that
;in general, would have to worry about hitting
;record end during eorec, but a screenful will
;usually end within a record
;
endf equ $+distnce
call eoln ;cr & lf
lxi d,eorec ;addr of string for fill
lhld dmaddr ;fill here
call fill ;with some eof's
call wrtseq ;write the last dma
call clsfl ;close file
;
lhld cpmstk ;replace the orig stack ptr
sphl ;hl -> sp
ret
;
;################ MACHINE DEPENDENT #################
; vvvvvvv vvvvvvvvv
;
;this routine switches from normal memory (bank 0) to
;video memory and prom (bank 1). it reads one char at
;the address calculated for the screen col and row
;supplied on the stack when rdvid is called, then
;returns that char in register c
;
;reset for input from bank 1, video memory and prom
;
rdvid equ $+distnce
in 1Ch ;get system byte from the Z80
ori 80h ;force msb -> 1 for bank one
out 1Ch ;set port
;
;stack on entry: rtn addr,row,col
;
pop h ;get rtn addr
pop b ;row in BC
pop d ;column in DE
push h ;restore rtn addr
;
;calculate the address in video mem
;
lxi h,3000h ;set up hl
mov a,c ;move row -> A
mvi c,80h ;BC = 0080, note B=00 assumed
;
;multiplication routine to get (row-1)*80h
;
rowx equ $+distnce
dcr a ;row-1
jz donex ;through multiplying ?
dad b ;addr + 80h
jnz rowx ;not yet HL=3000h+(row-1)*80h
;uses flag from dcr
;
donex equ $+distnce
dcx d ;col-1
dad d ;addr+(col-1) in HL
;
mov c,m ;get the byte from memory in c
;
;reset for bank 0 memory
;
in 1Ch ;get system byte
xri 80h ;msb -> 0, bank zero
out 1Ch ;set it
;
ret ;end of rdvid
;
; ^^^^^^^ ^^^^^^^^^
;################ MACHINE DEPENDENT ################
;
flnm equ $+distnce
db 'TOON $'
eorec equ $+distnce
db eof,eof,eof,eof,'$'
dmaddr equ $+distnce
ds 2 ;address of next write to dma
row equ $+distnce
ds 1 ;current screen column, 1->80
col equ $+distnce
ds 1 ;current screen row,1->24
filler equ $+distnce
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,'$'
;used to reinit fcb
fcb equ $+distnce
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;36 bytes init to 0
dma equ $+distnce
ds 128 ;space for sector buffer
ds 32 ;local stack
locstk equ $+distnce-1 ;top of stack
cpmstk equ $+distnce
ds 2 ;cpm's stack pointer on entry
;
endmv equ $
;local stack
locstk equ $+distnce-1 ;top of stack
cpmstk equ $+distnce
ds 2 ;c