page@swan.ulowell.edu (Bob Page) (03/08/89)
Submitted-by: jlydiatt@jlami.wimsey.bc.ca (Jeff Lydiatt) Posting-number: Volume 89, Issue 32 Archive-name: applications/simcpm23.1 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # simcpm.doc # ecpmdefs.i # options.i # mandog.com.uu # testprog.com.uu # simcpm2.asm2 # simcpm1.asm2 # This archive created: Tue Mar 7 22:33:54 1989 cat << \SHAR_EOF > simcpm.doc SimCPM - a CP/M simulator for the Amiga by Jim Cathey and Charlie Gibbs incorporating modifications by Willi Kusche Version 2.3 - January 9, 1989 This is a FREELY-DISTRIBUTABLE program. Spread it around all you like, just don't sell it, and please keep the entire package (including this file) intact. If you find any bugs or make any changes, please let me know - I'd like to keep my copy up to date. This program is based on an article by Jim Cathey which ran in Dr. Dobb's Journal from January to March 1986. The original program emulated an 8080, including CP/M BIOS and BDOS calls, on a CP/M-68K system. I have modified the operating system interface to run under AmigaDOS (from the CLI only, which shouldn't bother most CP/M-ers :-). Willi Kusche maintains that the proper term is "emulator", rather than "simulator." Although I agree, the original article called it a simulator, and the name seems to have stuck. *** NEW FOR VERSION 2.0 *** Due to popular demand, I have added support for the entire Z-80 instruction set (including undocumented opcodes). WARNING! This program uses the MOVE from SR instruction to set up the simulated Z-80 flags. Therefore, it will not run on the 68010 or higher processors. I didn't want to use the Exec's GetCC() call because it would be too slow. As a work-around I have set up a EQUate in options.i which you can change to indicate that you are running on a 68010, 68020, etc. Re-assembling with x680x0 equated to 1 will cause all MOVE from SR instructions to be replaced by the corresponding MOVE from CCR instructions (actually faked with a DC.W in case your assembler doesn't support 68010 opcodes). I have assembled a version with this flag set, and included it in the package; it is named SimCPM010. It should be possible to check whether x680x0 is equated to 2 and generate code optimized for a 68020 (as if it wouldn't be fast enough as is :-). SimCPM only looks at the first 12 bytes of the FCB (drive code, file name, and file type) when opening a file. The remainder of the FCB is neither altered nor checked, except for BDOS calls 17 (search for first file) and 18 (search for next file), which insert extent size and count information only. If a reference is made to any drive other than A:, SimCPM will insert the string CPMx: ahead of any file name it uses. For instance, if a program tries to open MYFILE.DAT on drive B:, SimCPM will try to open CPMB:MYFILE.DAT. You can ASSIGN these simulated drives anywhere you want. Drive A: will always go to the current directory, unless the user number is not zero. If you specify any user number other than zero, it will be included, e.g. if the above example were opened under user 1, SimCPM will look for CPMB01:MYFILE.DAT. If the file were on drive A under user 1, SimCPM will look for CPMA01:MYFILE.DAT. The only built-in commands supported are USER and SAVE. All others, such as DIR or TYPE, can easily be done using AmigaDOS equivalents. You might want to RUN SimCPM so that the original CLI window will be available for this. The EI and DI instructions are currently ignored. The IN and OUT instructions are ignored except for ports 14 and 15. Access to the Amiga's serial port is provided through a simulated Intel 8251 USART, which is currently set up to run at 1200 bps. Data is read from or written to port 14, and status input is simulated on port 15. All output to port 15 (command) is ignored. Note that CPU overhead may not permit an effective throughput of 1200 bps. (Yup, you guessed it, it emulates the modem port on my old IMSAI.) The following BDOS calls are not supported: 3 - reader input 4 - punch output 30 - set file attributes all above 36 The only BIOS calls supported are those for program termination and console and list I/O. (Low-level disk access could get scary.) If a program attempts to use an unsupported BIOS or BDOS call, an appropriate error message will be displayed, along with a register dump, and the program will be terminated. Basic H19 terminal emulation (similar to a VT52) has been provided. Escape sequences for cursor positioning, cursor to home, screen clearing, and insert and delete modes are translated to the corresponding Amiga sequences. The program MANDOG.COM, which I wrote for my original CP/M (H19) system and copied here unchanged, demonstrates the cursor addressing capabilities of SimCPM. Any escape sequences that SimCPM can't recognize are passed through unchanged. You can disable all escape sequence translation by changing the equated value "h19" (in options.i) to from 1 to 0 and re-assembling. To speed up console output for programs which write one character at a time, I have included a buffered output option. If you include the -b switch on the command-line parameter, all console output will be held until one of the following events occurs: - a carriage return, line feed, or bell character is written - the buffer (currently 2K) becomes full - a BIOS or BDOS call other than console output is made. It should be possible to use buffered output in just about any program. Note that if a program uses the "console output string" function (BDOS call 9), the entire string is written in a single operation even when buffering is not requested. If you include the -t switch on the command line, instruction and/or BIOS/BDOS tracing is available. Simulations run somewhat slower with this flag set, even if tracing is not currently active. Tracing is done using 8080 mnemonics by default. If you want Z-80 mnemonics, use -z instead of -t. If both -z and -t are specified, -t will be ignored. If the trace switch has been specified, SimCPM will prompt you for starting and ending addresses for tracing, and whether you want BIOS/BDOS calls traced. Simulation starts with tracing disabled. When SimCPM executes an instruction at the starting address, tracing is turned on. All Z-80 registers and the top four stack entries, as well as the current instruction, are displayed for each instruction until the ending address is reached. Tracing is then disabled until the start address is again encountered. After displaying 8 instructions, execution is suspended; enter S to stop tracing and continue executing, Q to quit the program, C to change the starting and ending addresses for tracing, or any other key to trace the next 8 instructions. If you have requested BIOS/BDOS call tracing, the message BIOS CALL nn (hex) AT aaaa or BDOS CALL nn (hex) AT aaaa will be displayed each time a BIOS or BDOS call is made. The BDOS call number (contents of register C in hex) will replace "nn" for BDOS calls, while BIOS calls will set "nn" to a sequential number starting at 01 for program termination, 02 for console status, etc. The address where the call is made will be taken from the top of the stack and displayed in place of "aaaa". List output is sent to PRT:RAW. This ensures that no newline translation will take place. The printer is not opened until the first attempt is made to access it. If the printer cannot be opened for any reason, the program will be terminated. At program termination the printer will be closed if it was used. If SimCPM is brought up with no command-line parameters, it will present the standard CP/M A> prompt. At this point you can run CP/M .COM files just like on a normal CP/M system. The command line will be scanned for up to two FCBs and the tail will be passed to the program. When the program terminates, the A> prompt will be re-displayed. To return to AmigaDOS, enter a control-C (CP/M warm boot) at the A> prompt. If command-line parameters are given, they will be passed to SimCPM as if they had been entered at the A> prompt. When the program terminates, SimCPM will automatically return to AmigaDOS. This allows you to run CP/M programs from an EXECUTE file. Here are some sample invocations of SimCPM: simcpm Loads the simulator, which presents the A> prompt and waits for CP/M commands. Type control-C at the prompt to exit. simcpm -b Same as above, except console output buffering is used. simcpm myprog Loads the simulator, which loads and runs the CP/M program MYPROG.COM. When MYPROG terminates, SimCPM returns to AmigaDOS. simcpm -t myprog Same as above, except that before MYPROG.COM is run, you will be prompted for trace parameters. simcpm -z myprog Same as above, except that Z-80 mnemonics will be used for tracing, rather than 8080 mnemonics. simcpm mbasic basprog Loads the simulator, which loads Microsoft BASIC-80 (if you have it), which in turn loads and runs BASPROG.BAS. When BASPROG issues a SYSTEM command, SimCPM returns to AmigaDOS. simcpm -b mbasic basprog Same as above, but with console output buffering. Since MBASIC does all console I/O one character at a time, the buffered option can speed it up considerably. I have included two CP/M programs for demonstration purposes. TESTPROG.COM is a simple "hello, world" program (try it using the trace option), while MANDOG.COM demonstrates cursor addressing for an emulated H19 terminal. SimCPM consists of two source modules, SIMCPM1.ASM and SIMCPM2.ASM. No include files are needed, although amiga.lib is required for linking. The makefile is set up to use my own assembler, A68k, and BLink - it should be relatively easy to adapt it to whatever assembler and linker you are using. Special thanks to: Jim Cathey for his article in Dr. Dobb's Journal - it provided the starting point for this program. Willi Kusche (for new ideas and corrections of my Z-80 code) SYSOP KMMM Pascal BBS (609) 232-0773 24 hours a day 7 days a week 300/1200/2400/9600 bps 9600 is USRobotics HST protocol Passing a simple IQ test required for full access Please address any kudos, flames, etc. to Charlie Gibbs 2121 Rindall Avenue Port Coquitlam, B.C. Canada V3C 1T9 or to Larry Phillips or Jeff Lydiatt on CompuServe or Usenet. (I don't have the time or money to live there myself.) SHAR_EOF cat << \SHAR_EOF > ecpmdefs.i * * Emulator register definitions * Note, only leaves D0-D1/A0 free for use by entire * program without saving registers for temporary use. * return equr A6 ;JMP (return) is fast return to MLOOP. pseudopc equr A5 ;Emulated program counter opptr equr A4 ;Address of opcode dispatch table pseudosp equr A3 ;Emulated stack pointer flagptr equr A2 ;Address of flag lookup table targbase equr A1 ;Address of emulated address space regs equr A1 ;Base pointer to emulated registers regcon0e equr D7 ;Register-based constant #$E (for speed) regcon01 equr D6 ;Register-based constant #$1 regcon0f equr D5 ;Register-based constant #$F regconff equr D4 ;Register-based constant #$FF regf equr D3 ;Emulated flag register rega equr D2 ;Emulated accumulator * * Target processor's data registers (offsets into storage area) * The emulated accumulator and flag register are kept in data registers. * The emulated program counter and stack pointer * are kept in address registers. * regb equ -22 ;B regc equ -21 ;C regd equ -20 ;D rege equ -19 ;E regh equ -18 ;H regl equ -17 ;L regix equ -16 ;IX regxh equ -16 regxl equ -15 regiy equ -14 ;IY regyh equ -14 regyl equ -13 regb2 equ -12 ;Alternate register set for Z-80 regc2 equ -11 regd2 equ -10 rege2 equ -9 regh2 equ -8 regl2 equ -7 rega2 equ -6 regf2 equ -5 regi equ -4 ;Interrupt page address register (I) regop1 equ -3 ;Operand 1 for DAA storage regop2 equ -2 ; " 2 " " " regop3 equ -1 ; " 3 " " " SHAR_EOF cat << \SHAR_EOF > options.i * SimCPM options * Processor flag - 0 for 68000, 1 for 68010 x680x0 equ 0 ;68000 * Set "h19" to 1 to emulate an H19, zero to pass escape codes unchanged. h19 equ 1 ;Emulate Heath/Zenith 19 escape codes. SHAR_EOF cat << \SHAR_EOF > mandog.com.uu begin 644 MANDOG.COM MS7T#S4D#$;D##@G-!0`^`S*+!3Y+,HP%S5@#.HP%_A7,/0(ZC`7^%,Q$`CJ,Q M!?X3S%$".HP%_A+,7@(ZC`7^$<QK`A'W`PX)S04`S5@#$3($#@G-!0#-6`,14 M;00."<T%`,U8`Q&H!`X)S04`.HP%/3*,!?(8`<U)`Q&Y`PX)S04`/@<RBP4^2 M23*,!<U8`SJ,!?X5S+8".HP%_A3,O0(ZC`7^$\S*`CJ,!?X2S-<".HP%_A',8 MY`(ZC`7^$,SQ`CJ,!?X/S/X"$>,$#@G-!0#-6`,1!`4."<T%`,U8`Q$E!0X)H MS04`S5@#$48%#@G-!0`ZC`4],HP%^CD"_@["BP$1%`#-J0/-6`,19P4."<T%% M`,U8`Q%P!0X)S04`S5@#$7D%#@G-!0`1'@#-J0/-6`,1@@4."<T%`,.+`<V3W M`\DA]P/-<@+)(?<#S94"(?@#S7("R2'X`\V5`B'Y`\UR`LDA^0/-E0(A^@/-I M<@+)(?H#S94"R1&-!08$Y0X'?A(V?-41"0`9T1,-PGH"X=41.P`9T07"=P+)= M$8T%!@3E#@<:=]41"0`9T1,-PIT"X=41.P`9T07"F@+)(>,$S04#R2'C!,TH- M`R'D!,T%`\DAY`3-*`,AY03-!0/)(>4$S2@#(>8$S04#R2'F!,TH`R'G!,T%? M`\DAYP3-*`,AZ`3-!0/)(>@$S2@#R1&-!08$Y0X#?A(V?-41#0`9T1,-P@T#] MX=41(0`9T07""@/)$8T%!@3E#@,:=]41#0`9T1,-PC`#X=41(0`9T07"+0/)G M'AL.`LT%`!Y%#@+-!0#)'AL.`LT%`!Y9#@+-!0`ZBP7&(%\.`LT%`#J,!<8@_ M7PX"S04`R1X;#@+-!0`>>`X"S04`'C4.`LT%`,D>&PX"S04`'GD.`LT%`!XU" M#@+-!0#)(8P@*WRUPJP#&WJSPJD#R2`@("`@("`@("`@("`@("`@("`@+2TM+ M"`@("GP@?`@("`HM+2T("`I\"`I\"`I\"`I\"`I\"`I\"`I\"`HD(%X@(`@(1 M"`@*($\@(`@("`@*('P@(`@("`@*('P@(`@("`@*('P@(`@("`@*('P@(`@(Q M"`@*('Q<("0@7B`@"`@("`H@3R`@"`@("`H@?"`@"`@("`H@?"`@"`@("`H@# M?"`@"`@("`H@?"`@"`@("`H@?"`@)"!>("`("`@("B!/("`("`@("B!\("`(1 M"`@("B]\7"`("`@("B!\("`("`@("B]\("`("`@("GQ\("`D(%X@(`@("`@*2 M($\@(`@("`@*('P@(`@("`@*+7PM(`@("`@*('P@(`@("`@*+WP@(`@("`@*: M?"!<("0]("`@?"`("`@("`@*?"TM+2T@"`@("`@("B]<(%PO("0]("`@+R`(G M"`@("`@*?"TM+2T@"`@("`@("GQ\('Q\("0]("`@?"`("`@("`@*?"TM+2T@3 M"`@("`@("EPO("]<("0]("`@?"`("`@("`@*?"TM+2T@"`@("`@("GQ\('Q\! M("0@/2`@(`H*("0@/2`@('P*+20@/2`@('P*+R0@/2`@('P*("0`````````* M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` 4````````````````````````````` `` end size 1280 SHAR_EOF cat << \SHAR_EOF > testprog.com.uu begin 644 testprog.com H$0D!#@G-!0#)2&5L;&\L('=O<FQD(0T*)",C(R,C(R,C(R,C(R,C(^!42 `` end size 40 SHAR_EOF cat << \SHAR_EOF > simcpm2.asm2 sbbflag sbbyl asr.b #1,regf ;FD9D SBB YL (undocumented) move.b regyl(regs),d0 sbbflag sbbiy calcind y ;FD9E SBB (IY+d) asr.b #1,regf move.b 0(targbase,d0.l),d0 sbbflag anayh and.b regyh(regs),rega ;FDA4 ANA YH (undocumented) move.b 16(flagptr,rega.w),regf jmp (return) anayl and.b regyl(regs),rega ;FDA5 ANA YL (undocumented) move.b 16(flagptr,rega.w),regf jmp (return) anaiy calcind y ;FDA6 ANA (IY+d) and.b 0(targbase,d0.l),rega move.b 16(flagptr,rega.w),regf jmp (return) xrayh move.b regyh(regs),d0 ;FDAC XRA YH (undocumented) eor.b d0,rega move.b 16(flagptr,rega.w),regf jmp (return) xrayl move.b regyl(regs),d0 ;FDAD XRA YL (undocumented) eor.b d0,rega move.b 16(flagptr,rega.w),regf jmp (return) xraiy calcind y ;FDAE XRA (IY+d) move.b 0(targbase,d0.l),d0 eor.b d0,rega move.b 16(flagptr,rega.w),regf jmp (return) orayh or.b regyh(regs),rega ;FDB4 ORA YH (undocumented) move.b 16(flagptr,rega.w),regf jmp (return) orayl or.b regyl(regs),rega ;FDB5 ORA YL (undocumented) move.b 16(flagptr,rega.w),regf jmp (return) oraiy calcind y ;FDB6 ORA (IY+d) or.b 0(targbase,d0.l),rega move.b 16(flagptr,rega.w),regf jmp (return) cmpyh cmp.b regyh(regs),rega ;FDBC CMP YH (undocumented) setflag cmpyl cmp.b regyl(regs),rega ;FDBD CMP YL (undocumented) setflag cmpiy calcind y ;FDBE CMP (IY+d) cmp.b 0(targbase,d0.l),rega setflag * FDCB-prefix instructions can use the DDCB-prefix routines, * since the operand address is already in D0. popiy move.b (pseudosp)+,regyl(regs) ;FDE1 POP IY move.b (pseudosp)+,regyh(regs) jmp (return) xtiy move.b regyl(regs),d0 ;FDE3 XTIY move.b (pseudosp),regyl(regs) move.b d0,(pseudosp) move.b regyh(regs),d0 move.b 1(pseudosp),regyh(regs) move.b d0,1(pseudosp) jmp (return) pushiy move.b regyh(regs),-(pseudosp) ;FDE5 PUSH IY move.b regyl(regs),-(pseudosp) jmp (return) pciy move.w regiy(regs),d0 ;FDE9 PCIY lea 0(targbase,d0.l),pseudopc jmp (return) spiy move.w regiy(regs),d0 ;FDF9 SPIY lea 0(targbase,d0.l),pseudosp jmp (return) page ************************************************************************* * * * Opcode dispatch table * * * ************************************************************************* data data even optabl dc.l nop00,lxib,staxb,inxb,inrb,dcrb,mvib,rlc dc.l exaf,dadb,ldaxb,dcxb,inrc,dcrc,mvic,rrc dc.l djnz,lxid,staxd,inxd,inrd,dcrd,mvid,ral dc.l jr,dadd,ldaxd,dcxd,inre,dcre,mvie,rar dc.l jrnz,lxih,shld,inxh,inrh,dcrh,mvih,daa dc.l jrz,dadh,lhld,dcxh,inrl,dcrl,mvil,cma dc.l jrnc,lxis,sta,inxs,inrm,dcrm,mvim,stc dc.l jrc,dads,lda,dcxs,inra,dcra,mvia,cmc dc.l movebb,movebc,movebd,movebe,movebh,movebl,movebm,moveba dc.l movecb,movecc,movecd,movece,movech,movecl,movecm,moveca dc.l movedb,movedc,movedd,movede,movedh,movedl,movedm,moveda dc.l moveeb,moveec,moveed,moveee,moveeh,moveel,moveem,moveea dc.l movehb,movehc,movehd,movehe,movehh,movehl,movehm,moveha dc.l movelb,movelc,moveld,movele,movelh,movell,movelm,movela dc.l movemb,movemc,movemd,moveme,movemh,moveml,halt,movema dc.l moveab,moveac,movead,moveae,moveah,moveal,moveam,moveaa dc.l addb,addc,addd,adde,addh,addl,addm,adda dc.l adcb,adcc,adcd,adce,adch,adcl,adcm,adca dc.l subb,subc,subd,sube,subh,subl,subm,suba dc.l sbbb,sbbc,sbbd,sbbe,sbbh,sbbl,sbbm,sbba dc.l andb,andc,andd,ande,andh,andl,andm,anda dc.l xrab,xrac,xrad,xrae,xrah,xral,xram,xraa dc.l orab,orac,orad,orae,orah,oral,oram,oraa dc.l cmpb,cmpc,cmpd,cmpe,cmph,cmpl,cmpam,cmpaa dc.l rnz,popb,jnz,jmpa,cnz,pushb,adi,rst0 dc.l rz,ret,jz,preCB,cz,call,aci,rst1 dc.l rnc,popd,jnc,out,cnc,pushd,sui,rst2 dc.l rc,exx,jc,in,cc,preDD,sbi,rst3 dc.l rpo,poph,jpo,xthl,cpo,pushh,ani,rst4 dc.l rpe,pchl,jpe,xchg,cpe,preED,xri,rst5 dc.l rp,popp,jp,di,cp,pushp,oria,rst6 dc.l rm,sphl,jm,ei,cm,preFD,cpi,rst7 page ************************************************************************* * * * Flag register lookup tables * * * ************************************************************************* flags dc.b $00,$01,$04,$05,$40,$41,$44,$45,$80,$81,$84,$85,$C0,$C1,$C4,$C5 dc.b $44,$00,$00,$04,$00,$04,$04,$00,$00,$04,$04,$00,$04,$00,$00,$04 dc.b $00,$04,$04,$00,$04,$00,$00,$04,$04,$00,$00,$04,$00,$04,$04,$00 dc.b $00,$04,$04,$00,$04,$00,$00,$04,$04,$00,$00,$04,$00,$04,$04,$00 dc.b $04,$00,$00,$04,$00,$04,$04,$00,$00,$04,$04,$00,$04,$00,$00,$04 dc.b $00,$04,$04,$00,$04,$00,$00,$04,$04,$00,$00,$04,$00,$04,$04,$00 dc.b $04,$00,$00,$04,$00,$04,$04,$00,$00,$04,$04,$00,$04,$00,$00,$04 dc.b $04,$00,$00,$04,$00,$04,$04,$00,$00,$04,$04,$00,$04,$00,$00,$04 dc.b $00,$04,$04,$00,$04,$00,$00,$04,$04,$00,$00,$04,$00,$04,$04,$00 dc.b $80,$84,$84,$80,$84,$80,$80,$84,$84,$80,$80,$84,$80,$84,$84,$80 dc.b $84,$80,$80,$84,$80,$84,$84,$80,$80,$84,$84,$80,$84,$80,$80,$84 dc.b $84,$80,$80,$84,$80,$84,$84,$80,$80,$84,$84,$80,$84,$80,$80,$84 dc.b $80,$84,$84,$80,$84,$80,$80,$84,$84,$80,$80,$84,$80,$84,$84,$80 dc.b $84,$80,$80,$84,$80,$84,$84,$80,$80,$84,$84,$80,$84,$80,$80,$84 dc.b $80,$84,$84,$80,$84,$80,$84,$80,$84,$80,$80,$84,$80,$84,$84,$80 dc.b $80,$84,$84,$80,$84,$80,$84,$80,$84,$80,$80,$84,$80,$84,$84,$80 dc.b $84,$80,$80,$84,$80,$84,$84,$80,$80,$84,$84,$80,$84,$80,$80,$84 page ************************************************************************* * * * Z-80 opcode dispatch table. One longword entry per opcode * * of the target (Z-80) processor, including illegals. * * * ************************************************************************* CBoptab: dc.l rlcb,rlcc,rlcd,rlce,rlch,rlcl,rlcm,rlca ;CB00 dc.l rrcb,rrcc,rrcd,rrce,rrch,rrcl,rrcm,rrca ;CB08 dc.l rlrb,rlrc,rlrd,rlre,rlrh,rlrl,rlrm,rlra ;CB10 dc.l rrrb,rrrc,rrrd,rrre,rrrh,rrrl,rrrm,rrra ;CB18 dc.l slab,slac,slad,slae,slah,slal,slam,slaa ;CB20 dc.l srab,srac,srad,srae,srah,sral,sram,sraa ;CB28 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;CB30 dc.l srlb,srlc,srld,srle,srlh,srll,srlm,srla ;CB38 dc.l bit0b,bit0c,bit0d,bit0e,bit0h,bit0l,bit0m,bit0a ;CB40 dc.l bit1b,bit1c,bit1d,bit1e,bit1h,bit1l,bit1m,bit1a ;CB48 dc.l bit2b,bit2c,bit2d,bit2e,bit2h,bit2l,bit2m,bit2a ;CB50 dc.l bit3b,bit3c,bit3d,bit3e,bit3h,bit3l,bit3m,bit3a ;CB58 dc.l bit4b,bit4c,bit4d,bit4e,bit4h,bit4l,bit4m,bit4a ;CB60 dc.l bit5b,bit5c,bit5d,bit5e,bit5h,bit5l,bit5m,bit5a ;CB68 dc.l bit6b,bit6c,bit6d,bit6e,bit6h,bit6l,bit6m,bit6a ;CB70 dc.l bit7b,bit7c,bit7d,bit7e,bit7h,bit7l,bit7m,bit7a ;CB78 dc.l res0b,res0c,res0d,res0e,res0h,res0l,res0m,res0a ;CB80 dc.l res1b,res1c,res1d,res1e,res1h,res1l,res1m,res1a ;CB88 dc.l res2b,res2c,res2d,res2e,res2h,res2l,res2m,res2a ;CB90 dc.l res3b,res3c,res3d,res3e,res3h,res3l,res3m,res3a ;CB98 dc.l res4b,res4c,res4d,res4e,res4h,res4l,res4m,res4a ;CBA0 dc.l res5b,res5c,res5d,res5e,res5h,res5l,res5m,res5a ;CBA8 dc.l res6b,res6c,res6d,res6e,res6h,res6l,res6m,res6a ;CBB0 dc.l res7b,res7c,res7d,res7e,res7h,res7l,res7m,res7a ;CBB8 dc.l set0b,set0c,set0d,set0e,set0h,set0l,set0m,set0a ;CBC0 dc.l set1b,set1c,set1d,set1e,set1h,set1l,set1m,set1a ;CBC8 dc.l set2b,set2c,set2d,set2e,set2h,set2l,set2m,set2a ;CBD0 dc.l set3b,set3c,set3d,set3e,set3h,set3l,set3m,set3a ;CBD8 dc.l set4b,set4c,set4d,set4e,set4h,set4l,set4m,set4a ;CBE0 dc.l set5b,set5c,set5d,set5e,set5h,set5l,set5m,set5a ;CBE8 dc.l set6b,set6c,set6d,set6e,set6h,set6l,set6m,set6a ;CBF0 dc.l set7b,set7c,set7d,set7e,set7h,set7l,set7m,set7a ;CBF8 DDoptab: dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;DD00 dc.l illgED,dadixb,illgED,illgED,illgED,illgED,illgED,illgED ;DD08 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;DD10 dc.l illgED,dadixd,illgED,illgED,illgED,illgED,illgED,illgED ;DD18 dc.l illgED,lxiix,sixd,inxix,inrxh,dcrxh,mvixh,illgED ;DD20 dc.l illgED,dadixx,lixd,dcxix,inrxl,dcrxl,mvixl,illgED ;DD28 dc.l illgED,illgED,illgED,illgED,inrix,dcrix,mviix,illgED ;DD30 dc.l illgED,dadixs,illgED,illgED,illgED,illgED,illgED,illgED ;DD38 dc.l illgED,illgED,illgED,illgED,movbxh,movbxl,movbix,illgED ;DD40 dc.l illgED,illgED,illgED,illgED,movcxh,movcxl,movcix,illgED ;DD48 dc.l illgED,illgED,illgED,illgED,movdxh,movdxl,movdix,illgED ;DD50 dc.l illgED,illgED,illgED,illgED,movexh,movexl,moveix,illgED ;DD58 dc.l movxhb,movxhc,movxhd,movxhe,mvxhxh,mvxhxl,movhix,illgED ;DD60 dc.l movxlb,movxlc,movxld,movxle,mvxlxh,mvxlxl,movlix,illgED ;DD60 dc.l movixb,movixc,movixd,movixe,movixh,movixl,illgED,movixa ;DD70 dc.l illgED,illgED,illgED,illgED,movaxh,movaxl,movaix,illgED ;DD78 dc.l illgED,illgED,illgED,illgED,addxh,addxl,addix,illgED ;DD80 dc.l illgED,illgED,illgED,illgED,adcxh,adcxl,adcix,illgED ;DD88 dc.l illgED,illgED,illgED,illgED,subxh,subxl,subix,illgED ;DD90 dc.l illgED,illgED,illgED,illgED,sbbxh,sbbxl,sbbix,illgED ;DD98 dc.l illgED,illgED,illgED,illgED,anaxh,anaxl,anaix,illgED ;DDA0 dc.l illgED,illgED,illgED,illgED,xraxh,xraxl,xraix,illgED ;DDA8 dc.l illgED,illgED,illgED,illgED,oraxh,oraxl,oraix,illgED ;DDB0 dc.l illgED,illgED,illgED,illgED,cmpxh,cmpxl,cmpix,illgED ;DDB8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;DDC0 dc.l illgED,illgED,illgED,prDDCB,illgED,illgED,illgED,illgED ;DDC8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;DDD0 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;DDD8 dc.l illgED,popix,illgED,xtix,illgED,pushix,illgED,illgED ;DDE0 dc.l illgED,pcix,illgED,illgED,illgED,illgED,illgED,illgED ;DDE8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;DDF0 dc.l illgED,spix,illgED,illgED,illgED,illgED,illgED,illgED ;DDF8 DDCBopt: dc.l rlcix,rrcix,rlix,rrix,slaix,sraix,ilgDDCB,srlix ;DDCB06 dc.l bit0ix,bit1ix,bit2ix,bit3ix,bit4ix,bit5ix,bit6ix,bit7ix ;DDCB46 dc.l res0ix,res1ix,res2ix,res3ix,res4ix,res5ix,res6ix,res7ix ;DDCB86 dc.l set0ix,set1ix,set2ix,set3ix,set4ix,set5ix,set6ix,set7ix ;DDCBC6 EDoptab: dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED00 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED08 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED10 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED18 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED20 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED28 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED30 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED38 dc.l inbc,outcb,dsbbb,sbcd,nega,retn,im0,moveia ;ED40 dc.l incc,outcc,dadcb,lbcd,illgED,reti,illgED,movera ;ED48 dc.l indc,outcd,dsbbd,sded,illgED,illgED,im1,moveai ;ED50 dc.l inec,outce,dadcd,lded,illgED,illgED,im2,movear ;ED58 dc.l inhc,outch,dsbbh,shld,illgED,illgED,illgED,rrd ;ED60 dc.l inlc,outcl,dadch,lhld,illgED,illgED,illgED,rld ;ED68 dc.l inmc,outcm,dsbbs,sspd,illgED,illgED,illgED,illgED ;ED70 dc.l inac,outca,dadcs,lspd,illgED,illgED,illgED,illgED ;ED78 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED80 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED88 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED90 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;ED98 dc.l ldi,cmpi,ini,outi,illgED,illgED,illgED,illgED ;EDA0 dc.l ldd,cpd,ind,outd,illgED,illgED,illgED,illgED ;EDA8 dc.l ldir,cpir,inir,otir,illgED,illgED,illgED,illgED ;EDB0 dc.l lddr,cpdr,indr,otdr,illgED,illgED,illgED,illgED ;EDB8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDC0 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDC8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDD0 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDD8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDE0 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDE8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDF0 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;EDF8 FDoptab: dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;FD00 dc.l illgED,dadiyb,illgED,illgED,illgED,illgED,illgED,illgED ;FD08 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;FD10 dc.l illgED,dadiyd,illgED,illgED,illgED,illgED,illgED,illgED ;FD18 dc.l illgED,lxiiy,siyd,inxiy,inryh,dcryh,mviyh,illgED ;FD20 dc.l illgED,dadiyy,liyd,dcxiy,inryl,dcryl,mviyl,illgED ;FD28 dc.l illgED,illgED,illgED,illgED,inriy,dcriy,mviiy,illgED ;FD30 dc.l illgED,dadiys,illgED,illgED,illgED,illgED,illgED,illgED ;FD38 dc.l illgED,illgED,illgED,illgED,movbyh,movbyl,movbiy,illgED ;FD40 dc.l illgED,illgED,illgED,illgED,movcyh,movcyl,movciy,illgED ;FD48 dc.l illgED,illgED,illgED,illgED,movdyh,movdyl,movdiy,illgED ;FD50 dc.l illgED,illgED,illgED,illgED,moveyh,moveyl,moveiy,illgED ;FD58 dc.l movyhb,movyhc,movyhd,movyhe,mvyhyh,mvyhyl,movhiy,illgED ;FD60 dc.l movylb,movylc,movyld,movyle,mvylyh,mvylyl,movliy,illgED ;FD60 dc.l moviyb,moviyc,moviyd,moviye,moviyh,moviyl,illgED,moviya ;FD70 dc.l illgED,illgED,illgED,illgED,movayh,movayl,movaiy,illgED ;FD78 dc.l illgED,illgED,illgED,illgED,addyh,addyl,addiy,illgED ;FD80 dc.l illgED,illgED,illgED,illgED,adcyh,adcyl,adciy,illgED ;FD88 dc.l illgED,illgED,illgED,illgED,subyh,subyl,subiy,illgED ;FD90 dc.l illgED,illgED,illgED,illgED,sbbyh,sbbyl,sbbiy,illgED ;FD98 dc.l illgED,illgED,illgED,illgED,anayh,anayl,anaiy,illgED ;FDA0 dc.l illgED,illgED,illgED,illgED,xrayh,xrayl,xraiy,illgED ;FDA8 dc.l illgED,illgED,illgED,illgED,orayh,orayl,oraiy,illgED ;FDB0 dc.l illgED,illgED,illgED,illgED,cmpyh,cmpyl,cmpiy,illgED ;FDB8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;FDC0 dc.l illgED,illgED,illgED,prFDCB,illgED,illgED,illgED,illgED ;FDC8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;FDD0 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;FDD8 dc.l illgED,popiy,illgED,xtiy,illgED,pushiy,illgED,illgED ;FDE0 dc.l illgED,pciy,illgED,illgED,illgED,illgED,illgED,illgED ;FDE8 dc.l illgED,illgED,illgED,illgED,illgED,illgED,illgED,illgED ;FDF0 dc.l illgED,spiy,illgED,illgED,illgED,illgED,illgED,illgED ;FDF8 * FDCBopt is not necessary - DDCBopt can be used, * since the operand address is in D0 for both routines. bss bss even tracesad ds.l 1 ;Start address for trace traceead ds.l 1 ;End address for trace traceflg ds.b 1 ;Trace activity flag tmprega ds.b 1 ;Work area end SHAR_EOF cat << \SHAR_EOF > simcpm1.asm2 beq.s getlinc ;Yes - stop here. cmpi.b #lf,(a1) ;Stop on a line feed too. beq.s getlinc cmpi.b #bs,(a1) ;Backspace? bne.s getlinp ;No. tst.b 1(a0) ;Do we have anything yet? beq.s getlinl ;No - ignore the backspace. subq.l #1,a1 ;Back over the previous character. subq.b #1,1(a0) ;Decrement character count. movem.l a0-a1,-(sp) move.l #bsmsg,d1 bsr pstring ;Erase the previous character on the screen. movem.l (sp)+,a0-a1 bra.s getlinl bsmsg dc.b bs,' ',bs,'$' ;Erases the previous character getlinp movem.l a0-a1,-(sp) sys Write ;Echo the current character. movem.l (sp)+,a0-a1 addq.b #1,1(a0) ;Bump character count. move.b 1(a0),d0 ;Number of bytes read so far. cmpi.b #3,(a1)+ ;Did we get a control-C? bne.s 1$ ;No. cmpi.b #1,d0 ;Is is the first character? beq.s getlinx ;Yes - exit now. 1$ cmp.b (a0),d0 ;Is the buffer full? bne.s getlinl ;No - try for another character. bra.s getlinx getlinc bsr pcrlf ;Carriage return or line feed getlinx movem.l (sp)+,d2-d3/a0-a1/a6 rts ;Exit. * * Display the message pointed to by D1. * The message must be terminated by a dollar sign. * pstring movem.l d2-d3/a1-a2,-(sp) ;Save work registers. move.l d1,a0 ;A0 scans the message. bset #0,testdol ;Suppress $ test? beq.s pstrs ;Yes (used by BDOS/BIOS character output) cmpi.b #'$',(a0) ;Null string? beq pstrx ;Yes - do nothing. pstrs move.l strptr,a1 ;A1 loads the output buffer. move.l #strbufn,d3 sub.l a1,d3 ;Number of bytes left in buffer ifne h19 moveq #0,d0 move.w esclen,d0 ;Is a partial escape sequence saved? beq.s pstrl ;No. lea escbuf,a2 adda.l d0,a2 ;Continue loading it here. clr.w esclen ;Reset "saved length" counter. cmpi.w #2,d0 ;Did we just save one byte? bcs.s pstresc ;Yes - get the remainder. bhi pstreY2 ;Get the last cursor positioning byte. subq.l #1,a2 ;Back over dummy byte. bra pstreY1 ;Get both cursor positioning bytes. endc pstrl cmpi.b #lf,(a0) ;Line feed? bne.s notlf ;No. lea escbuf,a2 ;Translate it to a cursor-down sequence. move.b #$9B,(a2)+ move.b #'B',(a2)+ addq.l #1,a0 bra pstrsub notlf: ifne h19 * Optional H19 escape sequence translation cmpi.b #esc,(a0) ;Escape character? bne pstrm ;No - treat it normally. lea escbuf,a2 ;Build translated escape sequence here. move.b #$9B,(a2)+ ;Start with an AmigaDOS escape character. addq.l #1,a0 ;Check the next character. cmpi.b #'$',(a0) ;End of string? bne.s pstresc ;No - analyze the sequence. move.w #1,esclen ;We've saved one byte for next time. bra pstrw ;Write everything up to the ESC character. pstresc move.b (a0)+,d0 cmpi.b #'[',d0 ;ANSI escape sequence? beq pstrsub ;Yes - pass the sequence with $9B header. cmpi.b #'Y',d0 beq.s pstreY ;Set cursor position. cmpi.b #'@',d0 beq.s pstrein ;Set insert mode. cmpi.b #'A',d0 bcs pstreun ;Unknown code - copy it as is. cmpi.b #'O',d0 beq.s pstreO ;Reset insert mode. bhi pstreun ;Unknown code move.l a0,-(sp) lea esctran(pc),a0 ;Translation table with offset move.b -'A'(a0,d0.w),d2;Get the translated code. move.l (sp)+,a0 btst #6,d2 ;Does the translated code stand alone? bne.s 1$ ;No. subq.l #1,a2 ;Back over stored CSI character. 1$ move.b d2,(a2)+ ;Get the translated code. bra.s pstrsub esctran dc.b 'ABCD',ff,so,si,'H',$8D,'JKLMP' ;Escape sequence translation pstrein move.b #1,insflag ;Set insert mode. bra.s pstrsbx pstreO clr.b insflag ;Reset insert mode. bra.s pstrsbx pstreY cmpi.b #'Y',d0 ;Set cursor position bne.s pstreun cmpi.b #'$',(a0) ;End of string? bne.s pstreY1 ;No. move.w #2,esclen ;Indicate we need both position bytes. bra pstrw ;Finish the sequence next time. pstreY1 moveq #0,d0 move.b (a0)+,d0 ;Get the first position byte. bsr pstrcvd ;Convert to decimal in save area. move.b #';',(a2)+ ;Add the separator character. cmpi.b #'$',(a0) ;End of string? bne.s pstreY2 ;No. sub.l #escbuf,a2 ;Number of bytes saved move.w a2,esclen bra pstrw ;Get the last byte next time. pstreY2 moveq #0,d0 move.b (a0)+,d0 ;Get the last position byte. bsr pstrcvd ;Convert to decimal in save area. move.b #'H',(a2)+ ;Terminate the sequence. bra.s pstrsub pstreun move.b #esc,escbuf ;Unidentified escape sequence - move.b d0,(a2)+ ; pass it through as is. endc * The translated escape sequence is now in "escbuf" - * copy it to the output buffer. pstrsub move.l a2,d0 lea escbuf,a2 ;A2 scans translated escape sequence. sub.l a2,d0 ;Length of translated escape sequence subq.l #1,d0 1$ move.b (a2)+,(a1)+ ;Copy substitution to output string. subq.w #1,d3 ;Count down remaining length. dbra d0,1$ pstrsbx cmpi.b #'$',(a0) ;End of string? beq pstrw ;Yes - write it out. tst.w d3 ;Is the buffer full? bmi pstrw ;Yes - write out what we have. cmpi.b #lf,-1(a0) ;Line feed? bne pstrl ;No. tst.b bufflag ;Is console buffering in effect? beq pstrl ;No. move.l a1,strptr bsr dmpstr ;Dump the buffer. move.l strptr,a1 bra pstrl ;Check for another escape sequence. * Subroutine to convert the byte in D0 to a character string at (A2)+ pstrcvd subi.b #' '-1,d0 ;Convert to binary row or column number. divu #10,d0 ;Convert to tens and units. tst.w d0 ;Is the number 10 or greater? beq.s 1$ ;No - just create a one-digit number. addi.b #'0',d0 ;Convert the tens digit to ASCII. move.b d0,(a2)+ ;Move it to the result field. 1$ swap d0 ;Get the units digit. addi.b #'0',d0 ;Convert it to ASCII. move.b d0,(a2)+ rts * Normal character processing pstrm tst.b insflag ;Are we in insert mode? beq.s pstrmv ;No. lea escbuf,a2 move.b #$9B,(a2)+ ;Build an insert-character sequence. move.b #'@',(a2)+ move.b (a0)+,(a2)+ ;Here's the character to insert. bra.s pstrsub ;Use the substitution routine. pstrmv move.b (a0)+,(a1)+ ;Move one character. tst.b bufflag ;Is console buffering in effect? beq.s 2$ ;No. cmpi.b #cr,-1(a0) ;Carriage return? beq.s 1$ ;Yes - dump the current segment. cmpi.b #bel,-1(a0) ;Bell? bne.s 2$ ;No - continue buffering. 1$ move.l a1,strptr bsr dmpstr ;Dump the buffer. move.l strptr,a1 2$ cmpi.b #'$',(a0) ;Test for end of string. dbeq d3,pstrl ;Loop until we get there or buffer is full. pstrw move.l a1,strptr tst d3 ;Is the buffer full? bmi.s 1$ ;Yes - dump it regardless. tst.b bufflag ;Is console buffering in effect? bne.s 2$ ;Yes - don't write anything yet. 1$ bsr dmpstr ;Dump the buffer. move.l strptr,a1 2$ tst d3 ;Did the output buffer overflow? bmi pstrs ;Yes - get another section of the message. pstrx movem.l (sp)+,d2-d3/a1-a2 ;Restore registers rts * * Write the contents of "strbuf" to RAW: if possible, or stdout if not. * The number of bytes to be written is calculated from "strptr". * dmpstr movem.l d2-d3/a0-a1/a6,-(sp) move.l strptr,d3 move.l #strbuf,d2 ;Address of buffer move.l d2,strptr ;Reset the buffer pointer. sub.l d2,d3 ;Length of output string beq.s 2$ ;Zero - don't write anything. move.l rawhand,d1 ;Assume we're writing to RAW: bne.s 1$ move.l stdout,d1 ;We don't have RAW: - use stdout. 1$ move.l _DOSBase,a6 sys Write ;Display the line. 2$ movem.l (sp)+,d2-d3/a0-a1/a6 rts * * Convert the file name in the FCB pointed to by A0 * to an AmigaDOS-format file name in the field pointed to by A1. * D0 is the only other register used by this routine. * convfn move.l a1,-(sp) move.l a0,-(sp) ;Save start address of FCB. move.b (a0)+,d0 ;Get the drive code. bne.s 1$ ;We have a drive code. move.b target+4,d0 ;Use the default drive code. andi.b #$0F,d0 addq.b #1,d0 ;Start at 1 for drive A:. 1$ cmpi.b #1,d0 ;Is it drive A:? beq.s 4$ ;Yes - don't add anything special. move.b #'C',(a1)+ move.b #'P',(a1)+ ;Set up the prefix CPMx: move.b #'M',(a1)+ ; where x is the drive letter. add.b #'A'-1,d0 move.b d0,(a1)+ move.b target+4,d0 ;Get user number. lsr.b #4,d0 ;Move it to low-order 4 bits. beq.s 3$ ;Don't insert user number if it's zero. move.b #'0',(a1)+ ;Assume user number is less than 10. cmpi.b #10,d0 ;Is user number 10 or greater? bcs.s 2$ ;No. move.b #'1',-1(a1) ;Change the first digit to 1. subi.b #10,d0 2$ addi.b #'0',d0 ;Convert user number to ASCII. move.b d0,(a1)+ ;Insert user number into file spec. 3$ move.b #':',(a1)+ 4$ moveq #7,d0 ;Maximum of 8 characters for file name convfn1 cmpi.b #' ',(a0) ;End of file name? beq.s 3$ ;Yes cmpi.b #'*',(a0) ;Wild card? bne.s 1$ ;No. move.b #'#',(a1)+ ;Convert to AmigaDOS format. move.b #'?',(a1)+ addq.l #1,a0 ;Skip over the asterisk. bra.s 2$ 1$ move.b (a0)+,(a1)+ ;Move one character of file name. 2$ dbra d0,convfn1 ;Try for more. 3$ movea.l (sp)+,a0 ;Back to start of FCB. lea 9(a0),a0 ;Go to start of file name extension. cmpi.b #' ',(a0) ;Do we have an extension? beq.s convfnx ;No. move.b #'.',(a1)+ ;Insert extension separator. moveq #2,d0 ;Maximum of 3 characters for extension. convfn2 cmpi.b #' ',(a0) ;End of extension? beq.s convfnx ;Yes. cmpi.b #'*',(a0) ;Wild card? bne.s 1$ ;No. move.b #'#',(a1)+ ;Convert to AmigaDOS format. move.b #'?',(a1)+ addq.l #1,a0 ;Skip over the asterisk. bra.s 2$ 1$ move.b (a0)+,(a1)+ ;Move one character of extension. 2$ dbra d0,convfn2 ;Try for more. convfnx clr.b (a1) ;Terminate file name string. move.l (sp)+,a1 rts * * Get the file handle indicated by the first 12 bytes of the CP/M FCB * whose CP/M address is in D1. The file handle (if found) is copied * to D1 from the file handle table entry (which is pointed to by A1). * If the file handle cannot be found, D1 will be set to zero. * In any event, A0 will be set to point to the FCB. * gethand lea 0(targbase,d1.l),a0 ;The FCB is here. lea handles,a1 ;A1 scans the file handle table. moveq #(handlen-handles)/16-1,d0 1$ movem.l d0/a0-a1,-(sp) tst.l (a1) ;Is this entry empty? beq.s 3$ ;Yes - ignore it. addq.l #4,a1 ;Skip over to file name in table. moveq #11,d1 2$ cmp.b (a0)+,(a1)+ ;Compare first 12 bytes of FCB with table. bne.s 3$ ;No match. dbra d1,2$ movem.l (sp)+,d0/a0-a1 move.l (a1),d1 ;Here's the file handle. rts 3$ movem.l (sp)+,d0/a0-a1 lea 16(a1),a1 ;Try the next table entry. dbra d0,1$ moveq #0,d1 ;Couldn't find the handle! rts page ************************************************************************* * * * Serial port routines * * * ************************************************************************* * * Read a byte from the port whose number is in D0. * A0 points to where to put it. * inp movem.l a1/a6/d2-d3,-(sp) cmp.b #$14,d0 ;Port 14? bne.s inp15 ;No. move.l a0,-(sp) tst.l rpport ;Is serial.device open? bne.s 1$ ;Yes. bsr initser ;Set up serial.device. 1$ bsr checkio tst.l d0 ;Is a character ready? beq.s 2$ ;No - give the previous one again. bsr serread ;Read the new character. 2$ move.l (sp)+,a0 move.b charin,(a0) ;Move it to user's area. bra.s inpx inp15 cmp.b #$15,d0 ;Port 15? bne.s inpx ;No - ignore it. move.b #7,(a0) ;Assume a character is ready. move.l a0,-(sp) bsr checkio ;Check whether a character is ready. move.l (sp)+,a0 tst.l d0 ;Is a character ready? bne.s inpx ;Yes. move.b #5,(a0) ;Don't set "receiver ready" bit. inpx movem.l (sp)+,a1/a6/d2-d3 rts * * Write the byte pointed to by A0 to the port whose number is in D0. * outp movem.l a1/a6/d2-d3,-(sp) cmp.l #$14,d0 ;Port 14? bne.s outpx ;No - ignore it. move.b (a0),charout ;Character to write tst.l rpport ;Is serial.device open? bne.s 1$ ;Yes. bsr initser ;Set up serial.device. 1$ bsr serwrit ;Write the character. outpx movem.l (sp)+,a1/a6/d2-d3 rts * * Initialize the serial port. * initser: * Open a reply port for the serial input device. lea readreq,a0 move.w #rsize-1,d0 1$ clr.b (a0)+ ;Clear the I/O request block. dbra d0,1$ clr.l -(sp) move.l #2$,-(sp) jsr _CreatePort ;rpport = CreatePort ("Read_RS", NULL); addq.l #8,sp move.l d0,rpport move.l d0,r_ReplyPort bne.s openin move.l #3$,d1 bsr pstring bra quitprg 2$ dc.b 'Read_RS',0 3$ dc.b 'Can''t create input port for serial.device!',cr,lf,'$' * Open the serial input device. openin move.w #rsize,r_MLength move.b #SERFLAGS,r_SerFlags move.l #CTLCHAR,r_CtlChar lea 1$,a0 moveq #0,d0 lea readreq,a1 moveq #0,d1 move.l _SysBase,a6 sys OpenDevice tst.l d0 ;Were we successful? beq.s setin ;Yes. move.l #2$,d1 bsr pstring bra quitprg 1$ dc.b 'serial.device',0 2$ dc.b 'Can''t open serial.device!',cr,lf,'$' setin move.l baud,r_Baud move.b bits,r_ReadLen ;Number of bits per character move.b bits,r_WriteLen move.w #SDCMD_SETPARAMS,r_Command lea readreq,a1 move.l _SysBase,a6 sys DoIO ;Set new input port parameters. * Set up the serial output port. lea readreq,a0 lea writreq,a1 move.w #wsize-1,d0 copw move.b (a0)+,(a1)+ ;Clone the read request block. dbra d0,copw clr.l -(sp) move.l #1$,-(sp) jsr _CreatePort ;wpport = CreatePort ("Write_RS", NULL); addq.l #8,sp move.l d0,wpport move.l d0,w_ReplyPort bne.s startup move.l #2$,d1 bsr pstring bra quitprg 1$ dc.b 'Write_RS',0 2$ dc.b 'Can''t create output port for serial.device!',cr,lf,'$' startup bsr setbaud ;Set parameters and start reading. rts * * Return TRUE (D0 <> 0) if the serial port has a character. * checkio lea readreq,a1 move.l _SysBase,a6 sys CheckIO rts * * Set the serial port's baud rate, number of data bits, etc. * setbaud tas frstset ;Is this the first call? beq.s 1$ ;Yes - input port is set up. lea readreq,a1 move.l _SysBase,a6 sys AbortIO ;Abort the outstanding read. move.l baud,r_Baud ;Baud rate move.b bits,r_ReadLen ;Number of bits per character move.b bits,r_WriteLen move.w #SDCMD_SETPARAMS,r_Command lea readreq,a1 move.l _SysBase,a6 sys DoIO ;Set new input port parameters. 1$ move.w #CMD_READ,r_Command move.l #1,r_Length move.l #charinb,r_Data lea readreq,a1 move.l _SysBase,a6 sys SendIO ;Start reading again. * Now set up the output port - this one is more straightforward. move.l baud,w_Baud move.b bits,w_ReadLen move.b bits,w_WriteLen move.w #SDCMD_SETPARAMS,w_Command lea writreq,a1 move.l _SysBase,a6 sys DoIO rts * * Write the byte in "charout" to the serial port. * serwrit move.w #CMD_WRITE,w_Command move.l #1,w_Length move.l #charout,w_Data lea writreq,a1 move.l _SysBase,a6 sys DoIO rts * * Read a byte from the serial port into "charin". * If a byte isn't ready, this routine will wait until one is. * serread lea readreq,a1 move.l _SysBase,a6 sys WaitIO ;Wait until a character is ready. move.b charinb,charin ;Get the character from the buffer. move.w #CMD_READ,r_Command move.l #1,r_Length move.l #charinb,r_Data lea readreq,a1 move.l _SysBase,a6 sys SendIO ;Get ready for the next character. rts page ************************************************************************* * * * Miscellaneous service routines * * (Inelegant, but rarely used so they stand as is.) * * * ************************************************************************* * * Display the contents of D1 in hex. * pbyte move.l #$20018,d0 ;2 nybbles, 24-bit shift first bra.s phex pword move.l #$40010,d0 ;4 nybbles, 16-bit shift first bra.s phex paddr move.l #$60008,d0 ;6 nybbles, 8-bit shift first bra.s phex plong move.l #$80000,d0 ;8 nybbles, no shift first phex lea workbuf,a0 move.l a0,-(sp) bsr pdigits move.b #'$',(a0)+ move.l (sp)+,d1 bsr pstring rts * * Convert the contents of D1 to hex at (A0). * On exit, A0 points to the next available byte. * ubyte move.l #$20018,d0 ;2 nybbles, 24-bit shift first bra.s pdigits uword move.l #$40010,d0 ;4 nybbles, 16-bit shift first bra.s pdigits uaddr move.l #$60008,d0 ;6 nybbles, 8-bit shift first bra.s pdigits ulong move.l #$80000,d0 ;8 nybbles, no shift first pdigits rol.l d0,d1 ;Do shift. bra.s 3$ 1$ swap d0 ;Save nybble count. rol.l #4,d1 ;Print variable in d1. move.l d1,-(sp) and #$F,d1 ;Isolate the current nybble. cmp #$A,d1 bcs.s 2$ add.b #'A'-'9'-1,d1 ;Adjust for digits A through F. 2$ add.b #'0',d1 ;Convert to ASCII. move.b d1,(a0)+ ;Add to the result string. move.l (sp)+,d1 3$ swap d0 ;Get nybble count. dbra d0,1$ rts pchar move.b d1,workbuf ;Print the character in D1. move.b #'$',workbuf+1 move.l #workbuf,d1 bsr pstring rts pspace move.l #1$,d1 ;Print a space. bsr pstring rts 1$ dc.b ' $' pcrlf move.l #1$,d1 ;Print a carriage return and line feed. bsr pstring rts 1$ dc.b cr,lf,'$' * * Convert the hex string pointed to by A0 to long in d1. * Stops on the first invalid hex digit, which is returned in d0. * A0 is left pointing to this first invalid digit. * d2 = 1 if any valid digits were found, 0 otherwise. * atol moveq #0,d1 moveq #0,d2 1$ move.b (a0)+,d0 ;Get the current byte. cmpi.b #$60,d0 bcs.s 2$ andi.b #$5F,d0 ;Mask to upper case. 2$ cmpi.b #'0',d0 ;Check range (0..9,A..F). bcs.s atolend cmpi.b #'F',d0 bhi.s atolend cmpi.b #'9',d0 bls.s 3$ cmpi.b #'A',d0 bcs.s atolend 3$ moveq #1,d2 ;Valid characters entered, set flag. sub.b #'0',d0 ;Convert to binary cmpi.b #$9,d0 ;Digit in range 0..9? bls.s 4$ ;Yes - conversion is complete sub.b #'A'-'9'-1,d0 ;Adjust digits A..F. 4$ ext d0 ;Convert to long. ext.l d0 asl.l #4,d1 ;Tack it onto d1. add.l d0,d1 bra.s 1$ ;Try for another digit. atolend subq.l #1,a0 ;Back onto the first invalid digit. rts page ************************************************************************* * * * Instruction mnemonic table (used for tracing) * * * ************************************************************************* data data * This table contains the mnemonic strings for the 8080/Z-80 opcodes. * * "q" denotes a register number in bits 3 through 5 of the opcode. * Values are interpreted as follows: * Normal 8080 Normal Z-80 DD prefix FD prefix * 000 B B B B * 001 C C C C * 010 D D D D * 011 E E E E * 100 H H XH YH * 101 L L XL YL * 110 M (HL) (IX+n) (IY+n) * 111 A A A A * * "r" denotes a register number in bits 0 through 2 of the opcode. * Values are interpreted the same as for "q" above. * * "p" denotes a 2-bit register pair number in bits 4 and 5 of the opcode. * Values are interpreted as follows: * 8080 Z-80 * 00 B BC * 01 D DE * 10 H HL (no DD or FD prefix) * 10 IX IX (with DD prefix) * 10 IX IX (with FD prefix) * 11 SP SP (if opcode is below F0) * 11 PSW AF (if opcode is F0 or greater) * * "h" is replaced by IX or IY if the opcode prefix is DD or FD respectively. * If the instruction is not prefixed, "h" is replaced by HL. * * "n" denotes an 8-bit number following the opcode. * * "a" denotes a 16-bit address following the opcode. * Mnemonics for 8080 opcodes 00 through 3F mnop008: dc.b 'NOP$ LXI p,a$ STAX p$ INX p$ ' ;00-03 dc.b 'INR q$ DCR q$ MVI q,n$ RLC$ ' ;04-07 dc.b 'EXAF$ DAD p$ LDAX p$ DCX p$ ' ;08-0B dc.b 'INR q$ DCR q$ MVI q,n$ RRC$ ' ;0C-0F dc.b 'DJNZ n$ LXI p,a$ STAX p$ INX p$ ' ;10-13 dc.b 'INR q$ DCR q$ MVI q,n$ RAL$ ' ;14-17 dc.b 'JR n$ DAD p$ LDAX p$ DCX p$ ' ;18-1B dc.b 'INR q$ DCR q$ MVI q,n$ RAR$ ' ;1C-1F dc.b 'JRNZ n$ LXI p,a$ ShD a$ INX p$ ' ;20-23 dc.b 'INR q$ DCR q$ MVI q,n$ DAA$ ' ;24-27 dc.b 'JRZ n$ DAD p$ LhD a$ DCX p$ ' ;28-2B dc.b 'INR q$ DCR q$ MVI q,n$ CMA$ ' ;2C-2F dc.b 'JRNC n$ LXI p,a$ STA a$ INX p$ ' ;30-33 dc.b 'INR q$ DCR q$ MVI q,n$ STC$ ' ;34-37 dc.b 'JRC n$ DAD p$ LDA a$ DCX p$ ' ;38-3B dc.b 'INR q$ DCR q$ MVI q,n$ CMC$ ' ;3C-3F * Mnemonics for Z-80 opcodes 00 through 3F mnop00z: dc.b 'NOP$ LD p,a$ LD (p),A$ INC p$ ' ;00-03 dc.b 'INC q$ DEC q$ LD q,n$ RLCA$ ' ;04-07 dc.b 'EX AF,AF$ ADD HL,p$ LD A,(p)$ DEC p$ ' ;08-0B dc.b 'INC q$ DEC q$ LD q,n$ RRCA$ ' ;0C-0F dc.b 'DJNZ n$ LD p,a$ LD (p),A$ INC p$ ' ;10-13 dc.b 'INC q$ DEC q$ LD q,n$ RLA$ ' ;14-17 dc.b 'JR n$ ADD HL,p$ LD A,(p)$ DEC p$ ' ;18-1B dc.b 'INC q$ DEC q$ LD q,n$ RRA$ ' ;1C-1F dc.b 'JR NZ,n$ LD p,a$ LD (a),HL$INC p$ ' ;20-23 dc.b 'INC q$ DEC q$ LD q,n$ DAA$ ' ;24-27 dc.b 'JR Z,n$ ADD HL,p$ LD HL,(a)$DEC p$ ' ;28-2B dc.b 'INC q$ DEC q$ LD q,n$ CPL$ ' ;2C-2F dc.b 'JR NC,n$ LD p,a$ LD (a),A$ INC p$ ' ;30-33 dc.b 'INC q$ DEC q$ LD q,n$ SCF$ ' ;34-37 dc.b 'JR C,n$ ADD HL,p$ LD A,(a)$ DEC p$ ' ;38-3B dc.b 'INC q$ DEC q$ LD q,n$ CCF$ ' ;3C-3F * Mnemonics for opcodes 40 through 7f are easy - 76 is HLT * (HALT for Z-80), and all others are MOV (LD for Z-80). mnop408 dc.b 'MOV q,r$' mnop40z dc.b 'LD q,r$' mnop768 dc.b 'HLT$' mnop76z dc.b 'HALT$' * Mnemonics for 8080 opcodes 80 through BF mnop808: dc.b 'ADD r$ ADC r$ SUB r$ SBB r$ ' ;80-9F dc.b 'ANA r$ XRA r$ ORA r$ CMP r$ ' ;A0-BF * Mnemonics for Z-80 opcodes 80 through BF mnop80z: dc.b 'ADD A,r$ADC A,r$SUB r$ SBC A,r$' ;80-9F dc.b 'AND r$ XOR r$ OR r$ CP r$ ' ;A0-BF * Mnemonics for 8080 opcodes C0 through FF * These are interpreted by the same routine as for opcodes 00 through 3F. mnopC08: dc.b 'RNZ$ POP p$ JNZ a$ JMP a$ ' ;C0-C3 dc.b 'CNZ a$ PUSH p$ ADI n$ RST 0$ ' ;C4-C7 dc.b 'RZ$ RET$ JZ a$ ILLEGAL$ ' ;C8-CB dc.b 'CZ a$ CALL a$ ACI n$ RST 1$ ' ;CC-CF dc.b 'RNC$ POP p$ JNC a$ OUT n$ ' ;D0-D3 dc.b 'CNC a$ PUSH p$ SUI n$ RST 2$ ' ;D4-D7 dc.b 'RC$ EXX$ JC a$ IN n$ ' ;D8-DB dc.b 'CC a$ ILLEGAL$ SBI n$ RST 3$ ' ;DC-DF dc.b 'RPO$ POP p$ JPO a$ XTh$ ' ;E0-E3 dc.b 'CPO a$ PUSH p$ ANI n$ RST 4$ ' ;E4-E7 dc.b 'RPE$ PCh$ JPE a$ XCHG$ ' ;E8-EB dc.b 'CPE a$ ILLEGAL$ XRI n$ RST 5$ ' ;EC-FF dc.b 'RP$ POP p$ JP a$ DI$ ' ;F0-F3 dc.b 'CP a$ PUSH p$ ORI n$ RST 6$ ' ;F4-F7 dc.b 'RM$ SPh$ JM a$ EI$ ' ;F8-FB dc.b 'CM a$ ILLEGAL$ CPI n$ RST 7$ ' ;FC-FF * Mnemonics for Z-80 opcodes C0 through FF * These are interpreted by the same routine as for opcodes 00 through 3F. mnopC0z: dc.b 'RET NZ$ LD p,(SP)$JP NZ,a$ JP a$ ' ;C0-C3 dc.b 'CALL NZ,a$ LD (SP),p$ADD A,n$ RST 0$ ' ;C4-C7 dc.b 'RET Z$ RET$ JP Z,a$ ILLEGAL$ ' ;C8-CB dc.b 'CALL Z,a$ CALL a$ ADC A,n$ RST 8$ ' ;CC-CF dc.b 'RET NC$ LD p,(SP)$JP NC,a$ OUT n,A$ ' ;D0-D3 dc.b 'CALL NC,a$ LD (SP),p$SUB A,n$ RST 10$ ' ;D4-D7 dc.b 'RET C$ EXX$ JP C,a$ IN A,n$ ' ;D8-DB dc.b 'CALL C,a$ ILLEGAL$ SBC A,n$ RST 18$ ' ;DC-DF dc.b 'RET PO$ LD p,(SP)$JP PO,a$ EX (SP),p$' ;E0-E3 dc.b 'CALL PO,a$ LD (SP),p$AND A,n$ RST 20$ ' ;E4-E7 dc.b 'RET PE$ JP (p)$ JP PE,a$ EX DE,p$ ' ;E8-EB dc.b 'CALL PE,a$ ILLEGAL$ XOR A,n$ RST 28$ ' ;EC-FF dc.b 'RET P$ LD p,(SP)$JP P,a$ DI$ ' ;F0-F3 dc.b 'CALL P,a$ LD (SP),p$OR A,n$ RST 30$ ' ;F4-F7 dc.b 'RET M$ LD SP,h$ JP M,a$ EI$ ' ;F8-FB dc.b 'CALL M,a$ ILLEGAL$ CP A,n$ RST 38$ ' ;FC-FF * Mnemonics for opcodes CB00 through CB3F - * these are the same for both the 8080 and the Z-80. mnopCB08: mnopCB0z: dc.b 'RLC r$ RRC r$ RL r$ RR r$ ' ;CB00-CB1F dc.b 'SLA r$ SRA r$ ILLEGAL$SRL r$ ' ;CB20-CB3F * Mnemonics for opcodes CB40 through CBFF - * these are the same for both the 8080 and the Z-80. mnopCB48: mnopCB4z: dc.b 'BIT $ RES $ SET $ ' * Mnemonics for 8080 opcodes ED40 through ED7F * These are interpreted by the same routine as for opcodes 00 through 3F. mnopE48: dc.b 'IN q,(C)$ OUT (C),q$ DSBB p$ SBCD a$ ' ;ED40-ED43 dc.b 'NEG$ RETN$ IM0$ MOV I,A$ ' ;ED44-ED47 dc.b 'IN q,(C)$ OUT (C),q$ DADC p$ LBCD a$ ' ;ED48-ED4B dc.b 'ILLEGAL$ RETI$ ILLEGAL$ MOV R,A$ ' ;ED4C-ED4F dc.b 'IN q,(C)$ OUT (C),q$ DSBB p$ SDED a$ ' ;ED50-ED53 dc.b 'ILLEGAL$ ILLEGAL$ IM1$ MOV A,I$ ' ;ED54-ED57 dc.b 'IN q,(C)$ OUT (C),q$ DADC p$ LDED a$ ' ;ED58-ED5B dc.b 'ILLEGAL$ ILLEGAL$ IM2$ MOV A,R$ ' ;ED5C-ED5F dc.b 'IN q,(C)$ OUT (C),q$ DSBB p$ SHLD a$ ' ;ED60-ED63 dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ RRD$ ' ;ED64-ED67 dc.b 'IN q,(C)$ OUT (C),q$ DADC p$ LHLD a$ ' ;ED68-ED6B dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ RLD$ ' ;ED6C-ED6F dc.b 'IN q,(C)$ OUT (C),q$ DSBB p$ SSPD a$ ' ;ED70-ED73 dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ ILLEGAL$ ' ;ED74-ED77 dc.b 'IN q,(C)$ OUT (C),q$ DADC p$ LSPD a$ ' ;ED78-ED7B dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ ILLEGAL$ ' ;ED7C-ED7F * Mnemonics for Z-80 opcodes ED40 through ED7F * These are interpreted by the same routine as for opcodes 00 through 3F. mnopE4z: dc.b 'IN q,(C)$ OUT (C),q$ SBC HL,p$ LD (a),p$ ' ;ED40-ED43 dc.b 'NEG$ RETN$ IM 0$ LD I,A$ ' ;ED44-ED47 dc.b 'IN q,(C)$ OUT (C),q$ ADC HL,p$ LD p,(a)$ ' ;ED48-ED4B dc.b 'ILLEGAL$ RETI$ ILLEGAL$ LD R,A$ ' ;ED4C-ED4F dc.b 'IN q,(C)$ OUT (C),q$ SBC HL,p$ LD (a),p$ ' ;ED50-ED53 dc.b 'ILLEGAL$ ILLEGAL$ IM 1$ LD A,I$ ' ;ED54-ED57 dc.b 'IN q,(C)$ OUT (C),q$ ADC HL,p$ LD p,(a)$ ' ;ED58-ED5B dc.b 'ILLEGAL$ ILLEGAL$ IM 2$ LD A,R$ ' ;ED5C-ED5F dc.b 'IN q,(C)$ OUT (C),q$ SBC HL,p$ LD (a),p$ ' ;ED60-ED63 dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ RRD$ ' ;ED64-ED67 dc.b 'IN q,(C)$ OUT (C),q$ ADC HL,p$ LD p,(a)$ ' ;ED68-ED6B dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ RLD$ ' ;ED6C-ED6F dc.b 'IN q,(C)$ OUT (C),q$ SBC HL,p$ LD (a),p$ ' ;ED70-ED73 dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ ILLEGAL$ ' ;ED74-ED77 dc.b 'IN q,(C)$ OUT (C),q$ ADC HL,p$ LD p,(a)$ ' ;ED78-ED7B dc.b 'ILLEGAL$ ILLEGAL$ ILLEGAL$ ILLEGAL$ ' ;ED7C-ED7F * Mnemonics for miscellaneous ED-prefix instructions - * these are the same for both the 8080 and the Z-80. mnopEA8: mnopEAz: dc.b 'LDI$ CPI$ INI$ OUTI$' ;EDA0-EDA3 dc.b ' ' ;EDA4-EDA7 (illegal) dc.b 'LDD$ CPD$ IND$ OUTD$' ;EDA8-EDAB dc.b ' ' ;EDAC-EDAF (illegal) dc.b 'LDIR$CPIR$INIR$OTIR$' ;EDB0-EDB3 dc.b ' ' ;EDB4-EDB7 (illegal) dc.b 'LDDR$CPDR$INDR$OTDR$' ;EDB8-EDBB * Mnemonic for illegal instructions mnopilg dc.b 'ILLEGAL$' page ************************************************************************* * * * Fake FDOS * * * ************************************************************************* * * Fake BDOS for target system * fdos dc.b tHLT,0,tRET ;BIOS jump table dc.b tJMP,$33,$FF ;Warm boot dc.b tJMP,$36,$FF ;Console status dc.b tJMP,$39,$FF ;Console input dc.b tJMP,$3C,$FF ;Console output dc.b tJMP,$3F,$FF ;List output dc.b tJMP,$42,$FF ;Punch output dc.b tJMP,$45,$FF ;Reader input dc.b tJMP,$48,$FF ;Home disk dc.b tJMP,$4B,$FF ;Select disk dc.b tJMP,$4E,$FF ;Set track dc.b tJMP,$51,$FF ;Set sector dc.b tJMP,$54,$FF ;Set DMA address dc.b tJMP,$57,$FF ;Read dc.b tJMP,$5A,$FF ;Write dc.b tJMP,$5D,$FF ;Get list device status dc.b tJMP,$60,$FF ;Sector translation * * Fake BIOS for target system * dc.b tHLT,1,tRET ;Warm boot dc.b tHLT,2,tRET ;Console status dc.b tHLT,3,tRET ;Console input dc.b tHLT,4,tRET ;Console output dc.b tHLT,5,tRET ;List output dc.b tHLT,6,tRET ;Punch output dc.b tHLT,7,tRET ;Reader input dc.b tHLT,8,tRET ;Home disk * dc.b tHLT,9,tRET ;Select disk * dc.b tHLT,10,tRET ;Set track * dc.b tHLT,11,tRET ;Set sector * dc.b tHLT,12,tRET ;Set DMA address * dc.b tHLT,13,tRET ;Read * dc.b tHLT,14,tRET ;Write * dc.b tHLT,15,tRET ;Get list device status * dc.b tHLT,16,tRET ;Sector translation * * * Fake Disk Parameter Block * fakedpb dc.b 11,0 ;SPT (sectors per track) dc.b 4 ;BSH (block shift to record number) dc.b 15 ;BLM (block number mask to record no.) dc.b 0 ;EXM (logical->physical extent shift) dc.b 439&255,439/256 ;DSM (highest allocation block number) dc.b 255,0 ;DRM (highest directory entry number) dc.b $F0,0 ;AL0, AL1 (initial allocation vector) dc.b 64,0 ;CKS (size of directory check area) dc.b 0,0 ;OFF (offset, number of reserved tracks) * * Fake Disk Block Allocation Table * fakealv dcb.b 21,$FF dc.b %11111100 dcb.b 10,0 fdoslen equ *-fdos * * BDOS function vector table * cnop 0,4 bdostab dc.l bdos00,bdos01,bdos02,bdos03,bdos04,bdos05,bdos06,bdos07 dc.l bdos08,bdos09,bdos10,bdos11,bdos12,bdos13,bdos14,bdos15 dc.l bdos16,bdos17,bdos18,bdos19,bdos20,bdos21,bdos22,bdos23 dc.l bdos24,bdos25,bdos26,bdos27,bdos28,bdos29,bdos30,bdos31 dc.l bdos32,bdos33,bdos34,bdos35,bdos36 bdostabn: * * BIOS function vector table * cnop 0,4 biostab dc.l bdosfn,bios01,bios02,bios03,bios04,bios05,bios06,bios07 dc.l bios08,bios09,bios10,bios11,bios12,bios13,bios14,bios15 biostabn: null dc.b 0 ;Null string page ************************************************************************* * * * Variable storage * * * ************************************************************************* bss bss * File information block - must be on a 4-byte boundary! fib: fibkey ds.l 1 fibtype ds.l 1 ;Type (file if negative, directory if positive) fibname ds.b 108 ;File name (null-terminated) fibprot ds.l 1 ;Protection mask fibent ds.l 1 fibsize ds.l 1 ;Number of bytes in file fibblks ds.l 1 ;Number of blocks in file fibdays ds.l 1 ;Date stamp - number of days since Jan. 1, 1978 fibmins ds.l 1 ;Date stamp - number of minutes past midnight fibtick ds.l 1 ;Date stamp - number of ticks past minute fibcmt ds.b 116 ;Comments (null-terminated) * InfoData structure InfoData: id_NumSoftErrors ds.l 1 ;number of soft errors on disk id_UnitNumber ds.l 1 ;Which unit disk is (was) mounted on id_DiskState ds.l 1 ;See defines below id_NumBlocks ds.l 1 ;Number of blocks on disk id_NumBlocksUsed ds.l 1 ;Number of block in use id_BytesPerBlock ds.l 1 id_DiskType ds.l 1 ;Disk Type code id_VolumeNode ds.l 1 ;BCPL pointer to volume node id_InUse ds.l 1 ;Flag, zero if not in use id_SIZEOF equ 36 * Miscellaneous storage areas savesp ds.l 1 ;Stack pointer save area _SysBase ds.l 1 ;Copy of _AbsExecBase _DOSBase ds.l 1 ;Pointer to dos.library stdin ds.l 1 ;Keyboard handle (stdin) stdout ds.l 1 ;Screen handle (stdout) rawhand ds.l 1 ;RAW: file handle prthand ds.l 1 ;PRT:RAW file handle handles ds.l 8*4 ;File handle (or zero) plus 12 bytes of FCB handlen: ;End of file handle table dmaaddr ds.l 1 ;Current DMA address comend ds.l 1 ;End of .COM file name on command line dtstamp ds.l 3 ;Date and time stamp rpport ds.l 1 ;Serial input message port wpport ds.l 1 ;Serial output message port baud ds.l 1 ;New baud rate for "setbaud" bits ds.b 1 ;Number of data bits charin ds.b 1 ;Current input character charinb ds.b 1 ;Serial input buffer charout ds.b 1 ;Current output character frstset ds.b 1 ;$80 after first call to "setbaud" cmdline ds.b 128 ;Command line cmdlinen: ;End of command line comname ds.b 20 ;Name of file to load comnamen: ;End of file name opnname ds.b 24 ;File name for OPEN or RENAME renname ds.b 24 ;New file name for RENAME srchnam ds.b 11 ;CP/M file name for search first/next ext17 ds.w 1 ;Extent counter for search first/next newrega ds.b 1 ;BIOS/BDOS accumulator work area workbuf ds.b 80 ;Work buffer for "pstring" (including $) workbufn: ;End of work buffer strbuf ds.b 2048 ;String output buffer strbufn ds.b 8 ;"strbuf" overflow area - must follow "strbuf"! strptr ds.l 1 ;Current position in "strbuf" escbuf ds.b 8 ;Translated escape sequence esclen ds.w 1 ;Number of bytes saved in "escbuf" cmdflag ds.b 1 ;Take program name from command line. quitflg ds.b 1 ;"quitprg" exit flag testdol ds.b 1 ;"pstring" should test for leading $ insflag ds.b 1 ;We're in insert mode. dumpcnt ds.b 1 ;"dump" counter for pausing traceit ds.b 1 ;-t (trace) flag was set on command line btrcflg ds.b 1 ;Trace BIOS/BDOS calls. bufflag ds.b 1 ;Console output is buffered. z80flag ds.b 1 ;Display Z-80 mnemonics in instruction trace. opcode ds.b 1 ;Current opcode (used for tracing) prefix ds.b 1 ;Instruction prefix (DD or FD) fcbptr ds.l 1 ;Pointer to current FCB listopn ds.b 1 ;The list device is open. builtin ds.b 1 ;1 = USER command, 2 = SAVE command acmap ds.w 1 ;Active drive map romap ds.w 1 ;Read-only map newdmap ds.w 1 ;Map bit from "mapdrv" * * Serial port read request * ds.l 0 readreq ;struct IOExtSer ;struct IOStdReq ;struct Message ds.b 14 ;struct Node r_ReplyPort ds.l 1 ;Pointer to MsgPort (message reply port) r_MLength ds.w 1 ;Message length in bytes ; End of struct Message ds.l 1 ;Pointer to device node ds.l 1 ;Pointer to Unit (driver private) r_Command ds.w 1 ;Device command ds.b 1 ;io_Flags ds.b 1 ;Error or warning number ; End of struct IOReq - IOStdReq continues... r_Actual ds.l 1 ;Actual number of bytes transferred r_Length ds.l 1 ;Requested number of bytes transferred r_Data ds.l 1 ;Points to data area. r_Offset ds.l 1 ;Offset for block-structured devices ; End of struct IOStdReq r_CtlChar ds.l 1 ;control char's (order = xON,xOFF,INQ,ACK) r_RBufLen ds.l 1 ;length in bytes of serial port's read buffer r_ExtFlags ds.l 1 ;additional serial flags (see bitdefs below) r_Baud ds.l 1 ;baud rate requested (true baud) ds.l 1 ;duration of break signal in MICROseconds ;struct IOTArray termination character array r_ReadLen ds.b 1 ;bits per read character (# of bits) r_WriteLen ds.b 1 ;bits per write character (# of bits) r_StopBits ds.b 1 ;stopbits for read (# of bits) r_SerFlags ds.b 1 ;see SerFlags bit definitions below r_Status ds.w 1 ;status of serial port rsize equ *-readreq * * Serial port write request * ds.l 0 writreq ;struct IOExtSer ;struct IOStdReq ;struct Message ds.b 14 ;struct Node w_ReplyPort ds.l 1 ;Pointer to MsgPort (message reply port) w_MLength ds.w 1 ;Message length in bytes ; End of struct Message ds.l 1 ;Pointer to device node ds.l 1 ;Pointer to Unit (driver private) w_Command ds.w 1 ;Device command ds.b 1 ;io_Flags ds.b 1 ;Error or warning number ; End of struct IOReq - IOStdReq continues... w_Actual ds.l 1 ;Actual number of bytes transferred w_Length ds.l 1 ;Requested number of bytes transferred w_Data ds.l 1 ;Points to data area. w_Offset ds.l 1 ;Offset for block-structured devices ; End of struct IOStdReq w_CtlChar ds.l 1 ;control char's (order = xON,xOFF,INQ,ACK) w_RBufLen ds.l 1 ;length in bytes of serial port's read buffer w_ExtFlags ds.l 1 ;additional serial flags (see bitdefs below) w_Baud ds.l 1 ;baud rate requested (true baud) ds.l 1 ;duration of break signal in MICROseconds ;struct IOTArray termination character array w_ReadLen ds.b 1 ;bits per read character (# of bits) w_WriteLen ds.b 1 ;bits per write character (# of bits) w_StopBits ds.b 1 ;stopbits for read (# of bits) w_SerFlags ds.b 1 ;see SerFlags bit definitions below w_Status ds.w 1 ;status of serial port, as follows: wsize equ *-writreq * BIT ACTIVE FUNCTION * 0 low busy * 1 low paper out * 2 low select * 3 low Data Set Ready * 4 low Clear To Send * 5 low Carrier Detect * 6 low Ready To Send * 7 low Data Terminal Ready * 8 high read overrun * 9 high break sent * 10 high break received * 11 high transmit x-OFFed * 12 high receive x-OFFed * 13-15 reserved ************************************************************************* * * * Target processor's address space * * * ************************************************************************* even registers ds.b 22 ;Actual storage for Z-80's other registers target ds.b $10000 ;Z-80's universe end SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.