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
/
ENTERPRS
/
CPM
/
UTILS
/
A
/
BIOSR4.ARC
/
CXIO.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-04-26
|
24KB
|
1,279 lines
; code in this module was modified to set the screen up for 80 col
; automaticly, all 40 column code has been deleted. the label NULL40 is
; still maintained in the device table as removing it would change
; the subsequent device numbers, affecting the use of RS-232 (it would
; require rewrites of all modem programs)
; code at the label ?rlccp has been added to reset the feel and repeat
; rate at every warm start, this corrects problems that arise after
; terminating a modem program.
;
; Code has been added to allow setting the cursor flash rate and shape,
; set the temporary drive, and the drive search chain.
;
; Code has been added to require a password to be entered before the
; system finishes initialization, 3 trys are allowed, the system locks
; up if you fail all three.
;
; A label has been added to allow the 6551 init code to install baud
; rates based on the value in DEVTBL.
;
; User assumes _ALL_ liability for the use of this module. Original
; Copyright is still maintained by Commodore
;
; Code to set cursor and drive chain; Copyright April 26, 1987 by
; James W. Waltrip IV
;
title 'C128 BIOS, main I/O and sys functions 26 April 87'
;
; This module contains CXIO,CXINIT,CXMOVE and CXTIME.
;
maclib cpm3
maclib z80
maclib cxequ
maclib modebaud
;**********************************************************
extrn repeat ; repeat rate
repeat$amt equ 3
extrn delay ; delay before repeat
delay$amt equ 24
printnum equ 08 ; printer device to init
; other printer is 010h (16 decimal)
pass equ false ; set to 'false' if password
;protection not wanted
pass$word macro
db 'PASS' ; password is defined here
; ; if using lower case letters
; ; use the HEX values rather than
; ; the characters themselves
; ; ie.-> 061h instead of 'a'
endm
;*************************************************************
public ?init,?ldccp,?rlccp
public ?user,?di$int
extrn ?sysint
bdos equ 5
extrn @civec,@covec,@aivec,@aovec,@lovec
extrn ?bnksl
public ?cinit,?ci,?co,?cist,?cost
public @ctbl
extrn ?kyscn
; Utility routines in standard BIOS
extrn ?wboot ; warm boot vector
extrn ?pmsg ; print message @<HL> up to 00
; saves <BC> & <DE>
extrn ?pdec ; print binary number in <A> from 0 to 99.
extrn ?pderr ; print BIOS disk error header
extrn ?conin,?cono ; con in and out
extrn ?const ; get console status
extrn @hour,@min,@sec,@date,?bnksl
public ?time
page
;
; keyboard scanning routine
;
extrn ?get$key,?int$cia
extrn Fx$V$tbl
;
; links to 80 column display
;
extrn ?out80,?int80
extrn ?pt$i$1101,?pt$o$1,?pt$o$2
;
; bios8502 function routines
;
public ?fun65
;
;
;
public X6551$baud
extrn ?int65,?in65,?ins65,?out65
extrn @drcha,@drchb,@drchc,@drchd,@tpdrv
DSEG
?fun65:
sta vic$cmd ; save the command passed in A
fun$di$wait:
lda RS232$status
ani 01000010b ; transmitting or receiving ?
jrnz fun$di$wait ; yes, wait for int to clean up
di
lda force$map ; get current MMU configuration
push psw ; save it
sta io$0 ; make I/O 0 current
lxi d,1 ; D=0, E=1
lxi b,page$1$h
outp d
dcr c
outp e ; page 1, 0-1
dcr c
outp d
dcr c
outp d ; page 0, 0-0
call enable$6502+6 ; go run the 8502
mvi c,low(page$1$h)
outp e
dcr c
outp e ; page 1, 1-1
dcr c
outp e
dcr c
outp d ; page 0, 1-0
pop psw ; recover the MMU config.
sta force$map ; restore it
ei ; turn interrupts back on
lda vic$data ; get command results
ora a ; set the zero flag if A=0
ret
?di$int:
push psw
di$int$1:
lda RS232$status
ani 01000010b ; transmitting or receiving ?
jrnz di$int$1 ; yes, wait for int to clean up
pop psw
di
ret
page
;
; set up the MMU for CP/M Plus
;
DSEG ; init done from banked memory
?init:
mvi a,3eh ; force MMU into I/O space
sta force$map ;
lxi h,mmu$table+11-1 ; table of 11 values
lxi b,mmu$start+11-1 ; to to MMU registers
mvi d,11 ; move all 11 bytes to the MMU
init$mmu$loop:
mov a,m
outp a
dcx h
dcx b
dcr d
jrnz init$mmu$loop
mvi a,1 ; enable track and sector status
sta stat$enable ; on the status line
; mvi a,1h ; no parity, 8 bits, 1 stop bit
sta XxD$config
lxi h,Fx$V$tbl
shld key$FX$function
;*********************************************************
;
; install I/O assignments
;
lxi h,4000h ; 80 and 40 column drivers
shld @covec
mvi h,80h
shld @civec ; assign console input to keys
mvi h,printnum ; device # 4
shld @lovec ; assign printer to LPT:
mvi h,00h
shld @aivec
shld @aovec ; assign rdr/pun port
;
; init SCB
;
mvi a,4 ; The following instr. set up the
sta @drcha ; Drive Serch Chain, and the Temp.
sta @tpdrv ; Drive. This replaces the SETDEF
mvi a,1 ; method of setting this up.
sta @drchb
mvi a,2
sta @drchc
mvi a,3
sta @drchd
;
; Where are the bytes for COM/SUB execution?
;
; 80 Col. screen cursor attributes
;
lxi b,0D600h ; 80 col cmd reg
mvi a,010 ; reg 10 of 8563 (cursor type, start scan line)
outp a ; tell 8563 you want reg 10
lx1:
inp a ; get status
jp lx1 ; loop until status good
lxi b,0D601h ; 80 col data reg
mvi a,01100011b ; slow cursor, scan line 4 lines from top
outp a
;
lxi b,0D600h
mvi a,011 ; reg 11 of 8563 (cursor end scan line)
outp a
lx2:
inp a
jp lx2
lxi b,0D601h
mvi a,00000101b ; Scan line 5 lines from top
outp a
lxi b,0D011h ; Vic controll reg 1
mvi a,00001000b ; turn off Vic
outp a
;
page
;
; print sign on message
;
call prt$msg ; print signon message
db 'Z'-'@' ; home and clear screen (to BG color)
db esc,esc,esc,21h,esc,esc,esc,30 ; black back, white char
db 'Z'-'@'
db esc,'=',32+2,32+37,'CP/M 3.0'
db esc,'=',32+3,32+31,'On the Commodore 128 '
db esc,'=',32+4,32+22,'6 Dec 85 System -*- Modified 26 Apr 87'
db cr,lf,lf,lf,lf,0
;;*********************************************************
page
;
;
mvi a,-1 ; set block move to NORMAL mode
sta source$bnk
;
; install mode 2 page vectors
;
mvi a,JMP
sta INT$vector ; install a JMP at vector location
lxi h,?sysint
shld INT$vector+1 ; install int$handler adr
;
; A software fix is required for the lack of hardware to force the
; LSB of the INT vector to 0. If the bus floats INT VECT could be
; read as 0FFh; thus ADRh=I (I=0FCh) ADRl=FF for first read, and
; ADRh=I+1 ADRl=00 for second, to ensure that control is retained
; 0FD00h will also have FDh in it.
;
lxi h,int$block ; FC00h
lxi d,int$block+1 ; FC01h
lxi b,256-1+1 ; interrupt pointer block
mvi m,INT$vector/256 ; high and low are equal (FD)
ldir
mvi a,INT$block/256
stai ; set interrupt page pointer
im2 ; enable mode 2 interrupts
page
;
;
mvi a,vicinit ; null command just to setup BIOS8502
call ?fun65
;
;
;
lda sys$freq ; 0=60Hz 0FFh=50Hz
ani 80h ; 0=60Hz 080h=50Hz
mov l,a ; save in L
lxi b,cia$1+0eh ; point to CRA
inp a ; get old config
ani 7fh ; clear freq bit
ora l ; add in new freq bit
outp a ; set new config
mvi c,8 ; start RTC
outp a
lxi h,date$hex
shld @date ; set date to system data
;
; setup the sound variables
;
lhld key$tbl
lxi d,58*4
dad d
mov e,m
inx h
mov d,m
inx h
xchg
shld sound1 ; H=SID reg 24, L=SID reg 5
xchg
mov e,m
inx h
mov d,m
xchg
shld sound2 ; H=SID reg 6, L=SID reg 1
lxi h,9
dad d
mov e,m
inx h
mov d,m
xchg
shld sound3 ; H=SID reg 4 then L=SID reg 4
;
; set-up key click sound registers
;
lxi b,sid+7
lxi h,0040h
outp l ; (sid+7)=40h
inr c
outp l ; (sid+8)=40h
mvi c,low(sid+12)
outp h ; (sid+12)=0 Attack=2ms, Decay=6ms
inr c
outp h ; (sid+13)=0 Sustain=0, Release=6ms
mvi a,6
sta tick$vol ; set keyclick volumn level
;**********************************************
; Password protection routine
;**********************************************
;
if pass
;
mvi a,0
sta count
loop1:
lda count
inr a
sta count
cpi 4
jnz over
call prt$msg
db cr,lf,lf,esc,'G2','Password Error, System Aborting....',0
there:
jmp there
over:
lxi h,cmp$string
push h
call prt$msg
db cr,lf,'Password: ',0
lz1:
call key$board$in
pop h
cmp m
jnz loop1
inx h
push h
mov a,m
cpi 0
jnz lz1
call prt$msg
db cr,lf,lf,0
;
endif
;
ret
;
if pass
;
cmp$string:
pass$word ;password macro
db 0
count:
ds 1
;
endif
;
;***************************************************
;
mmu$table:
mmu$tbl$M
page
;
;
;
CSEG
prt$msg:
xthl
call ?pmsg
xthl
ret
;
; placed in common memory to keep IO from stepping on this code
; always called from bank 0
;
CSEG
read$d505:
sta io$0 ; enable MMU (not RAM)
lxi b,0d505h
inp a ; read 40/80 column screen
sta bank$0 ; re-enable RAM
ret
page
;
;
;
DSEG
init$RS232:
di
xra a
sta RS232$status
lxi h,RxD$buf$count ; clear the count
mvi m,0
inr l ; point to RxD$buf$put
mvi m,low(RxD$buffer)
inr l ; point to RxD$buf$get
mvi m,low(RxD$buffer)
lxi h,NTSC$baud$table
;***************************************
; code to check for NTSC or PAL removed here, system now assumes
; that you are using a north american 128 at 60 hz.
; ***************************************
use$NTSC:
lda RS232$baud
cpi baud$1200 ; baud rate less then 1200 baud
jrc baud$ok ; yes, go set it
mvi a,baud$1200 ; no, 1200 baud is the max
sta RS232$baud ; (change to 1200 baud)
baud$ok:
mov e,a
mvi d,0
dad d ; +1X
dad d ; +1X
dad d ; +1X = +3X
mov e,m
inx h
mov d,m
inx h ;
mov a,m ; get rate #
sta int$rate ;
lxi b,CIA1+timer$b$low ;
outp e ;
inr c ; point to timer$b$high
outp d ;
mvi a,11h ;
mvi c,CIA$ctrl$b ; turn on timer B
outp a ;
lxi b,CIA2+data$b ; setup user port for RS232
inp a ; get old data
ori 6 ; set CTS and DTR
outp a ; update it
ei
ret
page
;
; NTSC rates (1.02273 MHz)
;
NTSC$baud$table:
dw 6818 ; no baud rate (6666.47)
db 1
dw 6818 ; 50 6666.7us (6666.47)
db 1
dw 4545 ; 75 4444.4us (4443.99)
db 1
dw 3099 ; 110 3030.3us (3030.13)
db 1
dw 2544 ; 134 2487.6us (2487.46)
db 1
dw 2273 ; 150 2222.2us (2222.48)
db 2
dw 1136 ; 300 1111.1us (1110.75)
db 3
dw 568 ; 600 555.6us ( 555.38)
db 6
dw 284 ; 1200 277.8us ( 277.69)
db 12
;****************************************************
; PAL baud table removed from here (redundant, as it is not checked for
; or used)
;******************************************************
page
;
;
;
out$RS232:
lda RS232$status
ani 80h
jrnz out$RS232
mov a,c
sta xmit$data ; get character to send in A
lxi h,RS232$status
setb 7,m ; set Xmit request bit
ret
;
;
;
out$st$RS232:
lda RS232$status
ani 80h ; bit 8 set if busy
xri 80h ; A cleared if busy (=80h if not)
rz
ori 0ffh ; A=ff if ready (not busy)
ret
;
;
;
in$RS232:
lda RS232$status
ani 1
jrz in$RS232
lda recv$data
lxi h,RS232$status
res 0,m
ret
;
;
;
in$st$RS232:
lda RS232$status
ani 1
rz
ori 0ffh ; set data ready (-1)
ret
page
;
; this routine is used to provide the user with a method
; of interfacing with low level system functions
;
CSEG
;
; input:
; all registers except HL and A are passed to function
;
; output:
; all resisters from function are preserved
;
?user:
shld user$hl$temp
xchg
shld de$temp ; save DE for called function
mov e,a ; place function number in E
mvi a,num$user$fun-1 ; last legal function number
call vector ; function
usr$tb: dw read$mem$0 ; 0
dw write$mem$0 ; 1
dw ?kyscn ; 2
dw do$rom$fun ; 3 (L=function #)
dw do$6502$fun ; 4 (L=function #)
dw read$d505 ; 5 returns MMU reg in A
dw code$error ; not 0 to 5 ret version number in HL
num$user$fun equ ($-usr$tb)/2
page
;
; address in DE is read and returned in C
; A=0 if no error
;
DSEG
read$mem$0:
ldax d ; read location addressed by DE
mov c,a ; value returned in C
xra a ; clear error flag
ret
;
; address in DE is written to with value in C
; A=0 if no errors
;
write$mem$0:
mvi a,-1 ; get error flag and 0ffh value
cmp d ; do not allow write from FF00 to FFFF
; this is 8502 space, MMU direct reg.
rz
mov a,d
cpi 10h ; do not allow write from 0000 to 0FFF
; this is ROM space
mvi a,-1 ; get error flag
rc ; return if 00h to 0fh
mov a,c
stax d
xra a ; clear error flag
ret
page
;
; This is the function code entry point for direct execution
; of driver functions. If the MSB of the function number is
; set, the 40 column driver is used; else the 80 column drive
; is used.
;
do$rom$fun:
lhld user$hl$temp ; get HL (L=fun #)
mvi a,7eh ; only allow even functions
ana l
cpi 79h
jrc no$hl$req
lhld @dma ; HL will be passed in @dma by
push h ; ..the user
no$hl$req:
mov l,a
rst 5 ; call rom functon (RCALL) L=fun #
ret
; mvi a,7eh ; only allow even functions
; ana l
; sta no$hl$req+1
; cpi 79h
; jrc no$hl$req
; lhld @dma ; HL will be passed in @dma by
; push h ; ..the user
;no$hl$req:
; will be changed to RCALL xx RET for next release (ROM FN 7A, 7C
; and 7E will not function with current code, they expect
; a return address on the stack
;
; RJMP 5Eh ; unused function, real fun# installed
; ..above
do$6502$fun:
lhld user$hl$temp
mov a,l
jmp ?fun65
;
;
;
code$error:
lxi h,date$hex
mvi a,-1
ret
page
;
;
;
CSEG
?rlccp:
;
;******************************************************************
mvi a,01 ; sets feel, put here to set it
sta 0fd52h ; on every warm start
mvi a,repeat$amt ; set at 3
sta repeat
mvi a,delay$amt ; set at 24
sta delay
;******************************************************************
lxi h,ccp$buffer
lxi b,0c80h
load$ccp:
sta bank$0
mov a,m
sta bank$1
lxi d,-ccp$buffer+100h
dad d
mov m,a
lxi d,ccp$buffer-100h+1
dad d
dcx b
mov a,b
ora c
jrnz load$ccp
ret
page
;
;
;
CSEG
?ldccp:
xra a
sta ccp$fcb+15 ; zero extent
lxi h,0
shld fcb$nr ; start at beginning of file
lxi d,ccp$fcb
call open ; open file containing CCP
inr a
jrz no$CCP ; error if no file...
lxi d,0100h
call setdma ; start of TPA
lxi d,128
call setmulti ; allow up to 16K bytes
lxi d,ccp$fcb
call read
lxi h,0100h
lxi b,0c80h
lda force$map
push psw
;
;
save$ccp:
sta bank$1
mov a,m
sta bank$0
lxi d,ccp$buffer-100h
dad d
mov m,a
lxi d,-ccp$buffer+100h+1
dad d
dcx b
mov a,b
ora c
jrnz save$ccp
pop psw
sta force$map
ret
page
;
;
;
no$CCP: ; here if we couldn't find the file
call prtmsg ; report this...
db cr,lf,'BIOS Err on A: No CCP.COM file',0
call ?conin ; get a response
jr ?ldccp ; and try again
;
; CP/M BDOS Function Interfaces
;
CSEG
open:
mvi c,15 ; open file control block
db 21h ; lxi h,(mvi c,26)
setdma:
mvi c,26 ; set data transfer address
db 21h ; lxi h,(mvi c,44)
setmulti:
mvi c,44 ; set record count
db 21h ; lxi h,(mvi c,20)
read:
mvi c,20 ; read records
jmp bdos
; 12345678901
ccp$fcb db 1,'CCP COM',0,0,0
fcb$rc db 0
ds 16
fcb$nr db 0,0,0
page
;
; CXIO.ASM and CXEM.ASM
;
;==========================================================
; ROUITINE TO VECTOR TO HANDLER
;==========================================================
; CP/M IO routines b=device : c=output char : a=input char
;
CSEG
;*********************************************************************
; code in the following vector tables has been altered to null the 40
; column screen
;--------------------------------------------------
?cinit: ; initialize usarts
mov b,c
call vector$io ; jump with table adr on stack
number$drivers:
dw ?int$cia ; keys
dw ?int80 ; 80col
dw rret ; 40col
dw ?pt$i$1101 ; prt1
dw ?pt$i$1101 ; prt2
dw ?int65 ; 6551
dw init$RS232 ; software RS232
dw rret ;
max$devices equ (($-number$drivers)/2)-1
;
;
;
?ci: ; character input
call vector$io ; jump with table adr on stack
dw key$board$in ; keys
dw rret ; 80col
dw rret ; 40col
dw rret ; ptr1
dw rret ; prt2
dw ?in65 ; 6551
dw in$RS232 ; software RS232
dw null$input
;
;
;
?cist: ; character input status
call vector$io ; jump with table adr on stack
dw key$board$stat ; keys
dw rret ; 80col
dw rret ; 40col
dw rret ; prt1
dw rret ; prt2
dw ?ins65 ; 6551
dw in$st$RS232 ; software RS232
dw rret
;
;
;
?co: ; character output
call vector$io ; jump with table adr on stack
dw rret ; keys
dw ?out80 ; 80col
dw rret ; 40col
dw ?pt$o$1 ; prt1
dw ?pt$o$2 ; prt2
dw ?out65 ; 6551
dw out$RS232 ; software RS232
dw rret
;
;
;
?cost: ; character output status
call vector$io ; jump with table adr on stack
dw ret$true ; keys
dw ret$true ; 80col
dw ret$true ; 40col
dw ret$true ; prt1 ?pt$s$1101
dw ret$true ; prt2
dw ret$true ; 6551
dw out$st$RS232 ; software RS232
dw ret$true
;************************************************************
page
;
; This entry does not care about values of DE
;
vector$io:
mvi a,max$devices ; check for device # to high
mov e,b ; get devive # in E
;
;
; INPUT:
; Vector # in E, Max device in A
; passes value in DE$TEMP in DE
; HL has routine's address in it on entering routine
;
; OUTPUT:
; ALL registers of returning routine are passed
;
vector:
pop h ; get address vector list
mvi d,0 ; zero out the MSB
cmp e ; is it too high?
jrnc exist ; no, go get the handler address
mov e,a ; yes, set to max$dev$handler(last one)
exist:
dad d ;
dad d ; point into table
mov a,m
inx h
mov h,m
mov l,a ; get routine adr in HL
shld hl$temp ; save exec adr
lxi h,0
dad sp
lxi sp,bios$stack
push h ; save old stack
lhld de$temp
xchg
lhld hl$temp ; recover exec adr
lda force$map ; get current bank
push psw
sta bank$0 ; set bank 0 as current
call ipchl
sta a$temp ; save value to return
pop psw
sta force$map ; set old bank back
lda a$temp ; recover value to return
shld hl$temp
pop h ; recover old stack
sphl ; set new stack
lhld hl$temp
ret
ipchl:
pchl ; jmp to handler
ds 30h
bios$stack:
page
;==========================================================
; CHARACTER INPUT ROUTINES
;==========================================================
DSEG
;
;
;
key$board$in:
call key$board$stat ; test if key is available
jrz key$board$in
lda key$buf
push psw ; save on stack
xra a ; clear key
sta key$buf
pop psw ; recover current key
rret:
ret
;
;
;
null$input: ; return a ctl-Z for no device
mvi a,1Ah
ret
page
;==========================================================
; CHARACTER DEVICE INPUT STATUS
;==========================================================
DSEG
;
;
;
key$board$stat:
lda key$buf
ora a
jrnz ret$true
call ?get$key
ora a ; =0 if none
rz ; return character not advailable
sta key$buf ; was one, save in key buffer
ret$true:
ori 0ffh ; and return true
ret
page
cseg
@ctbl
db 'KEYBRD' ; device 0, internal keyboard
db mb$input
db baud$none
db '80-COL' ; device 1, 80 column display
db mb$output
db baud$none
db 'NULL40' ; device 2, 40 column display
db mb$output
db baud$none
db 'PRT-LQ' ; device 3, serial bus printer (device 4)
db mb$output
db baud$none
db 'PRT-MX' ; device 4, serial bus printer (device 5)
db mb$output
db baud$none
db '6551 ' ; device 5, EXT CRT
db mb$in$out+mb$serial+mb$softbaud+mb$xonxoff
X6551$baud:
db baud$9600
db 'RS-232' ; device 6, software RS232 device
db mb$in$out+mb$serial+mb$xonxoff+mb$softbaud
RS232$baud:
db baud$300
db 0 ; mark end of table
page
;
; TIME.ASM
;
cseg
;
; HL and DE must be presevered
;
?time:
inr c
lxi b,cia$hours
jrz set$time
;
; update SCB time (READ THE TIME)
;
inp a ; read HR (sets sign flag)
jp is$am ; jmp if AM (positive)
ani 7fh
adi 12h ; noon=24(PM), midnight=12(AM)
daa
cpi 24h ; check for noon (12+12 PM)
jrnz set$hr
mvi a,12h
jr set$hr
is$am:
cpi 12h ; check for midnight (AM)
jrnz set$hr
xra a ; becomes 00:00
set$hr:
sta @hour
mov b,a
lda old$hr
mov c,a
mov a,b
sta old$hr
cmp c ; if @hour<old$hr
jrnc same$day
push h
lhld @date
inx h
shld @date
pop h
same$day:
lxi b,cia$hours-1
inp a ; read MIN
sta @min
dcr c
inp a ; read SEC
sta @sec
dcr c
inp a ; read 1/10 of SEC (a must to free
ret ; the holding register)
old$hr:
ds 1
page
;
;
;
set$time
lda @hour
cpi 12h ; test for noon
jrz set$as$is
ana a ; test for 00:xx
jrnz not$zero$hundred
mvi a,80h+12h ; set to midnight
jr set$as$is
not$zero$hundred:
cpi 11h+1 ; test for 1 to 11 AM
jrc set$as$is
sui 12h
daa ; decimal adjust
set$msb:
ori 80h ; set PM
set$as$is:
outp a
dcr c
lda @min
outp a
dcr c
lda @sec
outp a
dcr c
xra a
outp a
ret
page
;
page
;
; CXMOVE.ASM
;
public ?move,?xmove,?bank
;
; Move a block of data from DE to HL
; count is in BC (within current bank)
;
;
cseg ; place code in common
?move:
xchg ;*
lda source$bnk ; =FFh if normal block move
inr a ;
jrnz inter$bank$move
LDIR ;* do block move
xchg ;*
ret
;
;
;
?xmove: ; can be in bank 0
mov a,c
sta source$bnk
mov a,b
sta dest$bnk
ret ;*
page
;
;
;
inter$bank$move:
shld @buffer ; save HL TEMP
lxi h,0
dad sp
lxi sp,bios$stack
push h ; save old stack ;**1
lhld @buffer
mov a,b ; get msb of count
ora a
jrz count$less$than$256
push b ; save the count ;**2
push d ; save the dest ;**3
lxi d,@buffer ; make buffer the dest
lxi b,256 ; move 256 bytes
lda source$bnk
call ?bank
ldir ; move source to buffer
pop d ; recover dest ;**2
push h ; save updated source ;**3
lxi h,@buffer ; make the buffer the source
lxi b,256 ; move 256 bytes
lda dest$bnk
call ?bank
ldir ; move buffer to dest
pop h ; recover updated source ;**2
pop b ; recover count ;**1
dcr b ; subtract 256 from count
jr inter$bank$move
page
;
;
;
count$less$than$256:
ora c ; BC=0 [A (0) or'ed with C]
jrz exit$move
push d ; save count for 2nd half ;**2
push b ; save dest adr ;**3
lxi d,@buffer
lda source$bnk
call ?bank
ldir ; move source to buffer
pop b ; recover count ;**2
pop d ; recover dest ;**1
push h ; save updated dest ;**2
lxi h,@buffer
lda dest$bnk
call ?bank
ldir ; move buffer to dest
pop h ;**1
;
;
;
exit$move:
xchg
mvi a,-1
sta source$bnk ; set MOVE back to normal
lda @cbnk
shld @buffer
pop h ; recover old stack ;**0
sphl
lhld @buffer
; call ?bank ; set current bank
; ret
page
;
; switch bank to bank number in A
;
cseg ; (must be in common)
?bank:
ora a ; bank 0 ?
jrnz not$bank$0 ; go check for bank 1
sta bank$0 ; set bank 0
ret
;
;
not$bank$0:
dcr a ; bank 1 ?
rnz ; if not a valid bank just return
sta bank$1 ; set bank 1
ret
end
t
;
;
not$bank$0:
dcr a ; bank 1 ?
rnz ; if not a valid ban