home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d01xx
/
d0165.lha
/
CPM
/
Source
/
ce.a
next >
Wrap
Text File
|
1988-11-22
|
72KB
|
3,015 lines
; CP/M and terminal emulator for Amiga
; for z80 emulator
cever dc.b 'Ce Ver: 00090 Date: 03-Oct-88 19:57:44 ',0
; This source code is released into the public domain for
; non-profit use only.
; Copyright (C) 1988, Ulf Nordquist. All Rights Reserved !
; Ulf Nordquist
; Brunnehagen 36
; 417 47 Gothenburg
; Sweden
; History
; 871110 : osinit
; osentry, jumptable for bdos & bios but no functions
; 871114 : conwin
; console device
; bdos06
; 871117 : sizing for console window
; escape sequence decoding in bdos06
; 871118 : esc seq $3d,$4c in bdos06
; 871121 : msg port for console device
; 871122 : set up stack and pc in osinit
; oserr6 + errors report function no. in d6
; 871203 : osrun (ccp)
; conchk conwait
; 871213 : bios03
; command tail buffer in ccp
; 871214 : fcb1 & fcb2 setup
; 871217 : error texts
; bdos09
; 871219 : bios06,09,0c
; 871220 : bdos01,02,10,11
; clean up console status check/in/out routines
; getclin
; 871222 : bdos12
; 880111 : bdos15
; 880117 : bdos20
; 880119 : bug1 a=l & b=h at return from bdos
; real bios jump table
; 880205 : bug2 when waiting for chraracters from console
; 880208 : bdos17, 26
; 880221 : bdos18, 25
; 880224 : esc seq $27, $28, $2b, $2c, $4b
; bdos13, 14
; choice of error at undefined escape sequence
; 880226 : bdos31 & dpb
; bdos27 & alloc
; try to set up file size in bdos17 & 18
; 880227 : change osinit to allow more than one call and move it to
; osrun
; $1a as clear screen to terminal
; 880311 ; resident command dir, type
; serfir, sernxt
; log to file in conout
; 880312 : log to file via logbuf
; 880313 : serfir/nxt widcard in ex
; 880430 : ver 00001
; 880529 : reqstr
; 880531 : openlog asks for file name
; 880714 : bdos33
; bug3 update lastpos if repos in bdos20
; bdos16
; allow transient to open more than one file (5 for now)
; 880715 : console window is borderless
; remove windowsizing fron console window and make it
; max height direct
; 880816 : bug4 in cursor pos, add 1
; chk if file already open in bdos15
; 880822 : sizeable window during debug (Curse of the 512k Amiga)
; 880909 : ActivateGadget in reqstr
; bdos00,19,21,22,34
; bios0f,2d
; 880912 : bdos32,23,36
; ^C in getclin
; 880913 : start message in console window
; 880914 : oserr8
; 880915 : count bios & bdos calls
; 880918 : possible to load program to tpa bigger than $7ff0
; bug5 when read or write via bdos over $8000 boundry
; 880924 : really corrected bug5
; resident command era
; 880929 : change console window height and change BorderTop in struct
; to get 80x24 in 200 pixels
; Differences and limitations in emulation (as many as I can think of)
; unimplemented functions
; resident commands : ren
; bdos : 03,04,05,07,08,13,14,24
; 28,29,30,35,37,40
; bios : 00,12,15,18,1b,1e,21,24,27,2a,30
; dir no wildcards supported
; bdos15 (Open file) sets cr in fcb to 0 (to work with zsid) and
; same with ex (for symmetry (or whatever)). Always returns
; directory code 0 if successful
; bdos16 (Close file) always returns directory code 0 if successful
; bdos17 (Search for first) sets directory entry to 0, except for name,
; ex and rc. Wildcard only supported in ex, always gets first
; file in directory. Always returns directory code 0 if
; successful.
; bdos18 (Search for next) same limitations as bdos17, except gets
; next file in directory
; bdos19 (Delete file) always returns directory code 0 if successful
; bdos20 (Read sequential) always returns directory code 0 if
; successful
; bdos21 (Write sequential) always returns directory code 0 if
; successful
; bdos22 (Make file) always returns directory code 0 if successful
; bdos2 (Rename file) always returns directory code 0 if successful
; bdos27 (Get adddr(alloc)) the vector is wrong when used disk size is
; less than directory size (cks*recsiz)
; bdos32 (Set/get user code) always return 0, cannot set
; bdos33 (Read random) returns $ff if error
; bdos34 (Write random) returns $ff if error
; bios0f (List) recognized but ignored
; bios2d (Listst) will always return 0
; ccp (and bdos10) uses bs & cr for its expected use, ^C first in
; the line restart cpm, all other control codes is sent to user
; maximum of five files open by transient
; only user 0 is supported
; not possible to change default drive
; virtual terminal is adm3a (bdos02 06 09)
; --- implemented escape sequences ---
; 27 : start inverse video
; 28 : end inverse video
; 2b : end reduced intensity (ignored)
; 2c : start reduced intensity (ignored)
; 3d<line+$20><column+$20> : position cursor
; 4b : erase to end of line
; 4c : clear and home
; --- implemented control codes ---
; 1a : clear screen
; program area is $10000 bytes, logical start is at start+$8000
; logical start is $0000 for the processor
; map over program area (logical addresses) CP/M standard address
; $0000-$00ff system parameters BOOT:
; $0100-$feff transient program area TBASE:
; $fe00-$feff bdos jump FBASE:
; $ff00-$ff7f bios jump table
; $ff80-$ffff disk parameter block, allocation vector
; globals from this module
xdef cever
xdef closelog
xdef comdata
xdef conchk
xdef conmsgpsb
xdef conout1
xdef conwin
xdef dbgconwin
xdef inpbuftab
xdef inppmttab
xdef newline
xdef openlog
xdef osclose
xdef osentry
xdef osrun
xdef reqstr
; externals from cz
xref conwinptr
xref error2
xref error4
xref error5
xref error6
xref genntxt
xref gg_GadgetID
xref gg_NextGadget
xref gg_SpecialInfo
xref gg_TopEdge
xref glflgs
xref im_Class
xref im_IAddress
xref intbase
xref minpeh
xref MP_SIGBIT
xref osexit
xref wd_RPort
xref wd_Size
xref wd_UserPort
xref winbp
xref windp
xref winmnh
xref winmxh
xref winmnw
xref winmxw
xref xalloc
xref z80pc
xref z80pgmptr
xref z80sp
; externals from zek
xref bdosoffs
xref biosoffs
xref cntbuf
xref emucall
xref emuret
xref stoptrc
; externals from mystartup
xref _DOSBase
xref _SysBase
; externals from dos.library
xref _LVOClose
xref _LVODeleteFile
xref _LVOExamine
xref _LVOExNext
xref _LVOInfo
xref _LVOLock
xref _LVOOpen
xref _LVORead
xref _LVORename
xref _LVOSeek
xref _LVOUnLock
xref _LVOWrite
; externals from exec.library
xref _LVOAddPort
xref _LVOAllocSignal
xref _LVOCloseDevice
xref _LVODoIO
xref _LVOFindTask
xref _LVOFreeSignal
xref _LVOGetMsg
xref _LVOOpenDevice
xref _LVORemPort
xref _LVOReplyMsg
xref _LVOSendIO
xref _LVOWait
; externals from intuition.library
_LVOActivateGadget equ -$1ce ;($fe32) I have an 1.1 amiga.lib
xref _LVOCloseWindow
xref _LVOOpenWindow
; equates
; include/graphics/rastport.i
RP_JAM1 equ 0
RP_JAM2 equ 1
; include/intuition.i
ACTIVATE equ $1000
BOOLGADGET equ $0001
BORDERLESS equ $0800
GADGETUP equ $00000040
GADGHCOMP equ $0000
GRELBOTTOM equ $0008
NOCAREREFRESH equ $00020000
RELVERIFY equ $0001
SELECTED equ $0080
SMART_REFRESH equ $0000
STRGADGET equ $0004
WBENCHSCREEN equ $0001
WINDOWDEPTH equ $0004
WINDOWDRAG equ $0002
WINDOWSIZING equ $0001
; StringInfo structure
si_Buffer equ 0
si_UndoBuffer equ 4
si_BufferPos equ 8
si_MaxChars equ 10
si_DispPos equ 12
si_UndoPos equ 14
si_NumChars equ 16
si_DispCount equ 18
si_CLeft equ 20
si_CTop equ 22
si_LayerPtr equ 24
si_LongInt equ 28
si_AltKeyMap equ 32
si_SIZEOF equ 36
; NewWindow structure
nw_LeftEdge equ 0
nw_TopEdge equ 2
nw_Width equ 4
nw_Height equ 6
nw_DetailPen equ 8
nw_BlockPen equ 9
nw_IDCMPFlags equ 10
nw_Flags equ 14
nw_FirstGadget equ 18
nw_CheckMark equ 22
nw_Title equ 26
nw_Screen equ 30
nw_BitMap equ 34
nw_MinWidth equ 38
nw_MinHeight equ 40
nw_MaxWidth equ 42
nw_MaxHeight equ 44
nw_Type equ 46
nw_SIZE equ 48
; window struct
wd_BorderTop equ 13*4+2+1
; include/libraries/dos.i
ACCESS_READ equ -2
MODE_NEWFILE equ 1006
MODE_OLDFILE equ 1005
OFFSET_BEGINNING equ -1
OFFSET_CURRENT equ 0
; DateStamp structure
ds_Days equ 0 ;Number of days since Jan. 1, 1978
ds_Minute equ 4 ;Number of minutes past midnight
ds_Tick equ 8 ;Number of ticks past minute
ds_SIZEOF equ 12
; FileInfoBlock structure
fib_DiskKey equ 0
fib_DirEntryType equ 4 ;Type of Directory. If <0 file, if > 0 dir
fib_FileName equ 8 ;Null terminated. Max 30 chars used for now
fib_Protection equ 116 ;bit mask of protection, rwxd are 3-0
fib_EntryType equ 120
fib_Size equ 124 ;Number of bytes in file
fib_NumBlocks equ 128 ;Number of blocks in file
fib_DateStamp equ 132 ;Date file last changed
fib_Comment equ 144 ;Null terminated. Comment associated with file
fib_SIZEOF equ 260
; InfoData structure
id_NumSoftErrors equ 0 ;number of soft errors on disk
id_UnitNumber equ 4 ;Which unit disk is (was) mounted on
id_DiskState equ 8 ;See defines below
id_NumBlocks equ 12 ;Number of blocks on disk
id_NumBlocksUsed equ 16 ;Number of block in use
id_BytesPerBlock equ 20
id_DiskType equ 24 ;Disk Type code
id_VolumeNode equ 28 ;BCPL pointer to volume node
id_InUse equ 32 ;Flag, zero if not in use
id_SIZEOF equ 36
; include/exec/io.i
CMD_READ equ 2
CMD_WRITE equ 3
NT_MSGPORT equ 4
PA_SIGNAL equ 0
; for cpm program area
bios equ $ff00
biosentry equ $40 ;log addr to bios spec opcode (low)
bioshi equ $ff
bioslo equ $00 ;logical address to bios jump table
biostl equ 3 ;length of one bios table entry
ccpbufpos equ $80 ;ccp buffer position
dpb equ $ff80 ;disk parameter block
defdma equ $80 ;default file dma address
defdrv equ 0 ;default drive A:
fbase equ $fe00
fbasehi equ $fe
fbaselo equ $00 ;logical adress to FBASE:
iobyte equ %10010101 ;intel standard iobyte
;list is assigned to line printer
;punch is assigned to high speed puncher
;reader is assigned to high speed reader
;console is assigned to crt
tbase: equ $100 ;logical address to TBASE
; references backward
alloc equ dpb+15+2
ccpbuflen equ tbase-ccpbufpos ;ccp buffer length (pos here)
; for fcb
fcb1 equ $5c ;default fcb start
fcb2 equ $6c ;2:nd fcb, used only by ccp
fcbex equ $68 ;fcb1 current extent 0-31
fcbs1 equ $69 ;fcb1 s1
fcbs2 equ $6a ;fcb1 s2
fcbrc equ $6b ;fcb1 record count 0-127
fcbd0 equ $6c ;fcb1 d0
fcbcr equ $7c ;fcb1 current record
fcbr0 equ $7d ;fcb1 random record lsb
fcbr1 equ $7e ;fcb1 random record
fcbr2 equ $7f ;fcb1 random record msb
; for dpb
; BLS*(DSM+1)=901120, total bytes per disk
; set BLS=2048 -> DSM=901120/BLS-1=439, BSH=4, BLM=15, EXM=0
; set DRM=255 -> AL0=%11110000, AL1=0, CKS=64
blsiz equ 2048 ;BLS, cpm block size
dirsiz equ 4 ;dir size, in BLS
; actual dpb
spt equ 11 ;SPT sectors per track, 16b
bsh equ 4 ;BSH block shift factor, 8b
blm equ 15 ;BLM block mask, 8b
exm equ 0 ;EXM extent mask, 8b
dsm equ 439 ;DSM, 16b
drm equ 255 ;DRM dir entries - 1, 16b
al0 equ %11110000 ;AL0, 8b
al1 equ 0 ;AL1, 8b
cks equ 64 ;CKS, 16b
off equ 0 ;OFF, 16b
; various
chrh equ 7 ;character height
chrw equ 8 ;character width
cls equ $1a ;clear screen
cpmver equ $0022 ;cpm version 2.2
csi equ $9b
extsiz equ $4000 ;extent size
logsiz equ 1024 ;size of log buffer
namelen equ 8 ;max filename length
recmax equ 128 ;max no of records per extent
recsiz equ $80 ;record size
secsiz equ 512 ;amiga sector size
strbufsiz equ 31 ;max string gadget len+1, total
typelen equ 3 ;max filetype length
z80jp equ $c3 ;z80 jump instruction
z80pgmsiz equ $10000
; backward reference
logfilesize equ strbufsiz ;length of logfile name string
; for console window
; normal
btchg equ 1 ;change in BorderTop
winx equ 0 ;top x
winy equ 0 ;top y
conwinw equ 640 ;width
conwinh equ 200 ;height
conwinflg equ WINDOWDRAG+WINDOWDEPTH+SMART_REFRESH+NOCAREREFRESH+BORDERLESS
; special for debug
dbgconwinw equ 100 ;start width
dbgconwinh equ 50 ;start height
dbgconwinflg equ WINDOWDRAG+WINDOWDEPTH+WINDOWSIZING+SMART_REFRESH+NOCAREREFRESH
; for input window
strgadsiz equ 20*chrw+4 ;gadget size
txtxoff equ chrh+4
inpxmarg equ 2*chrw ;marginal to vert
inpymarg equ inpxmarg/2 ;marginal to horiz
inpwinw equ strgadsiz+2*inpxmarg ;width
; for input window gadgets
; ok
inpokw equ 6*chrw+5 ;width
inpokh equ chrh+5 ;height
inpokx equ inpxmarg ;top x
inpoky equ -2*chrh ;top y
inpoktx equ 2*chrw+2 ;text top x
okid equ 0 ;id#
; cancel
inpcanw equ inpokw ;width
inpcanh equ inpokh ;height
inpcanx equ inpwinw-inpxmarg-inpcanw ;top x
inpcany equ inpoky ;top y
canid equ 1 ;id#
; strings
inpstrw equ strgadsiz ;width
inpstrh equ chrh+4 ;height
inpstrx equ inpokx ;top x
strid equ 2 ;id#
; ascii control
bs equ $08
cr equ $0d
esc equ $1b
lf equ $0a
ds.w 0 ;alignment
section ce,code
; osinit
; initialize CP/M emulator
; console window must be open
; entry : d0.w=two byte opcode to transfer control from the z80emulator
; to the cpm emulator
; chg : d0,d1,d2,a0,a1,a6
osinit: clr.b flags
; put special opcode
; init fbase, the one and only jump
move.l z80pgmptr,a0
add.l #z80pgmsiz/2,a0 ;ptr log pgm start
move.l a0,a1
add.w #fbase,a0 ;ptr fbase
move.b d0,1(a0) ;2:nd opcode byte
rol.w #8,d0
move.b d0,(a0) ;1:st opcode byte
; init bios, the z80 jump table
move.l a1,a0 ;log pgm start
add.w #bios,a0 ;ptr bios
move.b #biosentry,d2 ;spec op code table start
move.w #(biostabend-biostab)/4-1,d1 ;cnt
osinit2: move.b #z80jp,(a0)+
move.b d2,(a0)+
move.b #bioshi,(a0)+ ;one entry in table
addq.b #biostl,d2 ;nxt 2:nd tab start
dbra d1,osinit2
; init bios, the special opcode table
add.w #bios+biosentry,a1 ;ptr bios entry addr
move.w #(biostabend-biostab)/4-1,d1 ;cnt
osinit4: rol.w #8,d0 ;restore opcode
move.b d0,1(a1) ;2:nd opcode byte
rol.w #8,d0
move.b d0,(a1) ;1:st opcode byte
addq.l #biostl,a1 ;nxt 2:nd tab start
dbra d1,osinit4
cmp.b #$ff,conmsgpsb
beq.s osinit1 ;if no signal alloc
rts
; open message port, console device & 2 StdIOReq
osinit1: move.l #-1,d0
move.l _SysBase,a6
jsr _LVOAllocSignal(a6)
cmp.l #-1,d0
beq osinit3 ;if no alloc
move.b d0,conmsgpsb ;signal #
move.l #0,a1
jsr _LVOFindTask(a6)
move.l d0,conmsgpt ;task ptr
move.l #conmsgp,a1
jsr _LVOAddPort(a6)
move.l #conname,a0 ;dev name
move.l #conimsg,a1 ;ptr IOReq, read
move.l conwinptr,a5
subq.b #btchg,wd_BorderTop(a5) ;to get 24 lines in console
move.l a5,cimdata ;conwinptr
move.l a1,a5
move.l #wd_Size,cimlen ;set up data
moveq.l #0,d0 ;unit #
moveq.l #0,d1 ;flgs
jsr _LVOOpenDevice(a6)
or.l d0,d0
bne.s osinit3 ;if error
move.l cimdev,comdev
move.l cimunit,comunit ;clone the 2:nd
; queue a read
move.l a5,a1 ;conimsg ptr
move.l #conichr,cimdata ;data ptr
move.l #1,cimlen
jsr _LVOSendIO(a6)
; message in console window
move.l #startmsg,comdata
jmp conout1
; error in open console
osinit3: jmp error5
; pzinit
; initialize z80 page zero
; dma address & disk parameter block
; close and/or unlock file
; exit : d2=ptr z80 pgm logical start
; chg : d0,d1,d2,d3
; a0,a1
pzinit: move.w #defdma,dmaddr
move.l _DOSBase,a6
move.l lock1,d1
beq.s pzinit5 ;if no lock
bclr.b #1,flags
clr.l lock1 ;flg no lock
jsr _LVOUnLock(a6)
; close all files opened by transient
pzinit5: move.l a2,-(a7)
move.l #handles,a2 ;ptr 1:st handle
move.w #maxhan-1,d2 ;loop cnt
pzinit6: move.l (a2),d1 ;handle
beq.s pzinit4 ;if file not open
jsr _LVOClose(a6)
pzinit4: clr.l (a2) ;flg closed
add.l #hanentsiz,a2
dbra d2,pzinit6 ;loop
move.l (a7)+,a2 ;restore
; data area initialization
move.l #pz1,a1
move.l z80pgmptr,d2
add.l #z80pgmsiz/2,d2 ;ptr log pgm start
pzinit3: move.l d2,a0 ;restore a0
move.w (a1)+,d1
bne.s pzinit1 ;if not end
rts
pzinit1: move.w (a1)+,d3 ;start
add.w d3,a0 ;start
pzinit2: move.b (a1)+,(a0)+ ;move to pgm area
dbra d1,pzinit2
bra.s pzinit3 ;nxt block
; osclose
; emulator end cleanup
; chg : d0,d1,a0,a1,a6
osclose: bsr closelog
jsr stoptrc
move.l _SysBase,a6
move.b conmsgpsb,d0 ;signal #
cmp.b #$ff,d0
bne.s osclose2 ;if signal alloc
rts
osclose2: jsr _LVOFreeSignal(a6)
move.l #conmsgp,a1
jsr _LVORemPort(a6)
tst.l cimdev
bne.s osclose1 ;if con is open
rts
osclose1: move.l #conimsg,a1
jsr _LVOCloseDevice(a6)
bra pzinit
; osrun
; initialize cpm and entry into cpm ccp
; entry : d0.w=two byte opcode to transfer control from the z80emulator
; to the cpm emulator
; exit : file loaded in tpa and z80pc & z80sp set up
; chg : d0,d1,d2,d3,d4,d5,d6,d7
; a0,a1,a2,a3,a6,a7
; 26->
osrun: bsr osinit
; entry from file not found
osrun9: move.l _SysBase,a6
move.l z80pgmptr,d5
add.l #z80pgmsiz/2+ccpbufpos,d5 ;ptr ccp buf start
bsr pzinit
move.l d5,a4
move.b (-ccpbufpos+(pzdrv-pagezero))(a4),d7 ;def drive
add.b #'A',d7 ;drive letter
move.b d7,d0
bsr conout
move.b #'>',d0
bsr conout ;prompt
move.l d5,d4
add.l #ccpbuflen,d4 ;max addr+1
; get data and process it
bsr getclin
; construct file name in tpa
move.l #newline,comdata
bsr conout1
move.l d4,a1 ;start of tpa
move.b d7,(a1)+ ;drive letter
move.b #':',(a1)+
move.l a4,d0
sub.l d5,d0 ;cmd line len
beq osrun9 ;if len=0
subq.l #1,d0
move.l d5,a2 ;buf start
osrun5: cmp.b #' ',(a2)
beq.s osrun4 ;if end of first word
move.b (a2)+,(a1)+ ;pgm name
dbra d0,osrun5 ;search
; end of first (or only) word found
; construct command line tail
osrun4: move.l d5,a3 ;ptr start of cmd tail buf
addq.l #1,d0 ;comp for dbxx
move.b d0,(a3)+ ;cmd tail len
move.b d0,d1
beq osrun11 ;if len=0
subq.l #1,d0
osrun12: move.b (a2)+,(a3)+
dbra d0,osrun12 ;move cmd tail
; construct fcb1 & fcb2
move.l d5,a3 ;ptr cmd tail buf
addq.l #1,a3 ;ptr 1:st chr
osrun24: cmp.b #' ',(a3)
bne.s osrun25 ;if start of word
addq.l #1,a3 ;nxt chr
sub.b #1,d1
beq osrun11 ;if cmd tail end
bra.s osrun24 ;search for 1:st word
osrun25: move.l #-ccpbufpos+fcb1,a0
add.l d5,a0 ;ptr fcb1
bclr.l #30,d1 ;flg fcb1 loop
; drive letter if any
osrun18: bclr.l #31,d1 ;flg file name loop
cmp.b #1,d1
beq.s osrun13 ;rem len =1
cmp.b #':',1(a3)
bne.s osrun13 ;if no drv spec
move.b (a3)+,(a0) ;drv letter
sub.b #'A'-1,(a0) ;cpm drv spec
addq.l #1,a3 ;skip ':'
sub.b #2,d1
beq osrun11 ;if cmd tail end
; file name & type
osrun13: addq.l #1,a0 ;ptr file mame
move.w #namelen-1,d0 ;chr cnt
osrun16: cmp.b #' ',(a3)
beq.s osrun14 ;if end of name&type
cmp.b #'.',(a3)+
beq.s osrun15 ;if end of name
move.b -1(a3),(a0)+ ;name letter
sub.b #1,d1
beq osrun11 ;if cmd tail end
dbra d0,osrun16 ;loop thru name or type
osrun17: cmp.b #' ',(a3)
beq.s osrun14 ;if end of name&type
cmp.b #'.',(a3)+
beq.s osrun15 ;if end of name
sub.b #1,d1
beq osrun11 ;if cmd tail end
bra.s osrun17 ;search for type
osrun15: sub.b #1,d1
beq.s osrun11 ;if cmd tail end
move.l #-ccpbufpos+fcb1+namelen+1,a0
btst.l #30,d1
beq.s osrun19 ;if fcb1 loop
move.l #-ccpbufpos+fcb2+namelen+1,a0
osrun19: add.l d5,a0 ;ptr fcb1 type
move.w #typelen-1,d0 ;chr cnt
bset.l #31,d1 ;flg file type loop
beq.s osrun16 ;if name loop
osrun20: sub.b #1,d1
beq.s osrun11 if cmd tail end
cmp.b #' ',(a3)+
bne.s osrun20 ;search for nxt word
bra.s osrun21
osrun14: addq.l #1,a3 ;skip ' '
sub.b #1,d1
beq.s osrun11 if cmd tail end
osrun21: cmp.b #' ',(a3)
bne.s osrun23 ;if nxt word
addq.l #1,a3 ;nxt chr
sub.b #1,d1
beq.s osrun11 ;if cmd tail end
bra.s osrun21 ;search for nxt word
osrun23: move.l #-ccpbufpos+fcb2,a0
add.l d5,a0 ;ptr fcb2
bset.l #30,d1 ;flg fcb2 loop
beq osrun18 ;if fcb1 loop
; check for resident commands
osrun11: move.b #' ',(a1) ;space last in name
move.l d4,a0
cmp.l #'DIR ',2(a0)
beq rcdir
cmp.l #'ERA ',2(a0)
beq rcera
cmp.l #'TYPE',2(a0)
bne.s osrun1 ;if not type
cmp.b #' ',2+4(a0)
beq rctype
; load file into tpa
osrun1: move.l #filetyp,a0
move.w #(filetype-filetyp)-1,d0
osrun6: move.b (a0)+,(a1)+
dbra d0,osrun6 ;move file type
move.l d4,d1 ;name ptr
move.l #MODE_OLDFILE,d2
move.l _DOSBase,a6
jsr _LVOOpen(a6) ;open file
or.l d0,d0
beq osrun7 ;if no file
move.l d0,d6 ;file handle
move.l d4,d2 ;ptr tpa
move.l #(z80pgmsiz/2)-tbase,d3 ;length
move.l d6,d1 ;file handle
jsr _LVORead(a6) ;read file
cmp.l d0,d3
bne.s osrun3 ;if no more to read
move.l d4,d2 ;ptr tpa
sub.l #(z80pgmsiz/2)+tbase,d2 ;ptr $8000 z80 mem
move.l #(z80pgmsiz/2)-($10000-fbase),d3 ;length
move.l d6,d1 ;file handle
jsr _LVORead(a6) ;read file again
osrun3: move.l d0,d4 ;result
move.l d6,d1 ;file handle
jsr _LVOClose(a6) ;close file
cmp.l #-1,d4
beq osrun8 ;if read error
; file successfully placed in tpa
move.w #tbase,z80pc ;set z80 pc
move.w #bios-2,z80sp ;stack in end of bdos
move.l d5,a0 ;ptr cmd tailbuf start
add.w #bios-ccpbuflen,a0 ;ptr bios
move.b pagezero+1,-2(a0)
move.b pagezero+2,-1(a0) ;wboot ret addr
rts
; file not found or read error
osrun8:
osrun7: move.l #ccpbuflen+2,a0
add.l d5,a0 ;ptr name
move.l a0,comdata
osrun22: cmp.b #'.',(a0)+
bne.s osrun22 ;search for '.'
clr.b -(a0) ;mark end
; entry from error in resident commands
osrun2: bsr conout1
move.b #'?',d0
bsr conout ;'name?'
move.l #newline,comdata
bsr conout1
bra osrun9 ;try again
; resident commands
; dir
rcdir: move.w #fcb1,d2save+2 ;fcbptr
sub.w #tbase,a0 ;ptr log start
move.l a0,a1
add.w #defdma+1,a1
move.l a1,d5 ;abs dir ptr
move.l a0,a4save
bsr serfir
beq.s rcdir1 ;if no find
; output dir list
rcdir7: move.w #3,d6 ;4 entries / line
rcdir6: cmp.w #3,d6
bne.s rcdir4 ;if not 1:st on line
move.b drvlet,d0
bsr conout
move.l #dirsep+1,comdata
bsr conout1
rcdir4: move.l d5,a2
move.w #namelen-1,d2
rcdir2: move.b (a2)+,d0
bsr conout
dbra d2,rcdir2 ;output name
move.b #' ',d0
bsr conout ;output nt separator
move.w #typelen-1,d2
rcdir3: move.b (a2)+,d0
bsr conout
dbra d2,rcdir3 ;output type
tst.w d6
beq.s rcdir5 ;if last on line
move.l #dirsep,comdata
bsr conout1
rcdir5: bsr sernxt
beq.s rcdir1 ;if no find
dbra d6,rcdir6 ;line loop
move.l #newline,comdata
bsr conout1
bra.s rcdir7 ;start new line
rcdir1: jmp osexit
; type
rctype: sub.w #tbase,a0 ;ptr log start
move.l a0,a4save
move.l a0,a3
add.w #fcb1,a3 ;abs fcb ptr
add.w #defdma,a0 ;abs dma addr
move.l a0,d4
bsr xlname
addq.l #2,d1 ;skip drv
move.l d1,comdata ;set up for error
subq.l #2,d1 ;restore
move.l #MODE_OLDFILE,d2
move.l _DOSBase,a6
jsr _LVOOpen(a6)
or.l d0,d0
beq osrun2 ;if no file
move.l d0,d5
; output file to terminal
rctype2: move.l d5,d1 ;handle
move.l d4,d2 ;ptr buffer
move.l #recsiz,d3 ;len
move.l _DOSBase,a6
jsr _LVORead(a6)
or.l d0,d0
beq.s rctype1 ;if eof
move.l d0,comlen ;length
move.l d4,comdata ;ptr buffer
bsr conout2
; allow pause and/or break of output
bsr conchk
beq.s rctype2 ;if no chr
cmp.b #3,d6
beq.s rctype1 ;if ctrl-c
bsr conwait
cmp.b #3,d6
bne.s rctype2 ;if not ctrl-c
rctype1: jmp osexit
; era
rcera: move.l _DOSBase,a6 ;for later use
move.w #fcb1,a3 ;z80 fcb ptr
add.l a4save,a3 ;abs fcb ptr
bsr xlname
jsr _LVODeleteFile(a6)
tst.l d0
beq osrun2 ;if no file
jmp osexit
; osentry
; entry into cpm fdos functions
; the z80 emulator should transfer control to this routine when it
; encounters the 2 byte opcode set up by osinit
; entry : registers as per emulation
; exit : register set up as defined by cpm bdos and bios calls
; last the routine does a ret by jumping to emuret
; d6.w=ffee, ff=function number, ee=error code
; error code 0 : no error
; 1 : transfer from over bios area
; 2 : call to unimplemented bios function
; 3 : transfer from under bdos area
; 4 : transfer from between bdos-bios area
; 5 : call to undefined bdos function
; 6 : call to unimplemented bdos function
; 7 : unimplemented terminal escape requence
; 8 : file handle table full
; chg : - (except as defined in exit)
osentry:
; save registers
move.l d0,d0save
move.l d1,d1save
move.l d2,d2save
move.l d3,d3save
move.l d4,d4save
move.l d5,d5save
move.l d7,d7save
move.l a0,a0save
move.l a1,a1save
move.l a2,a2save
move.l a3,a3save
move.l a4,a4save
move.l a6,a6save
; check were the routine were called
move.w a0,d6 ;pc
subq.w #2,d6 ;comp for 2 byte opcode
cmp.w #bios,d6
blt osentry1 ;if possible bdos entry
; possible bios entry
cmp.w #bios+biosentry+(biostabend-biostab)/4*biostl,d6
bge oserr1 ;if over bios
sub.w #biosentry,d6 ;rel ptr into bios
divu.w #biostl,d6
swap d6 ;q<->r
or.w d6,d6
bne oserr1 ;if not correct entry point
; correct bios call
swap d6
moveq.l #0,d3
move.b d6,d3 ;function #
btst.b #5,glflgs
beq.s osentry4 ;if no count
; count bios calls
move.l cntbuf,a5
add.w d3,a5
addq.b #1,biosoffs(a5) ;inc cnt
bne.s osentry2 ;if not max cnt
subq.b #1,biosoffs(a5) ;restore max cnt
osentry2: addq.l #1,a0
osentry4: move.l #biostab,a5
asl.w #2,d3 ;4 bytes per entry
move.l 0(a5,d3.l),a5 ;routine addr
lsr.w #2,d3 ;restore
jmp (a5) ;do routine
; possible bdos call
osentry1: cmp.w #fbase,d6
blt oserr3 ;if under fbase
bne oserr4 ;if not at start
; correct bdos call
and.l #$000000ff,d3 ;isolate routine #
btst.b #5,glflgs
beq.s osentry5 ;if no count
; count bdos calls
move.l cntbuf,a5
add.w d3,a5
addq.b #1,bdosoffs(a5) ;inc cnt
bne.s osentry6 ;if not max cnt
subq.b #1,bdosoffs(a5) ;restore max cnt
osentry6: addq.l #1,a0
osentry5: move.l #bdostab,a5
cmp.b #(bdostabend-bdostab)/4,d3
bgt oserr5 ;if undefined bdos call
asl.w #2,d3 ;4 bytes per entry
move.l 0(a5,d3.l),a5 ;routine addr
lsr.w #2,d3 ;restore #
jmp (a5) ;do routine
; common exit point from bdos & bios functions
; restore registers
osentry3: move.l d0save,d0
move.l d1save,d1
move.l d2save,d2
move.l d3save,d3
move.l d4save,d4
move.l d5save,d5
move.l d7save,d7
move.l a0save,a0
move.l a1save,a1
move.l a2save,a2
move.l a3save,a3
move.l a4save,a4
move.l a6save,a6
jmp emuret ;return to caller
; errors
oserr1: move.w #1,d6 ;transfer over bios
move.l #errtxt1,a5
bra.s osentry3
oserr2: move.b #2,d6 ;unimplemented bios
move.l #errtxt2,a5
bra.s oserr61
oserr3: move.w #3,d6 ;transfer under bdos
move.l #errtxt3,a5
bra.s osentry3
oserr4: move.w #4,d6 ;transfer betwee bdos/bios
move.l #errtxt4,a5
bra osentry3
oserr5: move.b #5,d6 ;undefined bdos
move.l #errtxt5,a5
bra.s oserr61
oserr6: move.b #6,d6 ;unimplemented bdos
move.l #errtxt6,a5
oserr61: rol.w #8,d6
move.b d3,d6 ;function no
rol.w #8,d6
bra osentry3
oserr7: move.b #7,d6 ;unimplemented esc seq
move.l #errtxt7,a5
bra.s oserr61
oserr8: move.w #8,d6 ;file handle table full
move.l #errtxt8,a5
bra osentry3
; bdos functions
; bdos function 0 : system reset
; entry : c=00h
bdos00: jmp osexit
; bdos function 1 : console input
; echo to console output, wait until character ready
; entry : c=01h
; exit : a=chr
bdos01: bsr biosci
move.b d6,d0save+3 ;chr to a reg
move.b d6,d1save+3 ;chr to l reg
move.b d6,d0
bra.s bdos0613 ;echo & exit
; bdos function 2 : console output
; entry : c=02h, e=chr
bdos02: move.b d2save+3,d0 ;e reg
bra.s bdos0613 ;output & exit
; bdos function 6 : direct console I/O
; entry : c=06h, e=$ff (if input) or chr (if output)
; exit : a=chr ($ff if no chr)
; 14->
bdos06: move.b d2save+3,d0 ;e reg
move.l _SysBase,a6 ;for later use
cmp.b #$ff,d0
beq bdos061 ;if input
; if console output
; NOTEZ BIEN !!!
; all output to console should be routed through this routine
; entry from bios0c
bdos0613: and.b #%01111111,d0 ;use 7 bits
btst.b #0,flags
bne.s bdos067 ;if esc seq
cmp.b #' ',d0
blt.s bdos062 ;if ctrl
; output alphanumeric
bdos066: bsr conout
bdos0611: move.b #0,d6 ;flg no error
beq osentry3 ;if no error
; output control characters
bdos062: cmp.b #esc,d0
beq.s bdos063 ;if <esc>
; control except esc
cmp.b #cls,d0
beq txl4c ;if clear screen
bra.s bdos066 ;go and output
; escape
bdos063: bset.b #0,flags ;flg esc
clr.b escptr ;seq rel ptr
bra.s bdos0611
; escape sequence
bdos067: tst.b escptr
bne.s bdos0610 ;if param rx
; first chr in escape sequence, get sequence lenght
move.b d0,escseq
move.w #(esctabend-esctab)/8,d1 ;cnt
move.l #esctab+1,a0 ;ptr 1:st
bdos069: cmp.b (a0)+,d0
beq.s bdos068 ;if find
addq.l #7,a0 ;nxt entry
dbra d1,bdos069 ;tab loop
bclr.b #0,flags ;flg no esc
btst.b #4,glflgs
beq.s bdos0611 ;if no req
move.b d0,d3 ;esc seq
bra oserr7 ;make requester
bdos068: move.l (a0)+,escxlt ;xlt addr
move.w (a0),escptr ;rel cnt
bne.s bdos0611 ;if seq len >0
bclr.b #0,flags ;flg no esc
bra.s bdos0612 ;do esc
; escape sequence parameter reception
bdos0610: move.l #escrx,a0 ;buffer ptr
move.w escptr,d1 ;rel ptr
move.b d0,0(a0,d1.w) ;save chr
addq.w #1,escptr ;nxt buf pos
bne bdos0611 ;if not last in seq
bclr.b #0,flags ;flg no esc
bdos0612: move.l escxlt,a1
jmp (a1) ;translate esc seq
; console input
bdos061: bsr bioscc
or.b d6,d6
beq.s bdos064 ;if no chr
bsr biosci
move.b d6,d0save+3 ;chr to a reg
move.b d6,d1save+3 ;chr to l reg
bra bdos0611 ;exit
; no message
bdos064: move.b d6,d0save+3 ;flg no chr
move.b d6,d1save+3 ;and i l reg
bra bdos0611 ;exit
; bdos function 9 : Print string
; entry : c=09h, de=ptr to string, string ends with '$'
bdos09: move.w d2save+2,d0 ;de reg
move.l z80pgmptr,a2
add.l #z80pgmsiz/2,a2 ;ptr log pgm start
add.w d0,a2 ;ptr string
move.l _SysBase,a6 ;for later use
bdos092: move.b (a2)+,d0 ;chr
cmp.b #'$',d0
beq bdos0611 ;if end, exit
bsr conout
bra.s bdos092 ;loop until end
; bdos function 10 : Read console buffer
; entry : c=0ah, de=ptr to buffer (buffer pos 00=buffer size)
; exit : characters in buffer (buffer pos 01=actual buffer size)
bdos10: move.w d2save+2,d0 ;de reg
move.l z80pgmptr,a4
add.l #z80pgmsiz/2,a4 ;ptr log pgm start
add.w d0,a4 ;ptr buffer
moveq.l #0,d4
move.b (a4),d4 ;buffer size
add.l a4,d4 ;max addr + 1
addq.l #2,a4 ;ptr 1:st in buffer
move.l a4,d5 ;min addr
bsr getclin
sub.l d5,a4 ;# of chrs
move.l a4,d4
move.l d5,a4 ;min addr
move.b d4,-1(a4) ;set # of chrs
bra bdos0611 ;exit
; bdos function 11 : Get console status
; entry : c=0bh
; exit : a=console status, $ff=chr rdy, $00=no chr
bdos11: bsr bioscc
move.b d6,d0save+3 ;flg in a
move.b d6,d1save+3 ;and in l
bra bdos0611 ;exit
; bdos function 12 : Return version number
; entry : c=0ch
; exit : hl=version number
bdos12: move.w #cpmver,d1save+2 ;hl reg
move.b d1save+2,d3save+2 ;copy h to b
move.b d1save+3,d0save+3 ;copy a to l
bra bdos0611 ;exit
; bdos function 13 : Reset disk system
; entry : c=0dh
bdos13: move.w #defdma,dmaddr ;dma address
move.l z80pgmptr,a4
move.b #defdrv,(-ccpbufpos+(pzdrv-pagezero))(a4) ;def drive
bra bdos0611 ;exit
; bdos function 14 : Select disk
; entry : c=0eh, e=selected disk
bdos14: move.b d2save+2,d0 ;e reg
cmp.b #15,d0
bgt bdos0611 ;exit if >15
tst.b d0
blt bdos0611 ;exit if <0
move.l z80pgmptr,a4
move.b d0,(-ccpbufpos+(pzdrv-pagezero))(a4) ;def drive
bra bdos0611 ;exit
; bdos function 15 : Open file
; entry : c=0fh, de=fcb address
; internal : d5.l b0=make file
; exit : a=directory code
bdos15: bclr.l #0,d5 ;flg open file
; entry from bdos22
bdos154: move.w d2save+2,a3 ;z80 fcb ptr
add.l a4save,a3 ;abs fcb ptr
clr.b fcbcr-fcb1(a3) ;clr cr (sic)
clr.b fcbex-fcb1(a3) ;clr ex (sic)
move.l a3,a5 ;abs fcb ptr
bsr gethan
bne.s bdos157 ;if already open
bsr xlname
; check directory for file
move.l #MODE_OLDFILE,d2 ;for open
btst.l #0,d5
beq.s bdos155 ;if open
move.l #MODE_NEWFILE,d2 ;for make
bdos155: move.l _DOSBase,a6
jsr _LVOOpen(a6) ;open file
or.l d0,d0
beq bdos156 ;if no file
; if successful open
; search for free place in table
move.l #handles,a2 ;ptr 1:st handle
move.w #maxhan-1,d2 ;loop cnt
bdos152: tst.l (a2) ;handle
beq.s bdos151 ;if free
add.l #hanentsiz,a2
dbra d2,bdos152
; no place found in table
move.l d0,d1 ;handle
jsr _LVOClose(a6)
bra oserr8
bra.s bdos156
; place found in table
bdos151: move.l d0,(a2)+ ;handle
move.w #hannamsiz-1,d2 ;loop cnt
bdos153: move.b (a5)+,(a2)+ ;copy FCB file name
dbra d2,bdos153
; successful exit from bdos16,17,18,19,20,23 also
bdos157: clr.b d0save+3 ;flg open success
clr.b d1save+3 ;and in l reg
bra bdos0611 ;exit
; if unsuccessful open
; if seek or read/write error or end of file from bdos20
; if no find from bdos17 & bdos18 & bdos19 & bdos23
; if no file open error from bdos16
bdos156: move.b #$ff,d0save+3 ;flg open failure
move.b #$ff,d1save+3 ;and in l reg
bra bdos0611 ;exit
; bdos function 16 : Close file
; entry : c=10h, de=fcb address
; exit : a=directory code
bdos16: move.l _DOSBase,a6 ;for later use
move.w d2save+2,a3 ;z80 fcb ptr
add.l a4save,a3 ;abs fcb ptr
bsr gethan
beq.s bdos156 ;if no handle found
clr.l (a2) ;flg closed
jsr _LVOClose(a6)
bra.s bdos157 ;exit
; bdos function 17 : Search for first
; entry : c=11h, de=fcb address
; exit : a=directory code
bdos17: bsr serfir
bdos171: beq.s bdos156
bra.s bdos157
; bdos function 18 : Search for next
; entry : c=12h, de=fcb address
; exit : a=directory code
bdos18: bsr sernxt
bra.s bdos171
; bdos function 19 : Delete file
; entry : c=13h, de=fcb address
; exit : a=directory code
bdos19: move.l _DOSBase,a6 ;for later use
move.w d2save+2,a3 ;z80 fcb ptr
add.l a4save,a3 ;abs fcb ptr
bsr gethan
bne.s bdos191 ;if handle found
clr.l d0
move.l d0,a2 ;flg no handle
bdos191: move.l a2,a5
bsr xlname
jsr _LVODeleteFile(a6)
tst.l d0
beq.s bdos156 ;if no file
move.l a5,d0
tst.l d0 ;flg closed
beq bdos157 ;exit if no handle
clr.l (a5) ;flg closed
bra bdos157 ;exit
; bdos function 20 : Read sequential
; entry : c=14h, de=fcb address
; internal : d5.l b0=random, b1=write
; exit : a=directory code
bdos20: bclr.l #0,d5 ;flg sequential
bclr.l #1,d5 ;flg read
; entry from bdos21,33,34
bdos203: move.l _DOSBase,a6 ;for later use
move.w d2save+2,a3 ;z80 fcb ptr
move.l a4save,a4 ;ptr pgm middle
add.l a4,a3 ;abs fcb ptr
moveq.l #0,d0
move.w d0,d6
btst.l #0,d5
beq.s bdos202 ;if read seq
; if random, calculate extent and record
move.b fcbr1-fcb1(a3),d0 ;rnd rec hi
asl.w #8,d0 ;move hi
move.b fcbr0-fcb1(a3),d0 ;rnd rec lo
divu.w #extsiz/recsiz,d0 ;rec.w ext.w
move.b d0,fcbex-fcb1(a3) ;set cur extent
swap d0 ;get rec
move.b d0,fcbcr-fcb1(a3) ;set cur record
moveq.l #0,d0
bdos202: move.b fcbex-fcb1(a3),d0 ;cur extent
mulu.w #extsiz,d0 ;tot extent size
move.b fcbcr-fcb1(a3),d6 ;cur record
mulu.w #recsiz,d6 ;tot record size
add.l d0,d6 ;pos in file
bsr gethan
beq bdos156 ;if no handle
move.l d1,d4 ;handle for later use
moveq.l #0,d2
move.l #OFFSET_CURRENT,d3
jsr _LVOSeek(a6) ;get position
cmp.l d0,d6
beq.s bdos201 ;if correct pos
; if repositioning in file is required
move.l d4,d1 ;handle
move.l d6,d2 ;pos
move.l #OFFSET_BEGINNING,d3
jsr _LVOSeek(a6) ;position
cmp.l #-1,d0
beq bdos156 ;if error
; read/write file
bdos201: moveq.l #0,d0
move.w dmaddr,d0
cmp.l #$8000-recsiz,d0
ble.s bdos206 ;if dma in lower z80 mem
cmp.l #$8000,d0
bge.s bdos206 ;if dma in upper z80 mem
; dma over $8000 boundry
move.w #$8000,d3
sub.w d0,d3 ;size to $8000
move.l a4,a5 ;mid ptr
add.w d0,a5
move.l a5,d2 ;abs dma ptr
move.l d4,d1 ;handle
btst.l #1,d5
bne.s bdos207 ;if write
jsr _LVORead(a6)
bra.s bdos208
bdos207: jsr _LVOWrite(a6)
bdos208: cmp.l #-1,d0
beq bdos156 ;if error
or.l d0,d0
beq bdos156 ;if end of file
move.w #recsiz,d0
sub.w d3,d0 ;remaining size
move.w d0,d3
move.w #$8000,d0 ;new dma addr
bra.s bdos209
; normal read/write
bdos206: move.l #recsiz,d3 ;length
bdos209: add.w d0,a4 ;abs ptr file dma
move.l a4,d2
move.l d4,d1 ;handle
btst.l #1,d5
bne.s bdos204 ;if write
jsr _LVORead(a6)
bra.s bdos205
bdos204: jsr _LVOWrite(a6)
bdos205: cmp.l #-1,d0
beq bdos156 ;if error
or.l d0,d0
beq bdos156 ;if end of file
btst.l #0,d5
bne bdos157 ;if read rnd
; if sequential, update record and extent
addq.b #1,fcbcr-fcb1(a3) ;next record
cmp.b #recmax,fcbcr-fcb1(a3)
bne bdos157 ;if no rec ovf
addq.b #1,fcbex-fcb1(a3) ;next extent
clr.b fcbcr-fcb1(a3) ;init record
bra bdos157 ;success exit
; bdos function 21 : Write sequential
; entry : c=15h, de=fcb address
; exit : a=directory code
bdos21: bclr.l #0,d5 ;flg sequential
bset.l #1,d5 ;flg write
bra bdos203
; bdos function 22 : Make file
; entry : c=16h, de=fcb address
; exit : a=directory code
bdos22: bset.l #0,d5 ;flg make file
bra bdos154
; bdos function 23 : Rename file
; entry : c=17h, de=fcb address old name, de+16=fcb new name
; exit : a=directory code
bdos23: move.w d2save+2,a5 ;z80 fcb ptr
add.l a4save,a5 ;abs fcb ptr old
move.l a5,a3
add.w #fcb2-fcb1,a3 ;abs fcb ptr new
bsr xlname
move.l d1,d2 ;ptr new name
move.l a5,a3 ;abs fcb old
move.l #fnbuf2,a4
bsr xlnameb
move.l _DOSBase,a6
jsr _LVORename(a6)
tst.l d0
beq bdos156 ;if failure
bra bdos157 ;exit
; bdos function 25 : Return current disk
; entry : c=19h
; exit : a=current disk
bdos25: move.l a4save,a2 ;ptr pgm middle
move.b pzdrv-pagezero(a2),d0 ;def drv
move.b d0,d0save+3 ;to a reg
move.b d0,d1save+3 ;and to l reg
bra bdos0611 ;exit
; bdos function 26 : Set DMA address
; entry : c=1ah, de=DMA address
bdos26: move.w d2save+2,dmaddr ;dma address
bra bdos0611 ;exit
; bdos function 27 : Get ADDR(Alloc)
; entry : c=1bh
; exit : hl=ALLOC address
bdos27: move.w #alloc,d1save+2 ;ptr to hl reg
move.b d1save+3,d0save+3 ;copy l to a
move.b d1save+2,d3save+2 ;copy h to b
; calculate allocation vector
; get info for current drive
bclr.b #1,flags ;flg fib & lock not valid
move.l a4save,a2 ;ptr pgm middle
move.b pzdrv-pagezero(a2),d0 ;def drive
add.b #'A',d0 ;drive letter
move.l #fnbuf,a1
move.l a1,d1 ;name ptr
move.b d0,(a1)+
move.b #':',(a1)+
clr.b (a1)+ ;disk name
move.l #ACCESS_READ,d2
move.l _DOSBase,a6
jsr _LVOLock(a6)
or.l d0,d0
beq bdos0611 ;if no lock, exit
move.l d0,d3
move.l fibptr,d0
bne.s bdos272 ;if allocated
move.l #fib_SIZEOF,d0 ;size
jsr xalloc
bne.s bdos273 ;if success
jmp error4
bdos273: move.l d0,fibptr
bdos272: move.l d0,d2 ;data ptr
move.l d0,a3
move.l d3,d1 ;lock
move.l _DOSBase,a6
jsr _LVOInfo(a6)
or.l d0,d0
beq bdos0611 ;if no info, exit
; set up allocation vector
move.l id_NumBlocksUsed(a3),d0
mulu.w #secsiz,d0 ;bytes used
add.w #alloc,a2 ;ptr alloc
move.b #al0,(a2)+
move.b #al1,(a2)+ ;move al
move.l a2,a3
move.w #(dsm>>3),d1 ;byte cnt
bdos271: clr.b (a2)+
dbra d1,bdos271 ;clr vector
divu.w #blsiz,d0 ;cpm blocks used
sub.w #dirsiz,d0 ;sub used by dir
bmi bdos0611 ;if neg allocated
move.w d0,d1
and.w #%0000000000000111,d1
beq.s bdos275 ;if no partial byte
subq.w #1,d1 ;use d1 as cnt
move.b #%10000000,d2
asr.b d1,d2 ;shift in bytes
move.b d2,(a3)+
bdos275: lsr.w #3,d0 ;whole bytes
beq bdos0611 ;if no whole bytes
subq.w #1,d0
bdos274: move.b #$ff,(a3)+
dbra d0,bdos274 ;fill bytes
bra bdos0611 ;exit
; bdos function 31 : Get ADDR(Disk parms)
; entry : c=1fh
; exit : hl=DPB address
bdos31: move.w #dpb,d1save+2 ;ptr to hl reg
move.b d1save+3,d0save+3 ;copy l to a
move.b d1save+2,d3save+2 ;copy h to b
bra bdos0611 ;exit
; bdos function 32 : Set/get user code
; entry : c=20h, e=ffh(get) else set user code
; exit : a=current user code
bdos32: move.b #0,d1save+3 ;user code to l
move.b d1save+3,d0save+3 ;copy l to a
move.b d1save+2,d3save+2 ;copy h to b
bra bdos0611 ;exit
; bdos function 33 : Read random
; entry : c=21h, de=FCB address
; exit : a=return code
bdos33: bset.l #0,d5 ;flg random
bclr.l #1,d5 ;flg read
bra bdos203 ;same as read seq
; bdos function 34 : Write random
; entry : c=22h, de=FCB address
; exit : a=return code
bdos34: bset.l #0,d5 ;flg random
bset.l #1,d5 ;flg write
bra bdos203 ;same as read seq
; bdos function 36 : Set random record
; entry : c=24h, de=FCB address
; exit : random record field set in FCB
bdos36: move.w d2save+2,a3 ;z80 fcb ptr
add.l a4save,a3 ;abs fcb ptr old
; set random record from extent and record
moveq.l #0,d0
move.l d0,d1
move.b fcbcr-fcb1(a3),d0 ;cur record
move.b fcbex-fcb1(a3),d1 ;cur extent
mulu.w #extsiz/recsiz,d1 ;tot extent size
add.w d0,d1 ;tot record size
move.b d1,fcbr0-fcb1(a3) ;rnd rec lo
lsr.w #8,d0 ;move hi->lo
move.b d1,fcbr1-fcb1(a3) ;rnd rec hi
move.b #0,fcbr2-fcb1(a3) ;rnd rec highest
bra bdos0611 ;exit
; ___ ___ ___ ___ ___ ___ ___ ___
; | | | | | | | | | | | | | |
; | ___| ___| |___| |___ |___ | |___| |___| | |
; | | | | | | | | | | | | |
; | |___ ___| | ___| |___| | |___| ___| |___|
ds.w 0 ;alignment
bdos03:
bdos04:
bdos05:
bdos07:
bdos08:
bdos24:
bdos28:
bdos29:
bdos30:
bdos35:
bdos37:
bdos40: bra oserr6
; gethan
; get a handle to a file from table
; entry : a3=ptr to FCB file name
; exit : a2=ptr to handle in tab, d1=handle, zflg=no find
; chg : d0,d1,d2,d3
; a2
gethan: move.l #handles,a2 ;ptr 1:st handle
move.w #maxhan-1,d1 ;handle loop cnt
gethan4: move.w #hannamsiz-1,d2 ;name loop cnt
tst.l (a2) ;handle
beq.s gethan1 ;if free
moveq.l #0,d0 ;name index
gethan3: move.b 0(a3,d0.w),d3 ;FCB chr
cmp.b 4(a2,d0.w),d3
bne.s gethan1 ;if no match
addq.l #1,d0 ;nxt chr
dbra d2,gethan3 ;name match loop
move.l (a2),d1 ;handle
rts ;exit
gethan1: add.l #hanentsiz,a2 ;nxt handle
dbra d1,gethan4
moveq.l #0,d1 ;flg no find
rts
; reqstr
; get strings from user
; entry : a2.l=ptr table of size.w of & ptrs.l to input buffers
; last size is 0
; a4.l=ptr table of ptrs to prompts to buffers, last is zero
; exit : d2.l=1 if ok gadget, 2 if cancel gadget
; chg : d0,d1,d2,d3
; a0,a1,a2,a3,a4,a6
; 8->
reqstr: move.l intbase,a6
; calculate window size and gadget positions
; init string gadget structures
move.w #txtxoff,d0 ;init height
move.l #inpstr1,a1 ;ptr 1:st gad
reqstr5: move.w (a2)+,d1 ;buf size
beq.s reqstr4 ;if end of tab
add.w #2*txtxoff,d0 ;y pos of nxt gadget
move.w d0,gg_TopEdge(a1)
move.l gg_SpecialInfo(a1),a3 ;ptr spec info
move.l (a2)+,si_Buffer(a3) ;buf ptr
move.w d1,si_MaxChars(a3) ;buf size
move.l gg_NextGadget(a1),d1 ;nxt gadget
move.l d1,a1
bne.s reqstr5 ;if more str gads
; open window
reqstr4: move.l #inpwin,a0 ;window ptr
move.w d0,d3 ;y pos last gadget
add.w #4*txtxoff,d0
move.w d0,nw_Height(a0) ;window height
jsr _LVOOpenWindow(a6)
or.l d0,d0
bne.s reqstr7 ;if window
jmp error2
reqstr7: move.l d0,a3 ;win ptr
move.l wd_RPort(a3),a2 ;rast port ptr
; display text
move.b #2*txtxoff,d1 ;1:st y coord
reqstr2: cmp.b d3,d1
bge.s reqstr3 ;if past last gadget
move.l (a4)+,d0 ;pmt ptr
beq.s reqstr3 ;if no more ptrs
move.l d0,a5
move.b #chrw,d0 ;1:st x coord
move.b d1,d2
move.l a2,a0 ;rast port ptr
jsr genntxt
move.b d2,d1 ;y coord
add.b #2*txtxoff,d1 ;new y coord
bra.s reqstr2 ;nxt pmt
; activate gadget and wait for user response
reqstr3: move.l a3,a1 ;winptr
move.l #inpstr1,a0 ;ptr 1:st gad
clr.l d0
move.l d0,a2 ;no req
jsr _LVOActivateGadget(a6)
move.l wd_UserPort(a3),a2 ;IDCMP ptr
move.b MP_SIGBIT(a2),d1 ;sigbit #
moveq.l #1,d0
asl.l d1,d0 ;sigbit mask
move.l _SysBase,a6
jsr _LVOWait(a6)
move.l a2,a0 ;IDCMP ptr
jsr _LVOGetMsg(a6)
or.l d0,d0
beq.s reqstr3 ;if no msg
move.l d0,a1 ;ptr msg
move.l im_Class(a1),d2 ;IDCMP class
move.l im_IAddress(a1),a2 ;gadget ptr
jsr _LVOReplyMsg(a6)
cmp.l #GADGETUP,d2
bne.s reqstr3 ;if not gadget
move.w gg_GadgetID(a2),d1
moveq.l #1,d2 ;flg ok gadget
cmp.w #okid,d1
beq.s reqstr6 ;if ok gadget
addq.l #1,d2 ;flg cancel gadget
cmp.w #canid,d1
bne.s reqstr3 ;if not cancel gadget
; close window
reqstr6: move.l a3,a0 ;win ptr
move.l intbase,a6
jmp _LVOCloseWindow(a6)
; close/openlog is called by minpeh and can *only*
; chg : d0,d1,d2,d3
; a0,a1,a2,a3,a6
; it is furthermore called by a menu handling routine and can *only*
; chg : d3
; a0,a1,a2,a3,a6
; closelog
; close terminal log file
; exit : z=no close
closelog: movem.l d0-d2,-(a7)
move.l handle2,d1
beq.s closelog1 ;if no log file open
; write buffer and close file
move.l logbuf,d2
move.l logcnt,d3
beq.s closelog2 ;if buffer empty
move.l _DOSBase,a6
jsr _LVOWrite(a6)
move.l handle2,d1
closelog2: clr.l handle2 ;flg no log
jsr _LVOClose(a6)
move.l #1,d0 ;flg success
closelog1: movem.l (a7)+,d0-d2
rts
; openlog
; open terminal log file
; exit : z=no open
openlog: movem.l d0-d3/a4-a5,-(a7)
; set up buffer and prompt tables and get file name
move.l #inpbuftab,a0
move.l a0,a2
move.w #logfilesize,(a0)+ ;size
move.l #logfile,(a0)+ ;ptr buf
move.w #0,(a0) ;end
move.l #inppmttab,a0
move.l a0,a4
move.l #openlogpmt,(a0)+ ;prompt
move.l #0,(a0) ;end
bsr reqstr
cmp.b #2,d2
beq.s openlog1 ;if cancel
; open file
move.l #logfile,d1 ;buf
move.l #MODE_NEWFILE,d2
move.l _DOSBase,a6
jsr _LVOOpen(a6)
move.l d0,handle2
beq.s openlog1 ;if failure
clr.l logcnt
tst.l logbuf
bne.s openlog1 ;if buffer allocated
move.l #logsiz,d0
jsr xalloc
bne.s openlog2 ;if we got memory
jmp error4
openlog2: move.l d0,logbuf ;ptr
openlog1: movem.l (a7)+,d0-d3/a4-a5
rts
; sernxt
; search for next file
; entry : (d2save+2)=z80 fcb ptr, (a4save)=ptr pgm middle
; (dmaddr)=ptr to directory entry
; exit : directory entry set up at (dmaddr)
; z=no find
sernxt: btst.b #1,flags
bne.s sernxt1
rts ;exit if fib & lock not valid
sernxt1: move.l lock1,d4 ;lock
move.l fibptr,a5 ;file info ptr
move.l _DOSBase,a6 ;yes, do not forget this
move.l a4save,d3 ;abs fcb ptr
add.w foobar,d3 ;z80 fcb ptr
bra serfir5
; serfir
; search for first file
; entry : (d2save+2)=z80 fcb ptr, (a4save)=ptr pgm middle
; (dmaddr)=ptr to directory entry
; exit : directory entry set up at (dmaddr)
; z=no find
; chg : d0,d1,d2,d3,d4
; a0,a1,a2,a3,a4,a5,a6
; 23->
serfir: bclr.b #1,flags ;flg fib & lock not valid
move.b #-1,excnt ;flg invalid
move.l fibptr,d0
bne.s serfir1 ;if allocated
move.l #fib_SIZEOF,d0 ;size
jsr xalloc
bne.s serfir2 ;if success
jmp error4
serfir2: move.l d0,fibptr
; get lock to directory
serfir1: move.l d0,a5
move.w d2save+2,a3 ;z80 fcb ptr
add.l a4save,a3 ;abs fcb ptr
move.l a3,d4
bsr xlname
move.l d1,a3
move.b 2(a3),d3
clr.b 2(a3) ;use only dir
move.l ACCESS_READ,d2
move.l _DOSBase,a6
jsr _LVOLock(a6) ;get lock
or.l d0,d0
bne.s serfir13
rts ;exit if no lock
serfir13: move.b d3,2(a3) ;restore
move.l d4,d3 ;ptr fcb
; get FileInfoBlock for dir
move.l d0,d4 ;lock
move.l d4,d1 ;lock
move.l a5,d2 ;fibptr
jsr _LVOExamine(a6)
or.l d0,d0
bne.s serfir14
rts ;exit if no success
serfir14: move.l d4,lock1 ;save lock
bset.b #1,flags ;flg fib & lock valid
; entry from sernxt
serfir5: move.b excnt,d2
serfir20: cmp.b #-1,d2
beq.s serfir16 ;if not valid
; if valid count
move.l d3,a0 ;fcb ptr
move.b fcbex-fcb1(a0),d0 ;fcb ex
cmp.b #'?',d0
beq.s serfir17 ;if ex wildcard
move.b d0,excnt ;set ex
bra.s serfir19
; if wildcard in extent count
serfir17: move.l fib_Size(a5),d1
move.l #14,d0
lsr.l d0,d1 ;/16384, ex count
cmp.b d1,d2
ble.s serfir9 ;if more ex
; get FileInfoBlock for next file
serfir16: clr.b excnt ;1:st ex
serfir19: move.l d4,d1 ;lock
move.l a5,d2 ;fibptr
jsr _LVOExNext(a6)
or.l d0,d0
bne.s serfir15
rts ;exit if no success
serfir15: tst.l fib_DirEntryType(a5)
bgt.s serfir21 ;if a directory, try again
; first file found, check name for cpm compatibility
; check if name <= namelen chrs
move.l a5,a3 ;fibptr
add.l #fib_FileName,a3 ;ptr name
move.l #fnbuf,a4 ;tmp file name buf
move.l a4,a1
move.w #namelen+typelen,d0
serfir8: move.b #' ',(a1)+
dbra d0,serfir8 ;fill tmp with ' '
move.w #namelen,d0
serfir6: cmp.b #'.',(a3)
beq.s serfir4 ;if type separator found
tst.b (a3)
beq.s serfir9 ;if end found
move.b (a3)+,(a4)+ ;to tmp
dbra d0,serfir6 ;name loop
serfir21: move.b #-1,d2 ;not valid
bra serfir20 ;if no cpm name, try again
; check if type <= typelen chrs
serfir4: add.w d0,a4 ;skip rest of name
addq.l #1,a3 ;skip '.'
move.w #typelen,d0
serfir7: tst.b (a3)
beq.s serfir9 ;if end found
move.b (a3)+,(a4)+ ;to tmp
dbra d0,serfir7 ;type loop
bra.s serfir21 ;if no cpm type, try again
; if file checks out
; set up directory entry at dma address
serfir9: move.l a4save,a2 ;ptr pgm middle
add.w dmaddr,a2 ;abs ptr file dma
move.l #fnbuf,a1
clr.b (a2)+ ;drive
move.w #namelen+typelen-1,d0
serfir10: cmp.b #'a',(a1)
blt.s serfir12 ;if upper case
sub.b #$20,(a1) ;to lower
serfir12: move.b (a1)+,(a2)+
dbra d0,serfir10 ;move file name
move.l fib_Size(a5),d1
move.l d1,d2
move.l #14,d0
lsr.l d0,d1 ;/16384, ex count
move.b excnt,d0
cmp.b d1,d0
ble.s serfir18
moveq.l #0,d0 ;flg no find
rts ;exit if ex too big for file
serfir18: beq.s serfir22 ;if last ex
move.w #$ffff,d2 ;set max size
serfir22: move.b d0,(a2)+ ;ex
addq.b #1,excnt ;nxt ex
clr.b (a2)+
clr.b (a2)+ ;clr s1 & s2
and.l #$00003fff,d2
move.l d2,d0
and.w #$7f,d0
beq.s serfir03 ;if exact rec
add.w #128,d2 ;add 1 rec
serfir03: lsr.l #7,d2 ;/128, rec cnt
move.b d2,(a2)+ ;rc
move.w #fcbcr-fcbd0-1,d0
serfir11: clr.b (a2)+
dbra d0,serfir11 ;clr rest
moveq.l #1,d2 ;flg no error
rts
; xlname xlnameb
; translate name from cpm fcb format to amigados format
; entry : xlname : a3=fcb ptr, (a4save)=ptr to log pgm start
; xlnameb: as xlname + a4=amiga name buffer
; exit : d1=ptr name
; chg : d0,d1
; a2,a3,a4
xlname: move.l #fnbuf,a4
xlnameb: move.l a4,-(a7)
move.b (a3)+,d0
bne.s xlname1 ;if not default
move.l a4save,a2 ;ptr pgm middle
move.b pzdrv-pagezero(a2),d0 ;def drv
addq.b #1,d0 ;fcb format
xlname1: add.b #$40,d0 ;drv letter
move.b d0,(a4)+ ;to name buf
move.b d0,drvlet ;and once again
move.b #':',(a4)+
; move name and type to buffer
bclr.l #31,d0 ;flg name loop
move.w #namelen-1,d0 ;name cnt
xlname3: move.b (a3)+,d1
cmp.b #' ',d1
beq.s xlname2 ;if end of name
move.b d1,(a4)+ ;to name buf
dbra d0,xlname3 ;name loop
xlname4: bset.l #31,d0
bne.s xlname5 ;if type loop
move.w #typelen-1,d0 ;type cnt
move.b #'.',(a4)+ ;name/type delimiter
bra.s xlname3 ;enter type loop
; premature end of name
xlname2: add.w d0,a3 ;skip empty part of name
beq.s xlname4
xlname5: clr.b (a4) ;end of name
move.l (a7)+,d1 ;name ptr
rts
; conchk
; check for character from console, receive it if any
; exit : d6.b=chr, z=no chr
; chg : d0,d1,d6
; a0,a1
conchk: move.l _SysBase,a6
move.l cimport,a0 ;con in port ptr
jsr _LVOGetMsg(a6)
or.l d0,d0
bne.s conchk1 ;if msg
rts ;exit if no msg
; message from console
; get chr, and queue new request
conchk1: move.b conichr,d6 ;chr
move.l #conimsg,a1 ;ptr IOReq, read
move.l #conichr,cimdata ;data ptr
move.l #1,cimlen
jsr _LVOSendIO(a6)
moveq.l #1,d0 ;flg chr
rts
; conwait
; wait for chr from console
; exit : d6.b=chr
; chg : d0,d1,d2,d3,d6
; a0,a1,a2,a3,a6
conwait: bset.b #2,glflgs ;flg conwait
bsr.s conchk
beq.s conwait1 ;if no chr
bclr.b #2,glflgs ;flg no conwait
rts
conwait1: jsr minpeh
bra.s conwait ;get chr
; conout conout1 conout2
; output chr to console
; output string to console
; entry : conout : d0.b=chr
; conout1: (comdata)=ptr to string+<nul>
; conout2: (comdata)=ptr to string, (comlen)=length of string
; chg : d0,d1
; a0,a1,a6,a7
conout1: move.l comdata,a0
move.l a0,d1
conout4: tst.b (a0)+
bne.s conout4 ;if not end
sub.l d1,a0
subq.l #1,a0 ;len
move.l a0,comlen
bra.s conout2
conout: move.b d0,conochr ;data
move.l #conochr,comdata
move.l #1,comlen
conout2: movem.l d2-d5,-(a7)
move.l comlen,d3 ;for use by Write
move.l comdata,d5
move.l _SysBase,a6
move.l #conomsg,a1 ;ptr IOReq, write
jsr _LVODoIO(a6)
or.l d0,d0
beq.s conout3 ;if no error
jmp error6
; log to file if so requested
conout3: move.l handle2,d1
beq.s conout5 ;if no log file
move.l logcnt,d4 ;used in buffer
add.l d3,d4
cmp.l #logsiz,d4
blt.s conout6 ;if new data will fit
; if new data will overflow buffer
; write buffer to file
sub.l d3,d4 ;logcnt
exg.l d3,d4 ;logcnt to d3
move.l logbuf,d2
move.l _DOSBase,a6
jsr _LVOWrite(a6)
clr.l logcnt
move.l d4,d3 ;new data len
cmp.l #logsiz,d4
blt.s conout6 ;if new data will fit
move.l handle2,d1
move.l d5,d2 ;new data ptr
jsr _LVOWrite(a6)
conout5: movem.l (a7)+,d2-d5
rts
; put new data in buffer
; d3=new data len, d4=total len, d5=ptr new data
conout6: move.l d5,a0 ;ptr new data
sub.l d3,d4 ;d4=present logcnt
move.l logbuf,a1
add.l d4,a1 ;ptr into logbuf
add.l d3,d4
move.l d4,logcnt
subq.l #1,d3
conout7: move.b (a0)+,(a1)+
dbra d3,conout7 ;move data to buf
bra.s conout5
; getclin
; get one line of data from console
; exit on <cr> or full buffer
; exit on ^C in pos 1 to main1
; convert all other ctrl chrs to ^<chr>
; entry : d4=max address + 1, d5=min address
; a4=buffer ptr
; exit : a4=ptr last used in buffer + 1
; d4,d5 same
; 9->
getclin: bsr conwait
cmp.b #$20,d6
bge.s getclin1 ;if no ctrl chr
; control chr
cmp.b #3,d6
beq.s getclin4 ;if ^C
cmp.b #bs,d6
beq.s getclin5 ;if backspace
cmp.b #cr,d6
beq.s getclin6 ;if cr
; unrecognized control chr
getclin8: move.b #'^',d0
bsr conout
move.b d6,d0
add.b #$40,d0 ;make real chr
bsr conout
bra.s getclin3
; normal chr
getclin1: move.b d6,d0 ;chr
getclin2: bsr conout
cmp.b #'a',d6
blt.s getclin3 ;if upper case
sub.b #$20,d6 ;make upper case
getclin3: move.b d6,(a4)+ ;store chr
cmp.l d4,a4
blt.s getclin ;if not at end
; cr
getclin6: rts
; ^C
getclin4: cmp.l d5,a4
bne.s getclin8 ;if not at start
jmp osexit ;restart cpm
; backspace
getclin5: cmp.l d5,a4
beq.s getclin ;if at start
move.b -(a4),d0
cmp.b #$20,d0
bge.s getclin7 ;if no ctrl chr
move.l #delete,comdata
bsr conout1
getclin7: move.l #delete,comdata
bsr conout1
bra getclin
; bioscc
; bios console check
; NOTEZ BIEN !!!
; all console status requests should be routed through this routine
; exit : d6.b=00 : if no chr, ff if chr
bioscc: move.l _SysBase,a6
btst.b #3,glflgs
bne.s bioscc1 ;if chr (old chk)
bsr conchk
beq.s bioscc2 ;if no chr
move.b d6,conbuf ;chr
bset.b #3,glflgs ;flg chr
bioscc1: move.b #$ff,d6 ;flg chr
rts
; no message
bioscc2: move.b #0,d6 ;flg no chr in a
rts
; biosci
; bios console input
; NOTEZ BIEN !!!
; all console input should be routed through this routine
; exit : d6.b=chr
biosci: move.l _SysBase,a6
btst.b #3,glflgs
bne.s biosci1 ;if old chr
bsr conwait
rts
; old character
biosci1: bclr.b #3,glflgs ;flg no chr
move.b conbuf,d6 ;old chr
rts
; routines for translating escape sequences
; from adm3a to ansi x3.64
; entry : a0=ptr to last in buffer +1
; txlnop
; recognized but ignored escape sequences
; entry : -
; exit : -
txlnop: bra bdos0611
; txl27
; start reverse video
; entry : -
; exit : <csi> 7 m
txl27: move.l #txl27d,comdata
bra txl3d4
; data to be sent to console
txl27d: dc.b csi,'7','m',0
ds.w 0 ;alignment
; txl28
; end reverse video
; entry : -
; exit : <csi> 0 m
txl28: move.l #txl28d,comdata
bra txl3d4
; data to be sent to console
txl28d: dc.b csi,'0','m',0
ds.w 0 ;alignment
; txl3d
; position cursor
; entry : <line+$20> <column+$20> (in hex, line & column starts at 0)
; exit : <csi> <line> ; <column> H (line & columns starts at 1)
txl3d: move.l #txl3dd+4,a1 ;ptr tx data tens col
move.w #1,d2 ;2 numbers
txl3d3: move.b -(a0),d0 ;col/line+$20
sub.b #$20,d0 ;col/line pos
addq.b #1,d0 ;conv to ansi pos
txl3d2: move.b #-1,d1 ;res
txl3d1: addq.b #1,d1
sub.b #10,d0
bcc.s txl3d1 ;if no cy
add.b #$30,d1 ;make ascii tens
move.b d1,(a1)+ ;put in tx data
add.b #$30+10,d0 ;make ascii units
move.b d0,(a1) ;put in tx data
subq.l #4,a1 ;ptr tx data tens line
dbra d2,txl3d3 ;do line
move.l #txl3dd,comdata
txl3d4: bsr conout1
bra bdos0611 ;exit
; data to be sent to console
txl3dd: dc.b csi,0,0,';',0,0,'H',0 ;zeros to be filled in
ds.w 0 ;alignment
; txl4b
; erase to end line
; entry : -
; exit : <csi> <$4b>
txl4b: move.l #txl4bd,comdata
bra txl3d4
; data to be sent to console
txl4bd: dc.b csi,$4b,0
ds.w 0 ;alignment
; txl4c
; clear and home
; entry : -
; exit : <$0c> <csi> H
txl4c: move.l #txl4cd,comdata
bra txl3d4
; data to be sent to console
txl4cd: dc.b $0c,csi,'H',0
ds.w 0 ;alignment
; esctab
; table for receiving escape sequences
; word : sequence character
; long : address to translation routine
; word : -(number of parameters)
esctab: dc.w $27 ;start reverse video
dc.l txl27
dc.w 0
dc.w $28 ;end reverse video
dc.l txl28
dc.w 0
dc.w $2b ;end reduced intensity
dc.l txlnop
dc.w 0
dc.w $2c ;start reduced intensity
dc.l txlnop
dc.w 0
dc.w $3d ;cursor positioning
dc.l txl3d
dc.w -2
dc.w $4b ;erase to end of line
dc.l txl4b
dc.w 0
dc.w $4c ;clear and home
dc.l txl4c
dc.w 0
esctabend:
; bios functions
; bios03, wboot
bios03: addq.l #4,a7 ;remove ret addr
jmp osexit
; bios06, const
; check for console char ready
; exit : a=0 : if no chr, ff if chr
bios06: bsr bioscc
move.b d6,d0save+3 ;flg in a
bra bdos0611 ;exit
; bios09, conin
; read console character in, wait until character available
; exit : a=chr
bios09: bsr biosci
move.b d6,d0save+3 ;chr in a
bra bdos0611 ;exit
; bios0c, conout
; write console character out
; entry : c=chr
bios0c: move.b d3save+3,d0 ;c reg
bra bdos0613
; bios0f, list
; write list character out
; entry : c=chr
bios0f: bra bdos0611 ;exit
; bios2d, listst
; check list status
; exit : a=$ff if ready, a=0 if not ready
bios2d: clr.b d0save+3 ;flg not rdy
bra bdos0611 ;exit
bios00:
bios12:
bios15:
bios18:
bios1b:
bios1e:
bios21:
bios24:
bios27:
bios2a:
bios30: bra oserr2
; initialized data
; strings
; errors, max 27 characters
; 123456789012345678901234567
errtxt1: dc.b 'Transfer over bios area',0
errtxt2: dc.b 'Unimplemented bios function',0
errtxt3: dc.b 'Transfer under bdos area',0
errtxt4: dc.b 'Transfer between bdos/bios',0
errtxt5: dc.b 'Undefined bdos function',0
errtxt6: dc.b 'Unimplemented bdos function',0
errtxt7: dc.b 'Unimplemented escape seq',0
errtxt8: dc.b 'File handle table full',0
; prompts
openlogpmt: dc.b 'Enter name of log file',0
; various
conname: dc.b 'console.device',0
delete: dc.b bs,' ',bs,0
dirsep: dc.b ' : ',0
filetyp: dc.b '.com',0
filetype:
logfile: dc.b 'a:cpm.log',0 ;default string
logfend:
ds.b logfilesize-(logfend-logfile) ;fill out
newline: dc.b cr,lf,0
startmsg: dc.b 'CP/M 2.2 - Z80 - ADM3A - emulator',cr,lf
dc.b 'AmigaDos Bios V1.02',cr,lf
dc.b 'Copyright (C) 1988 by Ulf Nordquist !',cr,lf,cr,lf,0
; cpm console window data area
; title
conwinttl: dc.b 'CP/M Console',0
; normal console NewWindow struct
conwin: dc.w winx,winy ;top x,y
dc.w conwinw,conwinh ;width, height
dc.b windp,winbp ;detail, block pen
dc.l 0 ;idcmp flags
dc.l conwinflg ;window flgs
dc.l 0 ;ptr 1st gadget
dc.l 0 ;ptr checkmark
dc.l conwinttl ;ptr title
dc.l 0 ;ptr screen
dc.l 0 ;ptr bit map
dc.w winmnw,winmnh ;min width height
dc.w winmxw,winmxh ;max width height
dc.w WBENCHSCREEN ;screen type
; debug console NewWindow struct
dbgconwin: dc.w winx,winy ;top x,y
dc.w dbgconwinw,dbgconwinh ;width, height
dc.b windp,winbp ;detail, block pen
dc.l 0 ;idcmp flags
dc.l dbgconwinflg ;window flgs
dc.l 0 ;ptr 1st gadget
dc.l 0 ;ptr checkmark
dc.l conwinttl ;ptr title
dc.l 0 ;ptr screen
dc.l 0 ;ptr bit map
dc.w winmnw,winmnh ;min width height
dc.w winmxw,winmxh ;max width height
dc.w WBENCHSCREEN ;screen type
; input window data area
; input window NewWindow struct
inpwin: dc.w winx,winy ;top x,y
dc.w inpwinw,0 ;width, height (setup)
dc.b windp,winbp ;detail, block pen
dc.l GADGETUP ;idcmp flags
dc.l WINDOWDRAG+WINDOWDEPTH+ACTIVATE ;window flags
dc.l inpok ;ptr 1st gadget
dc.l 0 ;ptr checkmark
dc.l conwinttl ;ptr title
dc.l 0 ;ptr screen
dc.l 0 ;ptr bit map
dc.w 0,0 ;min width height
dc.w 0,0 ;max width height
dc.w WBENCHSCREEN ;screen type
; input window gadget structs
; Ok
inpok: dc.l inpcan ;ptr nxt gadget
dc.w inpokx,inpoky ;top x,y
dc.w inpokw,inpokh ;width, height
dc.w GADGHCOMP+GRELBOTTOM ;flags
dc.w RELVERIFY ;activation
dc.w BOOLGADGET ;gadget type
dc.l inpbox ;ptr gadget render
dc.l 0 ;ptr select render
dc.l 1$ ;ptr gadget txt
dc.l 0 ;mutual exclude
dc.l 0 ;ptr spec info
dc.w okid ;id#
dc.l 0 ;ptr user data
; text to ok gadget
1$: dc.b winbp,windp ;front, back pen
dc.b RP_JAM2 ;draw mode
dc.b 0 ;word align fill
dc.w inpoktx,2 ;top x,y
dc.l 0 ;ptr font
dc.l 2$ ;ptr text
dc.l 0 ;ptr next intui text
2$: dc.b 'Ok',0
; box for ok & cancel gadgets
inpbox: dc.w 0,0 ;top x,y
dc.b winbp,windp ;front, back pen
dc.b RP_JAM2 ;draw mode
dc.b (2$-1$)/4 ;# coord pairs
dc.l 1$ ;ptr coord pairs
dc.l 0 ;nxt border
; coordinates for box
; x,y
1$: dc.w 0,0
dc.w 0,inpokh-1
dc.w inpokw-1,inpokh-1
dc.w inpokw-1,0
dc.w 0,0
2$:
; input window gadget structs
; cancel
inpcan: dc.l inpstr1 ;ptr nxt gadget
dc.w inpcanx,inpoky ;top x,y
dc.w inpcanw,inpcanh ;width, height
dc.w GADGHCOMP+GRELBOTTOM ;flags
dc.w RELVERIFY ;activation
dc.w BOOLGADGET ;gadget type
dc.l inpbox ;ptr gadget render
dc.l 0 ;ptr select render
dc.l 1$ ;ptr gadget txt
dc.l 0 ;mutual exclude
dc.l 0 ;ptr spec info
dc.w canid ;id#
dc.l 0 ;ptr user data
; text to cancel gadget
1$: dc.b winbp,windp ;front, back pen
dc.b RP_JAM2 ;draw mode
dc.b 0 ;word align fill
dc.w 2,2 ;top x,y
dc.l 0 ;ptr font
dc.l 2$ ;ptr text
dc.l 0 ;ptr next intui text
2$: dc.b 'Cancel',0
; input window gadget structs
; first string
inpstr1: dc.l 0 ;ptr nxt gadget
dc.w inpstrx,0 ;top x,y (setup)
dc.w inpstrw,inpstrh ;width, height
dc.w SELECTED+GADGHCOMP ;flags
dc.w RELVERIFY ;activation
dc.w STRGADGET ;gadget type
dc.l inpboxs ;ptr gadget render
dc.l 0 ;ptr select render
dc.l 0 ;ptr gadget txt
dc.l 0 ;mutual exclude
dc.l inpstr1info ;ptr spec info
dc.w strid ;id#
dc.l 0 ;ptr user data
; special info for first string gadget
inpstr1info: dc.l 0 ;ptr buffer (setup)
dc.l undobuf ;ptr undo buffer
dc.w 0 ;init buf pos
dc.w strbufsiz ;buf size (setup)
dc.w 0 ;pos of 1:st disp chr
dc.w 0 ;pos in undo buf
dc.w 0 ;# chr in buf
dc.w 0 ;# chr disp
dc.w 0,0 ;top x,y
dc.l 0 ;ptr layer
dc.l 0 ;result if int gadget
dc.l 0 ;ptr alt key map
; box for string cancel gadget
inpboxs: dc.w -2,-2 ;top x,y
dc.b winbp,windp ;front, back pen
dc.b RP_JAM2 ;draw mode
dc.b (2$-1$)/4 ;# coord pairs
dc.l 1$ ;ptr coord pairs
dc.l 0 ;nxt border
; coordinates for box
; x,y
1$: dc.w 0,0
dc.w 0,inpstrh
dc.w inpstrw,inpstrh
dc.w inpstrw,0
dc.w 0,0
2$:
; tables for buffer and prompt pointers
; set up by caller
inpbuftab: ds.b 2+4
inppmttab: ds.l 1
; parameters set up by pzinit
; area 1 : $0000-$0007
pz1: dc.w pz2-pz1-4-1 ;len of 1:st
dc.w 0 ;rel addr of 1:st
pagezero: dc.b z80jp ;0 z80 jp
dc.b bioslo+3 ;1
dc.b bioshi ;2 WBOOT in bios table
dc.b iobyte ;3
pzdrv: dc.b defdrv ;4 default drive
dc.b z80jp ;5 z80 jp
dc.b fbaselo ;6
dc.b fbasehi ;7 FBASE:
; area 2 : $005c-$007b fcb1 & fcb2
pz2: dc.w pz3-pz2-4-1 ;len of 2:nd
dc.w fcb1 ;rel addr of 2nd
dc.b 0 ;$5c fcb1 drive
dc.b ' ' ;$5d fcb1 n1
dc.b ' ' ;$5e fcb1 n2
dc.b ' ' ;$5f fcb1 n3
dc.b ' ' ;$60 fcb1 n4
dc.b ' ' ;$61 fcb1 n5
dc.b ' ' ;$62 fcb1 n6
dc.b ' ' ;$63 fcb1 n7
dc.b ' ' ;$64 fcb1 n8
dc.b ' ' ;$65 fcb1 t1
dc.b ' ' ;$66 fcb1 t2
dc.b ' ' ;$67 fcb1 t3
dc.b 0 ;$68 fcb1 ex
dc.b 0 ;$69 fcb1 s1
dc.b 0 ;$6a fcb1 s2
dc.b 0 ;$6b fcb1 rc
dc.b 0 ;$6c fcb2 drive
dc.b ' ' ;$6d fcb2 n1
dc.b ' ' ;$5e fcb2 n2
dc.b ' ' ;$5f fcb2 n3
dc.b ' ' ;$70 fcb2 n4
dc.b ' ' ;$71 fcb2 n5
dc.b ' ' ;$72 fcb2 n6
dc.b ' ' ;$73 fcb2 n7
dc.b ' ' ;$74 fcb2 n8
dc.b ' ' ;$75 fcb2 t1
dc.b ' ' ;$76 fcb2 t2
dc.b ' ' ;$77 fcb2 t3
dc.b 0 ;$78 fcb2 ex
dc.b 0 ;$79 fcb2 s1
dc.b 0 ;$7a fcb2 s2
dc.b 0 ;$7b fcb2 rc
; area 3 : disk parameter block
pz3: dc.w pz4-pz3-4-1 ;len of 3:rd
dc.w dpb ;rel addr of 3:rd
dc.b spt
dc.b 0 ;SPT sectors per track, 16b
dc.b bsh ;BSH block shift factor, 8b
dc.b blm ;BLM block mask, 8b
dc.b exm ;EXM extent mask, 8b
dc.b dsm&$000000ff
dc.b dsm>>8 ;DSM, 16b
dc.b drm&$000000ff
dc.b drm>>8 ;DRM dir entries - 1, 16b
dc.b al0 ;AL0, 8b
dc.b al1 ;AL1, 8b
dc.b cks&$000000ff
dc.b cks>>8 ;CKS, 16b
dc.b off&$000000ff
dc.b off>>8 ;OFF, 16b
; area 4 : empty
pz4: dc.w 0 ;len of 4:th, mark end
; bdostab
; jump table for bdos functions
bdostab: dc.l bdos00
dc.l bdos01
dc.l bdos02
dc.l bdos03
dc.l bdos04
dc.l bdos05
dc.l bdos06
dc.l bdos07
dc.l bdos08
dc.l bdos09
dc.l bdos10
dc.l bdos11
dc.l bdos12
dc.l bdos13
dc.l bdos14
dc.l bdos15
dc.l bdos16
dc.l bdos17
dc.l bdos18
dc.l bdos19
dc.l bdos20
dc.l bdos21
dc.l bdos22
dc.l bdos23
dc.l bdos24
dc.l bdos25
dc.l bdos26
dc.l bdos27
dc.l bdos28
dc.l bdos29
dc.l bdos30
dc.l bdos31
dc.l bdos32
dc.l bdos33
dc.l bdos34
dc.l bdos35
dc.l bdos36
dc.l bdos37
dc.l oserr5 ;38 is undefined in cpm
dc.l oserr5 ;39 is undefined in cpm
dc.l bdos40
bdostabend:
; biostab
; jump table for bios functions
; max length in z80 program area $40
biostab: dc.l bios00 ;0
dc.l bios03 ;1
dc.l bios06 ;2
dc.l bios09 ;3
dc.l bios0c ;4
dc.l bios0f ;5
dc.l bios12 ;6
dc.l bios15 ;7
dc.l bios18 ;8
dc.l bios1b ;9
dc.l bios1e ;a
dc.l bios21 ;b
dc.l bios24 ;c
dc.l bios27 ;d
dc.l bios2a ;e
dc.l bios2d ;f
dc.l bios30 ;10
biostabend:
; handles and associated filenames for CPM transient
handles: dc.l 0 ;handle
hnd1: ds.l 3 ;name, from FCB
hnd2: dc.l 0
ds.l 3
dc.l 0
ds.l 3
dc.l 0
ds.l 3
dc.l 0
ds.l 3
hndend:
hanentsiz equ hnd2-handles ;size of one entry
hannamsiz equ hnd2-hnd1 ;size of one name entry
maxhan equ (hndend-handles)/hanentsiz ;maximal number of handles
; various
excnt: dc.b -1 ;ex counter for search directory
fibptr: dc.l 0 ;ptr to file info area
flags: dc.b 0 ;bit 0 : esc seq decoding
; 1 : lock1 and fib valid
handle2: dc.l 0 ;file handle for log file
lock1: dc.l 0 ;file lock for search directory
logbuf: dc.l 0 ;ptr to log file buffer
; console MsgPort
conmsgp: dcb.l 2,0 ;succ,pred ptrs
dc.b NT_MSGPORT ;type
dc.b 0 ;priority
dc.l conmsgpn ;name ptr --- node
dc.b PA_SIGNAL ;action
conmsgpsb: dc.b $ff ;signalbit #
conmsgpt: dc.l 0 ;task ptr --- msg
2$: dc.l 3$ ;head ptr
3$: dc.l 0
dc.l 2$ ;tail ptr
dc.b NT_MSGPORT ;type
dc.b 0 ;word align --- list
conmsgpn: dc.b 'CPMConsolePort',0
; console device IOStdReq, read
conimsg: dcb.w 7,0 ;Node struct
cimport: dc.l conmsgp ;msg port ptr
dc.w cimend-cimdev ;msg size
cimdev: dc.l 0 ;ptr Device
cimunit: dc.l 0 ;ptr Unit
dc.w CMD_READ ;command
dc.b 0 ;flags
dc.b 0 ;error
dc.l 0 ;actual, byte cnt
cimlen: dc.l 0 ;length, byte cnt
cimdata: dc.l 0 ;data ptr
dc.l 0 ;offset
cimend:
; console device IOStdReq, write
conomsg: dcb.w 7,0 ;Node struct
comport: dc.l 0 ;msg port ptr
dc.w comend-comdev ;msg size
comdev: dc.l 0 ;ptr Device
comunit: dc.l 0 ;ptr Unit
dc.w CMD_WRITE ;command
dc.b 0 ;flags
dc.b 0 ;error
dc.l 0 ;actual, byte cnt
comlen: dc.l 0 ;length, byte cnt
comdata: dc.l 0 ;data ptr
dc.l 0 ;offset
comend:
; not initialized data
; to save registers
d0save: ds.l 1
d1save: ds.l 1
d2save: ds.l 1
d3save: ds.l 1
d4save: ds.l 1
d5save: ds.l 1
d7save: ds.l 1
a0save: ds.l 1
a1save: ds.l 1
a2save: ds.l 1
a3save: ds.l 1
a4save: ds.l 1
a6save: ds.l 1
foobar equ d2save+2
; various
conbuf: dc.b 1 ;console read buffer for bios 06,09
conichr: dc.l 1 ;read chr for con
conochr: dc.l 1 ;write chr for con
escptr: ds.w 1 ;rx cnt for esc seq
buffer: ds.b 8 ;8 byte esc seq rx buffer
escrx: ;end of rx buffer+1
dmaddr: ds.w 1 ;current cpm dma address
drvlet: ds.b 1 ;xlname saves drive letter
escseq: ds.b 1 ;current esc seq
escxlt: ds.l 1 ;address to esc xlate routine
fnbuf: ds.b 1+1+8+1+3+1 ;buffer for filename
fnbufe:
fnbuf2: ds.b 1+1+8+1+3+1 ;secondary buffer for filename
fnbuf2e:
logcnt: ds.l 1 ;byte count in logbuf
undobuf: ds.b strbufsiz ;undo buf for str gadgets
end