IMD 1.18: 7/12/2016 20:56:09 q e sus g source  UUUUUU@@@@UUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUU +(C)ZILOG,INC.1981MCZ-2 CP/M BOOTSTRAP 820951  !96 !ut!ut!ut  u t !6u t6!ut!ut!Ou t\X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<ܯ2 ݇!2:2a{_:ʖ:>Ľʖ:=2–!B!6#5ʖ:Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ "޷"͌#>?͌͘ =_.:;<> Oޅo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USERO !yO#< Ty#O 3߯21y_͸2y2ͽ:ܷ˜1͘A͌>>͌92^ :¥.!_~#fow]!v"!çREAD ERRORçNO FILE^: ! ~ 3#0 Wx x ހ ނ G ~ # 3x~#B!Y~ɯ2:=!ý:=!:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ w4!Y~ʆ͌†t=ʆf ^ T 2o&)|+!<ͧÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Ypsp2mÆÆf ͧÆFILE EXISTS _: É: :ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~22\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: ! Â$$$ SUBO "C{2!"E9"1A22!ty)K!G_^#V*C~E ,&-AGMS!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6 O͐  :E B 2>: b# : y! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #H: !  Hù H H $O͐: 2 *CN# x: 2 p&x~+é72 H! >w_: ! 5ͤNkͱ¦ͱxʊ#Nx: ! 2 ͤ! 5™#wO~x½p Hy<< ʑ :!qMD#2E>! ^#V w#P:BO|^#V#"##"##"##"!O*!O*|!6ʝ6>*w#w*w#w'û*! J*""!N#F*^#V*~#foyx*{_zW+*yx#*DM*s#r*s#ryOxG*0MD!!N: EG>O: \S*C :qn& ^#V>O^"*}:*)=":O:o"*C *C!ͮ~2~2ͦ:2ͮ:O:w:w |g}o*#  ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:o$*C~i6iw**{#zr+s{ozg**͕** ,w͜͸Ͳ!!N#F$**O!~#:A#~$=2Ek͌::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | s-|N-# S:2E!~Яw>T D^6k-äPYy 5*{zBK5ڋ>*Cw~#+w#w+ɯ2E22i^ *C :~w~͔͔# #  w ~>2!E5T*C!"C"C!w# F! w͌x2͢*C ~<wʃG:!ʎì 4~ʶ¬:<ʶ$ʶïZͻx>2>2ͻ:!Z2:Eẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C ::ddslO s#r:E͊:==»y==»*Ww#*"͸*:G#š"͸:!w4!iw:Z!E~=262*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!Bw!>2*C~=2u:B2~2wE:A*Cw>"!""2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*W}_*"}o|g":ʑ*C6:ʑw:2E**E}DQ>2*>Oa"'.3o?QüM222FFFWWWWi22FWQ MCZ-2 CP/M BIOS 82161 (C) ZILOG, INC. 19811!%2>211!: .!">2!"2!":O2222!C%!B:! >!J2(U!RW(y!Z(!yFˆ(  N(> ˎۆG(ۄ ۆG(ۄ ۆW(yӄ!b/w>ۆ>W !j0!r>!":2!y :>(o2))))?CCC> 2:?8[!ͷ>2>22>2:?8*ͷy2 >2:2*"K?":(I=2:! <*KB 0K?KB !hB *#" C22<22>*(<="!~6((:! *KB *KB($:!:2*"*":2*}o|g)[: (>2::2!:> >2:?ͷ:! ! 2"*"*!2*K "**:2*K!> >2*K! 2{ i` n`!!z~O< w! ~s1!U˿w{Ms1!4 T#4V(Nw++><4 D6+4 =6+4> 46+4F+~ +~#> < O !Q ~# 6+4> 6+4{M:@ (O ~#fo))MD))]T n f s#r~OW#!f""""!"t!k8!n8!]8!g8j͞yͼ(yͼ @!R(S/2:>2!  62! Fx/wp˗:2:W:! >>>>>>2!>2!2s_!qOyy( (q#p+ s#r<2 !5" ! !" : 2 :((: : O! ~( :(>7>~ G !"r>>կ2"> O(:(6 I>s1>2{MN#F#r(rH0X:rEhnEratr      ()23<=FGPQZ[de$%./89BCLMVW`a  !*+45>?HIRS\]fg &'01:;DENOXYbc"#,-67@AJKTU^_*+TU@A,-VWBC./XYDE01Z[FG 23\]HI 45^_ !JK 67`a"#LM89bc$%NO:;de&'PQ<=fg()RS>??h h @9& Zilog MCZ-2 CP/M Version 2.0 64k CP/M vers 2.2 Boot Error.     LGp,,<*7 ͣ,=-G~# "- *-͗,-x͗,G‰,&‰, "7͝ V- V- \-͗,C-d 1-k-d 1-͗,e-͝ ;ʍ--]5͗, >5͝ -]5]5 ʐ- ʐ-̈́5"9>5 >5> 4>5:9-*94.*9~-G+-~/_-~ .=G+~ ..-+<= .+.~>...?*9O #*96 2."9+D`E` Z.b8.,. .@@$@B B HH II$@DI ABI$"$H$H@$$I! H*  $H@@A I $D!!$I"BI"I"@$BIIH$$$$BBI$@BI!"$$A DI$@ A$@$$@H! "!$$" @B$!!!DH$$"H @@BHH  !$$A"D@ "A" "BHA " !$ D B I $ !$$ H@BD D$ HI DIA!$$$ $" "$D ! $"  $AB " BDD $$D!"DI$!$BH!"IB I$"D HD" " $"! @H !BI " I  $I$I$DI$ !I$@"$"$! $I$I$UUUUUUUP$I@@ II$ ! A D! DI"I I@$@"! D@DI"$@ @ !"  H I$$ H!@@ H $$  @@$@ @01AB7C8FE20DA0903C8FE3DC8FE5FC8FE31 :100440002EC8FE3AC8FE3BC8FE3CC8FE3EC8C91ACC :10045000B7C8FE20C013C34F03856FD024C93E0028 : >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: ! Â$$$ SUB"C {2!"E 9" 1A 22!ty)K!G_^#V*C   ~E , &-AGMS  !!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$ :B A2 ! ~6  O͐  : E  B 2 >: b # : y! 4 5~yy 5 6y Ґ ^H @Oy H  H : – ͬ   #H : !  H ù  H  H $O͐ : 2 *C N#  x : 2 p & x ~+é 7 2  H ! >w _ : ! 5ͤ N k ͱ ¦ ͱ xʊ #N x : ! 2 ͤ ! 5™ #wO ~x½  p H    y< < ʑ  : !qMD # 2E > ! ^#V w#P :B O|^#V#"##"##"##"!O *!O *|!6ʝ 6>*w#w*w#w'û *! J * ""!N#F*^#V*~#foyx *{_zW+ * yx # *DM*s#r*s#ryOxG*0MD!!N: E G>O: \ S *C  :q n& ^#V> O^ "*}:*)= ":O:o"*C  *C !ͮ ~2~2ͦ :2ͮ : O:w:w |g}o *# ) :B O! yoxg*:B O }!N#F "*#*s#r^  ~!J  ! J *:o$*C ~i 6i w**{#z r+s{ozg**͕ **  , w͜ ͸ Ͳ ! !N#F$**O !~#:A #~$=2E k͌ : :/GyO>2!q*C " ͡  -'   -@ ͦ ~^ *C  O x ! N!Fwyxʋ>ڋ>*C w~#+w#w+ɯ2E 22 i  ^ *C :~w~͔͔# #  w ~>2!E 5T *C !"C  "C !w# F! w͌ x 2͢ *C  ~<wʃG:!ʎì 4~ʶ ¬:<ʶ$ ʶïZͻ   x >2>2ͻ :!Z2:E w ̈́ ͊ Ͳ  >2>2T *C G ͻ : w ̈́ n> 2;O ^ DM;}H> "*C  ::dd slO s#r:E ͊ :==»y==»*Ww# *" ͸ *:G#š" ͸ :!w4!i w: Z!E ~=26 2*C !!~~#~O~G#n,-.‹! w! yG!x͢.:E <ʄ! q!pQ:E <. ʄ$.:E <ʄ i 6}2E x N! ~态O>G~G!~G} *C !r#r#r ^ ͥ_y#x#{s+p+q-*C  ͥ!!q#p#w*:B O Y G } ED1 S Q M ECONFIG + STAT COM)PIP COM: YXMETA DOCpE DOC` -2ZSYS o get uppercase EE: JP E0 ORG EE+0100 ...put stack here so can reenter MYSP: E0: PROC; JP EDIT0 ...normal entry & reentry E1: PROC; JP EDIT1 ...always ask for filename WORD SCRVEC WORD KEYVEC CRT: BYTE 0FF ...if<>0FF, holds CRT type (0=Infoton 20PUSH AF ... if B.CRT=I200 then begin ...if Infoton 200 ... PUT1(CRSXYI2) ...next 2 bytes are X & Y cursor coordinates+32 ... LD A,B ... end else begin ...if Visual 200 ... PUTESC(CRSYXV2) ...next 2 bytes are Y & X coordinates+32 ... POP AF; PUSQ1 COMZSYSLIB BADACS W ]DEFVWXZSYS f9:TUhijZSYSLIB [\]^_`abZSYSLIB cdG COMefY ppqrstuwoc. BLCMRF: BYTE 0 ...set<>0 if something on right part cmd. line SCLFLG: BYTE 0 ...if<>0, CONOUT allows this many scrolls ...TABTAB: DEFS NCOL+1 ...table of tab positions CMDBUF: DEFS NCOL-R1 ...command line buffer STRBUF: DEFS NCOL-R1-2 ...string bG M2  Q DOC34:=>?FIED2 S N$%ED22 S &'()*+,.XX S 0   !ZOOMA EQU/Q DOCJKLMNPQRQ DOC,STU0, 1=Visual 200) E_VERS: BYTE 2 ...@beg.+0B; inc. when E version changed ...addr. here=beg.+0C EEX0: WORD EEX ...addr. of EEX if defined; else =0 ECODE0: WORD ECODE ...addr. of ECODE if defined; else =0 ...next 24 bytes for reference by extensions (herH BC ...A & B swapped ... end ... R.A+32->R.B; POP AF; R.A+32 ... OUTTWO(); RET CLRSCR: ...clear screen CLRSCRN->R.A ... SCRCMD: ...do screen function for code in R.A; preserve other regs. PUSH AF if BIT 7,A not zero and B.LEADIN<>0 then PUT1(R.A) PXQ COMvTMP2 *SYS M <SYS S =ESPLIT COM.SSYS COMGHNSTPC S /0NXTPC S1 5zuffer XCMBUF: DEFS 5 ...buffer for "X" cmd. CMDTBC: ...table of char. cmds. for moving cursor, entering a mode, or ... executing cmd. line & address to go to DEFB 18 'E' 'I' 'R' 'X' CMDTBC2: DEFB '4' '6' '8' '2' '7' '1' TAB '_' ...this line set from ED22 S Z56789EEX DOCXVWXYZgED3 S ;<QBUG DOCDhijZOOMSYS DOCZOOMSYS DOC=GZDOS S 1YDOC 1 e ^EBUF=E0+010) EBUF: WORD EBUF0 ...start of edit buffer (must have 1 free space before) ENDDAT: WORD EBUF0 ...pos. in buffer of 'FF' at end of file ENDBUF: WORD EBUF9 ...end of edit buffer (^ENDBUF=beg.+014) WORD LOCSTR ...store addr. of LOCSTR routiOP AF; PUT1(R.A&07F) RET ...CLRSCR: ...clear screen ... if B.CRT=I200 then begin PUT1(CLRI2); RET end ...if I200 ... CLRV2->R.A ...if V200 ...PUTESC: PUSH AF; PUT1(ESC); PUT1(POP AF); RET ...put out escape+R.A ERASL: ...erase current line SCRCMD(B.CNXTPC S2 FNXTPC S3 yKEYVEC DEFB BKSP ' ' '-' LF CR CR2 DEFW CRSCR CRSCR CRSDN CRSUP CRSRT CRSLT DEFW CRSLTB CRSTAB CRSBTL CRSHM CRSDN CRSUP CRSRT CRSLT DEFW XEQ REPLCE INSERT ENTER CMDTB2: ...table of 1st char. of cmds. that go on cmd. line & addr. to go to DEFT '.;KPGWSYDOC 1 QD M OYDOC 1  BK1 S ]YDOC 2 YDOC 2 J1SYS M2 "EEXS S ane WORD NEWSTR ...store addr. of NEWSTR routine WORD LINBEG ...ditto these other routines: WORD NXTLIN WORD LTOCR WORD DIGIT WORD NUMBER WORD HEXD WORD HNUM EFLG: BYTE 0 ...set=1 when have file in OLDFLG: BYTE 0 ...if<>0, make .OLD file DUNFLGLRLIN); RET ...ERASL: ...erase current line ... if B.CRT=I200 then begin PUT1(ERSLI2); RET end ...if Infoton 200 ... ERSLV2->R.A; JR PUTESC ...if Visual 200 PRT0: ...print out msg. until byte 0; enter with R.HL->text @HL=0; RET Z; PUT1(R.A); INC HL; JBMOCLDFQTNJ' DEFW JOIN N T QUIT FORWRD DELETE LOCATE C OFF M BOTTOM SHOW WAIT G DEFW PREV KOMPAR NULL EXTN KEYVEC: ...def'n of keys for cursor move cmds + poss. redef'n of RUBOUT ...left,right,up,down,home,bottom corner,tab,back tab BYTE '4' '6' '8' 'MSUB S ^_`lmnopQBUG S yz{|}~QBUG S W03DEASM S IESYS S =efMSUB S 5q./E COM8G COMbc: BYTE 0 ...set by QUIT to 1 (or 2 if not to write file out) CMDSW: BYTE 0 ...if =0, cmds. from cons.; =1, cmds. from cmd file SVENDB: WORD 0 ...save orig. ENDBUF when allocate sp. for cmd file buff. CMFPOS: WORD 0 ...pos. in cmd. file buffer for next R PRT0 NAMEQ: PRT0(^TXNMQ) ...print "NAME?" ^CMDBUF->R.DE GET1IF() repeat B.P.GET1->@HL; PUT1(R.A); INC HL ...get filename from console if R.A=BKSP then begin DEC HL ...if backspace if R.HL-carry-R.DE+R.DE not zero then DEC HL endif end 2' '7' '1' TAB '_' LKEYVEC: EQU $-KEYVEC RUBOUT: BYTE RUB SCRVEC: ...screen function codes CSADRO: BYTE CSADROI2 ...cursor addr offset; bit 7=1 =>X-coord. sent first LEADIN: BYTE 0 ...lead-in char. (i.e. ESC); 0=>none ...in following, bit 7=1 =>requireEE ;SYS S "!Q COM[\  *SYS COM SUBMIT COM ZOOMPROGDOC 5EP COM9JKLX COM char. to be gotten BUFP0: WORD EBUF0 ...position in buffer corresponding to 1st printed char. BUFPOS: WORD EBUF0 ...pos. in buffer for action LSTROW: BYTE 0 ...row no. of last row printed out ROWNO: BYTE 1 ...row no. CRSROW: BYTE 0 ...row cursor is in until R.A=CR; RET ... LD B,LF ... ...OUTTWO: ...put out the 2 chars. in R.A & R.B ... PUT1(R.A) ... PUT1(R.B) ... RET ...DOTOLD: DEFM '.OLD' NOTASC: DEFM 'NOT ASCII'; DEFB CR 0 TOOBIG: DEFM 'FILE TOO BIG'; DEFB CR 0 ...LF 0 TXNMQ: DEFM 'NAME?'; DEFB C... FULL SCREEN EDITOR NROW: EQU 24 ...no. of rows on screen NCOL: EQU 80 ...no. of columns on screen LROW: EQU NROW-1 LCOL: EQU NCOL-1 DEFRL: EQU 080 ...RIO default file record length EOF: EQU 0FF ...end-of-file char. R1: EQU 15 ...dist. from right s lead-in CLRSCRN: BYTE CLRI2 ...clear screen CLRLIN: BYTE ERSLI2 ...clear line (or to end of line) ADRCRS: BYTE CRSXYI2 ...addr cursor INSLN: BYTE 0 ...insert line, 0=>don't have (not used) LSCRVEC: EQU $-SCRVEC FIXEOF: ...make sure end-of-file propUNSYM S ZSYS M2 dERASE S SHELL ZDOS S >G S tkQSYS S LIOS ASM (0-LROW) CRSCOL: BYTE 0 ...column cursor is in (0-LCOL) EIRFLG: BYTE 'E' ...set='E', 'I', or 'R' for enter, insert, or replace mode FULFLG: BYTE 0 ...set=1 when buffer full CRROW0: BYTE 0 ...row of CR before ins./repl. SHOWCR: BYTE 0 ...if not 0, cha...8-17-82 /?"When done, enter: /IMAGE Q.COM 100 " /?" --can then do Q QD.M to add disassembler" ORG 05000 WORD 0 ...offset stored here WORD 0 ...addr of new symbol table stored here JP 0 ...jump to procedure that moves symbol tablemargin to start cmd. line messages CR: EQU 0D ...carriage return TAB: EQU 9 ...tab LF: EQU 0A ...line feed BKSP: EQU 8 ...backspace (cursor left) ESC: EQU 01B ...escape RUB: EQU 07F ...used for deleting current character CR2: EQU 18 ...ctrl R; used er ('FF' at EOF & CR preceding, ... also put CR before beg. of file) ...preserve DE LD BC,(EBUF) if W.ENDDAT<>R.BC then begin @(R.HL-1)->R.A; R.HL+1 if R.A<>CR then R.HL+1 end LD BC,(ENDBUF) if R.HL>=R.BC then R.BC-1->R.HL R.HL->ENDDAT LD (HLIOS ASMLIOS ASMwGHIMNOE-ATOB SUBPE-BTOA SUBQS ^@ABCDEQ-ATOB SUBRQ-BTOA SUBSBUCKA EQUr. printed out at CR pos. SHOWTB: BYTE ' ' ...if set='~', print '~' at 1st pos. in tab CBUFPS: WORD CMDBUF ...command buffer position LCMCOL: BYTE 0 ...last col. except CR in cmd. buffer or "X" cmd. buffer NUM1: WORD 0 ...stores no. from cmd. STR2: WOR EXTSTR: DEFM 'EXTEND ' USCSTR: DEFM 'USERCC ' *DO OPTQ.S ...need 0300 ...*TABBSE->R.IX ...save TABBSE (IX must not be used) *LD HL,$; LD (05005),HL ...address of move symbol table routine ...PROC to move symbol table & adjust EXTEND,USERCC chain refs. to stand for CR in LOCATE string CLRI2: EQU 0C ...clear screen (Infoton 200) CLRV2: EQU 'v' ...clear screen (Visual 200); see CLRSCR routine below ERSLI2: EQU 0B ...erase line (Infoton 200) ERSLV2: EQU 't' ...erase line (Visual 200); see ERASL routine L),EOF; DEC HL; LD (HL),CR; W.EBUF-1; LD (HL),CR RET GETCHR: ...get char. from console or cmd. file->R.A B.CMDSW=0; JP NZ,GETCMF ...if CMDSW=1, get from cmd. file; else cont: ... GET1: ...get 1 char. from console repeat GET1IF() until not zero; RET EE COM8Y lmnoSYS EQUE COM8SYSEQU OLDSHELL ZSYS Q COM)+,-D STRBUF ...pos. start of where 2nd string stored NCPERL: BYTE 0 ...if <>'*', 1 chg. per line; else chg. all CHGALL: BYTE 0 ...set='*' when looking for changes on all lines CHGFLG: BYTE 0 ...0=no changes; 1=at least 1 change CHLFLG: BYTE 0 ...0=no cha Lkupnl(^EXTSTR); LD DE,(05000); @2IY+R.DE->@2IY Lkupnl(^USCSTR); LD DE,(05000); @2IY+R.DE->@2IY LD HL,(05002); R.HL-R.DE->R.DE ...^TABLE-offset TABBSE->R.HL; LD C,(HL); INC HL; LD B,(HL); DEC HL; LDIR RET *CLEAR *DO SYS.EQU ROMBEG: EQU 0100 ...MSIZbelow CRSXYI2: EQU 23 ...cursor pos. I200 (next 2 bytes are X & Y coordinates+32) CRSYXV2: EQU 'Y' ...ditto Visual 200 but Y,X (+32); see POSCRS routine below CSADROI2: EQU 0A0 ...cursor addr offset (+ X,Y order) for I200 CSADROV2: EQU 020 ...ditto V20PRCBL1: POSCRS(R.C;LD B,0); PUT1(' ') ...print space at col. R.C of cmd. line ... RETCRS: B.CRSROW->R.B; B.CRSCOL->R.A ...ret. cursor to spot in text ... POSCRS: ...position cursor; enter with X-coord. in R.A, Y-coord. in R.B PUSH BC; PUSH AF SCRCMD(XX S o"#$%&'4ZSYS gQ1 COMGHSPLIT S  ED1 S &XADDLF S ZSYS 5678OPTQ S (rstnges on line; 1=at least 1 chg. on line DIF: BYTE 0 ...if pos., diff. in length of STR2 vs. STR1 SFLFLG: BYTE 0 ...if set=1, indicates screen full TAGFLG: BYTE 0 ...if set=1, indicates a tag in place; =2, tag 2 in place ...the following 3 words must be E: EQU 0E000 QBEG: EQU MSIZE-07800 ENDTBL: EQU MSIZE-01800 *LD HL,QBEG-ROMBEG; LD (05000),HL ...save offset QROM: DEFL QBEG at ROMBEG ORG QROM LD BC,QSIZE;LD DE,QROM;LD HL,0100;LDIR;JP START0 *DO MMETA.S NLUS: EQU 7 ...for ZDOS.S *DO ZDOS.S *DO QSYS.S *0 INSLV2: EQU 'L' ...insert line (V200) (not used) I200: EQU 0 ...code for Infoton 200 CRT type V200: EQU 1 ...code for Visual 200 CRT type SHOWCH: EQU 023 ...'#': char. printed out in place of special chars. UPCASE: EQU 0DF ...'AND' with lower case tB.ADRCRS) CSADRO->R.A->R.C; RES 7,C if begin BIT 7,A; R.B->R.A end zero then begin POP AF; PUSH BC end R.A+R.C->R.B POP AF; R.A+R.C->R.A PUT1(R.A); PUT1(R.B) POP BC; RET ...POSCRS: ...position cursor; enter with X-coord. in R.A, Y-coord. in R.B ... MMETA S d#uvwxE M 2QSYS S ()ZSYSLIB BADZSYSLIB BAD1>EE <BgkSPLIT COM ZSYSLIB ;<=?@YZin order: TG1POS: WORD EBUF0 ...pos. of 1st tag ("from") TG2POS: WORD EBUF0 ...pos. of 2nd tag ("to") TG3POS: WORD EBUF0 ...pos. of invisible tag 3 EOFFLG: BYTE 0 ...set<>0 if "EOF" on current screen ESCFLG: BYTE 0 ...set<>0 if escape during WAITCH pr DO BK1.S *DO MSUB.S *DO QBUG.S *DO UNSYM.S ...handle referenced but unused symbols *DO XX.S CODE: EQU 0100 CODE2: EQU CODE+0400 TABLE: DEFS 2+NHASH*2 ...for len. of symbol table + initial links (32 entries) DEFS 0400 QSIZE: EQU $-QBEG *^TABLE; LD (05002f B.Getnum2()<>0 then R.A->CRSUP ?" '2' (cursor down) [32] ->" if B.Getnum2()<>0 then R.A->CRSDN ?" '7' (cursor to top left corner) [37] ->" if B.Getnum2()<>0 then R.A->CRSHM ?" '1' (cursor to bottom left corner) [31] ->" if B.Getnum2()<>HHͯ :^!w:<2:0}:@E}:!S!W6: z!]6:cm!c6:_z!_6l ::,: HHҰͯ : 2ó:E:1:2v!q!*8!*6: >e screen function codes? (enter Y or N)" Put1(' '); Put1(' '); Put1(' '); Put1(' '); Get1(); Put1(); ? if R.A&0DF<>'Y' then JP EC2 SET 0,FLAG ?"The following screen functions are used:" ?" clear screen" ?" clear line (either all or past co console done ...TIMECNT: BYTE 0 ...incs. to TIMESW, then int. Z8000 ...ETIME: BYTE 0[5] ...count elapsed time ...DATE: WORD RIODATE ...addr of DATE field; format YYMMDD NXTIN: WORD KBUF ...^ next char. into keybd buffer (initialize) NXTOUT: WORD KBUF),HL *PACK *CALL 05004 ...move symbol table /MAP 8 /LIST /LISTEND  s (32 entries) DEFS 0400 QSIZE: EQU $-QBEG *^TABLE; LD TABLE: DEFS 2+NHASH*2 ...for len. of symbol table + initial links (32 entries) DEFS 0400 QSIZE: EQU $-QBEG *^TABLE; LD (050020 then R.A->CRSBTL ?" tab (cursor tab) [09] ->" if B.Getnum2()<>0 then R.A->CRSTAB ?" '_' (cursor back-tab) [5F] ->" if B.Getnum2()<>0 then R.A->CRSBTB ?" DEL (delete in INSERT/REPLACE mode) [7F] ->" if B.Getnum()&07F<>0 then R.A->RUBOUT ͦ>ͦ!q:_  !p+q.*   !q*&!p+q*2!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q*ursor)" ?" position cursor" ?"Codes for screen functions may be either characters or characters" ?"preceded by a lead-in character (such as escape)" ?"(`pos. cursor' will then have 2 more chars. for the X & Y positions)" ? ?"Below, enter all value ...ditto next char. out COUNT: BYTE 0[5] ...above gets init'd^ KBUF: DEFS 16 KBUFEND: WRCONBUF: DEFS 0100 LCMDBUF0: EQU 5 ...only has to hold "I"CR, otherwise make 144 CMDBUF0: DEFS LCMDBUF0 LFNMBUF: EQU 40 FNMBUF: DEFS LFNMBUF ...read buffers BUFF1:BCo] o] B`(Fco] ͓c9]POP o]00 9]AF o] o]  _(9] EX (SP),HLo] 9]OUT (ͱa9]),A9]JP b o] "o] 9]LD SP,HL( 9]JP (HL)o] 9]EXX9]RETo] ͯb9]LD  o] $d(o]EC3: if FLAG=0 then JP EC4 ?"Do you want to write out new E with changes? (enter Y or N)" ?" (for now, writes out to EE.COM (rename to E.COM))" Put1(' '); Put1(' '); Put1(' '); Put1(' '); Get1(); Put1(); ? if R.A&0DF='Y' then begin if BIT 0,FLAG!p+q* !q*& *M *M !p+q*!!p+q*"!p+q*$!6  !kp+q*j> >ڪ Þ !qp+q/ *pDM9: :M2r:N!r !:r *r& N!r4 !6:s in hex followed by a :" ?"(in each case, an example value valid for an Infoton 200 terminal is" ?"shown in square brackets)" ? ?"If any function requires a lead-in, enter lead-in character, else 0:" ?" Example: if lead-in character=escape EQU BUFBEG BUFF2: EQU BUFBEG+RDBLKSZ ... ...BUFF vector offsets: BUFFVSZ: EQU 8 BUFFLEN: EQU 0 BUFFDST: EQU 2 BUFFFPOS: EQU 5 ... BUFF1VC: DEFS BUFFVSZ BUFF2VC: DEFS BUFFVSZ CURBUF: WORD 0 ...stores addr of last read buffer allocated XFBUF: WORD 0 ...i 9]A,(b/])(/](b 9]),Ao] !o] 9]A,((9]HL,(b/])o] /](b9]),A/](b 9]),HL o] >Y2-](>X2-]*+]ͥd "+] _o] !fo] /](7^D^/])(o] 9]JP (7^/])o]6 9]LD (7^D^9]) not zero then begin SCRVECP->R.DE; ^POSOFF->R.HL; LD BC,5; LDIR end if BIT 1,FLAG not zero then begin KEYVECP->R.DE; ^CRSLT->R.HL; LD BC,9; LDIR end SET 7,FLAG end EC4: RET /ECONFIG() /IF BIT 7,FLAG not zero THEN *IMAGE EE.COM͔: :ͳ.!ws+p+q+p+q:w=2wN *s*u w*s#"s*u#"u' !"*M^7 !x6:!xھ **DM͆ 2yʭ :yʗ ͯ *"*6:2x÷ *"!x4d !"/ !j}=2| !"*KM^'_ !z6:|!z1 *, enter 1B" ?" [00]" B.Getnum()->LEADIN ?"In the following, give code for the function plus set high bit (bit 7)" ?"if it needs a lead-in character:" ?" clear screen: [0C]" B.Getnum()->CLRSCR ?" clear line: [0B]" B.Getnum()->CLRLIN ?" f<>0, pts. to buffer to be xferred by XFDTA0 FILPOS: WORD 0 ...current file pos. FILPOSH: BYTE 0 ...high byte of above ENDFPOS: WORD 0 ...stores end fpos for read req. ENDFPOSH: BYTE 0 ...high byte of above LU0: BYTE 0 CMD0: BYTE 0 XFADR0: WORD 0 XFAD ORG 03000 /LOAD E.COM SCRVECP: WORD at 0206 ...points to screen vector KEYVECP: WORD at 0208 ...points to key vector FLAG: BYTE 0 POSOFF: BYTE 0 LEADIN: BYTE 0 CLRSCR: BYTE 0 CLRLIN: BYTE 0 POSCRS: BYTE 0 CRSLT: BYTE 0 CRSRT: BYTE 0 CRSUP: BYTE 0 CR 100 1DFF /ENDIF //  *IMAGE EE.COM 100 1DFF /ENDIF // C4: RET /ECONFIG() /IF BIT 7,FLAG not zero THEN ...*?"For now,R.DE; ^CRSLT->R.HL; LD BC,9; LDIR end SET 7,FLAG end EC4: RET /ECONFIG() /IF BIT 7,FLAG not zero THEN *IMAGE EE.COM "}*}DM͆ ' ͯ *"!z4 :e !"͆ !z6:|!z '? 2*H#"H!{6:{ր!Ң *{& :{4 2!{4m *":ڹ ͯ !z4I '2!"!q: !4>!S :S! :2*M position cursor: [17]" B.Getnum()->POSCRS ?" enter offset for X & Y positioning characters plus set high bit" ?" if order is to be XY (column first, then row) rather than YX" ?" (row first, then column):" ?" Example: 'A0' means if the 2(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)SDN: BYTE 0 CRSHM: BYTE 0 CRSBTL: BYTE 0 CRSTAB: BYTE 0 CRSBTB: BYTE 0 RUBOUT: BYTE 0 CONBUF: BYTE 0[20] Echo: ...echo char. & keep track of col. in R.C if R.A=9 then begin repeat Put1(' '); INC C until R.C&7 zero; RET end if R.A=0D then begin LD C,0;   DOWN: PROC ...enter with HL pointing to DEFT FILENAME ...send the file down serial link (8-bit bytes) to other computer R.HL->FILNAM; 00->HEXSW; INIT(); @HL=0; RET Z ...if len. filename=0 OPEN(1;FILNAM); if not zero then begin IFILERR(); RET end ! ^#V͎ * :w*#" = = = = = ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q   chars. sent are '20' then '21', the" ?" column will be set to 0 & the row will be set to 1" ?" [A0]" B.Getnum()->POSOFF EC2: ? ?"Do you want to change any key functions? (enter Y or N)" Put1(' '); Put1(' '); Put1(' '); Put1(' ');  COPYRIGHT (C) 1979, DIGITAL RESEARCH, PIP VERS 1.5$$$ SUB =.:,<> _[]INPIRDPTRUR1UR2RDROUTLPTUL1PRNLSTPTPUP1UP2PUNTTYCRTUC1CONNULEOFDISK READ ERROR$DISK WRITE ERROR$VERIFY ERROR$NOT A CHARACTER SINK$READER STOPPING $NOT A CHARACTER SOURCE$Put1(R.A); 0A end else begin DEC C if R.A<>8 then begin INC C; INC C; if R.A<' ' or R.A=07F then '#' end end Put1(); RET GetN: PROC ... gets to CR, echoing, backspacing, storing @DE (saves DE) ...limits to 10 chars. in buffer R.DE->R.HL; LD C, XMIT(ESC) if HEXSW=0 then DC2 else DC4 XMIT(R.A) ...tell other side sending down file SNDFNM(FILNAM) WAITACK() if not zero then begin OFILERR(); RET end ...if open error other side SNDDTA() ...send down file data PUSH AF WAITACK() ...waits for :2!q: " *M n :c4 *M n :2!c:Q !c:2: !:cw>!n !5 Y : { !6!q:!lwҙ  â :0O !q:O| :O| !6:]2l:o'2o:n'2n:m'2m*mMͣ *nMͣ *oMͣ :]Get1(); Put1(); ? if R.A&0DF<>'Y' then JP EC3 SET 1,FLAG KEYVECP->R.HL; LD DE,CRSLT; LD BC,9; LDIR ?"The following cursor movement keys (as well as the DELete key used" ?"in INSERT or REPLACE modes) may be changed:" ?" '4' (cursor left)" ?" ABORTED$BAD PARAMETER$INVALID USER NUMBER$RECORD TOO LONG$INVALID DIGIT$END OF FILE, CTL-Z?$CHECKSUM ERROR$CORRECT ERROR, TYPE RETURN OR CTL-Z$INVALID FORMAT$HEX$$$$NO DIRECTORY SPACE$NO FILE$COM$START NOT FOUND$QUIT NOT FOUND$CANNOT CLOSE DESTINATION FILE0 ...C=col. repeat B.Get1() ...get byte if R.A=8 then begin ...if backspace INC C; DEC C; JR Z,GetN PUSH DE; LD C,0 repeat LD B,C if @DE=9 then begin repeat INC C until R.C&7 zero; DEC C end INC DE; INC C until R.HL=R.DE; ...get R...Z80 operating system interface to Z8000 (MCZ-2) /DO BUCKA.EQU /DO SYS.EQU TOPMEM: EQU MSIZE-01C00 ...top of available memory ROM0: DEFL 0100 RAM0: DEFL 01000 BLKSZ: EQU 0400 BUFBEG: EQU 01400 BUFEND: EQU BUFBEG+((TOPMEM-BUFBEG)&-BLKSZ) ...0C400 ..:   *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z! '6' (cursor right)" ?" '8' (cursor up)" ?" '2' (cursor down)" ?" '7' (cursor to top left corner)" ?" '1' (cursor to bottom left corner)" ?" tab (cursor tab)" ?" '_' (cursor back-tab)" ? ?"In the following, enter the ascii value i$DESTINATION IS R/O, DELETE (Y/N)?$**NOT DELETED**$$$$$$$NOT FOUND$COPYING -$REQUIRES CP/M 2.0 OR NEWER FOR OPERATION.$UNRECOGNIZED DESTINATION$CANNOT WRITE$INVALID PIP FORMAT$CANNOT READ$INVALID SEPARATOR$1 :2L> ̈́M9 .B=col. of prev. char. repeat Echo(8); Echo(' '); Echo(8) until R.C=R.B; DEC HL POP DE; 8->R.A end else begin R.A->@HL; PUSH AF Echo(R.A) if R.L-R.E<10 then INC HL ...$$$ POP AF end until R.A=0D; RET GETCON: ...put out prompt R..BUFEND-BUFBEG must be mult. of BLKSZ DELXFFLG: EQU 0 ...0 if to not delay xfer to Z8000, 1 if to delay RDBLKSZ: EQU BLKSZ ...size of read buffer; must be mult. of BLKSZ ROM: DEFL ROM0 RAM: DEFL RAM0 ORG ROM Start: PROC JP Start2 ORG Start+0100 St/H:_2:!q:A/>Z!/H8: 2::=O>m:W!Q} Hmd>9>!6:2*M!E ^#V͎ڗO **~2*#"m2m͖ 2m!6m!6m!6 m2mn hex of the key you want" ?"to change to or 0 if no change is desired; end with :" ?"(the standard value for each case is shown in square brackets)" ? ?"(Avoid changing to keys that have other functions; also note that" ?"with cursor movement221@:2!o6+6+6!6#6!6#6:G*o .!N6:^*M^!K6!6!6+6' :$::=2K  :ʤ\:ҷ\x'Ͳ:!\͢  :͈'! A; get line of input & pt. DE at Put1(R.A); GetN(LD DE,CONBUF); RET Getnum: PROC Put1(' '); Put1(' '); Put1(' '); Put1(' ') GETCON('>') DEL() if Hexd() not then begin ?" Enter number in hex"; JR Getnum end DEC DE; HNum(); R.L->R.A RET Getnum2: ackStart: Start2: LD SP,StackStart MAIN() JP SYSRET NLUS: EQU 16 ...for ZDOS.S /DO ZDOS.S /DO GZDOS.S ROM: DEFL $ /DO G.S ROM: DEFL $ ENDROM: DEFL ROM ENDRAM: DEFL RAM ORG ENDRAM /MAP 8 /LD BC,RAM0; LD DE,BUFBEG; if ^ENDROM>R.BC or ^ENDRAM>R.DE thenͯ m!62m!62m!62m!62m'2:2:TҒ:2!6*ME:2::Ҳ:<22ý: 2:} >ͯ :i:2:d*M:[  keys, small letters (or any ascii values>=060)" ?"are equivalent to capital)" ?" '4' (cursor left) [34] ->" if B.Getnum2()<>0 then R.A->CRSLT ?" '6' (cursor right) [36] ->" if B.Getnum2()<>0 then R.A->CRSRT ?" '8' (cursor up) [38] ->" i:$: $͈Ͳ!N6' :!Cwͯ !6:^͢c!6{:/>!/H{ͯ :<2Š ::=HҮͯ !6:Ҿ:2 !6::/H͈;!6:> !/>PROC if B.Getnum()&07F>=060 then RES 5,A RET ECONFIG: PROC ?"Program to configure E editor for different terminals." ?"Both screen function codes and keys for cursor movement (+delete key)" ?"may be changed." ? ?"Do you want to chang ?"OVERFLOW" /?"Type in:" /?"/IMAGE G.COM ",^ROM0," ",^ENDROM  ",^ENDROM LD DE,BUFBEG; if ^ENDROM>R.BC or ^ENDRAM>R.DE thenOM: DEFL $ ENDROM: DEFL ROM ENDRAM: DEFL RAM ORG ENDRAM /MAP 8 /LD BC,RAM0; LD DE,BUFBEG; if ^ENDROM>R.BC or ^ENDRAM>R.DE then *M:>!(:=2%> >>!F!5+N! ~2!4<2T>>!b}*bMͭz:b2!b6:<2é>!`ҥ*`MͭҞ!`6!6> :é:(!q:!wO! ~2*& :w>!:!4!6>:N<2N!j6?\:'C:'ƀo&")!)6!"):)/)HҘ]!)6> !)ڎ*)&*)*)&*) y!)6 Ä:) 2):)<2)M*)#")/:)ҩ*)+")`*")#"]!*)!/H!")!"]*)) *)s#r!what object code should be generated for that language. XMETA converts this sequence of rules into a compiler. SYNTAX Briefly, a rule is an identifier (the NAME of the rule) followed by the characters ':=' followed by one or more ALTERNATIVES to be t Disk AssignmentWrong CP/M Version (Requires 2.0)!9"2!T OË!]6:\:] Hr3 Ë:\ʀË͇ /ҋͺ *2!"q*"&L ͐ ͐ ͐!$p+q*#~*#N͐*##"#÷!&p+q͠*%DMͱ O O!(q*(&2*">!b!ͯ >!`0ͯ !q:E:24J!46*}a!44EJ *KM^'́:‚ͯ !36'n::0:f9OY#9.3'ͳ.:020' 'ͳ'7 6'> *N& N2 !p+q!6!6+6 !6: S: M!6g8:N2M*M8p!6!6!6>!ڕ*&P 6!4z!6!6#6#6!6*M8:ھ:*͇g2ê::¿::,͡A<2O>)6> !).*)&*)*)&*) w:)<2)*)) >w#6*)) w#6*)!) w#6*)%) w#6*)) N#F*)) q#p*)%) *) ~e *) * ~o&͞ *)%) q#p!)6* >!)6!)6>!)=:)!)w=*)&*)~2):ested for, each separated by the characters ':=' or '/', and terminated by a ";". The "alternatives" are denoted by a sequence of one or more ITEMS to be tested for. An "item" can be the name of another rule within carets (i.e. ) a LITERAL surroundeL!*p+q*)O2'!,p+q*+O2'O2'O!.p+q*-LRRLR\LR" O!/q*/& L!1p+q*0#L~*##N!ͽ͞"T!Vq*VMͳ!Xp+q!W* >Wr#MͲ!_!j>A+!s!"@͓1!"<**"͓n "Dn"":!Q2҂:X!Wғä:ڤ*MEÓ:ұ@@:O2Mc;!6#6>!)*&P ~"::H:H*M8):[ͱ!N5!6ñ:5!6#6>!ڰ!6:<2O>/:!O!T *M͡H~K:¡!6[–ͱ!N5:2:2!4=:[¼ͱ4:!6:.2O8: :* ͇g)*)& *):)2):):*)!) *)) s, >X\:)“>!d!")>!)d!")!")*++!)a*)) ^#V")]*)")*)) ^#V")]!)6> !)T*)&*)~2)*)&*)~2)O;*)) ^#V"d by quotes to be tested (i.e. "DEF"), the characters '?' or '$' followed by an item (which means the item is either optional or that there can be any number of the item, respectively), or one or more "alternatives" each separated by the character '/' all p+q!`6>!`6*`&*^*`&Y />!`4 >*]& ~ O!]49!a6:a*]& ~2bO>z*bM >!b/~,H~:H~*H~.H~>H~<H~=H*]& 6!]4T!]4!cq*a&Y :cw!a4:H:H"!6!4:_jYO jM*"S*" 3@bl*M1͓!""7 *M^͆ \͔!":͎H*#"ͧÝ/ :>͛9ͯ .*#":_!:[ ͱ!N5!6:%:<2*6 * 6å!q!6> !d*&I :]>!4A>:<2O* :w:?†!6!q!6?!:ҠgÐ!q*&*~!6:22: :]Hں:A2O>: 2ͯ )*)) *)) N#Fq#p*)) *)s#r*)#")!)6 J:)!)J!)6 :)<2)*)")҈q:tw͠ͱ!"))ҍ*)) ^#V")]͠.*)DM\ -°!\6:\ͣ:ͱ*}DM'ͫ*)%) N#F'ͫ*)within parentheses. In addition, names of procedures or rules to call without testing or code for immediate execution can be included. (Rules are actually procedures which return the Z-flag set if true.) Examples: PARAMLIST := $("," ); !gr+s+p+q!h6>fr*d*f!is*d́"dPY! "f>!h#~Haͫo!h6:i0O͐!mr+s+p+q*lTZs#r*lڶ*l+s#r*jN#F+q#pÌ!nq!"o"q}2uo&"s* s:n*sDM2u:uqos' !'6!36' :1/!aE*#">z?C9IͲÁ.!6> !ڇ*&' ~2 ʀ: y.*M!4Q>!қ:=2á:2:Ҭ\>!ҿ:=2K:2K!:!:K\: \!p+q͈*÷:S:QHI:N<22: H@"2Í202O> c!6Í202O> ڍ*&O*& !sc*&P :w:·>!ұͯ :22:_!6=!6>'!E!4!p+q*0 !!) N#F'k͐ͫ*)) N#FͫR͐/͐ *) ~IO͐NW͐ͫ8AO͐:͐ *) ~2)t(͐:)҃)͐*)#")Ã& \!"))\Ұ*)")]͠*)M! ^#V *) >*) w *) >*) w *) >*) can be read as "a PARAMLIST is a PARAM followed by zero or more commas each followed by one PARAM". GROUP := "do" $((";"/",") ) "end" := ; can be read loosely as "a GROUP is the word `do' followed by an arbi- trary sequence*s"s*o͊O !v6>!vQ*v&w 6`i+46)A*:'ʓ:'O!) ~2vʍ:vO!w 6,]!v6>!v*v&w ~һ*vM !v4˜8AO͐:͐ͱ*##N!ͽ"* N#F*͠"DM!  ::=H-\:N2O_og_{ozg^#V))) _{ozg^#V) d^#V|g}o n_{ozgO{ozgi`N#Fogo&og H ©=¨r+s+p+q*~$7*>*>H&>*#"*#"> 2:R͎:!6!6=2:ʙ!6:“H9Ž>!6-e!6ͻ2=2ʺ-é:>>"ͻ2:!!5ͻ2ͬ!\  w *) >*) w.*)DM\ -+!\6uͱ:)O! DMͱ*)#")Ù*))))))"):m w>.Yn -:YS:Z Hҧ!6> 2)½>!)6> !)*)&*)>2) :) .͐*)M͐:)<2) of STMT's separated by a semicolon or comma, followed by `end'. Alternatively, a GROUP is a single STMT." Note: once a test is made and found true, any following test in the sequence must also be true or it is an error, i.e. if "do" is found above, !H% - *DM ͱͷDM  ͱ* N#F 9ͱ * ^#V))DM Tͱ* ~ *} *M9A.O:v8 ʝ0P,y6+,t0 410 <29̝ ó0͝ *1:9 141 ;,$1< 1>$141$1$1 w+0:941ͤ6++xt"9&i"9Z1N/>Ä0P/*9>29/,ʞ1 |-;q-'ʎ1"ʎ1-:>>!p+q:,!6*DM9:<!6:z 2W!6D*&L :w:<2Ov*:>=20O> ڒ:0:AO>Ҥ::A }}Hͬ!wͻO`idͻV[2O>2:!X!6:!99:Y=/9&ͩ c,Hͩ 9 EHͺ i`N#Fog_og_ogDM!>))덑o|gҘ =†DM!>))ҭ =¥~ ³^#V) ½^#V|g}o _{ozgi`N#Fogo&og_{_z#WT> (and also "end") must follow. POSNUM := ?"+" ; indicates that "a POSNUM is a NUM with an optional plus sign in front". A number of rules are pre-defined for the convenience of the compiler-writer, e.g.: Digit := "0"/"1"/2"/..../"9"; Id := CA!+s#r#4 !s+p+q!6!66:!ڄ !6!6>!r *&**&Y i !6!4+4A :} :!4- >!699 2¨ :!4: :2!6+6>! :O!9 DMi ͱ:!O!Y DMi :2-t1G[, |-ʈ1Ï1"94>5!*9*9*9!!1/>29"96 1:91x1*9##~#1+ð/5!275-̈́5. 2*9/ bk1{ tOD C2D42> D> D:v8 { t29O͝ q2 b2z2N/P/!7:9O~ʒ:=O!L NE!4 E E:/.*&L 6$L9k9.Xͯ *KM^020 :020:121'ͳ':²ͯ !G6!"!"7 *M^n/ :a/:H!6:ͯ !&6M!>))덑o|gҘ =†DM!>))ҭ =¥~ ³^#V) ½^#V|g}o _{ozgi`N#Fogo&og_{_z#WPITALLETTER $(ANYLETTER/Digit/"_"); Hexd := Digit/"A"/..../"F"; As an example of just calling a procedure without testing (to advance R7, which is used as the pointer to the source text, for example) is: COMM := "..." NOTCR; where NOTCR is a routine t:2͠!4 F :® )!6>!ګ ͠:O!9 DMi 8ͱ!6> !ڤ Å :2k ä  ͐:!O!Y DMi w !4C F :¿ >F : F :=229:Y= ;>9*&Y DM2 #Æ2!ɷ} ­2##^#V64#"9~(wͰ+"9A. ,ʽ2w+295*9*9#s#r*9P,!7< Ͱ+6+6"9+d. { ʎ3;ʎ3,Ĥ3 Copyright (c) 1979, Digital Research????????????CON:RDR:PUN:LST:DEV:VAL:USR:DSK:TTY:CRT:BAT:UC1:TTY:PTR:UR1:UR2:TTY:PTP:UP1:UP2:TTY:CRT:LPT:UL1:R/OR/WSYSDIRR/O R/W SYS DIR ** Aborted **Active User :Active Files: Drive Characteristics6r+s+p+q*~$7*>*>H&>*#"*#"> 2:R͎:!6!6=2:ʙ!6:“H9Ž>!6-e!6ͻ2=2ʺ-é:>>"ͻ2:!!5ͻ2ͬ!\o advance R7 to a carriage return. Alternatively, the routine could be written within a .DO(----) construction (putting within the parentheses instructions separated by ";"s which are to be executed immediately) as: COMM := "..." .DO(repeat B.@R7' until  =2 I>!6:=28 :2:2 :!!29:Y T >:Y,e \>Ì !p+q*~:ʉ *N͐*#"o :͐!p+q!'"!6> **{2*́"PY! ">!+~H !6:0O͐à k͐ XMETA DOCUMENTATION (Y) Currently same as in Y.DOC except with addition of procedure descriptions. Meta-compiler ------------- An extendable meta-compiler (known as XMETA) is included in Y. Using this language, syntactic and semantic modifications or5536: 128 Byte Record CapacityKilobyte Drive Capacity32 Byte Directory EntriesChecked Directory EntriesRecords/ ExtentRecords/ BlockSectors/ TrackReserved Tracks is Temp R/O Disk: d:=R/OSet Indicator: d:filename.typ $R/O $R/W $SYS $DIRDisk S-:>>!p+q:,!6*DM9:<!6:z 2W!6D*&L :w:<2Ov*:>=20O> ڒ:0:AO>Ҥ::A }}Hͬ!wͻO`idͻV[2O>2:!X!6:!RL0=0D; R7:-1==R7); SEMANTICS Constructions to facilitate generation of output code can be inserted at essentially any point in the syntatic description portion of the rule. Two forms are provided: .OUT(output-expression) generates codes as dire͠Q" 8AO͐jͱͷDM͏ m  Z"l"!6>ʥ *}҆ *M ͱ*}x O͐} W͐ͱ !+s#r!+s#r#4D ͠:\ʹ :\=Oͳͩ !6!)6l :) :)=2) :] & !"}2\!h6?! extensions to the base language can be developed by the programmer and used in the same source language module. The language consists of a sequence of rules which hierarchically describes the syntax of some target language, together with instructions on tatus : DSK: d:DSK:User Status : USR:Iobyte Assign: =Bad DelimiterInvalid AssignmentBad Delimiter: Bytes Remaining On R/, Space: Invalid File Indicator** Too Many Files **File Not Found Size Recs Bytes Ext Acc65536 set to R/O Invalid:=O!L NE!4 E E:/.*&L 6$L9k9.Xͯ *KM^020 :020:121'ͳ':²ͯ !G6!"!"7 *M^n/ :a/:H!6:ͯ !&6 cted by the result of a sequence of output expressions, and .SAV(output-expression) pushes the results of the output expressions onto an internal stack. Example: FLAG := ("Z" .SAV("60") / "C" .SAV("07")) .OUT("HAE"Re); Output-expressions: There ara carriage return. To allow for further extensions, the following construction can be made. (A symbol enclosed in square brackets is called only if it is defined.): EXTEND := [EXT2] / THIS_EXTEND ; To allow for another extension starting with EXTEND, fo R7 to be pointing to source.) Quit: Closes all open input or output files. To just close the output (list) file, call Quit+2. ile, call Quit+2. input or output files. To just close the output (list) file, call Quit+2. to be pointing to source.) representation of the code, e.g. .OUT("H9E08") generates code for the Z8000 RET instruction. 2. An initial ' (single quote) causes the following characters to be moved directly to the code area. Thus, .OUT("'ABC") is equivalent to .OUT("H414243").. Del: Goes past any spaces and tabs, updating R7. Returns Z=1 if at least one space or tab. Preserves registers except R7 and RL0. Getcon: When called, RL0 should contain desired prompt character. This will be put out; then, one line of input will e several primitives for use in generating data into the output area. (Note: The "output area" is actually defined as a buffer where the data is further processed, usually resulting in code put out to the "code area".) 1. "---" will generate code to apllow this by: /ZAP EXTEND EXT2 := [EXTEND]; /ZAP EXT2 An additional command is also furnished in Y to allow the user to see on the console the data that is sent to the output area, for use in debugging. This command is /DIAG entered (at the beginnin Quit: Closes all open input or output files. To just close the output (list) file, call Quit+2. d for, each separated by the characters ':=' or '/', and terminated by a ";". The "alternatives" are denoted by a sequence of one or more ITEMS to be teste 3. An initial L causes the following characters to be entered into the symbol table with the current location counter address as the symbol value, e.g. .OUT("LABC") In addition, prior unresolved references to the symbol are resolved. 4. An be accepted from the console and stored in an internal buffer. Returns with starting address of the input buffer stored in R7 and LASTCR. Output and Output Assembly: Outset: Stores R7 in NEXTDE and sets R7 to the first byte of an internal buffer. pend the characters within the quotes (at least one) to the current output. For example: INST:="RET".OUT("HC9"); 2. * will generate code to append the characters last detected by the prev- ious syntatic test to the output area. For example: g of a line) before starting compilation. (DIAG is turned off by /LIST or /LISTEND.) Note: All extensions should go in the same segment with Y. ******* Additional primitive for use in generating data into output area: Cnt: outputs a count byte equalFULL SCREEN EDITOR Note: The Z80 version of the editor is named "E"; the Z8000 version "EE". Call by typing E FILENAME (or E FILENAME,CMDFILENAME if want to edit from a command file--see below for a description of this case). If the file does not previoinitial D (for define), followed by a word in hex, causes the following characters to be entered into the symbol table with a value equal to the hex word, e.g. .OUT("D1234XXX") defines XXX to have the value 01234. In addition, prior unresolve Other registers unchanged. Copy: Copies a literal into an area pointed to by R7. R7 updated past copied literal. Other registers (except flag) unchanged. Calling seq: CALL Copy; DEFT 'STRING' (+0 byte if on odd boundary) Copyin: Copies data into aNAME:= .SAV(*); Here, * will copy the characters detected by the Id routine (if successful) to the output area, from where they will saved on the internal stack. 3. #1 will generate code to produce a unique temporary symbol (which is use-  to the number of characters last detected by a syntax routine. Additional first characters and interpretations of data in output area by .OUT routine: An initial O causes the following hex characters, taken in pairs, to be or'ed together and the usly exist, it will be created (when written out). To exit the editor, type either "QU" to write out the file, or "QU N" if it is desired not to write out the file. (This also avoids creating the file if the name was misspelled, for instance.) Commands:d references to the symbol are resolved. 5. An initial = (equal sign) causes the following characters to be pushed onto the SAVE stack and a call executed to the parser, pointing to the first character saved. (Note: for sucsessful parsing, the n output area pointed to by R7, updating R7. The data is addressed by the pointers LASTDE which contains the address of the first byte to be copied, and NEXTDE which addresses the byte after the last one to be copied. Outhex: Converts RL0. to the equi ful for implementing local jumps). The same symbol is generated at each use within a given rule at a given time, but outside that rule different symbols will be generated. For example, a Fortran-like implementation of logical IF statementsresulting byte put out to the code area, i.e. .OUT("O8817") is equivalent to .OUT("H9F"). An initial A1 causes the next characters to be interpreted as a symbol for which an 8-bit relative reference is made. A3,R Routines in Y Available to the User: ( Command mode is the normal mode. The commands are: Single character cursor commands: 6 or sp ..... move cursor right (with wrap-around) 4 or bksp ... move cursor left (with wrap-around) 2 or LF ..... move cursor down if at bottom row causes scrocharacters must form valid defined instructions separated by ";"s.) Thus, .OUT("=RET") will generate the code for RET. 6. An initial A2 causes the following characters to be interpreted as a 16-bit quantity determined by that symbol's value invalent two characters hexadecimal ascii representation, storing the two characters at R7 and R7+1. R7+2->R7. Other registers (except flag) unchanged. HLout: Puts out R3 in hex @R7. R7+4->R7. Other registers unchanged. Outp: Will output the characte could be: IFST := "IF(" ")" .OUT("=JR NZ," #1) .LABEL(#1) Zp; STMT := := ...etc. The above will permit nested IF statements. (Note that the procedure `Zp' should be called immediately after th needs correcting for Y) (Mainly for use in extensions.) Input and Input Checking: Test: Checks whether a sequence of bytes pointed to by R7 matches a literal (in DEFT form at the return address). If all bytes match: Z flag =1; R7 incremented past bytelling 8 or - ...... move cursor up if at top row causes "scrolling" down (may actually be screen reprinted from one line back) CR or ctl-R . move cursor to beginning of next row (scroll if at bottom) 7 ........... move cursor home (actually to be the symbol table. If the symbol is undefined, an in-place chain is established or extended for future resolution. 7. An initial C is interpreted as either a CALL or CALR to the following symbol, depending on the relative address of the syrs in the internal buffer up to R7 (adding a carriage return) to list file if open, otherwise to the console. ("Up to R7" means not including R7.) NEXTDE->R7, Z flag=1. Outmsg: If a list file is open, will put out characters in the internal buffer ue last reference to the temporary symbol in order to remove it from the symbol table.) 4. Re will generate code to concatenate the string of characters at the top of the internal stack to the current output and erase them from the stack. 5.  sequence; original R7->LASTDE If no match: Z=0; R7 restored Preserves registers>R3. Calling seq: CALL Test; DEFT 'STRING' (+0 byte if on odd boundary) Id: Checks whether a sequence of bytes pointed to by R7 consists of an upper case letter foginning of 1st printed row) 1 ........... move cursor to bottom left corner of screen tab ......... move cursor right to next tab position _ (underline) . move cursor left to next tab position Single character mode changing commands: R ...........mbol, e.g. .OUT("CCOPY") 8. An initial J is interpreted as either a JP or JR to a symbol. Immediately following the "J" is a condition code in hex followed by the symbol name, e.g. .OUT("J08SYM1") If the symbol is undefined, an in-place cp to R7 (adding a CR) to both the file and the console, otherwise just to the console. (Note: calling Outmsg+6 skips adding the CR.) Putcon: Outputs characters in the internal buffer up to R7 just to the con- sole (without adding a CR). MiscellaneoXc causes the top two strings in the stack to be exchanged. 6. Pp causes the string at the top of the stack to be concatenated to the output but left on the stack. 7. Ig causes the string at the top of the stack to be popped off without bellowed by a sequence of upper or lower case letters or digits. Z=1 iff match; original R7->LASTDE; R7 updated to next non-matching character. Digit: Tests whether R7 points to an ASCII digit. R.BC, R.HL unchanged. If match: Z=1, @R7->RL0; R7->LASTDE enter Replace mode (see below) I ........... enter Insert mode (see below) E ........... enter Enter mode (see below) Commands which must be followed by a carriage return: As they are typed in, these commands appear on the command line at the top ohain is established or extended for future resolution. 9. An initial W causes the following hex characters, taken in groups of 4, to be orred together and the resulting word put out to the code area, i.e. .OUT("W11112222") is equivalent to .OUTus: Lkup: Looks up symbol pointed to by R3 at the beginning and R7 at the end in Y's symbol table. If not found, it is added in. Returns R13 pointing to the entry in the symbol table. Z=1 if found, Carry=1 if referenced but not defined. (R7 preserving put anywhere. Additionally, if characters constituting any other identifier (Id) are found within an output-expression, code will be generated to call a user-provided routine of that name. A comma within an output-expression is equivalent to having; R7+1->R7 No match: Z=0, R7 unchanged. Other registers unaffected. Hexd: Tests whether R7 points to one digit or one of the upper case letters A through F. Input and output same as for digit. Num: Converts a sequence of decimal digits pointed to bf the screen. (Backspace may be used to back up.) Multiple commands may be typed separated by ";"s. The commands on the command line all execute at once (left to right) upon reception of the carriage return. After execution, the commands stay on the co("H3333"). Using XMETA: Two global undefined symbols are provided to establish linkage to the user's newly defined compiler extension. One symbol is called EXTEND. For example: EXTEND := "stay_here" .OUT("HE8FF"); will cause the compiler to gened.) Lkupnl: Same as Lkup but does not add symbol to table if not found. ...Name: Enter with an address in R3 (call $); returns R13=pointer to symbol ... table entry with symbol of greatest value <=$ (value=VAL); R1=$-VAL. ... Preserves R7; Z=1 if found. two .OUT's. That is, .OUT("xxx","yyy") is equivalent to .OUT("xxx").OUT("yyy") Output Code Generation: When the result of a series of output-expressions is delivered to the .OUT routine, it then is further processed (according to a rule which dey R7 to their binary equivalent, storing that in R3, and updating R7. Input RL0 contains assumed high order digit. Normal usage is: CALL Digit JR NZ,NOTDIG CALL Num ... SET R3 to value R3->NVAL ... save it NOTDIG: or: if Digimmand line and may be executed again by doing the "X" command (see below). T ........... top: print 1st page of file B ........... bottom: print last page of file N n ......... next: go forward n pages in file and print screen if not given, n defaerate the word 0E8FF whenever the string "stay_here" is encountered in places where an instruction could be, e.g. if RL0=0CA then begin ?"ERROR ",RL0; stay_here end The other symbol is USERCC which allows the user to redefine an entire line ending with  Err: Calls Y's error routine (R7 should point to the error in the source code) and then restarts starting at the next line. Errm: Same as Err except first prints out an error message which follows the call in DEFT form. (Also, it is not necessary forpends on the first character in the output area) and produces appropriate code. Some of the possible first characters and their interpretation follows: 1. An initial H causes the next characters, two at a time, to be interpreted as the hexadecimal t() then Num()->NVAL HNum: Converts a series of hex digits pointed to by R7 to their binary equivalent, storing that in R3, and updating R7. On entering, R7 is assumed to be pointing to first hex digit; if there are none, a value of 0 will be returned ...ZSYS ...last change 8/25/82 PSA_SC: WORD at PSA+01C ...addr of SC handler in PSA PSA_SCF: WORD at PSA+01A ...FCW for above PSANMI: WORD at PSA+02C ...addr of NMI handler in PSA PSANMIF: WORD at PSA+02A ...FCW for above PSABRK: WORD at PSA+0C ...ad.DE in buffer & R.C at corresponding pos. in row ...returns R.DE at 1st char. in next row; R.C=0 ...if row ends with CR, its col.->R.B ENRLUP: repeat @DE; INC DE R.A=0; JR Z,ENRLUP ...if at null char. if R.A=CR then begin LD B,C; JR ENDRX end ......... takes off 2nd tag only DE n ........ delete n lines starting at current line; if n not given, it defaults to 1 (tags must not be present) DET ......... if tags present, delete lines between tags; if only one tag, delete that line; else deSTRING .... locate: starting at the next character (if at EOF start at top), search for STRING cursor moves to beginning of STRING (or to EOF if not found) if off screen, screen printed so in middle (Note: do "L/STRING/" if more commands follow on r begin INC B; B.ROWNO-R.B end R.B; B.CRSROW-R.B->B.CRSROW; RET ...adjust cursor row end until begin R.A->B.ROWNO; PUSH AF; P.LINBEG; POP AF end zero ...go back tdr brk handler in PSA PSABRKF: WORD at PSA+0A PSAPRV: WORD at PSA+014 ...addr priv. inst. handler in PSA PSAPRVF: WORD at PSA+012 PSASeg: EQU PSASEG*0100|08000 FRSTSeg: EQU FRSTSEG*0100|08000 SCRSeg: EQU SCRSEG*0100|08000 BUCKL: EQU 256 ...1024 BLKSZ: EQ...if at CR (col.->R.B) R.A=TAB; CALL Z,TABPOS ...if at tab INC C until LCOLR.DE W.ENDDAT-carry-R.BC->W.ENDDAT R.HL-carry-R.DE+1->R.BC; U 0400 BLKSZPWR: EQU 10 ...2**BLKSZPWR=BLKSZ CTLS: EQU 013 CTLD: EQU 4 ...file open types: 0=input, 1=output (create) ...following used by SETMSZ (for M_MGR): MBUFSEG: EQU 3 ...default segment for buffer pool MBUFSeg: EQU MBUFSEG*0100|08000 MBUFF: ADDR rsor pos.; R.C=its col. no. LD B,C; LD C,0 ...R.B saves cursor col. FCLUP: R.B=R.C; RET Z ...go thru row until R.C=cursor col. @DE=CR; RET Z ...if at CR R.A=EOF; RET Z ...if at EOF if R.A=TAB then begin ...if at tab LD L,C; P.TABPOS; LD A,C; LDeleting, to the file (writes over or creates new file); tag(s) are kept in place MO .......... move text between or at tag(s) to right above current line; delete from original location, removing tags MO filename . move text between or at tag(s) to  n='*', then do all lines (the lines with changes will be printed out; continue same as with "W" below) if n not given, only do current line m: if m='*', change all occurences of STR1 on each line done; if m other than '*' or not given, only make 1POP HL LDIR; RET ...shift file back SHFTFD: ...shift file starting at R.DE forward R.BC places; update ENDDAT ...return R.HL at 1st opened-up spot R.B|R.C; RET Z ...if BC=0 W.ENDDAT; PUSH HL; PUSH BC; R.HL-carry-R.DE+1->R.BC POP HL; POP DE; R.HL+R.MBUFSEG.0 ...default beg. buffer MBUFSZ: EQU 0FE00 ...must be multiple of 16 ...& have room for 2 words after ...1st byte of bucket codes: ...FF=busy, 0=free, else have msg.: ...for Z8000: STARTCD: EQU 1 RDCODE: EQU 2 ...followed by adr (seg,adrH,adrL) C,L ...1 before next tab pos->R.A R.A=R.B; RET NC ...if cursor within tab area, R.C=col. of tab char. LD C,A ...R.C=1 before next tab pos. end INC DE; INC C JR FCLUP CHRPOS: ...enter with R.DE in buffer; ret. col. of char. at BUFPOS->R.C ...the file, deleting text and removing the tags (writes over or creates new file) GE filename . get the file and insert above current line G1 .......... go to position of current or last tag 1 (if off screen, screen printed so in middle) G2 ....... change per line (last delimiter only needed if n present or more commands follow on command line) J ........... join current line to line following (making one line) W ........... stop execution of command line, waiting until a keystroke to contDE->W.ENDDAT; EX DE,HL ...ENDDAT+n->ENDDAT->DE LDDR; INC HL; RET ...shift SHFIFR: ...do SHFTFD except if no room do P.NOROOM PUSH DE; LD DE,(ENDDAT); INC DE if begin W.ENDBUF-R.DE-carry-R.BC; POP DE end carry then begin P.NOROOM; OR 1; RET ...pri, len of data following, data WRCODE: EQU 3 ...ditto DUNCD: EQU 4 RD2CD: EQU 5 WR2CD: EQU 6 ...followed by data BRKCD: EQU 7 ...TIMECD: EQU 8 CONINCD: EQU 9 ...ETIMCD: EQU 0A WRSCRCD: EQU 0B PERINTCD: EQU 0C ...console write done ...for Z80: QUITCD: EQUno. of rows to BUFPOS (past first)->R.B ...ret. Z=0 if R.B gets bigger than no. rows that fit on scr., else Z=1 P.LINBEG; 00->R.C->R.B ...go to beg. of line; 0->row count CHPLUP: W.BUFPOS-R.DE; RET Z; RET C ...check if to BUFPOS (or if DE>BUFPOS) if @... go to position of current or last tag 2 G3 .......... go to position where tag 3 was last set (note: position of tags may change if file is changed) S ........... print current page showing position of each carriage return with a "~" ST .....inue; if character entered is an escape, return to command mode without finishing command line NA .......... print name of file being edited (continue same as with "W") T1 .......... tag 1: marks current line as start of tagged region (must not alrnt "NO ROOM"; set Z=0 end P.SHFTFD; XOR A; RET ...do SHFTFD; set Z=1 GETSTR: ...enter R.DE in cmd. buffer at delimiter before a string ...R.HL->beginning of where DEFT-like string should go (saved) ...returns Z=1 if string ends with orig. delim. (not 081 IOCODE: EQU 082 RDBKCD: EQU 083 TIMERCD: EQU 084 ...RQTIMCD: EQU 085 CONWRCD: EQU 086 Z80CD: EQU 087 ACKCD: EQU 0C0 ...file table: NLUs: EQU 16 LULEN: EQU 14 ... FLAG: EQU 0 ERRCD: EQU 1 DEVADR: EQU 2 FLEN: EQU 6 FPSREQ: EQU 10 ...RWPTR ...bits of F DE=CR then LD C,LCOL ...if at CR R.A=TAB; CALL Z,TABPOS ...if at tab INC DE; INC C R.C-NCOL; JR C,CHPLUP ...check if goes to next row LD C,A; INC B; LD A,NROW-2; CP B; RET C ...R.B>no. rows/scr. JR CHPLUP FNDCH0: LD DE,(BUFP0) FNDCHR: ...enter wi..... print current page showing position of each tab with a "~" K ........... compare text starting at beginning of line with cursor to text beginning after tag 1 (tag 1 must be set but not tag 2). When a difference is found, the cursor is moved to... Full Screen Editor - Part 2 EDIT: 00->B.DUNFLG ...zero DUNFLG; will be set to 1 when done CLRSCR(); PUT1('T') ...clear screen; print 'T' on cmd. line R.A->@^CMDBUF; INC HL; LD (HL),CR ...'T'->cmd. buff. P.TOP ...print 1st part of file repeat  CR) ...R.DE at final delim. (also ->CBUFPS); R.C contains length @DE->R.B; INC DE ...delim.->R.B LD C,0; PUSH HL ...init. len. count while @DE<>R.B and R.A<>CR do begin ...check for end R.A->@(R.HL+1); INC C; INC DE ...copy string into "DEFT" aLAG: LUOPNB: EQU 7 ISFILB: EQU 0 COMPB: EQU 1 ERRB: EQU 2 RDAFLGB: EQU 3 ...buffer headers: NBUFS: EQU 20 BHLEN: EQU 16 ... FLAG_: EQU 0 CCD: EQU 2 LU_: EQU 3 BLKNO: EQU 4 NBLKS: EQU 6 NBLKSDUN: EQU 8 BUFADR_: EQU 10 XFCNT: EQU 14 ...bits of FLAG_: ALLOCBth DE=next 1st scr. char.; set BUFP0=DE ...if char. at BUFPOS on screen, its row->CRSROW, col.->R.C, BUFPOS->DE ... Z=1; else Z=0 LD (BUFP0),DE; P.CHRPOS; RET NZ R.B+1->B.CRSROW; XOR A; RET FNDCR: ...enter with R.DE at char. in buffer; R.C corres. col that character in the 1st portion of text, and tag 2 is set above the corres- ponding line in the 2nd portion of text. (Also, tag 3 is set at the new cursor position.) X n ......... execute command line n times or until escape is typed if n not B.P.GETCHR->R.A ...get a character from keybd (or cmd file) R.A->R.E B.TAGFLG=0; CALL Z,BLCMR ...if no tags, blank right part cmd. line B.BLCMRF=2; CALL NZ,TAGSHW ...in case tags & tag ind. erased CMD(R.E;^CMDTBC) ...look for cursor move rea end LD (CBUFPS),DE ...advance CBUFPS to after string POP HL; LD (HL),C ...store len. at beg. of "DEFT" (may be 0) R.A=R.B ...set Z flag if ended with orig. delim. instead of CR RET GETNUM: ...enter with R.DE in cmd. buffer; go past spaces till: EQU 15 ...set if buffer belongs to the device; change if >1 device IOINPRGB: EQU 7 DELWRB: EQU 5 ...delayed write GDDTAB: EQU 4 RDB: EQU 0 ...1=read, 0=write RDAB: EQU 1 ASYNCB: EQU 3 ...if writing asynchronously (rel. buffer when done) ...used with. ...find CR ending curr. line: buffer pos.->R.DE; row->CRROW0; col.->R.B B.CRSROW->B.CRROW0 FCRLUP: P.ENDROW; DEC DE; @DE=CR; RET Z INC DE; ^CRROW0; INC (HL); JR FCRLUP NXTLIN: ...enter with R.DE in buffer; go to beg. of next line (->R.DE) EX DE,HL;  given, it defaults to 1; if n="*", no limit (note: this appears off to the right of the other commands on the command line) In addition to the above, most of the single character cursor commands and the three mode enter commands may go on the commanor mode enter cmds. CALL NZ,FILCML ...if not found, start filling cmd. line until B.DUNFLG<>0; RET FNDPOS: ...char. in buffer corresponding to cursor location->R.DE->BUFPOS ...sets ROWNO=CRSROW, R.C=col. of char. LD DE,(BUFP0); LD C,0 ...start co to num. & get it ...Z=1 if no. found; no.->R.HL; else Z=0, HL=1 P.TONOSP; W.1; RET NZ P.DIGIT; RET NZ P.NUMBER; RET ...no.->R.HL; Z=1 SRCH0: ...get string from cmd. line, store in string buffer; Z=0 if fail ...pos. in text buffer to start search foults to 1 P n ......... previous: go back n pages in file and print screen if not given, n defaults to 1 QU .......... quit, writing out the modified file QU N ........ quit, but without writing out the file (leaving it unchanged) F/STRING .... sCR; LD BC,0; CPIR; EX DE,HL; RET TABPOS: ...enter with R.C=col. of tab; return with R.C 1 before next tab pos. R.C|7->R.C; RET FNDPSB: ...do FNDPOS + PRTB P.FNDPOS PRTB: ...set DE=1st char. & ROWNO=1st row of line with char. at BUFPOS LD DE,(BUFPOS); d line as the second or later command (after a ";"), or else they may follow an initial ";" beginning a command line. (The exceptions are CR and backspace, for which "control-R" and "4", respectively, may be used instead.) In the case of mode-enter commal. 0, row 1 1->@^ROWNO while B.CRSROW<>@HL do begin ...check if cursor past current row @DE=EOF; RET Z ...needed by "NEXT" PUSH HL; P.ENDROW ...go to beg. of next row POP HL; INC (HL) end FNDCOL(B.CRSCOL->R.C) ...find char. & col. of chaeady be a tag) T2 .......... tag 2: marks line above current line as last line of tagged region (tag 1 must be present, but not tag 2 yet) Note: if only one tag is present, the tagged region is assumed to consist of only the one line T3 .........tarting on the next line (if at EOF, start at top), go forward until STRING found at the beginning of a line (after CR) print screen from that point (Note: do "F/STRING/" if more commands follow on command line) F n ......... go forward n lines froP.CHRPOS; B.CRSROW-R.B->B.ROWNO; P.LINBEG; RET PKLROW: LROW->R.A ...pick last row PIKROW: ...enter with DE at beg. of line, R.A=desired row for line to start ...adjust the row up if necs. to start scr. with beg. of a line ...note: changes BUFPOS ...sends, command line execution continues after return from the mode; if escape was typed to return, execution of the commnd line is halted. Desciption of Replace, Insert, and Enter modes: Replace: replaces the character at the cursor position with the tr. corres. to cursor col. LD (BUFPOS),DE; RET FNDPS0: ...do FNDPOS + LINBEG P.FNDPOS LINBEG: ...enter with R.DE in buffer; return beginning pos. current line->R.DE EX DE,HL; DEC HL; LD BC,0; LD A,CR; CPDR; R.HL+2; EX DE,HL; RET ENDROW: ...enter with R. tag 3: saves a position in the text without showing anything; meant to be used with the G3 command Note: references to tags in descriptions of other commands here generally refers to just tags 1 and 2 O ........... takes off tags (1 and 2) O2 .m current top line and print screen if n not given, print so current line with cursor is at top if possible, cursor remains with the same line M ........... print screen so current line with cursor is in middle of screen cursor stays with line L/t up for printing screen: ... DE at beg. 1st scr. line; CRSROW=row with orig. line R.A->B.CRSROW-1->B.ROWNO repeat W.EBUF-R.DE; JR Z,ADJROW ...chk if at beg. of file DEC DE; LD (BUFPOS),DE; P.CHRPOS ...no. rows prev. line-1->R.B if not zero o yped char- acter, advancing the cursor. Backspace backs the cursor up one character but doesn't delete it. Del (or rubout) deletes the current character unless it is a CR, shifting back the rest of the line. To exit Replace mode, type CR or escape. Io. of remote cpu's SWCON: EQU 1 ...5 ...inpt file log unit no.>SWCON=>from file; =SWCON=>from $CON NHASH: EQU 32 ...no. hash chains CdLCol: EQU 64 ...min. col. to start code output when listing (mult. of 8) NBRKS: EQU 8 ...max num breaks supported Q: PROft to tab pos. if B.CRSCOL=0 then begin ...check if in col. 0 @^CRSROW-1; RET Z ...ret. if in 1st row DEC (HL); LD A,NCOL end R.A-1&0F8->B.CRSCOL P.RETCRS; RET ...move cursor RSROW-1; RET Z ...ret. if in 1st row DEC (HL); LD A,NCOL end FD; OUT (C),A; OUT (CNTL),A IN A,(CNTL) until R.A<>0FF or R.HL-1=0; ...get bucket JP Z,ABORT ...HL=0 POP HL 00; OUT (C),A ...put in 0 2->R.H while DEC B not do begin PUSH BC; BUKLD(); LD DE,BUCKL-16; POP BC end GOBUK->R.H; BUKLD() RELBUK()maining characters RET CPIX: RET NZ; DEC A; RET ...ret. Z=1 if len.=1 ... cursor move cmds. follow: CRSRT: ...move cursor 1 space to right (with wrap-around) if B.CRSCOL+1=NCOL then begin ...check if at right margin B.LSTROW->R.B @^CRSROW=R.B; nsert: inserts the typed character in front of the character at the cursor position, shifting over the rest of the line and advancing the cursor. Back- space deletes the previous character (except a CR) and moves the cursor back. Del (or rubout) deletes C; JP START JP START0 ...entry point when first loaded (looks in RIO cmd. buffer) JP START1 ...same as START0 but DE pts. in user cmd. buffer QVERS: DEFM 'V2.07' ...Q version no. FPUTBF: ...file output buffer; also used to store file attr. for IMAGE c'~') ...stands for CR in LOCATE cmd. else begin ...if any other kind of char. CHRPRT(LD B,SHOWCH) ...print SHOWCH in place of actual char. end end ...end of case statement if R.C-NCOL zero then begin ...check if last col. LD C,A ..... 11-2-82 SCREENFLG: EQU 0 ...default for SCRFLG; 0=>don't load SCREEN, 1=>load SCREEN ...may change with "S.." (load) / "N" (don't) on cmd line ...Z8000 addrs. ...file "S": S_SEG: EQU 0 S_BEG: EQU 0800 S_ENT: EQU 0802 ...file SCREEN: SCREEN_SEG: EQRET Z ...check if on last row INC (HL); 00->R.A end R.A->B.CRSCOL; P.RETCRS; RET ...move cursor right CRSLT: ...move cursor 1 space to left (with wrap-around) if B.CRSCOL=0 then begin ...check if at 1st col. @^CRSROW-1; RET Z ...check if on 1the current character unless it is a CR, shifting back the rest of the line. To exit Insert mode, type CR or escape. Enter: upon entering, inserts a CR to move rest of line (from cursor on) down, leaving cursor in place with opened-up space following.md. FTYP: BYTE 080 ...file type ORG FPUTBF+3 F_RL: WORD RECL ...record length ORG FPUTBF+7 FPROPS: BYTE 0 ...file props. E_ADD: WORD 0 ...entry address ORG FPUTBF+28 SegDes: ...start of segment descriptors ORG FPUTBF+110 LO_ADD: WORD 0 ..."LOW ADDRES...ED22 ENTER: ...enter "enter" mode (inserts CR after present pos.) B.TAGFLG=0; RET NZ LD DE,(ENDDAT); INC DE W.ENDBUF-R.DE; JP Z,NOROOM ...if no room in buffer, write "NO ROOM" on cmd. line 'E'->B.EIRFLG PRCMR1(^TXTENT) ...print 'ENTER' on cmd.U 0 SCREEN_BEG: EQU 06000 BEGIN: JP START SCRFLG: BYTE SCREENFLG ...0=>don't load SCREEN, 1=>load SCREEN ORG BEGIN+0100 STKPTR: START: LD SP,STKPTR SS() JP SYSRET /DO BUCKA.EQU /DO SYS.EQU NLUS: EQU 1 ...for ZDOS.S /DO ZDOS.S /DO SYS.S BUFF: ...buffst printed row DEC (HL); LD A,NCOL end R.A-1->B.CRSCOL; P.RETCRS; RET ...move cursor CRSCR: ...move cursor to beginning of next row 00->B.CRSCOL; P.RETCRS ...move cursor to beg. of row CRSDN: ...move cursor down 1 space (but not past EOF) if B.L (Exception: if cursor is at the end of a line, but not in the first column, then no CR is inserted.) Backspace will delete any character, including a carriage return. Also, typing a carriage return will enter a new line. To exit Enter mode, type escapeS" HI_ADD: WORD 0 ..."HIGH ADDRESS" F_ST: WORD 0 ...stack size ...end of attributes SDesPs: WORD 0 ...pos. curr. segment descriptor (used with IMAGE) IOFFSET: WORD 0 ...neg. of offset associated with current image segment ORG FPUTBF+RECL FPUTRM: WORD REC line (right), return cursor P.FNDPOS; R.C->B.CRSCOL ...find pos. in buffer; adjust CRSCOL if R.A<>0 then begin @DE=CR; JR Z,EIR ...jump if at CR but not 1st col. end P.RETCRS ...pos. cursor right at char. P.INNULS ...insert nulls before BUFPOSer for file starts here /MAP 8 /?"/IMAGE SYS.COM ",^BEGIN," ",^BUFF  " ",^BUFF r ZDOS.S /DO ZDOS.S /DO SYS.S BUFF: ...buffR: START: LD SP,STKPTR SS() JP SYSRET /DO BUCKA.EQU /DO SYS.EQU NLUS: EQU 1 ...for ZDOS.S /DO ZDOS.S /DO SYS.S BUFF: ...buffSTROW=@^CRSROW then begin ...test if on last row B.EOFFLG=0; RET NZ ...ret. if at EOF ...(for fake scroll do FWD1(W.1);B.LSTROW=@^CRSROW;RET Z;JR LastLine) FNDPOS() ...get current BUFPOS, ROWNO LD DE,(BUFP0); NXTLIN() ...DE=new BUFP0 after ...11-2-82 ...program to download Z8000 system MAXLUP: EQU 05000 ...max. times to loop before aborting ...load addrs. of "S" S__BEG: WORD S_BEG S__SEG: BYTE S_SEG S__ENT: WORD S_ENT ...load addrs. of "SCREEN" SCR_BEG: WORD SCREEN_BEG SCR_SEG: BYTE SCREEL ...available space in buffer FPUTNX: WORD FPUTBF ...next free location RCADR1: WORD 0 ...absolute disk address of record put in low buffer RCAD1H: BYTE 0 ...high-order of 3-byte address RCADR2: WORD 0 ...disk address of record put in high buffer RCAD2H:  W.BUFPOS+R.BC-1; LD (HL),CR ...replace last null with CR P.PRNWFB; JR EIRLUP ...print (shifts following lines down) INSERT: ...enter insert mode 'I'->R.A ^TXTINS; JR IR ...pt. to text 'INSERT' REPLCE: ...enter replace mode 'R'->R.A ^TXTRPL ...er ... filename TBASE: EQU 0100 ...base of user programs ...BDOS function calls RESET: EQU 0 ...system reset CONIO: EQU 6 ...direct console I/O RESDSK: EQU 13 ...reset disk system SELDSK: EQU 14 ...select disk OPENF: EQU 15 ...open file CLOSEF: EQU 16 print FNDCHR() ...DE->BUFP0; if char. at BUFPOS on scr., new row->CRSROW, ... col.->R.C, BUFPOS->DE, Z=1; else Z=0 JP NZ,PRSCRH ...if not on screen (only when top line>page), print ... screen + do home B.ROWNO-@^CRSROW->B.SCLFLG ...no. oN_SEG SAVSP: WORD 0 PROGLEN: WORD 0 BUKGET: PROC ...wait for bucket of type R.A PUSH BC PUSH HL; LD HL,MAXLUP R.A->R.C repeat 1; repeat OUT (CNTL),A; IN A,(CNTL) until R.A<>0FF; R.A->R.B; IN A,(CNTL) until R.A=R.C and R.A=R.B or R.HL-1=0; BYTE 0 ...high-order byte RECPTR: DEFS 25 ...save record & pos. within record of old file FPOS: WORD 0 ...current file pos. $$$ FPOSH: BYTE 0 ...high order of file pos. $$$ FILTYP: BYTE 020 ...type of input file (bit 5=1=>ascii, bit 7=1=>proc.) NUMERR: pt. to text 'REPLACE' IR: R.A->B.EIRFLG B.TAGFLG=0; RET NZ PRCMR1() ...print 'INSERT' or 'REPLACE' on cmd. line P.FNDPOS ...find pos. in buffer to start (DE at char., R.C=col.) if @DE=EOF then begin P.BLCMR; JP QSTION end ...if at EOF R.C->B.CRSCOL...close file DELETEF: EQU 19 ...delete file CREATEF: EQU 22 ...create file SETDMA: EQU 26 ...set DMA address READR: EQU 33 ...random read WRITER: EQU 34 ...random write FILSZ: EQU 35 ...compute file size ...BIOS entry offsets WBOOTOFF: EQU 3 CONSTOFF: EQf lines to scroll PUSH HL PRSCR() ...print from current pos. while @^SCLFLG<>0 do begin ...in case got to EOF before n scrolls DEC (HL); ^LSTROW; DEC (HL) POSCRS(LD B,LROW;00); PUT1(CR) ...(LF) end R.A->B.ROWNO ...0->ROWNO for C R.HL=0; JP Z,ABORT POP HL;POP BC RET BUKLD: PROC ...to port C send message type H of: ...DE bytes @IX to address IY in Segment L PUSH HL BUKGET(3) OUT (C),H ...message type OUT (C),L ...to segment number R.IY->R.HL; OUT (C),H; OUT (C),L ...BYTE 0 ...error count Hash: BYTE 0 ...current hash code used by Nxtsym Link: WORD 0 ...by Nxtsym: link of cur. entry LASTCR: WORD DATA1 LSTLAB: WORD 0 ...addr. of last label (not equate) listed SAVNCD: WORD 0 ...saves NCODE when doing ORG, DEFS, EQU,  ...adjust CRSCOL EIR: RETCRS() ...move cursor to right at char. P.FNDCR ...get row (->CRROW0) & pos. (->R.DE) of next CR if B.EIRFLG='I' then LD DE,(BUFPOS) ...if insert mode P.INNULS ...spread line, putting in null chars. EIRLUP: B.GETCHR1()->R.EU 6 CONINOFF: EQU 9 CONOUTOFF: EQU 0C PUNCHOFF: EQU 012 RDROFF: EQU 015 LSTSTOFF: EQU 02D ...ZDOS error codes EOF_ERR: EQU 1 ...end of file error FNF_ERR: EQU 2 ...file not found error FALSE: EQU 0 TRUE: EQU 0FF CPMEOF: EQU 01A error codes EOF_ERR: EONOUT below LD DE,CMDBUF; PUSH DE ENDROW(); POP HL ...get DE after CR in cmd buf., R.C=0 CONOUT() ...reprint cmd. line TAGSHW() ...replace tag indicators POP HL ...^CRSROW end INC (HL); P.RETCRS; RET ...move cursor down CRSUP: ...movaddress R.HL+R.DE->R.IY OUT (C),D; OUT (C),E ...byte count R.E->R.B=0; R.D if not zero then R.A+1; R.IX; repeat OTIR until DEC A; R.HL->R.IX POP HL; RET MOD: PROC PUSH DE; LD DE,0FFFF repeat INC DE until R.HL-R.BCR.HL P.TONOSP; RET NZ ...no string in cmd. line GETSTR(^STRBUF) ...copy string to string buffer if @HL=0 then begin INC A; RET end ...set Z=0 if len=0 P.FNDPOS; EX DE,HL ...R.HL=buffer pos. if @HL=EOF then W.EBUF-1 ...if at EOF, p ...get a char. W.BUFPOS->R.HL if R.A=0 then ...ctrl-@ means put in next char. (except 0) verbatim repeat B.GETCHR()->R.E until R.A<>0 else begin B.RUBOUT->R.B if R.E=BKSP or R.A=R.B then begin P.DELCHR; JR EIRLUP ...delete last or currquitting ...doesn't ret. end if RL3=0 then begin ...if shell script GETARGV(R3:=^S_ARGV; R5:=MAXS_ARGS)->S_ARGC ...store ^'s to args. & cnt (needed by GETSCRPT) TOTRM(); R9:->CMDPTR0 ...save level 0 CMDPTR LVL:+1; RETe cursor up 1 space if B.CRSROW-1 zero then begin LD DE,(EBUF); W.BUFP0-R.DE; W.1; CALL NZ,BAK1 ...if top line & not beg. of file, do fake scroll down end @^CRSROW-1; RET Z ...do nothing if on top line DEC (HL); P.RETCRS; RET ...move cursor u POP DE; RET GOBUK: BYTE 0 BOOT: PROC ...send BC bytes @HL to address DE in Segment A ...start execution @IX PUSH HL;PUSH AF; W.6+R.BC->R.BC ...add space for jump if R.IX+1=0 then 2 else 1 ...0FFFF means load and don't execute R.A->GOBUK POP At. before beginning XOR A; RET ...set Z=1 CMPSTR: ...enter R.DE at "DEFT"; R.HL at text to be compared; saves R.C ...return Z=1 if compares equal; else Z=0, HL=1st unsuccessful char. @DE=0; RET Z ...if null string LD B,A ...len. repeat INC DE; @DEent char. end if R.A=ESC then begin PUSH HL; ABTCML(); POP HL; JR EIRX end ...exit end if R.A=CR then begin B.EIRFLG='E'; JR NZ,EIRX end ...exit if @HL=CR or R.A<>0 and B.EIRFLG='I' then begin ...if all nulls replaced, add some more PUSH H end end LDL LSTENT,RR10 DEL() if CPB @R9,#',' not and BIT R11,0 zero then begin CKREDIR() ...poss. redirect i-o TOTRM(); R9:->CMDPTR ...go till @R9=';' or CR & set CMDPTR R0:=flag; SET R0,15; R0:->flag /SEG PUSHL RR1p CRSHM: ...move cursor home (row 1, col. 0) 00->B.CRSCOL; R.A+1->B.CRSROW P.RETCRS; RET CRSBTL: ...move cursor to bottom left corner of screen 00->B.CRSCOL; B.LSTROW->B.CRSROW; P.RETCRS; RET CRSTAB: ...move cursor to next tab pos. B.CRSCOL->R.C; P.F;POP HL; PUSH HL; PUSH DE; PUSH BC; R.A|080->R.D ...create JP to entry @IX R.HL+R.BC; LD BC,6; R.HL-R.BC->R.HL 05E->@HL; INC HL; 8->@HL; INC HL; R.D->@HL; INC HL; 0->@HL; INC HL PUSH IX; POP BC; R.B->@HL; INC HL; R.C->@HL; INC HL R.D; POP BC; POP=@HL; RET NZ ...unsuccessful INC HL until DEC B zero; RET ...successful (Z=1) ...search text to find string ...BC count; DE points to DEFT 'STRING'; HL points to text ...returns: HL after 1st char. of string in text; Z=1 if found CPILUP: POP HL;L; PUSH DE; EX DE,HL; P.INNULS; POP DE; POP HL if B.FULFLG<>0 then begin P.NOROOM; JR EIRLUP end ...if no room to add any nulls end P.NEWCHR; JR EIRLUP ...replace with new char. & print out EIRX: LD BC,0 ...HL=BUFPOS coming here if B.EIRFLG<>...11/10 WRTERR fixed ...12/02 BRKEXT added; P_ESC does Quit1 instead of Quit, calls RESNST (new) ...12/02 Err calls RESNST ...04/09/82 removed RIO dependent code to QSYS RECL: EQU 0200 LINEL: EQU 080 ...in & out max. line lengths MAXCPU: EQU 5 ...max. nTABPOS; INC C ...find next tab pos. if R.C-NCOL>=zero then begin ...check if goes to new row LD C,A; B.LSTROW->R.B; @^CRSROW=R.B; RET Z ...check if on last row INC (HL) end R.C->B.CRSCOL; P.RETCRS; RET ...move cursor CRSLTB: ...move cursor le DE; POP HL R.HL->R.IX; R.DE->R.IY; MOD(R.BC; LD BC,BUCKL-16)->R.HL R.A->R.B; INC C if R.HL=0 then begin LD HL,BUCKL-16; if DEC C zero then begin POP IX; RET end end R.HL->R.DE R.B->R.L; R.C->R.B; DATA->R.C PUSH HL; LD HL,MAXLUP repeat 0 POP DE; POP BC CPSIR: INC DE; @DE; DEC DE; CPIR; @DE; JP PO,CPIX ...1st character if DEC A not zero then begin PUSH BC; PUSH DE; PUSH HL R.A->R.B; INC DE INC DE; @DE; CP (HL); JR NZ,CPILUP; INC HL; DJNZ $-6 POP HL; POP DE; POP BC end ...re 'R' then begin ...if insert or enter mode while @HL=0 do begin ...go to 1st non-null char. (->R.HL) INC HL; INC BC ...R.BC=no. nulls end end else ...jump here if replace mode while @HL<>CR do begin ...find no. nulls left in line->R.BC C ...save B P.LINBEG; PIKROW(LD A,LROW/2-1); POP BC; INC B; ^CRSROW while @HLB.CHGFLG->B.SFLFLG ...zero flags R.A+1->B.ROWNO ...start printing row 1 if @W.STR2-@^STRBUFB.FULFLG P.BLCMR; RET ...blank out right part of cmd. line; ret. cursor INNULS: ...expand line, inserting n null chars. in buffer (updating ENDDAG=0; JP NZ,QSTION ...don't do if tags present P.FNDPOS; @DE=EOF; JP Z,QSTION ...find pos. in buf. (check if at EOF) P.FNDCR ...find pos. of next CR (R.B=its col.) INC DE; @DE=EOF; JP Z,QSTION ...check if on last line of file PUSH BC; PUSH DE; SHFTBve line with 2nd char. B.TAGFLG-1; JP NZ,QSTION ...must be tag 1 but not tag 2 P.FNDPSB ...get DE=beg. current line LD BC,LTAG1; W.TG1POS+R.BC ...HL=just past "--From here:" (carry=0) R.HL-carry-R.DE; JP Z,QSTION ...HL & DE must not pt. same spot t updated screen B.CRSCOL->R.C if R.E=CR then LD C,LCOL ...if CR R.A=TAB; CALL Z,TABPOS ...if tab INC C ...R.C=col. pos. PUSH DE; PUSH HL ...save new char., BUFPOS...->DE & save B.CRSROW->R.B ...for ROWNO (maybe) if R.C>=NCOL then begin ...if  XOR A ...carry reset after R.A->B.DIF ...diff. in string lengths if new string longer LD BC,(ENDDAT); INC BC W.ENDBUF-carry-R.BC->R.BC ...empty space in buffer R.HL+R.DE ...same as BUFPOS+R.BC->R.HL PUSH HL; PUSH DE P.SHFTFD; POP DE ...shift reT) ...n=lesser of 128 or available space (returned in R.BC) ...enter with R.DE->buffer loc. of char. to insert nulls before LD A,128 INNLS2: ...supply R.A when enter here W.ENDBUF; LD BC,(ENDDAT); INC BC R.HL-R.BC; LD C,A; LD B,0 ...avail. space in bK(LD BC,1) ...shift file past CR back 1 space POP DE; POP BC; DEC DE B.CRROW0=NROW; RET NC ...don't print if CR off screen R.A->B.ROWNO; LD C,B; P.PRSCR; RET ...print out ...JNERR: P.QSTION; RET ...print "???" LOCATE: ...starting next char., searchR.HL+R.DE while @DE=@HL do begin INC DE; INC HL end PUSH DE; EX DE,HL; LINBEG() ...DE=pos. for tag 2 if SETTG2() zero then begin ...put in tag 2 (Z=0 if no room) ...DE at TG2POS, BC=LTAG2 POP HL ...new cursor pos. if R.HL>=R.DE then R.HL+R.Bgoes to next row B.CRSROW=LROW; CALL Z,MIDPBP ...print so BUFPOS in mid. screen ^CRSROW; LD B,(HL) ...B is for ROWNO INC (HL); 00->R.A end ^CRSCOL; LD C,(HL); LD (HL),A ...present CRSCOL->R.C; update CRSCOL POP HL; R.HL+1->W.BUFPOS-1 POP DEm. part of file to end of buffer LD HL,STRBUF+1; LD C,(HL); POP HL ...1st char. in STR1->R.C CHGLUP: while @HL<>CR do begin ...check for CR if B.STRBUF=0 then LD C,(HL) ...if 1st string null, then want match if @HL<>R.C or B.NCPERL<>'*' and B.CHLuffer->R.HL; R.A->R.BC if SBC HL,BC R.BC ...BC=min(R.A, avail. space)=no. nulls to insert end ^FULFLG; LD (HL),0 ...reset flag if R.B|R.C zero then begin INC (HL); RET end ...set flag for buf. full PUSH BC; P.SHFTFD  for string taken from cmd. line ...if at EOF, start at top ...if found, print screen from that line; else "EOF" ..."ctrl R" in string stands for CR P.SRCH0; JP NZ,QSTION ...get str. from cmd. line; HL=start pos. for search-1 EX DE,HL; @^STRBUF->R.C ...if cursor>=tag2 then inc. cursor ptr PUSH HL if W.BUFP0>=R.DE then R.HL+R.BC->W.BUFP0 ...inc. BUFP0 if>TG2POS TAGSHW() ...print "TAG 2" on cmd. line end POP DE; LD (TG3POS),DE ...new cursor pos. (set tag 3 there) LOCPRT() ...if new po ...R.E=new char. if begin R.E=CR; R.B; LD B,(HL); LD (HL),E; EX DE,HL; R.A->@^ROWNO end ...B->ROWNO; old char. in buffer->B; E->buffer, test if CR; HL->DE then begin INC (HL) ...inc. ROWNO LD BC,0-1 repeat INC DE; INC BC until @DFLG<>0 then begin ...check if no match with 1st str. char. or doing no more on line CHG2: @HL->@DE; INC HL; INC DE; JR CHGLUP ...move byte back down end PUSH HL; PUSH DE CMPSTR(LD DE,STRBUF); POP DE ...check if whole string matches i...shift file past R.DE fwd. to make room for nulls LD (HL),0; R.HL->R.DE; INC DE ...R.HL pts. to 1st opened-up space POP BC; PUSH BC; DEC BC if R.B|R.C not zero then LDIR ...fill opened-up space with 0's POP BC; RET DELCHR: ...if R.A=BKSP: delete cB; LD A,CR2; PUSH HL repeat if R.A=@(R.HL+1) then LD (HL),CR until DEC B zero; ...if a "ctrl R" in string, replace with CR INC DE; POP HL ...DE=start pos.; HL->DEFT 'STRING' LD BC,0FFFF; P.LOCSTR ...search till EOF for string ...if found, DE ptss. off screen, print so in middle CALL Z,PRSCRN; RET ...else reprint screen (tag 2 may change screen) SETTG2: ...put in tag 2; enter with DE=pos. for tag ...if room, ret. Z=1, DE=TG2POS, BC=LTAG2; else Z=0 SHFIFR(LD BC,LTAG2); RET NZ ...shift rem. fiE<>0; ...DE->1st char. past nulls, BC=count of nulls if W.128-R.BCW.NUM1; POP HL; POP BC; LD C,EOF; JR CHG2 ...finish line &har. before BUFPOS; if replace mode just bksp. ...if R.A=RUBOUT: delete char. at BUFPOS, but not CR ...come here with HL=BUFPOS if R.A<>BKSP then begin ...if RUBOUT @HL=CR; RET Z ...don't do if at CR B.EIRFLG='E'; RET Z ...don't do if in enter  . at 1st str. char.; else at EOF ...fall thru: ... LOCPRT: ...if char. at DE (->BUFPOS) on screen, move cursor there, ret. Z=1; ...else print screen so char. in middle, ret. Z=0 LD (BUFPOS),DE LOCPBP: ...enter here if BUFPOS already set if FNDCH0() nole fwd. 11 sp. if room R.HL->W.TG2POS; PUSH HL ...TG2POS pts. to 1st spot opened up EX DE,HL; ^TXTTOH; LD BC,LTAG2; PUSH BC; LDIR ...put in "--To here^" ^TAGFLG; INC (HL) ...2->TAGFLG POP BC; POP DE; 00; RET TXTFRH: DEFM '--From here:'; DEFB CR LTAC; POP DE ...print out R.B=TAB; RET NZ; B.EIRFLG='R'; RET NZ ...if replacing a tab, print blanks at end of line: ... BLKEND: ...enter with DE in buffer (not at CR); R.C corres. col. ...print up to 8 blanks at end of line PUSH DE; P.FNDCR; LD C,B ... exit end POP HL; W.STR2 ...pt. to STR2 if @HL<>0 then begin LD B,A ...move STR2 into place: repeat INC HL; @HL->@DE; INC DE until DEC B zero; end if B.CHGALL='N' then begin ...check if doing 1st ocurrence of string LD (BUFPOS),mode R.HL->R.DE; LD BC,0 if R.A='R' then begin ...if replace mode @HL=0; RET Z ...if at null PUSH HL while @(R.HL+1)<>0 and R.A<>CR do INC BC ...note: test on null above not really needed if R.B|R.C not zero then begin ...BC=t zero then begin MIDPBP(); OR 1; RET end R.C->B.CRSCOL; RETCRS(); 00; RET ...CHGERR: P.QSTION; RET ...illegal CHANGE cmd. C: @DE & UPCASE='O'; JP Z,COPY ..."CO" means COPY routine CHANGE: ...change STRING1 to STR2; do spec. no. of lines, once or all . Editing using a command file: The option exists to take all the edit commands from a command file instead of from the console. Starting from the beginning of the file, each succeeding byte is equivalent to the next keystroke in normal editing, up thfind pos. of following CR (R.B=R.C=col) POP DE LROW=@^CRROW0; RET C ...ret. if CR is off screen if zero then INC B ...if on last row repeat INC DE until @DE<>0; ...go past nulls LD D,8; if R.A=CR then LD D,1 if NCOL-R.BW.NUM1; 00->B.NCPERL ...so will stop end POP HL; 1->B.CHLFLG->B.CHGFLG ...set change on line & change flags end @HL->@DE; PUSH HL if @^CHLFLG<>0 then begin ...if a change on the line DEC (HL) if B.CHGALL='*' then begin ...check dist. to 1st null or CR R.DE->R.HL; INC HL; LDIR ...shift intervening chars. back 1 sp. end 00->@DE; POP DE ...put in null; DE=BUFPOS end else begin ...if insert mode while @DE=0 do INC DE ...go to 1st non-null R.A=CR; RETper line ...start current line B.TAGFLG=0; JP NZ,QSTION ...don't do if tags present P.TONOSP; JP NZ,QSTION ...find delimiter GETSTR(^STRBUF); JP NZ,QSTION ...get 1st string; err if no 2nd delim. LD B,0; R.HL+1+R.BC->W.STR2 ...where to put 2nd strirough a "quit" command (only exception: the escape to end an "X*" command must come from the console). If the command file happens to end before a "quit" command is given, an automatic "QU N" will be executed. Note: on the Z8000, input from a command fi(8 or 1,cols. left in row) R.D=0; RET Z ...D=no. spaces to print starting at CR POSCRS(R.C; LD B,(HL)) repeat PUT1(' ') until DEC D zero; P.RETCRS; RET ...ret. cursor T: @DE='1'; JP Z,TAG1 ..."T1" means go to TAG1 R.A='2'; JP Z,TAG2 ..."T2" meansif doing all lines PUSH DE; PUSH BC P.LINBEG; LD C,0; P.PRLIN ...print out line with change if not zero then 1->B.SFLFLG ...indicates screen full POP BC; POP DE end end INC DE; W.NUM1-1->W.NUM1=0 ...check if done POP HL; INC HL Z ...don't do if at CR 00->@DE ...replace char. with null end endif ^CRSROW; B.CRSCOL->R.C ...for printing end else begin ...if was BKSP if @(R.HL-1)=CR then begin ...check if char. before BUFPOS is CR B.EIRFLG='E'; RET NZ ...if ng (R.C=len.) GETSTR(R.HL) ...get 2nd string if zero then begin ...2nd string ends with delimiter, not CR or ";" INC DE; if @DE='n' then LD A,'N' ...'N' indicates do next occurrence R.A->B.CHGALL ...if ='*', indicates do all lines if R.A='*'le is enabled by redirecting input when the editor is loaded. This is done by typing EE FILENAME B.CRSCOL P.PRSCRF; RET ...print last page of file M: @DE & UPCASE='O'; JP Z,MOVE ..."MO"=do MOVE MIDDL; JR Z,CHGX @HL=EOF; JP NZ,CHGLUP ...if not EOF, do another line CHGX: PUSH HL; R.HL-R.DE->R.BC; POP DE P.SHFTBK ...shift back rem. portion of file B.CHGFLG=0; JP Z,NOCHG ...chk if any changes; if none, print msg. if B.CHGALL='*' then begin ...if wnot enter mode, don't delete CR B.CRSROW-1; RET Z ...if on top row, don't delete CR end R.HL->W.BUFPOS EX DE,HL; P.CHRPOS ...find col. of the char. at BUFPOS (->R.C) ^CRSROW if B.CRSCOL=0 then DEC (HL) R.C->B.CRSCOL ...update curs or R.A='N' then begin INC DE; LD HL,0FFFF ...no limit on no. of lines end else begin P.DIGIT; JR NZ,CHG1 ...check if no. P.NUMBER ...complete no.->R.HL end P.SPC ...skip spaces; 1st non-space char.->R.A end else begin CHG1: LD can be used to break up extra large files into smaller ones. 2. Commands may be typed in either capital or small letters. 3. If tags (1 and 2) are present, no changes may be made to the file other than with operations utilizing the tags. 4. In commandsE: ...print screen with current line in middle; cursor stays with line P.FNDPOS ...fall thru: ... MIDPBP: ...print screen so char. at BUFPOS & cursor in middle LD DE,(BUFPOS) ...MIDPRT: LD (BUFPOS),DE ...no longer used CHRPOS(); R.C->B.CRSCOL; PUSH Bere doing all lines ^ROWNO if B.SFLFLG=0 then DEC (HL) SCRRES(LD C,(HL)); RET ...blank rem. scr.; wait for key hit; reprint scr. end if R.A='N' then begin ...chk doing next occur. B.CHGFLG=0; CALL NZ,LOCPBP; RET NZ ...if change offor pos. if B.EIRFLG='R' then begin ...if replace mode P.RETCRS; RET ...just backspace without deleting char. end LD DE,(BUFPOS); 00->@DE ...put in null char. end endif @HL->B.ROWNO ...for printing PUSH DE; PUSH BC; P.PRNEW ...print st HL,1; 00->B.CHGALL ...default=1 line, once per line end endif R.HL->W.NUM1; PUSH HL ...NUM1=no. of lines to do R.A->@^NCPERL ...if NCPERL<>'*' then once per line if B.STRBUF=0 then R.A->@HL ...if 1st string is null, only do 1/line P.FNDPOS; POP H   containing strings, the string delimiters (indicated by "/"s above) may be any character not contained in the string except space, carriage return, or escape (or digits where they would be interpreted as a number in the command). Spaces are optional befo8 IXYD: no error if "(" not followed by IXY; NVAL calls NN2 ...3/18 /IF, etc. replaces /COND: ...3/18 DOTDO,QINST added, STR removed ...3/18 .OR.,R.A+C,R.A+(HL),etc. made invalid ...3/18 WORD,BYTE,PROC at nn added ...3/26 "#" added; -n added ...3/26  To call, give the command ".J m,n", where m=number of columns wide to make and n=number of lines to do (starting with current line). (The most likely place to use this would be from the beginning to the end of a paragraph.) Another extension built into  marked by TAG 1 endif LD BC,LTAG1; W.TG2POS-R.BC->W.TG2POS ...correct TG2POS LD DE,(TG1POS); JR TAGOFF ...remove TAG 1 TG2OFF: LD C,LTAG2; LD DE,(TG2POS) ...remove TAG 2; drop thru: ... TAGOFF: ...enter with DE=either TG1POS or TG2POS; R.C=LTAG1 o&0DF<>'X' then CACHEON() CP A end ...else Z=0 RET CACHEOFF: PROC ...if ZOOM system, turn cache off TSTZOOM(); RET NZ ZOOM(CACHE_OFF); RET CACHEON: PROC ...if ZOOM system, turn cache on TSTZOOM(); RET NZ ZOOM(CACHE_ON); RET TSTZOOM: ...ret. Zre the first delimiter. 5. With commands followed by a number, spaces are optional before the number. 6. In the Locate command, "control-R"s may be used to represent carriage returns in the string. 7. In the Change command, if the first string is null,  BIT n,ABC, etc. added ...9/9/82 GET added for CPM ITEM := .OUT("H200113") / ITEM0 ; ITEM0 := .OUT("HD7") SREND := "<" ">" := "[" .OUT("C Latch") OUTA2ST "]" := ORCL ; ...note: 0D7 is RST 10, then JP Tthe CP/M Z80 editor is ".A" to add line feeds after all the carriage returns in the file. e after the last one to be copied. Outhex: Converts RL0. to the equi...ZOOMA equates ...Bucket Equates BUCKET: EQU 0FF ...@@@ 07B modified for ZOOMA BUCKL: EQU 0100 CNTL: EQU BUCKET DATA: EQU BUCKET-2 ...the following is referenced but not actually called on ZOOMA ZOOM: EQU 0DA00+033 ...additional ZOOM BIOS entry ...cod=1 iff ZOOM system ('ZZZ' at ^BIOS) LD HL,(1); LD L,0 ...HL=^BIOS 'Z'=@HL; RET NZ; R.A=@(R.HL+1); RET NZ; R.A=@(R.HL+1); RET *ZAP ZFNF_ERR CKZSL FIXERRCD TSTZOOM  'Z'=@HL; RET NZ; R.A=@(R.HL+1); RET NZ; R.A=@(R.HL+1)the second string will be inserted at the current location or at the beginning of any following lines (no more than one change per line). However, no change will be made at a carriage return. 8. In order to enter the characters "backspace", "del" (ruboutest ORCL := ANDCL $("/" .OUT("H28","A1"#1) ANDCL .LABEL(#1) Zp OPTM2) ; ITEM1 := .SAV("H13") := .SAV() ; ITEM2 := XCOMS .OUT("HCF13") := .OUT("HCF") := OUTPT ; ...note: 0CF is RST 8, then JP Err0 (rets. if Z) OUTPT := XC Q DOCUMENTATION Q Overview ---------- Q is an extension of the standard Z80 assembler (ASM) which provides several new features: 1. Direct code generation into memory. 2. Immediate execution of statements preceded by "*" or "/". 3. Symbolic debues for ZOOM entry ZOOM_RDY: EQU 0 CACHE_OFF: EQU 1 CACHE_ON: EQU 2 SCREEN_RDY: EQU 3  Y: EQU 0 CACHE_OFF: EQU 1 CACHE_ON: EQUKET-2 ...the following is referenced but not actually called on ZOOMA ZOOM: EQU 0DA00+033 ...additional ZOOM BIOS entry ...codDEFT @HL, FCB @DE returns error A file length CDE LD C,A; if B.CCPM() < 4 then begin B.CCPM(LD C,023); LD HL,FCBSZ-3; RanRecF(R.HL+R.DE); 00->R.A; end OR A; RET RanRecF: PROC ...expects Random Record Field @HL returns CDE wit), or "escape" into a file, this can be done by first typing "control-@" (when in one of the input modes) followed by the character. 9. Hitting "escape" will always cause a return to normal command mode (except in the case after a "control-@" noted above)OMS ".OUT(" / ".LABEL(" .OUT("HDF014C") := ".SAV(" OUTBEG $ .OUT("C Sav") := DOTDO := "{" ORCL "}" := PROCITEM / TRUEITEM ; ...note: 0DF is RST 18, then JP Icopy TRUEITEM := "$" .LABEL(#1) .OUT("H28","A1"#1) Zgging. 4. Comments introduced by "..." instead of ";". 5. Multiple instructions per line separated by ";". For example: INC DE; INC DE; INC DE ...skip 3 6. Speed of execution. 7. Simple register handling expressions. Two types are introduced, those BIOS+51 ...disk parameters MAXTRK5: EQU 160 ...maximum number of tracks per disk MAXTRK8: EQU 76 CPM: EQU 5 ...CPM entry point SYSRET: EQU 0 ...system reentry point (CPM warm boot) CDISK: EQU 4 ...current disk INPTR: EQU 080 ...addr of CPM buffer containh @HL*128 @HL->R.D; @(R.HL+1)->R.C; @(R.HL+1)->R.A; LD E,0; RRA; RR C; RR D; RR E; ...length*128 RET ParseName: PROC ...expects DEFT @HL, FCB @DE returns error A PUSH BC;PUSH DE;PUSH HL ...SAVE ALL R.DE+1->R.HL;LD BC,FCBSZ-1;EX DE,HL;00->@HL;G1: EQU $-TXTFRH TXTTOH: DEFM '--To here^'; DEFB CR LTAG2: EQU $-TXTTOH ...TAGERR: P.QSTION; RET ...illegal TAG1 or TAG2 cmd. TAG1: B.TAGFLG=0; JP NZ,QSTION ...don't do if tag already set P.FNDPSB ...find pos. (->DE) & ROWNO of beg. current line SHFp .OUT("HBF") := "?" .OUT("HBF") ; SR1S := """ { .OUT("H1AFE") OUTSTARI / .DO(DEC DE)} ; OUTP1 := .DO(PUSH DE) .DO(PUSH HL) .OUT("HEF") .DO(POP HL;LD C,L;LD B,0;OUTHRL(SRL L);POP HL;R.HL+2;LDIR;Out()) (RPAREN / .DO(INC DE) OUTP1) :that are computed in 8 bit precision whose values are left in register A, and those that are computed to 16 bits and whose values are left in register HL. In addition, the value can optionally be stored in one or more places. For example: ing len + cmd line after ... filename TBASE: EQU 0100 ...base of user programs ...BDOS function calls RESET: EQU 0 ...system reset CONIO: EQU 6 ...direct console I/O RESDSK: EQU 13 ...reset disk system SELDSK: EQU 14 ...select disk OPENF: EQU 15 ...ope. This may be used, for instance, to leave the command line without executing it. 10. After quitting from the editor ("QU" or "QU N"), the editor may be reentered at its entry point with everything intact (type "X" from RIO or ZOOMSYS or execute X.COM frIFR(LD BC,LTAG1); RET NZ ...shift rem. file fwd. 13 sp. if room R.HL->W.TG1POS; PUSH HL ...TG1POS pts. to 1st spot opened up EX DE,HL; ^TXTFRH; LD BC,LTAG1; LDIR ...put in "--From here:" ^TAGFLG; INC (HL) ...1->TAGFLG POP DE; JR TAGX ...print "TAG  = .DO(POP DE) OUTBEG OUTP2 ; ...note: 0EF is RST 28, then JP OutN OUTP2 := $ .OUT("HE7") (RPAREN / "," OUTP1) ; ...note: 0E7 is RST 20, then JP Out OUTBEG := .OUT("HDF") SREND / .OUT("C Outset") ; ...note: 0DF is RST 18, then JP Icop 99+R.C->R.B->SAVE generates LD A,99; ADD C; LD B,A; LD (SAVE),A R.L+1->@DE generates LD A,L; INC A; LD (DE),A R.BC-R.DE->W.STORE generates LD H,B; LD L,C; OR A; SBC HL,DE; LD (STORE),HL 8. Pascal-like "structured" extensions to permit self-documen file CLOSEF: EQU 16 ...close file DELETEF: EQU 19 ...delete file CREATEF: EQU 22 ...create file SETDMA: EQU 26 ...set DMA address READR: EQU 33 ...random read WRITER: EQU 34 ...random write FILSZ: EQU 35 ...compute file size ...BIOS entry offsets WBOOTOom CP/M). This could be used after an inadvertant "QU N" or after an error on writing the file out, for instance. Terminal and keyboard configuration: The screen function codes and keys for doing cursor movements (as well as the Delete key used in inse 1", fill screen, get allow. cmds. TAG2: B.TAGFLG-1; JP NZ,QSTION ...tag 1 must be already set but not tag 2 P.FNDPSB ...find pos. (->DE) & ROWNO of beg. current line W.TG1POS-R.DE; JP NC,QSTION ...must be after TAG 1 pos. SETTG2(); RET NZ ...put iy OUTITEM := DEL """ { .OUT("H3E") OUTSTARI .OUT("H1213") / OUTSTR} := "*" .OUT("C Copyin") := "#1" .OUT("C Gen") := DOTDO := PROCITEM ; PROCITEM := .OUT("C " *) ; DOTDO := ".DO(" QINST $(DEL ";" QINST) ; SRBEG := """ Sr ; OUTSTR := nting use of control structures. Four types are introduced: a) if R.A='*' and R.HL>R.DE then INC DE else RET b) while @HL= ' ' do begin LD (HL),B; INC HL end c) repeat PROC(R.C); PROC(R.B) until R.C>=5 or R.HL-R.DE<=zero d) case BYTEI of 'A': CALFF: EQU 3 CONSTOFF: EQU 6 CONINOFF: EQU 9 CONOUTOFF: EQU 0C PUNCHOFF: EQU 012 RDROFF: EQU 015 LSTSTOFF: EQU 02D ...Bucket Equates BUCKET: EQU 0FF ...@@@ 07B modified for ZOOMA BUCKL: EQU 0100 CNTL: EQU BUCKET DATA: EQU BUCKET-2 ZOOM: EQU BIOS+033 ...addrt mode) may be changed. (At the present, the usual initial set-up is with support for the Infoton 200 and Visual 200 terminals.) See the program ECONFIG. Extensions: Provision is made to incorporate extensions into the editor to handle writer- definen tag 2 (Z=0 if no room); TG2POS->DE TAGX: if @^CRSROWR.A JP GetC CKZSL: ...chk for "0/" before name (@HL) & change to "A:" PUSH HL if @HL='0' and @(R.HL+1)='/' then begin ':'->@HL; 'A'->@(R.HL X 'B': CDE + 1 -> @DE else CALL ERROR end (Note small letters.) Q is currently implemented on CP/M vers. 2.2 and RIO Rel 2.06. A - Expressions --------------- A-expressions, which deliver a value to R.A, consist of a load paritional ZOOM BIOS entry ...codes for ZOOM entry ZOOM_RDY: EQU 0 CACHE_OFF: EQU 1 CACHE_ON: EQU 2 SCREEN_RDY: EQU 3 ...ZDOS error codes EOF_ERR: EQU 1 ...end of file error FNF_ERR: EQU 2 ...file not found error FALSE: EQU 0 TRUE: EQU 0FF CPMEOF: EQU 01A d searching and changing operations. If any extensions are defined, they are called after a "." is encountered at the beginning of a command. At this point, a supplied routine to parse the command is called. If the parsing returns true, another supplied then begin ..."O2" means OFF2 R.A=2; JP NZ,QSTION ...check if a TAG 2 DEC (HL); P.FNDPOS; P.TG2OFF ...remove TAG 2 end else begin R.A=0; JP Z,QSTION ...check if any tags P.FNDPOS; P.TGSOFF ...remove tags end FNDCH0(); PRSCRN(); RET ..L-1) end POP HL; RET OpenF_: PROC ...chk for "0/" before name (@HL) & change to "A:" ...then call OpenF CKZSL() OpenF() if not zero and R.A=FNF_ERR then ZFNF_ERR|R.A->R.A JR FIXERRCD CreateF_: PROC CKZSL() CreateF() JR FIXERRCD ReadF_: PROC t followed by any number of modifier parts and/or store parts. These parts are described as follows: (Note: In the following examples, including for the HL-expressions below, spaces are generally not permitted except where shown. They are also not requi  EQU 01A EQU 01A A IN A,(CNTL) until R.A<>0FF or R.HL-1=0; ...get bucket JP Z,ABORT ...HL=0 POP HL 00; OUT r codes EOF_ERR: EQU 1 ...end of file error FNF_ERR: EQU 2 ...file not found error FALSE: EQU 0 TRUE: EQU 0FF CPMEOF: EQU 01A  routine is called which executes the command. Note: Special extension files may be made which the Z8000 (and RIO Z80) versions of the editor can load in using the "GE" command. Extensions defined in them are then available for use. See separate docume.find CRSROW of new BUFPOS; print scr. ...OFFERR: P.QSTION; RET ..."???"->cmd. line PLTAG2: LD DE,(TG1POS); P.NXTLIN ...find place for TG2POS if no TAG 2 @DE=EOF; CALL NZ,NXTLIN; LD (TG2POS),DE; RET ...end of 1 tagged line TGSOFF: ...remove & shift fReadF() FIXERRCD: if not zero then R.A|0C0 else 080->R.A RET WriteF0: PROC ...prelim. to write 080; CP A; RET ...Z=1 =>no err WriteF_: PROC WriteF() JR FIXERRCD CloseF_: PROC CloseF() JR FIXERRCD Seek_: PROC SeekF() JR FIXERRCD ...DSKINIT: red. Spaces are permitted between parts.) Load Parts Generated Code ---------- -------------- @R.BC or @BC .................................. LD A,(BC) @R.DE or @DE .................................. LD A,(DE) @R.HL or @HL .........................11/10 NN2 with IdDEF calls OUTA2ST again ...11/10 /COND: works opp. Skip;REVA new;GETSKP->GETCND ...12/2 RESNCD tests if SAVNCD=0 ...12/8 "0" test removed from HEXN ...12/9 SavB works on whole byte; ORe0->Re, some Xc's removed: ORe3,Re swapped ...3/1ntation (E.X.DOC) for details. Further note: An extension is available to right justify text (at least within a word length). On the Z8000, use ("GE") the extension file RJ.X. On the CP/M Z80, this extension has been assembled into the editor already. ile back over tags; correct BUFP0, TG2POS, BUFPOS ...at least tag 1 must be on when come here ^TAGFLG; DEC (HL) if not zero then begin ...if there is a tag 2 DEC (HL); P.TG2OFF ...remove TAG 2 end else P.PLTAG2 ...if no TAG 2, TG2POS=end of linePROC ...init. disk ... CACHEOFF() ... JP DskInit DOZ80CMD: PROC ...cmd string @HL; ret. Z=0 iff can't do if @HL&0DF='I' and @(R.HL+1)=' ' or R.A=0D then begin PUSH HL CACHEOFF(); DskInit() POP HL repeat @HL; INC HL until R.A<>' '; if R.A  ............ LD A,(HL) @R.IX or @IX .................................. LD A,(IX) @R.IY or @IY .................................. LD A,(IY) or @R.IX(n) or @IX(n) (same with IY) where n is an expression for a 1-byte numeric value (see 'Numeric Values' belogin @DE & UPCASE='T'; JR NZ,DGTERR ...if tags, must have "DET" P.FNDPOS; P.DELBTG; RET ...del. bet. tags; remove tags; print end P.GETNUM ...get no. lines to delete->HL; default=1 PUSH HL P.FNDPS0; PUSH DE ...find pos. in buffer; save beg. of..alternate entry pt. while begin PUSH HL; W.EBUF-R.DE; POP HL end not zero and R.HL<>0 do begin ...check if done or to beg. of file DEC HL; PUSH HL DEC DE; P.LINBEG; POP HL ...go to beg. of prev. line end PUSH DE; P.FNDPOS; P LD HL,STRBUF ... TSTDRV() PUSH HL; LD C,0; @DE repeat R.A->@(R.HL+1); INC DE; INC C until @DE=CR or R.A=';' or R.A=' ' ...move filename to str. buffer POP HL; LD (HL),C; RET ...put in len.; Z=1 COPY: ...copy (without deleting) text bet. tags or on NDPS0 ...no no. or str.: get BUFPOS & DE=next BUFP0 end else begin ...if no. (now in HL) FWD1: LD DE,(BUFP0) ...count from top line (alternate entrance here) while R.HL<>0 and @DE<>EOF do begin ...check done or EOF DEC HL; PUSH HL; P.NXTLINw) .... LD A,(IX+n) (or LD A,(IY+n)) also @hl where "hl" stands for an HL-load part (see 'HL-Expressions' below) .......... Load HL,--- LD A,(HL) R.B (or R.C.,D,E,H,L) ......................... LD A,B (or LD A,C etc.) R.A ........................... line P.CHRPOS ...get rows in line-1->R.B B.CRSROW-R.B->B.CRSROW->B.ROWNO ...1st row of line 00->B.CRSCOL->R.B->R.C ...0->CRSCOL->BC POP HL; POP DE; PUSH HL ...HL=beg. line pos.; DE=no. lines to delete while R.D|R.E not zero and @HL<>EOF do begin OP DE ...get BUFPOS; DE=next BUFP0 ... end endif P.FNDCHR; PUSH AF ...get new cursor pos. if char. on screen (Z=1) P.PRSCRN; POP AF ...print screen CALL NZ,CRSBTL; RET ...if Z=0, set cursor to bottom line XEQ: ...execute command line LD E,A; P.BLCtagged line if no TAG2 ... to right above current line ...if cmd. followed by a filename, copy to the file instead ...keep tags in place B.TAGFLG=0; JP Z,QSTION ...chk if tags present if P.TSTFNM zero then begin ...test if a filename given P.TAGR; POP HL ...go to next line end PUSH DE; P.FNDPOS; POP DE ...get BUFPOS; DE=next BUFP0 end endif if P.FNDCHR not zero then begin P.PRSCRH; RET end PRSCRN(); RET ...get new cursor pos.; print out FIND: ...search for string taken from cmd. line ................ No code B.VARNAME ..................................... LD A,(VARNAME) VARNAME (if previously defined as a BYTE) ..... LD A,(VARNAME) B.PROCEDURE() (see 'Procedures' section below) CALL PROCEDURE 00 ....................................... ...go thru buffer counting lines until n lines or EOF DEC DE; LD A,CR; CPIR ...find beg. next line end EX DE,HL; W.0-R.BC->R.BC ...no. of chars. to delete->R.BC P.SHFTBK ...shift file past deleted lines back; update ENDDAT POP DE; P.PRNWF0; REMR ...'X'->R.E; blank right part cmd. line ^XCMBUF; PUSH HL ...start of "X" cmd. buffer LD D,NCOL-R1+1 ...R.D=beg. col. for cmd. print LD A,NCOL-R1+4 ...R.A=last col. for "X" cmd (not counting CR) P.FILCL2; POP DE ...fill "X" cmd line; DE=beg. 1-GN ...HL=beg. of tagged region, DE=end P.PUTFIL ...text bet. tags->file P.PRSCRN; RET ...only print so know done end P.COPY1; CALL Z,PRNWFB; RET ...copy text; print out COPY1: ...if all OK, copy text bet. tags, ret. Z=1; else ret. Z=0 ...updaat beginning of a line ...if found, print screen from that point; else "EOF" ...entered with HL=start pos. for search: ...start search line after cursor pos.; if at EOF, start at top FNDLUP: CR; LD BC,0; CPIR ...find next CR if @HL<>EOF then begin ....... XOR A (note that this affects the flags) 99 or other decimal number .................... LD A,99 0C3 or other hex number ....................... LD A,0C3H 'Z' ........................................... LD A,'Z' 2**n (where n is a constant) .T ...print out MOVE: ...move (& delete) text bet. tags or on tagged line if omly 1 tag ... to right above current line ...if a filename given, move to the file instead B.TAGFLG=0; JR Z,DGTERR ...chk if tags present if P.TSTFNM zero then begin ...te>B.BLCMRF ...flag something on rt. part cmd. line if not zero then begin ...chk if to execute INC DE if P.GETNUM not zero then begin ...chk if no. follows 'X' ...note: HL set=1 in GETNUM if @DE='*' then R.HL-2 ...if "*", then HL=0FFFF te BUFP0, BUFPOS, TG1POS, TG2POS P.TAGRGN; R.HL->W.NUM1 ...beg. of text to be copied PUSH HL; P.FNDPS0; LD (BUFPOS),DE ...BUFPOS=DE=beg. curr. line POP BC; W.TG2POS-R.BC->R.BC ...len. of text to be copied if W.TG1POS-carry-R.DE B.ESCFLG P.XEQCML; POP HL; DEC HL until B.ESCFLG<>0 or P.GET1IF not zero and R.A=ESC; ...execute cmd. line HL times or until escape end XEQX: ...if tags, replace tag indicators: ... TAGSHWDE>=zero then if not zero or B.TAGFLG-1 not zero then begin P.QSTION; RET ...if DE bet. tags; Z=0 end endif PUSH DE; PUSH BC P.SHFIFR; POP BC; POP DE; RET NZ ...shift file fwd. to make room if W.TG1POS-R.DE>=zero then begin W.TG1POS+R.BCRS(00; LD B,1); ERASL() ...go to 1st line & erase it PRTNAM(); LD C,1 ...fall thru: ... SCRRES: ...blank rem. screen after row R.C; wait for key hit; reprint scr. P.BLNKLS ...fill rem. scr. with blank lines P.HITKEY ...print "HIT KEY" on cmd. lin-------------- +carry+ R.B or C, etc. ........................ ADC A,B etc. +carry+ 99 (or other constant) ................ ADC A,99 (or other constant) +carry+ @HL ................................... ADC A,(HL) +carry+ @IX (or @IY) ......................  print P.TGSOFF ...remove tags; TG1POS=beg. & TG2POS=end of text to be del. LD BC,(TG1POS); PUSH BC; W.TG2POS->R.DE-R.BC->R.BC ...BC=len bet. tags PUSH BC; P.SHFTBK ...shift back file over deleted portion POP BC; POP DE ...BC=len. deleted; DE=TG1POS: ...print "TAG 1" / "TAG 2" on right part cmd. line B.TAGFLG=0; RET Z ...if no tags PUSH AF; PRCMR1(^TXTTG1) ...print "TAG 1" ^TXTBL7; POP AF; if R.A-1 not zero then ^TXTTG2 PRCMR0() ...if 2nd tag, print "TAG 2" to right of "TAG 1", else blanks INC->W.TG1POS; W.TG2POS+R.BC->W.TG2POS; W.NUM1+R.BC->W.NUM1 end ...update tag positions if shifted fwd. W.NUM1; R.B|C; RET Z; LDIR ...move text 00->B.CRSCOL; RET ...cursor->1st col.; Z=1 TAGRGN: ...beg. of text to be copied->R.HL; end->R.DE->TG2POS Le POSCRS(00;LD B,1) ...move cursor to home pos. P.WAITCH ...wait for key to be hit; test if esc.; blank cmd line msg P.PRSCRN; RET ...print out scr. starting same spot as before N: @DE & UPCASE='A'; JR Z,NAME ..."NA" means NAME NEXT: ...present las.... ADC A,(IX) (or ADC A,(IY)) +carry+ @IX(n) (or @IY(n)) .................... ADC A,(IX+n) (or ADC A,(IY+n)) +carry+ @^DATA (or other HL-load part) ........ LD HL,DATA (or other HL-load) ADC A,(HL) (*see note below) -carry- (options are the s if W.BUFP0-R.DEW.BUFPOS ...BUFPOS=BUFPOS-len. bet. tags end else ...if TG2POS>=BUFPOS if W.TG1POS-carry-R. .XOR. (same as +carry+) ....................... XOR A,--- & (same as +carry+) ........................... AND --- | (same as +carry+) ........................... OR --- = or :: (same as +carry+) ..................... CP --- (except note "=0" below) = 0 (oD DE,(TG2POS) B.TAGFLG-1; CALL Z,PLTAG2 ...if no TAG 2, find pos. for it->DE LD BC,LTAG1; W.TG1POS+R.BC->R.HL; RET G: if @DE>='1' and R.A<'4' then begin ...goto tag 1, 2 or 3 R.A-'1'*2->R.C; LD B,0; ^TG1POS+R.BC LD E,(HL); INC HL; LD D,(HL) it line becomes 1st line next page; repeat n times; print P.GETNUM ...get no. after cmd., default=1 LD DE,(BUFP0) ...in case 0 while R.HL<>0 do begin DEC HL; PUSH HL; FNDPS0(LROW->B.CRSROW; 00->B.CRSCOL) LD (BUFP0),DE; POP HL ...beg. last line oame as +carry+) ..... SBC A,--- +1 ............................................ INC A -1 ............................................ DEC A + (options are the same as +carry+) ........... ADD A,--- - (same as +carry+) ........................... SUB A, ---DEW.BUFPOS endif ...if BUFPOS bet. tags, BUFPOS=TG1POS endif end else begin ...if BUFP0>=TG1POS R.HL+R.DE; LD DE,(TG2POS) ...HL=BUFP0 if R.HL-carry-R.DE>=zero then begin ...if BUFP0>=TG2POS R.HL+R.DE-carry-R.Br :: 0) ................................. OR A *2 ............................................ ADD A,A /2 ............................................ SRL A Store Parts Generated Code ----------- -------------- -> B.ABC ..........................f W.ENDDAT=zero then EX DE,HL LOCPRT(); RET end GET: ...get a file, inserting above current line @DE & UPCASE='E'; JR NZ,DGTERR; B.TAGFLG=0; JR NZ,DGTERR P.TSTFNM; JR NZ,DGTERR ...get filename P.FNDPSB ...get BUFPOSn page->DE->BUFP0 end P.PRSCR0; RET ...print out screen PREV: ...back up to prev. page: curr. 1st line becomes last line if possible ...do n times, then print page P.GETNUM ...get no. after cmd.; default=1 LD DE,(BUFP0) while R.HL<>0 do begin Dr LTAG2 ...blank tag ind. on cmd. line; shift file back over tag ...correct BUFP0 & BUFPOS P.BLCMR; P.TAGSHW; LD B,0 ...blank tag ind. from cmd. line (R.C saved) if W.BUFP0-R.DE+R.DE>zero then R.HL-carry-R.BC->W.BUFP0 ...if BUFP0>TGXPOS then BUFP0=C->W.BUFP0 ...BUFP0=BUFP0-len. bet. tags W.BUFPOS-carry-R.BC->W.BUFPOS ...BUFPOS=BUFPOS-len. bet. tags end else begin ...if BUFP0 bet. tags W.TG1POS->W.BUFP0->R.BC if W.BUFPOS-R.DE ABC (where ABC prev. classified as BYTE) ... LD (ABC),A -> @R.BC or @BC ............................... LD (BC),A -> @R.DE or @DE ............................... LD (DE),A -> @R.HL or @HL ............................... LD (HL),A + DE=pos. & ROWNO=row at beg. of line PUSH DE GETFIL(); POP DE ...read in file if zero then begin ...read in file LD (BUFPOS),DE; 00->B.CRSCOL ...for printing (beg. of read-in text) B.ROWNO->B.CRSROW ...adjust cursor row end P.PRNWFB; RET EC HL; PUSH HL; PKLROW(); POP HL end P.PRSCR0; RET ...B: @DE & UPCASE='O'; JP Z,BOTTOM ..."BO" means BOTTOM ...BACK: ...if number given, go back that many lines & print screen ... ...if no number, current line->last line ... ...cursor stays with currenBUFP0-LTAGX if W.BUFPOS-R.DE>=zero and R.HL-carry-R.BCR.HL else R.HL+R.DE->R.HL endif ...if BUFPOS>TGXPOS then BUFPOS=max(TGXPOS,BUFPOS-LTAGX) R.HL->W.BUFPOS EX DE,HL; R.HL+R.BC; EX DE,HL; P.SHFTBK; RET ...shift back over tag TSTFN...then BUFPOS=TG1POS else R.HL+R.BC->W.BUFPOS ...else BUFPOS=TG1POS+(BUFPOS-TG2POS) endif end endif end endif FNDCH0(); PRSCRN(); RET ...find row corr. to BUFPOS->CRSROW; print scr. FORWRD: ...if no. given, print screen starting n lines d -> @R.IX or @IX (same with IY) ................ LD (IX),A (or LD (IY),A) -> @R.IX(n) or @IX(n) (same with IY) .......... LD (IX+n),A (or LD (IY+n),A) also -> @hl where "hl" stands for an HL-load part (see 'HL-Expressions' below) .......... Load HL,--- ...print out (BUFPOS=start of new text) DGTERR: JP QSTION ...ill. cmd.; print "???" DELETE: ...delete n lines starting at current line ...if tags present, delete bet. tags @DE & UPCASE='E'; JR NZ,DGTERR ...must be "DE" INC DE if B.TAGFLG<>0 then bet line unless off screen ... if P.GETNUM not zero then begin ... P.FNDPS0; W.BUFPOS; PUSH HL; PKLROW(); POP HL; R.HL->W.BUFPOS ... ...if no no. given: get BUFPOS & DE=next BUFP0 ... end ... else begin ...if no. given (in HL) BAK1: LD DE,(BUFP0) .M: ...test if filename given in cmd. line; if not, ret. Z=0 ...if so, put drive # at STRBUF+1, followed by DEFT 'FILENAME'; Z=1 P.FNDSPC; RET NZ ...if CR or ';' comes before sp., Z=0 TSTFN2: P.TONOSP; RET NZ ...find next non-space; check not CR or ";" own from top ...if string given, do FIND; else print starting at current line ...cursor stays with curr. line unless off screen if P.GETNUM not zero then begin ...check if a no. follows cmd. P.SRCH0; JR Z,FIND ...chk if a string follows cmd. P.F   LD (HL),A (*see note below) -> R.A ........................................ No code -> R.B (or R.C, D, --- etc.) .................. LD B,A (etc.) Additional 8-bit stores may be indicated directly by: R.A -> @HL -> SAVE -> R.B ..................9 (or other decimal number) ............... LD HL,999 W.0EFF (or other hex number) .................. LD HL,0EFF #5000 (or other number) ....................... LD HL,5000 #CONST ........................................ LD HL,CONST @2HL goes l level indirer ">=", corresponding to unsigned comparisons as determined from the zero and carry flags. These may optionally be followed by either "zero", by a CP.OPERAND (defined below) if the preceding instruction is not an HL-expression, or by 0, R.BC, or R.DE if t.sign-on msg. DEFM ' SCREEN EDITOR - 11/22/82' BYTE CR 0 ENDE: ...note: make label EBUF0 =beginning of text buffer (there must be 1 free space ... before this) & label EBUF9 =address 1 past end of text buffer ... (EBUF9 not necessary on CPM) ...Ex; INC HL LD (HL),D; DEC HL; EX DE,HL -> @2IX or @2R.IX (or IY) ..................... LD (IX),L; LD (IX+1),H -> @2IX(n) or @2R.IX(n) (same with IY) ........ LD (IX+n),L; LD (IX+n+1),H -> W.VARNAME .................................. LD (VARNAME),HL -> . LD (HL),A LD (SAVE),A LD B,A *Note: Some HL-expressions can modify R.A; thus R.A+@(@2HL) or R.A+@(^DATA+32) don't do the addition on the original R.A. HL - Expressions ---------------- HL-expressions deliver a l6-bit value to the HL regct .................... LD A,(HL); INC HL LD H,(HL); LD L,A (*note use of R.A) @2BC or @2R.BC ................................ LD H,B; LD L,C; LD A,(HL) INC HL; LD H,(HL); LD L,A (*note use of R.A) @2DE or @2R.DE ...................he intruction is an HL-expression. In the second case (with the CP.OPERAND), a CP instruction to compare with R.A is first generated before the flags are tested (an OR A is generated in the case of a compare with 0). In the last case, the code correspondample: EBUF0 EQU ENDROM&0FF00+0100 ... EBUF9 EQU EBUF0+((0F900-EBUF0)/0200*0200)  ... (EBUF9 not necessary on CPM) ...Ex must be 1 free space ... before this) & label EBUF9 =address 1 past end of text buffer ... (EBUF9 not necessary on CPM) ...ExVARNAME (if previously defined as WORD) .... LD (VARNAME),HL -> R.HL ....................................... No code Procedures ---------- Q also introduces new ways to call procedures. The following examples demon- strate: P.PROC1 , PROC1() , or PROCister. They also consist of a load part followed by any number of modifier and/or store parts. Load Parts Generated Code ---------- -------------- R.DE .......................................... LD H,D; LD L,E R.BC ........................................... EX DE,HL; LD E,(HL); INC HL LD D,(HL); DEC HL; EX DE,HL @2IX or @2R.IX ................................ LD L,(IX); LD H,(IX+1) @2IY or @2R.IY ................................ LD L,(IY); LD H,(IY+1) @2IX(n) or @2R.IX(n) (same with IY) whIV1.00 4!}:o*oo o ],!V]! p] ]!}!͹   ͞ x( >"͹   S)lgx !!GH 4 # (  >>KB>#vbk1 , where PROC1 has been previously defined as a 'PROCedure' symbol type (see below), all generate .......................... CALL PROC1 There can be optional arguments in the form of instructions separated by ";"s and enclosed by parentheses immediatel............ LD H,B: LD L,C R.HL .......................................... No code R.IX .......................................... PUSH IX; POP HL R.IY .......................................... PUSH IY; POP HL ^VARNAME ...................................ere n is an expression for a 1-byte numeric value (see 'Numeric Values' below) .... LD L,(IX+n); LD H,(IX+n+1) (or LD L,(IY+n); LD H,(IY+n+1)) also @2hl where "hl" stands for an HL-load part .... Load HL,--- @2HL (as above) ^"string" (effecti78 88&848B8P8^4.x!p4.nT $G7B]4/!0:J70L84CON4-4!@B_5 潒baL8L8!o8r!! %UU !UU % !/!a` ^B!q 6 k > k}͈(ɯ21:((Ì *."|!N#T]> wh  ͪ !+~ď  DM*c "W ( ! >2(ͧ:*=G ̓,̙> <2+( ͽ *d~#bk̓{8>(O ! y following the symbol. (This is so as to load values into various registers for instance.): PROCEDURE() ................................... CALL PROCEDURE P.PROC1(R.H) .................................. LD A,H; CALL PROC1 PROC2(B.VARNAME->R.B; 99->R.A) ... part 3 of Editor TSTV2SW: EQU 0 ...=1 if to test between Infoton 200 & Visual 200 terminals ...=0 if to just use default (presently Infoton) without testing ...see GETTERM below CRTTYP: ...determine type of CRT (Infoton 200 or Visual 200) ively points HL to in-line assembled DEFT) .................... CALL #1; DEFT 'string' #1: POP HL (HL-expression) e.g. (R.HL+R.BC)*2 ........... whatever is generated by HL-expr Modifier Parts Generated Code -------------- -----  !7.X3.XC: : :::13L8g7Q7^5f8~b8~{?P   g7 7Q7A  < -7 X2 c- ! 7 ( !E yK*B BR0 !" PYl (E ( ~ +> +R8!U !7 (Wy(KBͩ(ͽ `il (W!ͽ bk c RDMxW!U !F  ѷR................ LD A,VARNAME; LD B,A LD A,99; CALL PROC2 PROC3(W.VARNAME) .............................. LD HL,(VARNAME); CALL PROC3 Also, when procedures return values to be used in expressions, the type of value returned can be specified by the Wf not known B.CRT+1 ...if B.CRT=FF, CRT type not yet determined CALL Z,CRTI; RET ...det. CRT type + print version msg. ENDROM: ...the following code may be overlaid by edit text: CRTI: ...get terminal type, print msg., set CRT=1 1->CRT GETTERM() .  ---------- +carry+ R.BC (or DE or HL or SP) .............. ADC HL,BC etc. -carry- R.BC (or DE or HL or SP) .............. SBC HL,BC etc. + R.BC (or DE, HL, SP) ........................ ADD HL,BC etc. + 1 ........................................... INC A( #   ^hB⠉o  f8^ ~b8{^ :{Ѐ:: :4::~ ߼:::78 39  '2' ! 2::4:%1#2ͅ 5 ͽ (W 6#+ 06 #6#K B  w#+ 0! F * [Rͅ ͽ (E!y ͏ HIT KEY TO REENTER:!U !7 (5E*",".R"QU N [,*.R #*".!l (*".! *.~( ˿#. or B. prefix. For example, W.PROC()->R.BC or B.PROC()->@DE (The default for no prefix is word.) Relational Expressions ---------------------- The "if", "while", "repeat", and "case" statements take the following forms: "if" RELATION.BLOCK "then" ..get terminal type, poss. change contents of SCRVEC,KEYVEC SETKEYS() CLRSCR(); POSCRS(00; LD B,1) ...LROW-2) PRT0(^REVMSG) ...print version msg. RET SETKEYS: ...put KEYVEC (not DELKEY) in cmd table ^KEYVEC->R.HL; LD DE,CMDTBC2; LD BC,LKEYVEC; LDIR;HL + 2 ........................................... INC HL; INC HL - R.BC (or DE, HL, SP) ........................ OR A ... Reset Carry SBC HL,BC (etc.) - 1 ........................................... DEC HL - 2 ......................................103$j8&2$#j8:ȃ:!1!:B !<$G<%<-<#<+5+1+7+3+!!1!: @5+7+M8L8/L85`L8<T@:J2L8L".!+~=w*,"( ɯ2*>T !Uw#6 ͈_:J̗:SĽ{!0@:*([0>!5w:6( ͏4:7OͩS2U+> ##( A " >O0Ax i"yMO ͂OG*2R O " yP8O>[0S0x<26INSTRUCTION ["else" INSTRUCTION] ["endif"] "while" RELATION.BLOCK "do" INSTRUCTION "repeat" INSTRUCTION.LIST "until" RELATION.BLOCK "case" INSTRUCTION "of" CP.OPERAND or PROCEDURE or BEGIN.END ":" INSTRUCTION CP.OPERAND or PROCEDURE or BEGIN.END ":" I RET GETTERM: ...can test between diff. terminals (if can) & possibly change SCRVEC ... or just RET if not to change default terminal /IF TSTV2SW=0 THEN RET /ELSE ...below is set to test between Infoton 200 & Visual 200: ASKCRT(^RQIDV2) ...send msg. ..... DEC HL; DEC HL + R.[B] or other A-load part or (A-expression) e.g. +(R.A&0F) ........ LD A,[B] etc. (Note: A-expression may reuse R.HL) ADD A,L; LD L,A JR NC,$+3 INC H - R.[B] or other A-load part or (A-expression) ...................81+!.(o8K83+L80 8!8ĞjL8< 4 B:@_`TR7 …U7)x 7)p 4)p  ߲Ȁ($ O  pp :62:͏ !:4> yOU[2:625͂>26=25*R(S2 :50:5G:62625͂ xB*B"R#DMx*R#DM"#[*RB0w͑G( (#w S=qt!ͬt!~ <NSTRUCTION etc. ["else" INSTRUCTION] "end" (Brackets indicate optional constructions.) RELATION.BLOCK is a group of logical TEST's "and"ed and "or"ed together without parentheses, i.e.: TEST.1 and TEST.2 or TEST.3 . Higher priority is given to for request terminal id for Visual 200 ...Z=1 =>default (Infoton 200), Z=0 =>Visual 200 ...note: after request id, Visual 200 doesn't work unless clear screen CALL NZ,SETV2 RET RQIDV2: ...msg. to request V200 id which will not print on I200 DEFB 23 E..... LD A,[B] etc. CPL; ADD A,L; LD L,A JR C,$+3; DEC H INC HL *2 ............................................ ADD HL,HL /2 ............................................ SRL H; RR L = 0 (or :: 0) ................................. LD A,H;  OAȀ  H  4*m! H.(0P4*P.I驓 I PNE4(p 7CU5)a8x5'  B!B>S T4   K8r!7)5o8x5)v7U~ *+G#;=(G #=:7

P=27͠ɯ27͠:4!6 N:QU[0:5!62T!T~(5!45ͧ> 25U͏~ͽ4͠:6= [*0R!P!6~=5͠ɯ27<26͠"and"s. TEST is of the form INSTRUCTION RELATION. RELATION may be of several forms. In all cases a test is made on the Zero and/or Carry flags (sometimes code is generated to set the flags) and appro- priate JR CC,--- instructions are generated. The fiSC 'Z' 0 ASKCRT: ...output string @HL; chk if anything back, if so, goes to BC ...return Z=1 iff no response repeat until GET1IF() zero; ...get rid of any pending input PRT0(R.HL) ...output string @HL LD BC,0; W.1000; LD E,0 repeat if GET1IF() nOR L (*note use of R.A) = R.BC (or R.DE) (same with ::) ............... OR A; SBC HL,BC (or DE) ADD HL,BC Store Parts Generated Code ----------- -------------- -> R.BC (or R.DE) ............................. LD B,H LD C,L -> R.I)x1)ropFg`upF5)RݟFp6eFfc0cpFc g6SuFeQ!Gg/G5S3B3ݿ5(H5SFYyw0&7Yi0&)cF\ 85BS77(13(K3o58+3... LD HL,VARNAME W.VARNAME ..................................... LD HL,(VARNAME) VARNAME (where VARNAME previously defined as WORD) .............................. LD HL,(VARNAME) W.PROCEDURE() (see 'Procedures' section below) CALL PROCEDURE W.99rst form of RELATION is simply "zero", "not zero", "carry", or "not carry". ("not" by itself is the same as "not zero".) Example: if R.A+R.B carry then ... generates ADD B; JR NC,$+n Secondly, RELATION may be "=", "<>" (not equal), "<", "<=", ">", oot zero then begin LD B,C; LD C,A; INC E end until R.HL-1=0; R.E=0; RET SCRV2: BYTE CSADROV2 ESC CLRV2+080 ERSLV2+080 CRSYXV2+080 INSLV2+080 SETV2: ...put codes for V200 in SCRVEC ^SCRV2->R.HL; LD DE,SCRVEC; LD BC,LSCRVEC; LDIR; RET /ENDIF REVMSG: ..X (or R.IY) ............................. PUSH HL; POP IX -> @2BC or @2R.BC ............................. LD A,L; LD (BC),A; INC BC LD A,H; LD (BC),A; DEC BC (*note use of R.A) -> @2DE or @2R.DE ............................. EX DE,HL; LD (HL),E  a38. *QI/I/\8y8\ 813!o8.\8{M8L8/ Ȅ:: „!7&^&О5'̞4 &&A $. ‘6L8!Hȇ#`#a# T#`#a#҇a#/{qw   $GOD ҙq8Q|!?(Qo#{Q|!N7o#{ q @!da# c] #n#o#qx] #nAlso note that because jumps are limited to +/-128 bytes, there is a limit to the complexity of control structures.) If RELATION is left blank, a "zero" (or "=") is assumed. INSTRUCTION is any single Z-80 assembler or Q statement. In RELATION.BLOCK it  @B7 5B75 T%'13 ý %6` 11S06'`^^Ȁ###0#%##%Ȁ%Ȁ4@ :I '8RV"""""###,#T#%%v$'T)X+,v1?  "G???\na- .. /093 00 99 AA FF aa ff  AAߴys!>p!x!Bء8 !  M>psXsDB!>p L>p##L>s<ҍCЯ mkL (0  R U[G2NL8]ȁaciWyg75%7{ f''^ ^ ^< ?^ >^ ~11 '@ ; O6 $1  Ќ, 2' 3" в .  Г #o#C@0!ӭ] #n#o#T #`#a#X,!}ӡJQ!T#`#a#Ӳi!T#`#a#ӲT#`#a#Oq] #n#o#__!] #n#o#T #`#a#r|!is used to set the zero and carry flags. In "case" statements it is used to place a value in R.A which will be compared. Note: The BEGIN.END construction is considered an INSTRUCTION. INSTRUCTION.LIST is any number of instructions separated by ";"s or oa"3!-{Д$1 ?1 0 !{B1 _1   !{!2/!{ }63 5.75*7{5! 00,$wU 8  0PV!>Nt1@.K! `x // ::!>L0.X/nXޞ   uު` >>a c e` >>aec  ;; << >>C6hL,!>N1.cAe!>N!@ Г Л Ё ŕ{ 1 1 {   ߨ Ѡ3a;!  &ˍCwa{! &554 $&  m!'T#`#a# __!8T#`#a# a#ӜӾ n #j !L#] #n#o# [MA=!T #`#a# T#a#`# @!VL#1T #`#a#@!ԡn differ- ent lines and may also include labels (at the beginning of a line) or comments. (Remember that comments must start with "...".) CP.OPERAND is any single operand that can go on the right side of a Q-type compare instruction (R.A::op), such as a n4 U %%4q  BBߨ% CC.kp WW߶ SS!u߬ DDߣ FF2q ߌ.hp \\  NN  TT .hp.hp 4Hq1ս}> {8ಁ00 99.hp (0 A7!>p!Aa ҋ!hs@5j af! >a3 5aa7̡6"0! JC']>]>a<_Cf}} $00(   % 0}} ]>!5   ;; <<$ CJ Ϟ҈^$7 ꠱^" 5 5B7 ꠱{! Ľ1&0/C57B0qȂ>x>q>y>r>z>s>{>v>~>t>|>u>}>v>~ĕb8~L8~?] #n#o#T #`#a#ԒT#a#`#ԈL# T #`#a#] #n#o#qԴ] #n#o#T!T#`#a#eG!] #n#o#T #`#a#e2!eG!T#`#aumeric value. As used in the "case" statement, it is compared to the value in R.A. If the comparison is true, that case is selected and the following INSTRUCTION is executed; otherwise, it is skipped and the next case is checked. PROCEDURE, as used in tPP!`'d  -.hp24!A/ 00 .hpQ P !`W5p w @qp  !b paq*;v  0b/* L >>    60/caqW  /iap s'Y2!B .80.8T>P>T>ߜj>a >}} H?!  / $$" 11 99 0K? 3a5>!U HPk.hp.hp b8L8>a8¡]4_`M8a8…U AȆ>H>M4:"@M8žW*w@L8=L84za8i  .`   .` po8…L8 L8i3Q@iL8s}a8#T#`#a# f#d!9f# q d!&`#Ԟ{Ԣ{@!] #n#o#  pԾT #`#a#w  !Ҟ{ X !h] #ޠ n #so#T #`#!he "case" statement, refers to Q-type procedure call; that is, P.PROCNAME or PROCNAME(optional args.). When this is used, the zero flag is tested upon return from the procedure; if set, it is the same as if a match was found in the case of a CP.OPERAND c$`(! `dO(qwhcvyps3c27p߲]dT`ic桢qTd@x]w   * wB1 .kp.k}} ]>! ? !  ! @- 90100-(00 99...800 99. !@ {p  먐    #K8 ! (o8ȀЏ  qȀ &/ .k !.kҡ=Ȁ  L8_`Ȁ M8ȀM8L8L8!8o8o8(<=]]J 3& ˡ   Zy!Ղ] #ڠ n #so#@!չ] #n#o#T #`#a#@!հT#`#a#զ] #n#o#q] #n#o#jI!UM!T#`#a#@!T#`#a#X !ompared with R.A (see above). BEGIN.END is the sequence "begin" INSTRUCTION.LIST "end". In the "case" state- ment, it is used the same as a PROCEDURE to set the zero flag. Further notes: 1. End-of-lines (including possible comments) may go after INSTRU//%w @߳ !      ++ -- 00 99߹ ..  00 99ʫ) EE ee1 --5Ƀx V2!C7 }3 813 257 ,\  AD@!@}Ѐ~ BREAK AT TAdzZ` -  GG JJ DD߷ RR SS PP!@!P9?`!@^aAd  RR  HH]Ad}} a ֊n  . ա      ި      ^  @@0ɗ ߾ f  ݯT#`#a#,ՠՂ{\U!] #n#o#o#wq] #o#n#EJ!3] #o#n#T #a#`#qIcߜ!u] #o#n#T#a#`#f] #o#n#T #a#`#T#a#`lJh!vzqv~qV2.07. tdd disassemblerWrrdi {i Ói pj j j j" 7k 6 w * KDDDS $OeKKG]G;D DSKD(*** l:KK CLL3HfW""+L $O"  K++<Ёx!TP!  qr9諀  詀*" * p 00 99  ~w;P!  qr{諀 M詀  PX詀 vg A`}\A@yA`A@-͑1 ,,0& . .|.s   .. |.* }bғC5X bA}R_}Z (}R_}Z.(0_}ZX2 c- Kh8"Ѩ&Ȁ&0  S 0 &2$.&Ȁq&$5BB303%%5 5BɞB5%1% $\5 %0#֤T#a#`#xa# L(!֘ Zy!֣ k~e!֮a#YsS7{QB] #o#n#*]#o#n#ӹ]#wT #a#`#ѴT#a#`#c\# @!oT#D(**B*KQ.HfWEU۵w&wwwU~]$wk~kBinfFN~h #x ^VBi~kBi~kfnͦiѷbk# w>2@i#~: +~@##+x8( ~9j #x 2jx8(> >2@i~.   E++ E--P E..P *ު EEEP  E--P E++P E  00.IPn00.FP APbSE{m^P{xi[{уtf{юѠ P.GETNUM ...get no. after cmd.; default=1 LD DE,(BUFP0) while R.HL<>0 do begin DEC HL; PUSH HL; PKLROW(); POP HL end P.PRSCR0; RET ...B: @DE & UPCASE='O'; JP Z,BOTTOM ..."BO" means BOTTOM ...BACK: ...if number given, go back that many lines & pСc}߽)!c % 5 $P5 @B7 c1S9 05 `Ȁɞ0P!@!@ ߩ%l0|6ފވ '0a1111011'11Ȁ!T #a#`#O$@P]#] #o#n#q @!] #o#n#M# T#M]#(k#$] #o#n#qIT#M]# T#a#`#\k#k#M#-:JL>}2?}:a >J(2j#x8( ~9j #xh> 2@i:@iGj( k#v@@@@@kkkjkj!+h$=(x͆jkj0x͆jj >jx͆jj kj>jOkj0#kj!!jw#w#w(>~W#~O#~{*l{{ѣh{ѭя{ 1 (  0 !4ȅ!@ H4$уѼ{ 1 (0.HP{4|4ving to the expression R.HL=0, R.HL=R.BC, or R.HL=R.DE is generated before the flags are tested. Examples: if PROC() <> then ... generates CALL PROC; JR Z,$+n if PROC() >= zero then ... generates CALL PROC; JR C,$+n if R.A<2 then ... generates CP 2; }4!.'閭 213033'Ȁ''ɗ51@E B1@E B5364~ҿ'6 7 2c %333 ::CՕ ::5 & ''Ɋ'05 11@E %h!L>` -!?!l^M>Jߐ l ;;   // //[ ## ߡߓj8!   XXT - **K*  II o >JH !>Zo? o >h>] - ,, ޽o >J}bk##w#~: +~@##+>Jk~. #>Jk>\k >Gx( ~hk #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ x͆j((#kj!!jOW_}T]Oů)lau!t"w##lx( >!>l  olQ|!҄mo# q @!Ҙ] #n#o#qҢ] #n#o#G!T#`#a#ҼC!] #n#o#T #`#a#dm'!j6T!T#`#a#a#   qT JR NC,$+n if R.A<>0 then ... generates OR A; JR Z,$+n if R.HL<>R.BC then ... generates R.HL=R.BC [Q expr]; JR Z,$+n if R.A<=R.B then ... generates CP B; JR Z,$+4; JR NC,$+n (Note that "<=" and ">" each require the generation of two JR instructions. 8'%ᢗ(ᦗ'ȀщО5 ‘%1% $P5 %6Е!  c % 5 $U3c % 5B c 09 }Н<3Ȁ  c % Ž@B5Bc}c}'c}+A5} ]莞        ;;   .  󡕃5  ;,<>=* !! ~~ !/hTEM>Jݣݼ F GFILE NOT FOUND\n F GWRONG FILE TYPE\n F G%B???\nF   #lx( >">l  ol͆j!!x2(hS)h)lgxlGkjHkj 4 # (  >>:(hGj*)hDMBuCxuV2.07}!o~ (# ~ (>.~ (# êr/DO }rÊlÁr>2f!!m"g>! ming from left to right (no hierarchy of operations) except that there can be parentheses. No spaces are allowed. Numeric values are all calculated as 2-byte quantities; if only one byte is needed, the value will be truncated to the low-order portion. Nuch have been referenced (as well as any undefined symbols). /BANK n where n=1 or 2 sets memory bank n (bank 1 is the one contain- ing Q) to be the one on which code is put out. (There is a separate pointer to where code is to be put out for each bank;Ͳr:oWKj*j6 # x +6 Cj!h"j`i:vGͱu:v̯pMwpWRITE:vv>2vSv>iw!oUw*vGrtSw$*v:vGct :p > >!v~=wmypOPEN!v~׀2f!Om"g>!:m!= rÉwLx?yÜSmSm+"m!9" mRhh1p] Cs!mp~ (# ~ (>.~ (# ps/DO CsmmGsV2.07m* lpn pnp`m*meric values can consist of hex or decimal numbers (if the number starts with "0" it is considered hex--a trailing "H" is optional and has no effect), symbols, single ascii characters in quotes (e.g. 'A'), "2**n" (2 raised to the nth power), where "n" is a the bank 2 pointer is nominally initialized to 0400 more than that for bank 1.) n can also be left off, in which case this command will return the number of the currently set memory bank to the console. Additionally, /BANK SAV will save the currently-CTION, RELATION, "then", "else", "do", "until", or "of". 2. In the case statement, the various cases may alternatively be separated by ";"s instead of end-of-lines. 3. The case statement uses the stack to store an address while it is execu- ting. Thus, l is defined as 'PROCedure' low-order nibble=4: symbol was defined by DEFL low-order nibble=5: symbol was defined by EQU low-order nibble=8: symbol is undefined bit 4=1: symbol goes with memory bank 2 (otherwise with bank 1) bit 6=1: if symbol is unde pn qn'n*Kn,KntDD}M~ :L !D~lnP2/n cp]w@@@@@cpcpnlplpn@ plnother numeric value, or the expression "value(-----)" (to be described below). The above forms may also be preceded by a "-" sign, or combined and modified via the operations of addition (+), subtraction (-), multiplication (*), division (/), or anding (set memory bank and /BANK RES will restore the bank saved with the most recent /BANK SAV. (Default bank is bank 1.) Note: when faking 2-bank operation on a 1-bank system, be aware that an auto- matic ORG will take place when banks are switched. /if jumping out of the case statement (without returning), the stack should be popped. 4. Special code utilizing the Z80 DJNZ instruction is generated for "repeat" loops ending with "until DEC B zero;" ("zero" is optional). (The ";" must be present; if lfined, indicates referenced by JR instruction if symbol is defined, indicates there is no reference to it bit 7=1: symbol is global The symbol information is stored in a `symbol table' in memory. (This table initially contains global symbols from Q w@@@@@ppo*G;TͼMշB8(!HB0bk+>?_OM*G"G:D( *G> 1+H* G|(įNͩQǁ1+H (;(HET/DO ~#~ (; > ͯNH%RDPSD͇MsS1D( > &D y &D>  ( &). The expression "value(-----)" works as follows: Inside the parentheses is an INSTRUCTION.LIST (defined above) which is executed immediately (at compile time) to put a value in R.HL which becomes the numeric value. An example is WORD value(P.GETVIMAGE filename $(?(symbol:) addr1 addr2) ?("E="addr3) ?("RL=80") where $(--) and ?(--) mean `some no. of' and `optional', respectively, will image a file of name filename between memory addresses addr1 and addr2 (there may be up to 16 sets of addr1,addr2 peft off, the normal DEC B; JR NZ,$-n code will be generated.) Be aware that the zero flag is not automatically set in the DJNZ form of the loop. Symbolic Names -------------- A symbol in Q consists of one or more letters (upper and lower case) and dihich may be needed for extensions, debugging, etc.) The symbol table can be altered with the following commands: /CLEAR clears symbol table /ZAP list of symbol names e.g. /ZAP SYM1 SYM2 effectively deletes (zaps) those symbols from table (although thkk(+H_O>cv!v~v5͏p:oW( vwMw2okk͚z***** > *Gjv> }=O!kj"ij*ejq͚z ERROR ${*ejAL)*3 Using Q ------- Q's may be made to reside in either high or low memory and with different length symbol tables. In one common release format, Q resides in memory at 0A000 to 0F9FF and starts generating code into memory at 04400H. In addition, Q'airs) with the entry point set to addr3. ("symbol:" has to do with associating an offset with addr1 and addr2; this is described in more detail below under `Assembling with an Offset'.) addr1,2,3 may be either a hex number (must start with "0" if first digits (or "_"), of which the first character is an upper case letter. In addition, a "type" (BYTE, WORD, or PROCedure) may be assigned to the symbol when it is defined, using "BYTE", "WORD", and "PROC" pseudo-operations. Example: BYTE1: BYTE 5 0 BYTEVALey still take up space in memory) /ZAPALL [mask] zaps all symbols not masked out (see below) /PACK [mask] packs symbol table into minimum space saving only global symbols (not zapped or masked out) and undefined symbols /PACK ALL [mask] packs symbol qʹpN#ʹpcrkk!Cj4*Sj{pշB8(!kB0bk+>?crp*Qj"Sj:v( *Gj> 1kk*Mj|(ijqUxa1kk͕ (;(k͚z/DO ~; > # ͳqkxvpv|v͏pyv( > v y v>  ( 8 >#vbk  s which handle two memory banks use 0FA00-0FBFF for dual memory common code. To invoke Q, type Q or Q filename In the first case the system will respond with the prompt "-" awaiting the first line of input from the console. In the second case, an autgit is "A"-"F"), an HL-expression, or a "value(---)" expression (as described above under 'Numeric Values'). If the entry point is not given, it defaults to 0. Including "RL=80" causes the image file to be given a record length of 80H, otherwise the recor+3 This defines BYTE1 as a 'BYTE' variable and in addition assembles and stores the BYTE expressions which follow (one-byte numeric values, see below) in the following bytes. If now a statement is used like BYTE1 -> R.B R.B would get the value 5. It table saving all symbols not zapped or masked out Note: undefined symbols cannot be zapped or eliminated through packing. The form and meaning of the mask allowed in some of the commands above is as follows (where the brackets indicate optional constructq 6 (A  y  R >q> q>qy +>w#q "ejkkcr> :oWĨr!kkR0~q#v?( q͜r?( ͏pp:oW(!kkRDM*jB0Kj"j*j w 0w"j* Os* omatic /DO filename is generated and executed first (see below). The following is a list of commands which may either be entered from the con- sole or be in a file (either a program or a DO-file). Note that they all must start with either a "/" (as showd length is set to 200H. (The stack size is set to 0.) Example: /IMAGE FILEX ^START ^END E=^START+3 /IF relation.block THEN sets a conditional assembly state according to the result when `relation.block' is executed, where `relation.block' is exactlworks similarly for word quantities, e.g.: WORD1: WORD 999 998+VALUE 0B40 Note: There may be repeat counts (indicated by [n]) following any of the word or byte expressions; e.g.: WORD 0[10] 0800[5] The "PROC" pseudo-op simply defines a symbol as a 'PRions): mask=[c [m]] [R=[n1][,n2]] c and m are one-byte hex numbers (requiring a starting '0' if 1st digit is 'A'-'F'). c is compared with the 'type' byte with m used as a mask. A symbol is accepted if the bits of c which are '1' in m agree with the corrs(  s!s> 1p*n|(~svW1p͋ (;(pOx/DO ~#~ (; > ~sp͊vcmm mVr}wjm( > dm y dm>  ( 8 >#dmbk͍s 6 (A  y  R >͓s> ͓s>͓sy n) or a "*", and that this must be the first character on a line. ("/" and "*" are generally interchangeable except during conditional assembly, described below.): To assemble a file (and/or execute commands from it), enter /DO source-file name (If the y the same as the RELATION.BLOCK described above used with regular "if" statements. (The execution is done immediately, at compile time.) If the result is true, assembly proceeds normally; if false, the following statements (except for statements beginniOCedure' type, which enables a call to the procedure just by stating the name. Example: PROC1: PROC (followed by the statements of the procedure) WORDs, BYTEs, and PROCs normally receive the value of the current location counter. However, it is possibesponding bits in the 'type' byte. If m is not given, it is set equal to c; if neither c nor m is given, they are by default 0 (and thus all symbols would be accep- ted). "R=n1,n2" specifies that the symbol must be within the range n1-n2 (inclusive) to b+>w#͓s "o t:_ t!$s$=(xBt t0xBtͷt >͆txBtͷt  t>͆tO t0# t!!ͦtw#w#w(>V#N#~$#~+: ~@##>t~. #>t> u >Gx( ~file is of procedure type, it will just be loaded.) To obtain a source listing with generated object code, first enter /LIST listing-file name before entering /DO. /LIST without a name will display on the console. (To get a printed listing, first list tong with "/") are skipped. (This is the differ- ence between "/" and "*"; a command starting with "*" may be skipped, while those starting with "/" are always done.) In addition to /IF, the conditional assembly state may also be changed by the following: le to define them to be at an arbitrary position in memory as follows: ABC: BYTE at 02000 XYZ: WORD at ABC+10 etc. In this case no data can be assembled following the BYTE or WORD definition. Numeric Values -------------- Q allows some compile-time ee accepted. n1 and n2 are either hex numbers (requiring a starting '0' if 1st digit is 'A'-'F') or HL-expressions, e.g. ^L0+3. (n1 defaults to 0 and n2 to 0FFFF.) Examples: /MAP 8 will produce a map just containing all the undefined symbols. /MAPA 2 7 u #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ xBt((# t!!ͦtOW_}T]Oů)lau!t"w#ux( >!u  vux( >"u  vS"s)lgxBt!!G tH t 4 # a file, then print the file.) /LIST OFF turns the listing off but leaves the listing-file open /LIST ON turns the listing back on after a /LIST OFF /LIST END turns the listing off and closes the listing-file /MAP [mask] or /MAPA [mask] (where mask /ELSE reverses the conditional assembly state; /ENDIF resets the state to unconditional assembly. Note that the effect of these commands is independent of any nesting. Example: OPTIONS EQU 2 /IF OPTIONS=3 or R.A&8 not zero THEN ...result is false valuation of numeric values as used in expressions like LD HL,2*(VALUE+512) or ORG $+0FF&0FF00 or BYTE 2**3 (This does not apply to Q's extended A- and HL-expressions described above.) There may be any number of terms, with evaluation normally procedR=,5000 will produce an alphabetic map just containing symbols defined as WORDs with addresses <=05000. /ZAPALL R=^ABC,^XYZ will zap all symbols whose values are between ABC and XYZ. /PACK 0 40 will pack the symbol table saving only global symbols whi (  >>K"sB@8Z80(.`8}8&($/898(!8)8(+( >>2f!v"g>!v!= qy×zP{íïvïv+"dv!9"fvcrr1kk!N#T]> w~qGTtѯ: p  !vv is optional and will be des- cribed below) will display a compact listing of the source symbols and their addresses (or defined values) plus a byte in hex representing the symbol type on the console (and in a file if open for listing). (/MAP prints symbo  LD A,B ...this statement is skipped *DO FILE2 ...this statement is skipped /ELSE LD A,C ...this statement is compiled /ENDIF ...restores unconditional assembly state /START name or /START 0hhhh causes control to be transfered to the given ains with "$", the "$" is always considered to have the value of the current code position, regardless of the offset. The other case is when the expression begins with a symbol which has an offset associated with it (from a previous DEFL "at" statement). should be called if it is defined; if that fails, a procedure called "Id" is to be called (to check for an identifier) and if found, a 2-byte reference to the symbol of that name is made. Note that an XMETA rule must end with a ";", and that, since they c(00->R.C->R.D->R.E) W.080->R.HL->R.DE ...R.IX; LD C,0; LD DE,0; ReadF(@IY(RLU)->R.B); ...read in attributes POP BC; POP HL; LD DE,080; LDIR PutFPOS(00->R.C->R.D->R.E) W.080->R.HL->R.DE ...R.IX; LD C,0; LD DE,0; Write output files will be closed). The prompt is a "*". (To return to normal compile mode, type "Q".) From debug mode, any in- struction (or instruction list) that is typed will be executed immediately, with registers preserved from one line to the next (inddress, closing files first. /* jumps to debug mode (see below under 'Debugging') /BRKS->Q and /BRKS->P control the destination for breaks (see QBUG doc- umentation) /RESET EXTEND causes any extensions which have been made to that point using the labe In this case that associated offset will be subtracted off, giving a value correspond- ing to the location where code for that symbol would be put. Example: HIROM DEFL 0E000 at 05000 ...HIROM gets associated offset of .... 0E000-05000=09000 ROMall proce- dures in Q, they must go on bank 1. (To eliminate the calling of previously defined extensions, restoring the original condition with 'EXTEND' undefined in the symbol table, use the command "/RESET EXTEND".) For a fuller description of the XMEF(@IY(RLU)->R.B); ...write out attributes end POP DE; POP BC; PutFPOS(); 080; RET GetAtt: PROC @2IY(RLEN)->R.BC; @2IY(RDMA)->R.HL; if R.H|R.L not and R.B|R.C not then begin PutFPOS(00->R.C->R.D->R.E) W.080->R.HL->R.DE ...R.IX; LD C,0; Lcluding any changes made). All of the commands (beginning with a "/") are also valid. In addi- tion, there is a set of special QBUG commands (see `QBUG DOCUMENTATION'). Patch Statement --------------- To do patching of code, a "patch" statement of thel EXTEND (see below under 'Extensions') to be cleared /EOF (in a file) marks end of file. (It will be closed at that point.) // exits the program, closing files and returning to the monitor. In addition, any instruction or instruction list may be exec DEFL HIROM at HIROM ...define ROM=HIROM=0E000; ROM also gets ... associated offset of 0E000-05000=09000; code for ROM (after ... ORG ROM) will go same place as HIROM, i.e. at 05000 The IMAGE command is able to handle imaging of offset regions suchTA language in Q, see `XMETA DOCUMENTATION'. Miscellaneous Notes ------------------- 1. Before a label is defined, all references to it must be of the same type; that is, either all one-byte (relative) references, as in JR instructions, or all D DE,0; ReadF(@IY(RLU)->R.B); ...read in attributes ... W.080->R.HL->R.IX; LD C,0; LD DE,0; ... ReadF(@IY(RLU)->R.B); ...read in attributes @2IY(RLEN)->R.BC; @2IY(RDMA)->R.HL; if R.H|R.L not and R.B|R.C not then begin LD DE,080;  following form is provided: patch address,instlist This inserts at "address" a JP to the current code area; there the given in- struction list is inserted, followed by the 3 bytes of instructions displaced by the JP, followed by a JP back (to "address"uted immediately (from the console or during compilation) by entering /instruction.list e.g. /LD B,2; P.TEST Assembling with an Offset ------------------------- It is possible to assemble code at one location for execution at an- other. This is don that the file is imaged from the section of memory where the actual assembly took place while the offset addresses are stored on the file descriptor record (so they can be used for subsequent loading). The syntax for this is as in the follow- ing exampletwo-byte (absolute) references, as with JP or CALL or two-byte loads. This is because, depending on the type of reference, either a one or two-byte chain is set up in order to resolve the references when a sym- bol becomes defined. (Other thaEX DE,HL; LDIR end end RET  )->R.BC; @2IY(RDMA)->R.HL; if R.H|R.L not and R.B|R.C not then begin LD DE,080; EX DB); ...read in attributes @2IY(RLEN)->R.BC; @2IY(RDMA)->R.HL; if R.H|R.L not and R.B|R.C not then begin LD DE,080; +3). (A JP back to "address"+n, where n is a digit in the range 4-9, can be generated instead by replacing "address" by "address[n]".) "address" takes the form of either a hex number (must start with "0" if the 1st digit is A-F) or an HL-expression. Exe by setting the word variable OFFSET equal to the differ- ence between the desired value of a label (that is, so that references to it work properly after the code is moved for execution) and the location at which it is assembled. For example, to assembl: /IMAGE FILEA ROM: ^ROMBEG ^ROMEND RAM: ^RAMBEG ^RAMEND E=^ROMBEG Here, "ROM" and "RAM" have offsets associated with them which is applied to that particular image segment. (The labels ROMBEG, ROMEND, RAMBEG, RAMEND are offset; that is, they correspn with JR, one-byte references to undefined symbols are not supported.) 2. Numeric values, if they are to contain an undefined symbol, must not also contain a modification to the symbol value. As an example, the statement LD HL,NOTKNOWN+3 whe+R.DE->R.HL; ...Rec_Ptr->HL RET InitRW: PROC ...returns BC record count; FCB @DE; Random Record Pointer @HL R.B->LUN; LD (DMABEG),IX; R.HL+07F; 00; R.HL*2; RLA; LD L,H; LD H,A; ...HL/128 PUSH HL; if R.C<>0FF then begin 00; R.DE*2->R.HL; RL C; Rample: patch ^ABC+012, R.A->@HL; INC HL An alternate form of the `patch' statement is: patchr address,instlist This is the same except that the 3 (or n) bytes of instructions displaced by the JP to the patch area are not copied into the patch area. Noe code at 04800H to run at 06000H, do (in bank 1): /LD HL,06000-04800; R.HL->OFFSET (Return to normal operation with /W.0->OFFSET.) Note that labels (including "$") are all given the offset value, but symbols defined by EQU or DEFL are not (although the ond to the load addresses, not the addresses where the code was assembled.) A memory bank may also be associated with a symbol. If the (first) symbol in an ORG statement is not found on the current bank, the opposite bank is checked for a symbol of that re NOTKNOWN is undefined is an error. (This is because the chain set up to resolve the symbol reference would be messed up by the modification.) Statements like LD HL,NOTKNOWN or JP KNOWN+3 where KNOWN is defined are fine. 3. Numbers s the value 05400 ORG AA ...orgs to 04400 (code will be put out there) ORG 0+AA ...orgs to 05400 Note: Beware of trying to execute or reference code that is offset (specific- ally with regard to absolute memory references) Automatic Offset Handte that the `patch' statement must be entered during compile (as opposed to debug) mode. Extensions ---------- There are no Macros as such; however, user-defined extensions of the Q language using the XMETA compiler language may be made. This is done by could effectively be offset by being equated to an offset label). Special case: In an ORG statement, if the first item following "ORG" is a sym- bol or "$", the offset value is subtracted from it, thus cancelling its offset. (If the symbol was not offsename which was defined with an associated offset as above. If found, banks are automatically switched and the ORG then done. Write Statement --------------- A-expressions (which put out in hex the byte value ending up in R.A), HL-expressions (which put representing addresses in JP, CALL, or ORG statements, or the START command, are always considered to be hex, even without the leading "0" normally required to differentiate from decimal numbers. The leading "0" is still necessary, though, wheling: Besides setting OFFSET manually, there can be an offset assosiated with a symbol such that ORGs to that symbol cause a resetting of OFFSET. (Actually whenever the symbol is the first item following "ORG".) Example: ORG 05000 ROM DEFL 03000y defining an XMETA rule and giving it the label EXTEND. EXTEND is called at the point when Q is ready to parse an instruction. Examples: EXTEND:= "BRK" .OUT("HFF"); EXTEND:= "getit" GETIT / "putit" PUTIT; EXTEND:= "#CALL PROC1#" .OUT("=PUSH HL;P.PROCt, this would be an error.) The value of any fol- lowing symbols is taken as is. Note that the address supplied in an ORG state- ment should be the location at which the code is to be assembled. Example: ORG 04400 /W.01000->OFFSET AA: ...AA getout in hex the word value ending up in R.HL), and strings ("..."), separated by commas, can be printed out (to the console and an output file if open). For example, ?"VALUE=",W.VALUE,"X=",R.C+2 This statement would write out during execution of the progn the first hex digit is between "A"-"F". 4. Incrementing and decrementing R.HL does not set the flags; thus, the expressions: (HL-load part) +1, +2, -1, or -2 cannot be used to set the flags for a relation test. 5. Z80 instructions and register at $ ...define ROM=03000; ORG ROM will cause an ... actual ORG to $=05000 (place where code goes out) with ... OFFSET set to 03000-05000=0E000 RAM DEFL 0F000 at 07000 ...define RAM=0F000; ORG RAM will cause an ... actual ORG to 07000 with OFFSE1;POP HL"); EXTEND:= [EXT2] / .OUT("A2" *); The first case says that if the string "BRK" is encountered in a program, the hex code--this is what the "H" denotes--"FF" should be sent out to the code area. The second case says that if the string "get...assumes Q entry code as follows in 1st 14 bytes: ... LD BC,LEN; LD DE,QBEG; LD HL,0100; LDIR; JP START0 ...add DEASM below ^Q & put adjusted entry code below that QBEG: EQU Q-14 NEWQBEG: EQU QBEG-0B00 DEASM: EQU Q-0B00 ...start of DEASM (0B00=length) ram. To write out in immediate mode--i.e. from the console or during compilation--enter: /? .... Notes: R.DE changed at time of execution (pointed to output buffer) but old value stored in LASTDE and restored at end of `write' statement. R.A and R. names must be uppercase only. 6. Labels must start in the first column. The colon is optional. 7. "DEFB" and "DEFW" may define more than one byte or word as with "BYTE" and "WORD"; however, they do not define 'BYTE' or 'WORD' symbol types. 8. SymbT set to 0F000-07000=08000 CRAM DEFL 09000 at 09000 ...define CRAM=09000; ORG CRAM will cause an ... ORG to 09000 with OFFSET set to 09000-09000=0 The symbols defined in this way may be redefined as usual with a regular DEFL- statement, with the associt" is encountered, the procedure GETIT is to be called (which may do anything--do further testing, put out code, etc.); failing that, if the string "putit" is there, the proce- dure PUTIT is to be called. (GETIT and PUTIT should both return with the Z-flSCRATCH: EQU 0500 /LD DE,NEWQBEG; LD HL,QBEG; LD BC,14; LDIR ...move entry code /LD IY,NEWQBEG; LD DE,0B00; @2IY(1)+R.DE->@2IY(1); @2IY(4)-R.DE->@2IY(4) ORG DEASM /DO DEASM.S ORG 0100 /?"/IMAGE Q.COM ",begin LD BC,0B0E end,^Q-R.BC," 0",@2(TABBSE->R.BC)HL changed with each A- or HL-expression put out. "begin-end" blocks, separated by commas, may also be included within the `write' statement to do calcultions or put output data @DE. The procedures 'WSbgn', 'WSend', 'Copy', 'HLout', and 'Outhex' (whiols are made global by appearing in a GLOBAL statement of the form GLOBAL symbol1 symbol2 etc. (Slightly better speed results when GLOBAL statements come after the symbols in them have been otherwise referenced.) To get rid of local symbols,iated offset remaining the same, or given a different associated offset by another DEFL "at" statement. Note that the expression on the right of the "at" should be a numeric value of the same form as that pre- ceding, but with two special cases: if it begag set.) In the third case, if the string there is encountered the code for the instructions following the "=" sign in the ".OUT()" expression would be put out to the code area. The fourth case shows how to allow for further extensions, namely that EXT2 +R.BC-1  .COM ",begin LD BC,0B0E end,^Q-R.BC," 0",@2(TABBSE->R.BC1); @2IY(4)-R.DE->@2IY(4) ORG DEASM /DO DEASM.S ORG 0100 /?"/IMAGE Q.COM ",begin LD BC,0B0E end,^Q-R.BC," 0",@2(TABBSE->R.BC)ch are in Q) must be present (and in the symbol table during compila- tion) in order to use the `write' statement. Debugging --------- Q contains a symbolic debugger. To enter debug mode, type "/*" (this can also be in a file; any open input or  use /PACK or /PACK ALL (along with /ZAP--). (Global symbols may also be zapped if desired.) There is no EXTERNAL statement. 9. Normally, only symbols defined in the memory bank currently set may be re- ferenced. However, symbols in the oppositw) E0+01A & following: 7 more WORDs equal to the addresses of the following additional routines (also described below): LINBEG NXTLIN LTOCR DIGIT NUMBER HEXD HNUM EBUF, ENDDAT, and ENDBUF may be referenced as needed in ECODE but should not beere E0 is the low address of the editor) and return with the Z-flag set. This code may also check the version no. of the editor (stored at E0+0C) against that for which the extension was made and return with the Z-flag reset if it doesn't match. Finally,urn. LTOCR: enter with R.DE in text buffer; returns with R.BC=distance to next CR (0 if at a CR). R.HL, R.DE preserved. DIGIT: checks if a digit ('0'-'9') is at R.DE: if so, its value goes to R.A, R.DE is incremented, and the zero flag is set; otherwe bank may be referenced in EQU or DEFL statements by prefixing a "1." for bank 1 or "2." for bank 2 (or "s." for the bank last saved with a /BANK SAV command) before the symbol name. Example: ABC2: EQU 2.ABC (this would be used in bank 1) changed. ENDDAT is changed automatically by NEWSTR (see below). The addresses of routines inside the editor which may be of use (particularly NEWSTR) are also provided here so that they may be set up as equates in case EEX and ECODE are assembled separa the file must be set to subtype "E". [There is a file E.X.M which, when assembled by Q, automatically gets relevant addresses from E and turns an appropriate extension source file (i.e. one con- taining the routines EEX and ECODE) into a special editor ex Extensions to Full Screen Editor (This is for the Z80 version; for differences with Z8000 version, see at bottom.) Extensions to the editor can be made to handle writer-defined searching and changing operations. Two routines must be supplied, one, labise returns with zero flag reset. R.HL, R.BC unaffected. NUMBER: enter with a digit in R.A (thus normally called after DIGIT); continues to get digits from @DE (incrementing R.DE) as long as there are more; returns with the value of the digit sequence 10. Q contains a byte variable QOPTS which is used to specify certain assembly options. Currently, there are two: In order to allow redefinition of labels, e.g. so a program can be rerun (ORGing to the original starting address) so as to obttely from the rest of the editor. ECODE may replace any character in the text buffer and do any searching, etc. with its own routines; however, to insert or delete text, a routine in the editor called NEWSTR must be used. When called, this is to be provitension file.] ******************************************************************************* Notes on using Editor Extensions with Z8000 EE: The general procedure is to assemble the editor extension file by running :Y EE.X.MAKE which asks for the nameled EEX, is called to parse the command and the other, labeled ECODE, is called to execute the command. These two routines may either be assembled with the rest of the editor or else separately and then linked to the editor by poking the address of EEX i in R.HL and the zero flag set. HEXD: same as DIGIT but checks for a hex digit ('0'-'9','A'-'F'). HNUM: same as NUMBER but gets a sequence of hex digits. Examples: In the first example, EEX just tests for a "1" or "2" and sets a switch. The result wiain a listing with all the correct addresses showing, set bit 0 of QOPTS equal to 1 (e.g. by /1->QOPTS, done in bank 1). Secondly, in order to get listings to show the offset addresses of code assembled with an offset, instead of the actual codded, in R.A, the number of characters to be deleted starting at the current position in the buffer as marked by R.DE, and also, in R.HL, a pointer to a DEFT-like string which is to be inserted at the current position. (The first, or length byte of this ste of the source file and then the name for the image file. The source file would generally be the same as described above, that is, with the routines EEX and ECODE. R7 is the pointer to the command string in the case of EEX and the the text in the case onto locations E0+0C and E0+0D (where E0 is the low address (normally 4400) of the editor) and poking the address of ECODE into locations E0+0E and E0+0F. In this latter case, in order to provide room for these routines, it may be necessary to adjust the vll be that, if a "1" follows the "." in the command, U1 will be called when ECODE is called, and if a "2" follows, U2 will be called. If neither a "1" nor a "2" is given in the command, EEX resets the zero flag so ECODE will not be called. U1 here simplye locations, set bit 1 of QOPTS equal to 1. 11. Some instructions or commands, in particular those needing to do some cal- culations or immediate execution, may temporarily use a few extra bytes in the code area. However, ORG, DEFS, EQU and DEring may be 0.) The specifications on this, as well as some other routines in the editor are given below. Note that the the 'FF' marking the end of the file and also a carriage return in the byte preceding it are required; the editor will put these back f ECODE (corresponding to R.DE above). Also, the addresses of the words EBUF, ENDDAT, ENDBUF, and the procedures LINBEG, NXTLIN, LOCSTR, NEWSTR, and NUMBER are known and can be used. LINBEG, NXTLIN, LOCSTR, NEWSTR, and NUMBER work as follows: LINBEG: enalue of EBUF, a word storing the start address of the text buffer, or ENDBUF, a word storing the end address of the text buf- fer. The locations of these are given below. Also note that there must be one free space before the start of the buffer. If def says to advance the cursor to the next charac- ter, while U2 says to replace the next occurrence of the string 'XX' with the string '333'. EEX: if @DE='1' then 1->B.XSW; if @DE='2' then 2->B.XSW; RET ECODE: if B.XSW=1 then P.U1 else P.U2; RET U1: INC DE;FL statements, and the QBUG commands, will not. 12. "stop" generates BYTE 0FF. 13. It is possible to move the symbol table elsewhere in memory or change the amount of space allocated for it. There is a global symbol TABBSE at which is stored  over anything else put in these posi- tions. Upon returning from ECODE, the screen will be printed with the cursor on the character pointed to by R.DE. Description of some routines in the editor which may be used: LOCSTR: search text for string: enterter with R7 in text buffer; returns with R7 pointing to character after previous carriage return or at beginning of file. NXTLIN: enter with R7 in text buffer; returns with R7 pointing to character after next (or current) carriage return. LOCSTR: Call ined, EEX is called after a "." is encountered as the first character in a command. (Tags must not be present.) It is passed, in R.DE, the position in the command buffer of the character following the ".". EEX should parse the command, setting switches, RET U2: LD BC,0FFFF; LOCSTR(^TXX); RET NZ; NEWSTR(2;^T333); RET XSW: BYTE 0 TXX: DEFT 'XX' T333: DEFT '333' In the next example, EEX simply tests for a "S". ECODE in this case consists of a procedure to change a list file (according to the format of Q vthe starting address of the symbol table; in the following word is stored the address 1 past the last location allocated for the table. The 1st word of the table stores its current size. Simply move the table as desired and patch into TABBSE a with R.DE pointing to position in text buffer to start search for string, R.HL pointing to a DEFT-like string (that is, where the first byte = the no. of bytes following), and R.BC= the maximum no. of bytes to search (except that the search will not gowith R7 pointing to text, R3 pointing to a DEFT-like string (that is, where the first byte = the no. of bytes following) to search for, and R5=max. number of bytes to search (won't search past end-of-file). If the string is found, R7 is returned pointin counts, etc. It may even generate code, if desired, at ECODE (Q may be used if it is also in memory). In any case, EEX should return with the zero flag set if there is a valid command; otherwise reset. Also, R.DE should be in the command buffer at or beersion 1.45) to a source file. EEX: @DE='S'; RET ECODE: P.LINBEG while @DE<>0FF do begin ^CT; LD (HL),1 if P.HEXD then begin INC (HL);INC (HL);INC (HL);INC (HL) INC DE;INC DE;INC DE if @DE=' ' then begin INC (HL);INC (HL);INC (HL) end nd TABBSE+2 its new position. Example: Suppose the symbol table starts at 0A000 and it is desired to move it so it starts at 09000. The following code will accomplish this: *@2TABBSE->R.BC; TABBSE->R.HL; LD DE,09000; LD (TABBSE),DE; LDIR  past the end of file). If the string is found, R.DE is returned point- ing to the first character in the string and the zero flag is set; otherwise, R.DE is pointed after the last character searched and the zero flag is reset. R.HL is preserved. NEg to the first character in the string and the zero flag is set; otherwise, R7 is pointed after the last character searched and the zero flag is reset. NEWSTR: delete and insert text: enter with R7 pointing to position in text buffer, R5=no. of characfore the ";" or carriage return terminating the command and after any ";" used in the command. If EEX indicates a valid command, ECODE is called. It is provided, in R.DE, the position in the text buffer of the character at the current cursor loca- tion.  P.LINBEG end NEWSTR(B.CT;^NULSTR); P.LTOCR if LOCSTR(^TBBRAK) then begin repeat DEC DE until @DE<>9; INC DE P.LTOCR; NEWSTR(R.C;^NULSTR) end P.NXTLIN end RET CT: DEFB 0 NULSTR: DEFB 0 TBBRAK: DEFT ' [' Special Editor Extension The symbol table may now be re-imaged (along with the rest of Q if desired) between the addresses TABBSE and @2(TABBSE->R.BC)+R.BC-1. 14. The following are entry points into Q (referenced to "Q", a symbol equal to Q's link address): Q: normal WSTR: delete and insert text: enter with R.DE pointing to position in text buffer, R.A=no. of characters to delete starting at R.DE, and R.HL pointing to a DEFT-like string (see LOCSTR above) to insert at the same position. (Won't delete past EOF.) Iters to delete starting at R7, and R3 pointing to a DEFT-like string (see LOCSTR above) to insert at the same position. (Won't delete past EOF; also, if R3 or @R3=0, no insertion will be done.) If operation sucessful, returns zero flag=1 (unsucessful In addition, there is a vector starting at E0+010 consisting of the following: E0+010: EBUF, a WORD containing the start position of the text buffer E0+012: ENDDAT, a WORD containing the buffer position of the 'FF' marking the end of the file  Files: It is possible to make a special type procedure file containing assembled editor extensions as described above which can be loaded in by the editor with a "GE" command, thus making those extensions available for use. This file must be made to loadentry or reentry Q+3: entry point when first loaded (looks at system command buffer for file name) Q+6: same as above but looks wherever R.DE is pointing 15. This documentation is for Q version 2.07 of 3/26/81. same as above but looks wherever R.DEf operation sucessful, returns zero flag=1 (unsucessful might be if no room to insert string after deletion takes place) and R.DE pointing after the last character in- serted. ENDDAT, the pointer to the end of the file, is updated; R.HL is preserved.  might be if no room to insert string after deletion takes place) and R7 pointing after the last character inserted. ENDDAT, the pointer to the end of the file, is updated. NUMBER: enter with R7 pointing to command string or text. If a decimal number  E0+014: ENDBUF, a WORD containing the position of the 1st byte past the end of the text buffer E0+016: a WORD equal to the address of the routine LOCSTR (described below) E0+018: a WORD equal to the address of the routine NEWSTR (described belo into a free area of memory (such as possibly above the text buffer). In addition, there must be code at its entry address (which must also be the low address), to store the addresses of its EEX and ECODE labels into E0+0C,0D and E0+0E,0F respectively (wh LINBEG: enter with R.DE in text buffer; returns with R.DE pointing to character after previous carriage return or at beginning of file. NXTLIN: enter with R.DE in text buffer; returns with R.DE pointing to character after next (or current) carriage ret lU]!v")]Gr> []e^e]Wr*)]e][]e]N#[]́]͘]e]>0{S+][)]S)][+]ͯyo]*+]w#"+]o]og}(%#o]oo]gXxe] ~ N#y( >+>0y${[]ɯ2.]e]>!8{!( (,(( GH L( []:.]=>P; ^NMI_Rtn->W.BRKRTN; RET ...set brk ret addr RSTS: PROC 7; LD BC,3; ^JPR; LD DE,8 ... repeat PUSH BC;LDIR;PUSH HL ...move jump into place W.5+R.DE;EX DE,HL ...advance to next rstrce ptr '!'->@DE; INC DE ...put '!' at end to stop parsing LD BC,(FREE); PUSH BC ...save stack top SAVX() ...save INSTLIST (@HL--DE) in user stack POP DE ...recall start of INSTLIST in stack INSTLIST() ...go parse statement POP DE .^Jh!vzqv~qV2.07. tdd disassemblerWr]&T {i Ói pj j j j" 7k 6 w * KDD@hDS $OeKKG]G;D DSKD(*** l:KK CLL3HfW""+L $O"  KDE+1 LD C,'"' SR2: SRDO(LD B,80) ...max count=80 RET Z TULONG: Errm(); DEFT 'TOO LONG' SRDO: ...enter with R.C=end str. char; R.B=max. count LD (LASTDE),DE; @DE->R.A repeat R.A=0D; JR Z,TULONG; INC DE; @DE=R.C; RET Z until DEC B zero; ...note: abo2.]-^x( }O(###T]#+#[]D^e]>I:-]e]-^"o]o]( 9]-0D9]+0e]${[]o] `o]v  _@o] 9]LD B_/],`o] _o] co] a o] Ϳeo] o] 9]JR ( 9]DJNZ G]o] 9] loc. POP HL;POP BC until DEC A zero RET JPR: JP Err0; JP Test; JP Icopy; JP Out; JP OutN; JP BrkRtn; JP BrkRtn NMI_Rtn: PROC EI; EX (SP),HL; JR BrkRtn2 ... BrkRtn: PROC ...*****temporary break routine******** EX (SP),HL;R.HL-..recall NEXTDE Ig() ...pop text from stack 00; RET ...1->Z end LD C,E; LD B,D LD DE,(NCODE) OUTCP() ...go handle data in buffer (R.A=1st char., HL at 2nd) LD (NCODE),DE ...new NCODE OUTDUN: LD DE,(NEXTDE) 00; RET OUTCP: ...checks 1st charD(**B*KQ.HfWEU۵w&wwwU~]$wk~kBinfFN~h #x ^VBi~kBi~kfnͦiѷbk# w>2@i#~: +~@##+x8( ~9j #x 2jx8(> >2@i~.ve must be DJNZ RET Sr1: PROC ...testing for exactly one byte not " SRDO(LD C,'"'; LD B,1); RET Z DEC DE; RET Count: PROC ...inserts count byte into output B.LASTDE->R.B B.NEXTDE-R.B->@DE INC DE; RET Inhex: PROC ...convert 2 hex digits @HL to val EX AF,AF'9]DEFB 0?^o] ͔ao] 9]DEC (9]INC  o] ͂_o] o_o] /]C/]Bo] /]E/]Do] ͢_o] /]L/]Ho] /]A9](HL)o] /]E/]Do] _o] /]L/]Ho] /]A9](H1; BrkRtn2: R.HL->D_PC; PUSH AF; W.4+R.SP->D_SP; POP AF; EX (SP),HL JP B_RTN I_INIT: PROC ...make sure set up right for interrupts ... BYTE 0ED 057; ...LD A,I; ... if R.A=0FF then 1 else 0; ... R.A->IOP; ... 0E0; OUT (CTC0),A ...program CTC int. vect. & then does the appropriate ops. on data in buffer if R.A='"' then begin DEC BC; JR CPQ end if R.A=''' then begin CPQ: repeat WRaDEi(@HL) until R.HL+1=R.BC; RET end ...CPC: if R.A='C' then begin ...CHECK FOR CALL TYPE WRaDEi(0CD) ...put out(2j#x8( ~9j #xh> km2i(̀ xk#v@@@@@lmkj0000NH28707H20!+h$=(x͆jkj0x͆jj >jx͆jj kj>jOkj0#kj!!jw#w#w(>~W#~O#~ue in R.A, inc. HL; uses R.C B.ASCtoN(@HL)*2*2*2*2->R.C ...high nibble B.ASCtoN(@(R.HL+1))|R.C->R.A R.HL+1; RET ASCtoN: PROC ...converts ascii char. 0-9,A-F in R.A to its value if R.A>='A' then R.A-7; R.A&0F; RET HLout: PROC ...put out R.HL in hexL)@o]  e͉` o] _o] ͹_o] /]C/]B o] o]  _( 9]EX DE,HLo] 9]IN A,(ͱa/])f  o] `o] `o] 9]ADC A,9]ADD A,o] 9]SBC A,9]SUB o] ao] 9]XOR 9...12/9 ORe0 removed Test: PROC ...enter with DE->data; ret. addr.->DEFT 'STR' to compare against ...returns Z=1 if found, DE->next char., LASTDE=old DE POP HL LD C,(HL); INC HL ...get count if @DE<>@HL then begin ...test 1st char. LD B,0; R.HL CALL opcode ... LD (NCODE),DE ...SO Lkup WILL WORK JR ISA2 ...GO INSERT ADDRESS end R.A='A' ...symbol reference JP NZ,CPB ISA2: ...ENTER HERE AFTER C TYPE, 2ND CHAR = ' ' @HL='1' ...GET SECOND CHAR INC HL JR Z,ISA1 if begin LD BC,(SAVNCD); R.bk##w#~: +~@##+*t*tssB B RmB B $*t*tisHs""mkuu55w]ylȑR@HL; LD DE,(LASTDE) ...test failed, restore DE LD C,B; LD B,0 ...remaining count->R.BC R.HL+R.BC; JP (HL) XLAT: B|R.C end not zero and @HL>='A' then begin Lkupnl(); JR NZ,NDFERR; JR C,NDFERR ...if imm. ex. or ORG, etc. then symbol (exc. tmp.) must be defined end else Lkup() ...look up Id @HL; afterwards HL,IY->table entry endif if not zero then begin ..125 ORG DEASM /DO DEASM.S ORG 0100 /?"/IMAGE QD.COM ",begin LD BC,0B0E end,^Q-R.BC," 0",@2(TABBSE->R.BC)F / 40 EDNN / EDBY;; &ED427A := (08 .O("ADC HL,") / .O("SBC HL,")) SS45;; &ED437B := .O("LD ") 08 SS45 .O(",(") NN .O(")") / ED437BP2;~ &ED437BP2 :=; POP AF HBTHEX: R.A&0F|R.A; DAA; R.A+0F0+carry+040->@DE; INC DE; RET ...TABLE ENTRY FORMAT OF SYMBOLS (byte pos. from beg. of entry): LOC: EQU 0 ...value of symbol LINK: EQU 2 ...link : 2 bytes TYPE: EQU 4 LNGTH: EQU 5 ...length of symbol name NAME: EQU 9]LD b /],͏]/]0?^ ?^o] yd o] ~g9]CALL o] $b9]CALL Je /],o] o]  _(͉` ͱao] Ibo] 9]PUSH 4co] 9]DEC (9]INC  o] o] 9]SP(9]HLo] 9]DE9] DEFM ' :;<=>?' ... 0 - 9 DEFM '@ ' ... A - O DEFM ' [\]^ ' ... P - Z and _ DEFM '` ' ... a - o DEFM ' {|}~'; BYTE 07F ... p - z Id: PROC ...test for upper or lower case seq of letters & digits, .if not found WRaDEi(00); WRaDEi() ...00->addr. to mark end of chain SET UNDEFB,(IY+TYPE) ...mark as undefined end else begin WRaDEi(@HL) ...copy low-order table entry->code area WRaDEi(@(R.HL+1)) ...copy high-order table entry->code area ...for single-bank Q: SvSP2: EQU 0 ...Skip2: EQU 0 RETSYS: JP SYSRET ...ret. to RIO RDaHL: @HL->R.A; RET RDa2HL: LD C,(HL); INC HL; LD B,(HL); DEC HL; RET WRaHL: R.A->@HL; RET WRaDEi: R.A->@DE; INC DE; RET WRa2HL: LD (HL),E; INC HL; LD (HL),D; DEC HL; R6 ...start pos. of name ...bits of TYPE byte: BYTET: EQU 1 ...XXXX0001 if defined as BYTE WORDT: EQU 2 ...XXXX0010 if defined as WORD PROCT: EQU 3 ...XXXX0011 if PROCedure definition DEFLT: EQU 4 ...XXXX0100 if defined by DEFL EQUT: EQU 5 ...XXXX0101 if deBCo] o] B`(Fco] ͓c9]POP o]00 9]AF o] o]  _(9] EX (SP),HLo] 9]OUT (ͱa9]),A9]JP b o] "o] 9]LD SP,HL( 9]JP (HL)o] 9]EXX9]RETo] ͯb9]LD  o] $d(o]starting ... with upper case letter; i-o same as Test @DE='A'; RET C R.A->R.L; 'Z'=R.L; RET C LD (LASTDE),DE LD BC,XLAT-'0' repeat INC DE; @DE='0'; JR C,RetZ LD H,0; R.A->R.L ...char.->HL until R.A=@(R.HL+R.BC); RET ...Z=1 Digit: PROC .....this file includes editor extensions ".A" & ".J" CMDTYP: BYTE 0 EEX: PROC if EEXA() or EEXJ() then R.A->CMDTYP RET ECODE: PROC if CMDTYP='A' then ECODEA() else ECODEJ() RET ...editor extension to add LF's after every CR + add ctrl-Z at end ... (ET WBCa2HL: LD (HL),C; INC HL; LD (HL),B; DEC HL; RET RDLDIR: WRLDIR: LDIR; RET Q_B: 080; JR SETBF ...set brks->Q P_B: 020 ...control back to PROM debugger SETBF: R.A->B.BRKFLG; RET TSTCPU: CP A ORGOTHR: B_RTN2: Step2: Debug2: BK_P2: Ret1: GO2: RET ..fined by EQU UNDEFB: EQU 3 ...XXXX1XXX if undefined BANK2B: EQU 4 ...XXX1XXXX if symbol in memory bank 2 ZAPB: EQU 5 ...XX1XXXXX if symbol reusable AL1B: EQU 6 ...X1XXXXXX if undefined, indicates AL1 chain exists ... if defined, indicates no refs. to  9]A,(b/])(/](b 9]),Ao] !o] 9]A,((9]HL,(b/])o] /](b9]),A/](b 9]),HL o] >Y2-](>X2-]*+]ͥd "+] _o] !fo] /](7^D^/])(o] 9]JP (7^/])o]6 9]LD (7^D^9]).test for a digit @DE='0'; RET C if R.A<>'9' then RET NC STARIT: LD (LASTDE),DE; INC DE RetZ: CP A; RET ...set Z=1, R.A=char. tested Hexd: PROC ...test for a hex digit; ret. in R.A Digit(); RET Z R.A='A'; RET C R.A='G'; JR C,STARIT R.A='a'; RET C still have CRFF at very end) ...call with ".A" EEXA: PROC @DE&0DF='A'; RET EOFSTR: BYTE 2 01A 0D ECODEA: PROC EBUF->R.DE->R.HL PUSH DE LD BC,0 repeat ...count no. lines (->BC) if @HL=0D then INC BC INC HL until R.A=0FF; PUSH BC; PUSH DE S.*ZAP SP2 SYSRET BRKFLG BRKRTN NCDTAB BKINIT CHKRD ...in MMETA *ZAP SETBF ...*PACK ALL .control back to PROM debugger SETBF: R.A->B.BRKFLG; RET TSTCPU: CP A ORGOTHR: B_RTN2: Step2: Debug2: BK_P2: Ret1: GO2: RET ..symbol exist GLOBLB: EQU 7 ...1XXXXXXX if global Outset: PROC ...set up for OUT functions LD (NEXTDE),DE LD DE,BUFF RET Outp: PROC ...put out from ^BUFF to R.DE (+CR) to file if open, else to $CON 0D->@DE; INC DE; PUTREC() JR OUTDUN ...NEXTDE->DE;,ͱae^ ]o] jbo] co] 9]JP Je/],b9]RET  o] ͋eo] o] /]C(9]NCo] /]Z9]NZo] o] /]M(/]Po] 9]PE9]PO9]JR e /],G]o] o] /]C(9]NCo] /]Z R.A='g'; JR C,STARIT R.A|R.A; RET ...false ... [ABC] => CALL Latch;DEFW ABC ... Latch is a call allowing undefined symbols Latch: PROC POP BC ...^^ABC @BC->R.L; INC BC; @BC->R.H; INC BC ...^ABC->R.HL PUSH BC ...return address Latch2: if R.HL=0 not zeHFIFR() ...or could do SHFIFR_ POP DE; POP BC EBUF+R.BC->R.HL repeat @HL->@DE; INC HL; INC DE if R.A=0D then begin 0A->@DE; INC DE end until R.A=0FF; DEC DE NEWSTR(00; ^EOFSTR) POP DE; RET ...BIGSTR: BYTE 255 ...STRCNT: BYTE 0 ...SHFIFR_: .) BRKJMP: BYTE at 066 BRKRTN: WORD at 067 ...@@@ at 013CE ...RIO jump address if BRKFLG set D_PC: WORD 0 ...@@@ at 012D5 ...RIO saves PC here D_SP: WORD 0 ...@@@ at 012D7 ...RIO saves SP here RR_AF: WORD 0 ...@@@ at 01000 ...start of stored regs on remote  1->Z ... OUTHHL: OUTHRL(); Outhex(R.H) ...puts out "H"+R.L in hex + R.H in hex; cont: ... Out: PROC ...C->CALL L->LABEL B->BINARY "->STRING ...A1->AL1 A2->AL2 H->HEX V->1 byte =->ASM ...D->DEFINE LABEL = ((NCODE)-2) B.DIAGSW->R.A if BIT 3,A 9]NZo] kf@o] ͝f o] ͧfo] o] 9]RR (9]RL o] 9]RRC 9]RLC @o] 9]SET ͈f9]RES o]e]${>,[]9]BIT /]So] /]R(/]L o] /]L(/]A/] @o](o] >g o] Fo] ro then JP (HL) ...if HL<>0, jump to routine DEC A; RET ...Z=0 ...COPY routines: output to at DE with DE updated Icopy: PROC Outset() Copy: PROC ...DEFT to copy follows call EX (SP),HL; PUSH BC LD C,(HL); INC HL ...get count COPYSB() POP BC; EX (SP..fake SHFIFR using NEWSTR ... PUSH DE ... while W.255R.BC ... W.255+R.DE->R.DE ... end ... R.C->STRCNT ... NEWSTR(00; ^STRCNT) ... POP HL ... RET .cpu (AF,BC,DE,HL,IX,IY) RR_SP: WORD 0 ...@@@ at 0100C ...stored SP on remote cpu RR_PC: WORD 0 ...@@@ at 0100E ...ditto PC SRR_AF: WORD 0 ...@@@ at 01010 ...start of stored shadow regs. on remote cpu ...IOP: BYTE 1 ...1 if IOP; 0 if not BKINIT: 0C3->BRKJMnot zero then begin ...check for /DIAG output Putcon(); Put1(';') end ' '->@DE ...put space at end of stuff in buffer @^BUFF->R.A; INC HL ...get first char if R.A='=' then begin ...check for assembler type LD BC,(NEXTDE); PUSH BC ...save sou>g(o] 9]CP(9]LDo] /]D(/]Io] /]R9]DEFW 0?^ 9]EDo] >go] o] g(͛go] f@o] Tgo] 9]ADC HL,( 9]SBC HL, b9]LD o] b9],(b/])/](b 9]),b]),HL RET Copyin: PROC ...copies from LASTDE to NEXTDE W.LASTDE->R.HL B.NEXTDE-R.L->R.C COPYSB: LD B,0 LDIR RET STRING: DEL() if @DE<>''' then begin R.A='"'; RET NZ end INC DE; R.A->R.C; JR SR2 Sr: PROC ...advance DE until @DE=quote, starting at  ..editor extension to right justify text (keep within n columns) ...call by .J m,n (m=# cols. wide to make, n=# lines to do) NC: BYTE 0 NR: BYTE 0 TXTCR: BYTE 1 0D NULSTR: BYTE 0 SP: while @DE=' ' do INC DE; RET EEXJ: @DE&0DF='J'; RET NZ; INC DE; SP(); Ddebugger in shell PSA: ADDR PSASEG.0300 ...needs 023C if allow space for all vectors MYSP: ADDR MYSEG.0800 ...top of stack; free down to 0.53C ...RAM1: ADDR MYSEG.0540 ROM0: ADDR MYSEG.0800 in ASMSEG RAM2: ADDR MYSEG.03700 ...part used by SHELL FREE: AD CLFRET ... end ... EX DE,HL ...HL=len. ... PUSH BC; POP IX ...IX=beg. buffer ... ReadF(LD B,LU0; LD C,0FF) ... if not zero then begin ... ERROR(); JP CLFRET; ... end ... PUSH HL; ...save length read ... CloseF(LD B,LU0); ... POP HL; ... RET NAMEND: Pw#!"">2!w#ͩ ͨ(͙ >ͳ ͮ  ! !6b͙ 2O: Ͳ y ͼ ((   (>>2 ?R 2222`h"`h"22`h"`h"ͩ ɷ <8>G>(?20; CALL NZ,CFINIT ...if using cmd. file, open it, set ptrs. READIT(); R.HL->R.BC; EBUF->R.HL FNDEOF() ...get HL=^'FF'/'1A' or after last char of file R.HL->ENDDAT FIXEOF() ...make certain 'FF' at EOF; CR before; + put CR before beg. ...if wereIGIT(); RET NZ; NUMBER(); R.L->NC @DE=','; RET NZ; INC DE; DIGIT(); RET NZ; NUMBER(); R.L->NR 'J'; RET ECODEJ: LINBEG() L1: NR=0; RET Z; NC->R.C=0; RET Z L2: @DE=0FF; RET Z repeat DEC C if @DE=0D then begin ^NR; DEC (HL); RET Z if R.C<>DR MYSEG.04200 SCREEN: PROC at MYSEG.06000 ...addr of hi-res screen handler MYSeg: EQU MYSEG*0100|08000 ...system calls (basic inst orred in): SC_IO: EQU 07F00 SC_SETTMR: EQU 07F01 SC_ACT: EQU 07F02 SC_SEEK: EQU 07F05 SC_FSTAT: EQU 07F07 SC_GETTM: EQUROC ...00 at end of DEFT @HL ...preserve DE PUSH AF; PUSH HL; @HL+1->R.A; R.HL+R.A; 00->@HL POP HL; POP AF; RET FNDEOF: ...enter with HL=^text, BC=len to look ...ret. HL=^'FF'/'1A' or after last char R.B|R.C; RET Z PUSH BC; PUSH HL EOF->R.A; CPI~ #= (ͩ > >2CAN'T DO CMD !=(!$ *m :G: ͥͶ2Sy2  b *:G'A >&8~O# w!H [ "2O:G(2J !" `i:G;2(+> * *" *| >(  doing, open & write out .OLD file here if TSTASC() not then begin PRT0(^NOTASC); JP CCFRET end ...make sure file ascii 1->B.EFLG; EDIT2: repeat EDIT() ...go edit CLSCMF() ...close cmd. file if one POSCRS(00;LD B,LROW-1);ERASL(); ...c0 then begin if NC-1<>R.C and @(R.DE+1)<>' ' and R.A<>0D then begin ' '->@DE; INC DE end else begin PUSH BC; NEWSTR(1;^NULSTR); POP BC; INC C end JR L2 end INC DE; JR L1 end if R.A=9 then begin if R.C-7- 07F09 SC_Z80: EQU 07F0C SC_EXIT: EQU 07F0D SC_RESTRT: EQU 07F0E SC_QUIT: EQU 07F0F SC_MREQ: EQU 07F10 SC_MREL: EQU 07F11 SC_RDBKH: EQU 07F12 SC_WRBKH: EQU 07F13 SC_XFSEG: EQU 07F14 SC_RETSEG: EQU 07F15 SC_CHGM: EQU 07F16 SC_BKR: EQU 07F3E SC_INTR: EQU 0 is @R7, the zero flag is set, R7 is updated past all the digits, and the value of the number is returned in R3; otherwise, the zero flag is is reset and R7 is unchanged. (Note that this is equal to the combination of DIGIT + NUMBER above.) With the cb *|!oB !wNF^V~ͪ nf~ G[:Ox 0ͱ O:G(2@ `i:G(2(:*A `i:G2 *| b :G2 b G!=T]ͩ   *:"2*B 0DM!!"lear second to last line B.DUNFLG-1; JP NZ,SYSRET ...if DUNFLG=2, don't write out file until WRITIT(); JP SYSRET ...write out edited file CKPARM: ...check if parameters after space after filename: "N"=no .OLD file; ..."RL=hh" means create new fi>R.C::*|}:: :*|} :*|}ͮ ] G: o >::[QYAaiͮ [:O "2ɹR*le (hh is record length) ...if "filename,filename" ?, 2nd filename is cmd. file P.FNDSPC; RET NZ ...look for sp. or "," R.A=','; INC DE; CALL Z,TSTFN2 ...","=>cmd filename should follow LD A,0; if zero then INC A R.A->B.CMDSW ...set CMDSW if]!v")]Gr> []e^e]Wr*)]e][]e]N#[]́]͘]e]>0{S+][)]S)][+]ͯyo]*+]w#"+]o]og}(%#o]oo]gXxe] ~ N#y( >+>0y${[]ɯ2.]e]>!8{!( (,(( GH L( []:.]=>U 0C1 NOTRDYERR: EQU 0C2 NOTFNDERR: EQU 0C7 EOFERR: EQU 0C9 NOTOPNERR: EQU 0CB TUMNYERR: EQU 0CF WRGTYPERR: EQU 0D2 ...******* ORG ROM0 ...sets asm & runseg RAM: ADDR RAM2 ROM: ADDR ROM0 /DO ZSYS /DO ZSYSLIB /DO SHELL ENDROM: ADDR ROM ENDRAM: ADDR Rscribed above. Example: GE X.RJ ...entered on EE command line, loads extension image ... file X.RJ .J 80,5 ...calls extension command "J" with parameters "80,5" (This example is an existing extension file to right-justify text: 80=number of column "*B":O! 6:O! 6ɯO! (wA<8x o >ͳ ͛ ͮ `iB8(́ >ͳ ͊ ͮ   DḾ Ͳ ͊ ͩ yx(ͳ ͛ `iB0 DM  B8 (   DMo >ͳ yx(R.HL; LD B,100 repeat @HL=CPMEOF; R1** O9* 9(  9G 9]-0D9]+0e]${[]o] `o]v  _@o] 9]LD B_/],`o] _o] co] a o] Ϳeo] o] 9]JR ( 9]DJNZ G]o] 9] AM /MAP UNDEF /if ^ENDRAM1>^PSA then ?"ENDRAM1 OVERFLOW->PSA"; /if ^ENDROM>^RAM2 then ?"ENDROM OVERFLOW->RAM2"; /if ^ENDRAM>^FREE then ?"ENDRAM (RAM2) OVERFLOW->FREE"; /WRITE"Type in:" /WRITE"/IMAGE S ROM: ",^ROM0," ",^ENDROM-1," ...E=",^START0 .../IMAGs to right-justify to; 5=number of lines to do.) le is an existing extension file to right-justify text: 80=number of columns to right-justify to; 5=number of lines to do.) NC DE;INC DE;INC DE if @DE=' ' then begin INC (HL);INC (HL);INC (HL) end ͮ =#B !͍*w "[*R~G> >Z  R ":!> Z O:o yͳ xͳ ͮ ͙  ͩ B(((ͩ ((Ͳ >ɯɯ>2@i#~: +~@##+x8( ~9j #x 2jx8(> >2@i~.ET Z R.A=EOF; RET Z BIT 7,A; RET NZ R.HL+1 until DEC B zero; 00; RET SAVE_NAME: PROC PUSH DE R.DE->R.HL FNDSPC() if R.E-R.L>=15 then 14 if not zero then begin R.A->R.C; LD B,0; LD DE,NEW_NAME; LDIR end 00->@DE POP DE; RET PRTNAM: PR EX AF,AF'9]DEFB 0?^o] ͔ao] 9]DEC (9]INC  o] ͂_o] o_o] /]C/]Bo] /]E/]Do] ͢_o] /]L/]Ho] /]A9](HL)o] /]E/]Do] _o] /]L/]Ho] /]A9](HE S ROM: ^ROM0 ^ENDROM-1  E"; /WRITE"Type in:" /WRITE"/IMAGE S ROM: ",^ROM0," ",^ENDROM-1," ...E=",^START0 .../IMAGE S ROM: EE then ?"ENDRAM (RAM2) OVERFLOW->FREE"; /WRITE"Type in:" /WRITE"/IMAGE S ROM: ",^ROM0," ",^ENDROM-1," ...E=",^START0 .../IMAG>!f  ( :* >͑1x( >"f  ͑x2+",>o0$)lgbk)lax!!q#p#wGnHn(2*>4 # :+G8*,DMBO!"2 '*T]`i>o0$}o:O 5NN :Fkͪ:J=* *K R* #rh R8 *0R8 "0ͭSOg ͙"M! !J4ѯ--From here: --To here^ :J* ͙"K! !J4:J=**KR*h!6~04ͭͭESO2!J~ *5OC ...Prints name PRT0(^NEW_NAME); RET ... ^NEW_NAME; LD B,(HL); INC B; ... while DEC B not and @(R.HL+1)<>0D and R.A<>' ' do PUT1(R.A) ... RET READIT: PROC ...read in file; ret. HL=len read LD HL,NEW_NAME if OpenF(LD B,LU0) not then begin if R.L)@o]  e͉` o] _o] ͹_o] /]C/]B o] o]  _( 9]EX DE,HLo] 9]IN A,(ͱa/])f  ͊:_͊!J$=(xͬ͊0xͬ! >xͬ! ͊>O͊0#͊!!...system dependent part of E LU0: EQU 0 ...logical units LU1: EQU 1 RECLN: EQU 080 ...record length for command file NEW_NAME: DEFS 15 ...name given with input line SAVCHBF: DEFS 3 ...used by PUTEOFSQ,RESEOFCH PUT1: PROC ...put out 1 char. to con$y2DMbk"!L LLCOL ITOP2 DEL XCOMM WN BN GLOBAL COMMAND LABELCOL LCOL T; RET NZ LKIDPL: ...look up last id+"+linking &.k[F rr@@@@@rrEL *E+[KSM!J5(5L *MB"M[K [M͗ͭ*0R8(B"0*2R8B0bk"2 h̓t!#w  (;( q:J*ͅ * ̪*"@oS2*MBDM*KR0*MR8 :J=(*͙*A=FNF_ERR then begin W.0;RET end else begin ERROR();JP CCFRET end end ...CDE=file len. R.C->R.A LD BC,(EBUF) if R.A<>0 or ENDBUF-R.BCV#N#~$#~+: ~@##>c~. #>c>u >Gx( ~́ #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ xͬ((#͊!!OW_}T]Oů)lau!t"w#sole ...save all regs. incl. flag PUSH AF PutC(R.A) if R.A=CR then PutC(LF) POP AF RET GET1IF: PROC ...get 1 char. from console->R.A if ready ...save other regs. B.GetC() ...->B.LASTCHAR; RET GETCHR1: PROC repeat GETCHR() until R.A<>CPMEOF; RE7M2D!D}M~ :L !D~OM5͇M:LW( *F6O)P2L+HET***** > *Gv> }=O!+G")Gy*%GMET ERROR T*%GMKR8*K "K*M "M*@ "@*@x27[M:J= *K 18'40#1O!K ^#V*R8*R8gE ':J !ͅ ́ S227:526ͪ*E :J(T Eoͷ:6262527GOz( ~(> !BDMhͭ:J(ͅ  ...PUSH BC; POP IX ...IX=beg. buffer ReadF(LD B,LU0) ...; LD C,0FF) if not zero then begin ERROR(); JP CLFRET; end PUSH HL; ...save length read CloseF(LD B,LU0) POP HL; RET ...READIT: PROC ... LD HL,NEW_NAME ... if OpenF(LD B,LU0) not then beg4x( >!O  ̀4x( >"O  ̀SH)lgxͬ!!G͊H͊ 4 # (  >>KHB~0 #~/ >:w>A+w͐( >Ƿ ͐(>>;Ϳ~I #~ ( ͜~# (XT EDIT1: 00; LD (INPTR),A ...so will ask for filename EDIT0: PROC LD SP,MYSP ...allocate stack if B.EFLG<>0 then JP EDIT2 LD HL,(CPM+1); LD L,0; R.HL->ENDBUF ...set ENDBUF CRTTYP(); ^INPTR->R.HL LD C,(HL); LD B,0 ...len. R.HL+1->R.DE 0D->@(R.ͮMN#ͮM_O+H!G4*G;TͼMշB8(!HB0bk+>?_OM*G"G:D( *G> 1+H* G|(įNͩQǁ1+H (;(HET/DO ~#~ (; > ͯNH%RDPSD͇MsS1D( > &D y &D>  ( 8 >#&Dbk;N ...ZSYS.M2 (ZOOMA) ...bucket ports CNTL: EQU 3 ...0B on ZOOMB DATA: EQU CNTL-2 PSASEG: EQU 0 MYSEG: EQU 0 ASMSEG: EQU 1 FRSTSEG: EQU 0 MAXNSEG: EQU 4 SCRSEG: EQU 07E ...1st of 2 screen segs. RAM1: ADDR MYSEG.0100 ...DBUGSP: ADDR MYSEG.01A0 ...used by in ... if R.A=FNF_ERR then begin W.0;RET end ... else begin ERROR();JP CCFRET end ... end ... ...CDE=file len. ... R.C->R.A ... LD BC,(EBUF); ENDBUF-R.BC->R.HL ...HL=len. of buffer ... if R.A<>0 or R.HL-R.BC3>3*.>Z##{:(+:!b ͏  S D  ͫ :(( :3   & ́ b͕͠L ɯ!w#4#(!4#(͙ ͦ !͙ Gͦ x+| !@́ (+| >Gͦ xZ8000 SYS NOT READY 2222!HL+R.BC) ...make sure CR at end of input in sys cmd buff SPC(); R.A=CR CALL Z,NAMEQ ...if filename not given, ask for it @DE=CR; JP Z,SYSRET ...if still no name, ret. SAVE_NAME() ...SAVE INPUT NAME CKPARM(); ...check param. after name @^CMDSW=  Using QBUG Enter the Q-debugger from Q by typing "/*" (can also be in a file; any open input or output files are closed). The prompt is a "*". (To return type "Q".) From here, any instruction (or instruction list) that is typed will be executed `skipping' a subrou- tine (in the "T" command, this happens when going below the maximum level to be traced), QBUG checks to see if it can set a temporary break at the return address and `go' rather than stepping all the way through. This will be done if  chain RES UNDEFB,(IY+TYPE) ...set defined LD C,(HL); INC HL; LD B,(HL) ...(LOC)->BC LD (HL),D; DEC HL; LD (HL),E ...DE->(LOC) BIT AL1B,(IY+TYPE); PUSH AF if R.B|R.C zero then SET AL1B,(IY+TYPE) ...if no back ref. else RES AL1B,(IY+TYPE) ...indiying registers that change. If n is not given, it defaults to 1. S n ........... same as "N" above, but skips over procedure calls. Note: CALL instructions at the PC are disassembled (including the procedure name) after breaks and steps. (If DEASM if not carry then begin ...if found & defined RES AL1B,(IY+TYPE); RET ...indicate symbol has been referenced end BIT AL1B,(IY+TYPE); JR NZ,CPAMIX ...check for mixed ref. DEC HL end DEC DE; DEC DE LD (HL),E; INC HL; LD (HL),D ...storimmediately, with registers preserved from one line to the next (including any changes made). All of the commands (beginning with a "/") are also valid in the debugger. Upon entering Q, breaks (opcode "FF") are set to go to the Q-debugger. To change bacafter 4 instructions of the subroutine there have not been any pops or ex- changes with the stack (which might indicate an altered return address). If the return address is otherwise changed, oops!. 2. During execution of a multiple step command, e.g.cate symbol has been referenced POP AF; JR NZ,AL1 ...go resolve 1-byte chain ...store R.DE (NCODE or def. value) into places referenced by chain: CPLLUP: R.BC->R.HL=0; RET Z ...next loc. in chain->R.HL, end of chain if 0 RDa2HL(); WRa2HL(); JR CPLLUP  is present, all instructions are disassembled.) G ............. resume execution after a break--or any time there are valid values for the saved PC, SP, etc. (as shown with the "R" command)--with all registers restored. Note: if R_PC is at a set e addr. in symbol table INC DE; INC DE ...DE=NCODE RET CPAMIX: CALL Errm; DEFT 'MIXED REF' ISA1: if Lkup() zero then begin ...if found LD C,(HL); INC HL; LD B,(HL) ...(LOC)->BC if carry then begin ...if back ref. BIT AL1B,(IY+TYPE); JR Z,k to the PROM-debugger getting breaks, use the command "/BRKS->P". "/BRKS->Q" sends them to Q again. On leaving Q, breaks are again sent to the PROM. In addition to the regular Q instructions, there are some debug instructions which may only be executed  N 255 or S 255, or the "T" command, `escape' can be pressed to cleanly abort the operation at that point. 3. The debugger uses CTC channel 3 for stepping through programs (used by the "N", "S", "T", and "G" (first instruction executed when at a breakp ...@2HL->BC; DE->@2HL RDFERR: B.QOPTS; BIT 0,A; RET NZ ...if BIT 0,QOPTS=1 then ok to redefine label LD BC,BUFF; if @BC='D' then begin B.GETTYP()=DEFLT; RET Z end ...ok to redefine DEFL with "D" type CALL Errm; DEFT 'REDEFINED LABEL' AL1: ...1-bytbreakpoint, a "Next" will be executed first in order to restore the breakpoint; otherwise will just "go". J address ..... sets the stored program counter (R_PC) equal to "address", where "address" takes the same form as above with "D", then beginsCPAMIX ...check for mixed ref. LD (HL),D; DEC HL; LD (HL),E ...DE (NCODE) ->(LOC) W.OFFSET+R.BC ...because DISP subtracts offset end else begin ...if defined RES AL1B,(IY+TYPE) ...ind. has been referenced R.BC->R.HL ...old (LOCfrom the debugger: D address,n ... displays n lines of memory, 16 bytes per line, starting at "address". ",n" is optional and defaults to n=1. If "D" alone is typed, one line starting at the value of the stored program counter (R_PC) will be displ...Z80 system ...changed 11/26: RETFLG stuff, DOCMD0 ...last change 10/15/82 NLU: EQU 16 ...no. of logical units BASCNTMSK: EQU 07F ...default for CNTMSK MAXLUP: EQU 04000 ...system cmds.: OPN: EQU 0 CLS: EQU 1 RD: EQU 2 WRT: EQU 3 RDAHD: EQU 0A ...1se chain will now be resolved R.BC->R.HL ...addr. of last ref. (from table) -> HL AL1LUP: PUSH DE ...value of label (NCODE) EX DE,HL; DISP(); EX DE,HL ...get diff. $-addr-1 in R.A, checking for out-of-range POP DE ...$ RDa2HL() ...contents of cur execution, initializing the registers with the values as shown with the "R" command. Note that regular jump or call instructions may also be used to start execution (without initializing the registers). R ............. displays the values of the r)->R.HL end DISP() ...disp. to be inserted ->R.A end else begin ...if not found SET UNDEFB,(IY+TYPE) ...mark undef. SET AL1B,(IY+TYPE) ...set AL1 LD (HL),E; INC HL; LD (HL),D ...DE (NCODE) ->(LOC) 00 ...0 to mark end of 1-byte chaayed. "address" may be either a hex number (must start with "0" if 1st digit is A-F), or an HL-expression, e.g. D ^ABC+012. Also note that R.HL is ini- tialized to the starting address of the previous line dumped before the HL-expression is evalut byte of bucket codes: FF=busy, 0=free, else as below: ...for Z80: QUITCD: EQU 081 IOCODE: EQU 082 RDBKCD: EQU 083 TIMERCD: EQU 084 CONWRCD: EQU 086 Z80CD: EQU 087 ACKCD: EQU 0C0 ...for Z8000: STARTCD: EQU 1 RDCODE: EQU 2 WRCODE: EQU 3 DUNCD: EQU 4 RD2CD:rent addr. in chain ->R.C WRaHL() ...store at addr. the calculated rel. displacement R.C=0; RET Z ...check for 0 => end of chain BIT 7,C; JR Z,OORERR ...error if chain pts. forward LD B,-1 R.HL+R.BC+1 ...next chain location ->R.HL JR AL1LUP DISPegisters that have been saved following a break or after an "N", "S", or "T" command R, ............ displays the values of the saved registers and puts the cursor underneath. The cursor may then be moved along to under any nibble in any register ain end WRaDEi() ...put out rel. disp. to addr. or prev. ref. RET NDFERR: CALL Errm; DEFT 'NOT DEFINED' CPB: if R.A='B' then begin ...BINARY type LD B,8 ...next 8 bytes are 0 or 1 RRC (HL); ADC A; INC HL; DJNZ $-4 ...R.A can start at anything ated; thus, for example, a linked list (where the link address is the 1st word of the previous dump) may be followed by doing D @2HL. A special case of this command is when either n=0 or there is a comma with nothing following. One line is dumped  EQU 5 WR2CD: EQU 6 BRKCD: EQU 7 CONINCD: EQU 9 WRSCRCD: EQU 0B ...not used here PERINTCD: EQU 0C ...***************** ORG RAM LUFLAGS: BYTE 0[NLU] ...set corres. byte=1 when LU active REQFLG: BYTE 0 ...set=1 if Z80 requesting bucket but must empty : ...calcs. HL-OFFSET-DE-1, checking for out-of-range, & stores in R.A ...DE not changed LD BC,(OFFSET); R.HL-R.BC SCF; R.HL-carry-R.DE R.L->R.A if INC H zero then begin BIT 7,L; RET NZ end if DEC H zero then begin BIT 7,L; RET Z end OORERR: CALL Errnd the value there changed in the same manner as used to change memory (see the "D" command above). Hitting return completes the operation. R' ............ displays the values of the shadow registers H n ........... history: displays the last n addre WRaDEi(); RET end if R.A='H' then begin ...HEXADECIMAL TYPE CPHLUP: @HL=' '; RET Z Inhex() ...get 2 hex digits @HL converted to its value (->R.A) WRaDEi() ...put out byte JR CPHLUP end if R.A='O' then begin ...OR type LD B,0 ... and the cur- sor positioned under the 1st byte. The cursor may be advanced by typing a space or tab (to advance to the next word) or backed up using the backspace. Memory can be changed a nibble at a time by typing the desired hex digit when thefirst RETFLG: BYTE 0 BRKFLG: BYTE 0 ...set when ctrl-C input; break Z8000 CNTMSK: BYTE BASCNTMSK NXTIN: WORD KBUF ...^ next char. into keybd buffer (initialize) NXTOUT: WORD KBUF ...ditto next char. out COUNT: BYTE 0[5] ...above gets init'd^ KBUF: DEFSm; DEFT 'OUT OF RANGE' Lkupnl: PROC 1->B.LINKSW ...don't add to symbol table if not found; FALL THRU: ...Lkup EXPECTS HL POINTING TO DATA ENDING WITH A ' ' ... RETURNS HL,IY POINTING TO TABLE ENTRY ... Z=1 if found, CARRY=1 if referenced & not defined sses or values on the stack (including corresponding symbol names if any) following a break (or step, etc.). If n is not given, it defaults to 1. T n ........... starting after a break, traces program execution displaying the names of all subroutinOR following pairs of hex digits together: while @HL<>' ' do B.Inhex()|R.B->R.B; WRaDEi(R.B); RET end if R.A='V' then begin ...ONE BYTE ABSOLUTE Lkupnl() ...call Lkup without linking in JR C,NDFERR JR NZ,NDFERR WRaDEi(@HL) ...put out l cursor is in position. Hitting return or line feed completes the operation and displays the changed line. Line feed additionally causes the operation to be repeated on the next line. B address,n ... sets a breakpoint with a repeat count of n at " 32 KBUFEND: WRCONBUF: DEFS 0100 LCMDBUF0: EQU 10 ...only has to hold "I X"CR, otherwise make 144 CMDBUF0: DEFS LCMDBUF0 LFNMBUF: EQU 40 FNMBUF: DEFS LFNMBUF ...read buffers BUFF1: EQU BUFBEG BUFF2: EQU BUFBEG+RDBLKSZ ... ...BUFF vector offsets: BUFFVSZ... DE unchanged Lkup: PROC PUSH DE LD D,H; LD E,L ...HL->DE LD A,' ' LD BC,080 ...limit to search CPIR DEC HL; EX DE,HL ...DE points to ' ' NLKUP() POP DE; RET LINKER: ...expects : HL at base link; IY at new entry ...performs: if (HL)=0, 0->(es entered indented to subroutine depth (as measured by the stack pointer), up to a depth of n (or infinitely deep, if n is not given). Continues until depth is less than original depth. L address,hh .. locate a string in memory; hh is an even-numbow-order byte RES AL1B,(IY+TYPE) ...indicate symbol has been referenced RET end if R.A='D' then begin ...check for DEFINE type DEC DE; DEC DE; PUSH DE ...save for NCODE EX DE,HL; RDa2HL(); EX DE,HL; LD E,C; LD D,B ...@2DE->DE(def. value) address". "address" may be either a hex number (must start with "0" if 1st digit is A-F), or an HL-expression, as described above for "D". There may be a maximum of 8 different breakpoints at one time. A repeat count of n means the break will not: EQU 8 BUFFLEN: EQU 0 BUFFDST: EQU 2 BUFFFPOS: EQU 5 ... BUFF1VC: DEFS BUFFVSZ BUFF2VC: DEFS BUFFVSZ CURBUF: WORD 0 ...stores addr of last read buffer allocated XFBUF: WORD 0 ...if<>0, pts. to buffer to be xferred by XFDTA0 FILPOS: WORD 0 ...current fIY+LINK); else (HL)-[IY+LINK-HL]->(IY+LINK) ... [IY+LINK-HL]->(HL) ...returns : IY unchanged LD C,(HL); INC HL; LD B,(HL); DEC HL ...@2HL->R.BC PUSH HL; LD DE,LINK; R.IY+R.DE; POP DE ...HL=IY+LINK, DE=orig. HL R.HL-R.DE; EX DE,HL ...DE=IY+LINKered length string of hex digits, each pair representing a byte in the string. The search starts at "address", which takes the same form as above with "D". (If "address" is left off, the search starts after the starting address of the most recent  JR CPDL1 end R.A='L'; RET NZ ...do nothing if 1st char. anything else ...LABEL PUSH DE ...save for NCODE PUSH HL; W.OFFSET+R.DE; EX DE,HL; POP HL ...add offset CPDL1: if Lkup() not carry then begin ...call Lkup, chk if no back ref. CALL Z,RDF occur until the nth time the breakpoint is hit. (After the break occurs, the repeat count is left at 1.) ",n" may be left off, with n defaulting to 1. In addition, just typing "B" will cause a listing of all the currently active breakpoints. Xile pos. FILPOSH: BYTE 0 ...high byte of above ENDFPOS: WORD 0 ...stores end fpos for read req. ENDFPOSH: BYTE 0 ...high byte of above LU0: BYTE 0 CMD0: BYTE 0 XFADR0: WORD 0 XFADR0H: BYTE 0 XFLEN0: WORD 0 FNM_POS: WORD 0 POS_H: BYTE 0 FNM_H: BYTE 0 BU-HL, HL=orig. HL LD (HL),E; INC HL; LD (HL),D ...DE->@2HL if R.B|R.C not zero then R.BC-carry-R.DE->R.BC ...BC=(HL)-[IY+LINK-HL] LD (IY+LINK),C; LD (IY+LINK+1),B ...BC->(IY+LINK) RET HASHER: PROC ...generates hash code for lookup table ...expects line dumped.) U address,n ... (valid only if DEASM is present) unassemble (dissassemble) n instructions starting at "address". "address" takes the same form as above with "D". Miscellaneous: 1. During operation of the "S" or "T" commands, when ERR ...if already defined, chk if can redefine RES AL1B,(IY+TYPE) ...indicate no AL1 chain 00->@HL->@(R.HL+1); DEC HL ...00->(LOC) end CPDL2() ...put value in symbol table, resolve chain POP DE; RET CPDL2: ...store DE in symbol table, resolve address ..... removes breakpoint at "address" where "address" takes the same form as above. "X" by itself causes all breakpoints to be removed. N n ........... execute next n instructions (after a breakpoint has been hit or a previous step) displaFHDR: WORD 0 OPNTYP: BYTE 0 CC0: BYTE 0 STATUS: BYTE 0 RAM: DEFL $ ...***************** ORG ROM MAIN: PROC INIT(); RET NZ ...init. ram & start up Z8000 (NZ=>Z8000 not ready) repeat CKSTUF() if STATUS<>0 then begin case CMD0&7 of RD: R R.A with symbol length; symbol @HL ...returns code*2+2 in R.DE, init. link in HL DEC A; @HL->R.A if not zero then R.A*2*2.XOR.@(R.HL+1) AND NHASH-1 R.A+1*2->R.E; LD D,0; W.TABBSE+R.DE->R.HL; RET NLKUP: ...expects: HL pointing to first source characteB.MAPMSK->R.B if B.MAPCMP.XOR.@HL&R.B zero then begin if W.MAPEND-R.DE>=zero and W.MAPBEG-carry-R.DER.BC; POP HL; R.HL=R.BC; RET TABINT: ...set 1st 2 bytes @HL = rel. disp. to init. table end position ...0's -> init. links (@(R.HL+2...)); ret. HL at pos. for 1st entry W.TABBSE; LD B,2*NHASH+2 LD (H ; RET Push: PROC LD BC,Louta*5; LD DE,OutaM5; ^OutaM4; LDIR; RET Compare: PROC ... compares R.DE with DEFT pointed to by HL LD B,(HL) ... get length repeat @DE; INC DE until R.A<>@(R.HL+1) or DEC B zero; RET IsSameLab: PROC @(R.HL+2+1) = @(^Outa+2) r ... DE pointing after last source character ...returns: HL,IY pointing to table entry ... DE pointing after source symbol ... Z=1 if found, CARRY=1 if referenced & not defined PUSH DE PUSH HL R.E-R.L->R.A->R.B ...length of symbol LD stsym(); 1 end; RET Nm00: DEFB 0 ...min. symbol alphabetically NmFF: DEFB 0FF ...max. symbol Map: PROC ...prints out symbols and values PUSH DE; ^BUFF->Nxtpos if B.MAPTYP<>'A' then begin ...do by order of occurrence: W.TABBSE; LD BC,NHASH*2+2 0C3; NCODE-2-1) ... CALL -> JP if LKUP(^OutaM1) zero then begin EX DE,HL; NCODE-R.DE->R.HL if R.H=0 and BIT 7,L then begin PUSH HL; NumJR(); POP HL 1-R.L -> R.A ... calc JR R.A POP BC;POP DE ; POP HL ... recall R.DE L),B; DEC B TBINT2: INC HL; 00; repeat R.A->@HL; INC HL until DEC B zero; RET TABLEN: ...enter with DE at end of symbols; store rel. len. of table @2TABBSE W.TABBSE; EX DE,HL; R.HL-R.DE; EX DE,HL LD (HL),E; INC HL; LD (HL),D; RET PACK: PROC ...pack sy; RET ...for temp. symbols only IsRet: PROC Compare(EX DE,HL; ^HC9) ; RET IsRetNZ: PROC @^OutaM1=' '; RET NZ; Compare(LD DE,OutaM2; ^HC0); RET IsJrNZ: PROC Compare(EX DE,HL; ^H20) ; RET IsJrZ: PROC Compare(EX DE,HL; ^H28); RET IsCall: PROC PUSH HL; CompaC,(HL) ...1st char. HASHER() ...get HL=^init. link LD DE,0-LINK R.HL+R.DE->R.IY ...pt. to appropriate base link-LINK JR LKLUP LKLUP0: POP BC LKLUP: repeat LD E,(IY+LINK); LD D,(IY+LINK+1) R.D|R.E; JR Z,LKEND ...end chain ADD IY,DE until R.C=while TSTEND(R.HL+R.BC) NCODE WRaHL(R.HL-1) ; WRaHL(018; R.HL-1) ... make JR end end end end end else begin if B.Outa='L' and IsCall(^OutaM2) and IsRet(^OutaM1) and IsSameLbl(^OutaM2) thembol table PUSH DE LD B,2*NHASH; TBINT2(W.TABBSE+1) ...zero init. links R.HL->R.IY; EX DE,HL ...IY,DE->1st entry JR PK2 PKLUP: ADD IY,BC PK2: while TSTEND(R.IY) R.C; LD B,0 ...lere(EX DE,HL; ^CALL); POP DE; RET NZ if Compare(^Cspec) then R.A|1 else 00 ; RET ... won't work for CALL ZZ types; bug if subr messes with stack IsSameLbl: PROC ...for any symbols; assumes 'L' type in Outa, 'A2' or 'C ' @HL R.HL+2; LD DE,Outa+1; LD B,@IY(NAME); R.B=@IY(LNGTH); JR NZ,LKLUP LD DE,NAME+1; R.IY+R.DE->R.HL ...pt. HL to name+1 POP DE; PUSH DE ...source starting char. PUSH BC if DEC B not zero then begin repeat INC DE @DE=@HL; JR NZ,LKLUP0 INC HL until DEC B zero; end cally: ^Nm00->LastNm while GetLNm() zero do PutOut() end LD DE,(Nxtpos); ^BUFF; PUSH HL R.HL-R.DE; CALL NZ,Outmsg ...if not 1st col., put out last line POP DE; P.Copy; DEFT 'Rem Space=' TSTEND(); W.ENDTAB-R.BC ...calc. remaining space (BC=end n begin ...test if can delete JP AA (optm'd from AA();RET) followed ... by AA def'n NbrDrThr() POP BC; POP DE; POP HL ...HL=saved DE=NCODE R.HL-2-1 ...dec. saved DE R.HL->W.LSTNCD->W.DOLLAR ...for listing or xref table PUSH HL; PUSH DE; Pn. of entry->BC if BIT UNDEFB,(IY+TYPE) zero then begin ...save undef'd symbols Tstsym(); JR NZ,PKLUP ...skip if masked out if B.PAKSW=0 then begin ...chk if packing just globals BIT GLOBLB,(IY+TYPE); JR Z,PKLUP ...skip if not globaLouta-2 repeat @DE=@HL; RET NZ; R.A=' '; RET Z; INC HL; INC DE until DEC B zero; RET ...note: must be DJNZ here for Z=0 HC9: DEFT 'HC9 ' ... RET output HC0: DEFT 'HC0 ' ... RET NZ output H20: DEFT 'H20 ' ... jr nz, op H28: DEFT 'H28 ' ... JR Z, op CALL if BIT BANK2B,(IY+TYPE) not zero then INC B ...B=0 or 1 B.CODEBK=R.B; JR NZ,LKLUP0 ...bank symbol in must match CODEBK POP BC POP DE ...source starting character BIT ZAPB,(IY+TYPE) ...check if zapped JR NZ,LKFIN R.A|R.A ...reset the CARRY BIT UNDof symbols) HLout(R.HL); Outmsg() ...print Rem Space=hhhh POP DE; RET GetLNm: ...get least name>LastNm pointed to by HL (@LOC) & LastNm (@NAME) LD BC,NmFF; 00->R.A ...current least name stored in BC while NXTsym() zero do begin LD DE,NAME; R.HL+RUSH BC end end POP HL;POP AF;POP DE;POP BC;RET LKUP: PROC ... looks up sym at HL+2, ret LOC->R.HL if defined, & Z set Lkupnl(R.HL+2) @2HL -> R.HL RET NC OR 1; RET ... reset Z patch ^Optm,TSTLCL() ...if last clause in QRULE, can subst. RET NZ l end end BIT ZAPB,(IY+TYPE); JR NZ,PKLUP ...skip if zapped PUSH DE; POP IY ...^old entry->HL; ^new entry->IY LDIR ...move old entry to new table PUSH DE; PUSH HL ...save DE,HL @IY(LNGTH)->R.A LD DE,NAME; R.IY+R.DE ...HL pts.: DEFT 'C ' ... CALL OP Cspec: DEFT 'C WSend ' ... exception TSTLCL: PROC ...test if ANDCL last clause in a QRULE ...if so, can substitute RET NZ for JR NZ,--- to end if BASESP=0 then R.HL+R.SP->BASESP ...init. BASESP ...NOTE: 1st time ANDCL called EFB,(IY+TYPE) ...SETS Z=1 IF SYMBOL DEFINED JR Z,LKEXIT ...OK, Z=1,C=0 00->R.A ...Z<-1,C<-0 CCF ...Z=1,C<-1 PREV REF JR LKEXIT LKEND: POP DE ...start of source symbol B.LINKSW|R.A; JR NZ,LKEXIT ...if don't want linked up (Z=0, C=0) PUSH DE ...start  .DE ...HL pts. @NAME of next entry LD DE,(LastNm) ...last symbol put out if CPName() LastNm LD D,B; LD E,C ...current least name if CPName() >=zero then R.HL->R.BC ...new least name end LD A,1 ..for JR NZ patch ^Optm+3,TESTCJ() patch ^Out+03C,TESTCR() patch ^Eff1,JP TESTcj ...if last clause in QRULE, can subst. RET NZ for JR NZ patch ^Optm+3,TESTCJ() patch ^Out+03C,TESTCR() patch ^Eff1,JP TESTcj STCR() patch ^Eff1,JP TESTcj JR NZ patch ^Optm to symbol name HASHER() ...base of table + HASH = 1st link -> HL LINKER() ...link @HL->here; here->prev. link @HL (IY=^new entry) POP IY; POP DE ...IY=^next entry orig. tbl; DE=^next new entry end TABLEN() ...store len. of new table at TABBmust not be from in parentheses!! R.HL-carry-R.SP; RET NZ ...must not be in paren. (diff. level) PUSH DE while @DE<>0D do begin ...must not be '/' or ':=' before ';' R.A='/'; JR Z,NOTLCL INC DE if R.A=':' then begin @DE='='; JR Z,NOTLCL esource symbol W.TABBSE; LD E,(HL); INC HL; LD D,(HL); DEC HL ...DE=@2W.TABBSE R.HL+R.DE->R.IY ...next free loc. (ENDSYM) ->R.HL->IY LD C,B; LD B,0 ...length LD DE,NAME; R.HL+R.DE+R.BC->R.HL ...HL gets new end of symbol table LD DE,(ENDTAB) ...end o.for NXTsym end LD (LastNm),BC if ^NmFF-R.BC zero then INC L else CP A ...set Z flag LD HL,-NAME; R.HL+R.BC->R.HL RET CPName: PROC ...compare name pointed to by DE to name pointed to by HL ...enter HL,DE at NAME in symbol tbl (LNGTH before); preserH!p ˎ~{OG!p ˆ){!kk.Þ{{O[ij(SijOVV"ij*ij+NGBBBPY..Bbk{/{*Qj+~+~ "Qj x <! =(G #7R(ٯQ` hRV ͠,muRJSE POP DE; 00; RET Nxtsym: PROC ...steps through symbol table by hash codes and links ...if R.A=0 then returns first symbol first chain, else returns next ... symbol same chain (then next chain) ...returns Z=1, HL,IY at symbol tbl entry if found; Z=0 nd end DEC DE; @DE=';'; POP DE CALL Z,ORETNZ; RET NOTLCL: OR A; POP DE; RET ORETNZ := NLstCl .OUT("HC0",Re); Fix3: PROC PUSH AF ; Nbr2003() ... 2003yyaaaa -> R.A aaaa B.RDaHL(NCODE-1)->R.B; B.RDaHL(R.HL-1)->R.C R.HL->NCODE WRaHL(R.B; R.HL-1); WRaHL(f symbol table SCF; R.HL-carry-R.DE ...test if room left in symbol table for new entry JR NC,TUMANY ...too many symbols LD (IY+LNGTH),C ...length of symbol name ^NAME->R.HL PUSH IY POP DE ...table entry R.HL+R.DE->R.HL ...name in table entry POP D... Optimizer ...7/09 JP AA (optm'd from AA();RET) followed by AA def'n -> drop thru *if @(^Out+03C)<>0CD then begin ?"Out has been modified ... ERROR"; stop end; LSTNCD: EQU NCODE+2 DOLLAR: EQU LASTDE-2 Louta: DEFL 16 ... length of saved output buffersDV ϷfmN\ 16S\ 16G` >2apJN Ͳ"p>2apB`̔BN Ͳ!ЇX`XN ͲPT\ :6H\ 1ͺUV :fƆLN EͲ(*op#,>H!kkw#z w#zw#("gj1*Qj "Qj[{*Qj}͌if at end PUSH BC if R.A=0 then begin R.A->Hash; W.TABBSE+2 end else W.Link while begin ...get ptr. to link of next entry (R.HL+@2HL->Link): LD C,(HL); INC HL; LD B,(HL); DEC HL R.HL+R.BC->W.Link; R.B|R.C ...Z=1 iff end of chain (@2HL=0) end zR.C; R.HL-1) ...move addr R.HL-1; PUSH HL if LKUP(^OutaM1) not zero then begin R.HL-2; LD (IY),L LD (IY+1),H end ... fix chain POP HL; POP AF; WRaHL(); RET TESTcj: PROC PUSH DE ...used on C of A:= C / D; if B.Outa='L' and IsCall(^OutaM1) aE ...start of source symbol EX DE,HL; PUSH DE ...save ^name in tbl entry LDIR ...symbol name in table (DE->new end of symbols) TABLEN() ...store rel. len. of table at TABBSE POP HL; @IY(LNGTH)->R.A ...^name->HL HASHER() ...base link->HL LINKER() ... ORG ($+15)&(0-16) ... helpful for debugging OutaM5: BYTE ' '[Louta] OutaM4: BYTE ' '[Louta] OutaM3: BYTE ' '[Louta] OutaM2: BYTE ' '[Louta] OutaM1: BYTE ' '[Louta] Outa: BYTE ' '[Louta] BASESP: WORD 0 ...stores SP of TSTLCL when called from ANDCL ͈ |}۟ȯͲ(  (,*p, > < >2`p!ap' b,bN ߸"mpO  Ir*mp"op{$Àky"mp~/{#~#>|~0 0>.#>|Yr !RDM* 5~#foR0&B8!~_ o g(ero and B.HashB.Hash; R.A+1*2->R.C; LD B,0 ...R.A+1*2=2+(R.A*2) W.TABBSE+R.BC->R.HL ...ptr. to next base link end LD BC,0-LINK; R.HL+R.BC->R.HL B.Hash::NHASH ...done if Hash>=NHASH if R.IY; CP A ennd IsJrNZ(^OutaM4) and IsSameLab(^OutaM3) and B.OutaM2<>'H' then Fix3(0CC) POP DE B.RDaHL(NCODE-1)=0; RET NZ B.RDaHL(R.HL-1)=020; RET NZ R.HL->NCODE ...do Eff1 RET TESTCJ: PROC PUSH DE ...used on C of A := (B/C) D ; if B.Outa='L' and IsCall( ...link up (IY at new table entry) LKFIN: B.LINKSW=0; JR NZ,LKEXIT ...Z=0, C=0 R.IY->R.HL ...table entry R.A->@HL->@(R.HL+1) ...00->(LOC) if B.CODEBK<>0 then LD A,2**BANK2B R.A->@IY(TYPE) ...clear type byte except BANK2B bit set if bank 2 R.A|1 on base level NumLstCl: WORD 0 ... no. last clauses (JR NZ changed to RET NZ) NumbJR: WORD 0 ... no. calls changed to JR Numbr: WORD 0 ... no. RETs deleted Num2003: WORD 0 ... no. 2003yynnnn -> zznnnn NumDrThr: WORD 0 ... no. JP $+3's elim. Total: WORD 0 :p  DM>y/Ox/G| <!9}G`À̃ 'x #y N> 0O( O>+y/{u>|>IrOA(*p{$I ͺy/{``:rpG:p I(x2pͥz A=/{Y:qpG:p I(x2pͥz F=/{YAx y ( d else OR A ...set Z flag POP BC; RET Tstsym: PROC ...tests symbol @HL to see if not masked out ...chk MAPCMP, MAPMSK, MAPBEG & MAPEND PUSH DE; PUSH BC; PUSH HL LD E,(HL); INC HL; LD D,(HL) ...DE=(LOC) LD BC,TYPE-1; R.HL+R.BC ...HL pts. to TYPE ^OutaM1) and IsJrZ(^OutaM3) and IsSameLab(^OutaM2) then Fix3(0C4) POP DE ; CP A; RET ...set Z=1 TESTCR: PROC PUSH BC;PUSH DE;PUSH AF;PUSH HL Push() ; POP HL ;PUSH HL; R.HL-1 -> R.HL LD DE,Outa ; LD BC,Louta ; LDIR if IsRet(^Outa) then begin  ...set Z=0,C=0 LKEXIT: 0->B.LINKSW R.IY->R.HL POP DE ...after source symbol RET TUMANY: CALL Errm; DEFT 'TOO MANY SYMBOLS' TSTEND: ...performs R.HL::(W.TABBSE+@2W.TABBSE); preserves HL,DE,IY,A ...returns BC->end of symbols (ENDSYM) PUSH HL; W.TABB... bytes saved NbrDrThr: LD B,3; repeat NDrThr() until DEC B zero; RET NDrThr: ^NumDrThr; JR INC NLstCl: ^NumLstCl; JR INC Numbrit: ^Numbr; JR INC NumJR: ^NumbJR; JR INC Nbr2003: ^Num2003 INC: Inc(R.HL); ^Total Inc: repeat INC (HL);INC HL until not zero DEFL or in Debug SAVSP: WORD 0 ...saves SP from in Debug (used by Err) TMPCD: WORD ATMPCD ...temp. code area (for ORG,DEFS,EQU,DEFL,debug stmts.) ...could also set=TMPSP NCODE: WORD CODE ...current spot for code to be put out LSTNCD: WORD CODE ...NCto buffer; ret. with Z=1 if no text RET RESNST: ^STACK->W.FREE; RESNCD(); RET ...res. STACK & NCODE (if tmp. NCODE) ERRMCC: LASTDE->R.HL ...^ Error EX (SP),HL ...LASTDE (ptr. to error)->stack; length of text->HL PUSH AF ...R.A contains CC ERMGET() .. R.A&0DF = @DE and @(DE+1)=R.C (DE=DE+1) @DE&0DF=R.B; RET NZ INC DE; @DE=R.C; RET Z; DEC DE; RET Dump: PROC ...print R.A lines starting at R.HL (preserves regs except 1->Z) PUSH BC; R.HL->DmpAdd LD C,A; if R.A=0 then INC C repeat WSbgn() HLout(Dmeep ints. disabled when on bank 1 SvSP1: WORD MYSP ...saves SP of bank 1 XAdd: WORD 0 ...addr. to execute at (used by Debug; jps. to other bank) TMPTAB: BYTE 0[16] ...table to mark temp. symbols as used (=1) or not (=0) TABBSE: WORD TABLE ...beg. of sym...8-17-82 I2_JMP ...12/2 test for BRKEXT added to B_RTN; CALLHL,CONTX new ...12/2 DBUG0 calls Quit1 instead of Quit ...12/2 save AF around ResSVs in DBUG3 ...used by Step: STSP: WORD 0 STBADDR: WORD 0 STBINST: BYTE 0 ...the following code gets moved ODE at beginning of line NCODE1: WORD CODE ...saves NCODE of bank 1 when change to bank 2 NCDTAB: WORD CODE2 ...saves NCODE of bank 2 when in bank 1 WORD 0FF40[MAXCPU] ...save NCODE of other cpu's DOLLAR: WORD CODE ...NCODE beginning of line or instr..get msg. & put into buffer CALL Copy; DEFT ' ERROR ' ...goes into buffer POP AF ...CC in R.A Outhex() ...puts out value of unsuccessful completion code JR ERR1 Errm: PROC ... PRINT MESSAGE AFTER CALL LASTDE->R.HL EX (SP),HL ...LASTDE (ptr. to error)pAdd->LstDmp) ...address out DNAM() ...print last label+disp. OutSP() ...out 1 sp. PUSH DE; LD DE,BUFF+80; PUSH DE; RDLDIR(LD BC,16) R.HL->DmpAdd POP HL; POP DE; PUSH HL ...HL pts. to 16 bytes just read into buffer LD B,8 ...count ofbol table ENDTAB: WORD ENDTBL ...end of space allocated for symbol table EXTADR: WORD EXTEND ...gets addr. of EXTEND when defined, else 0 UCCADR: WORD USERCC ...gets addr. of USERCC when defined, else 0 ...QBUG variables follow: BRKLST: BYTE 0[NBRKS*5] to TMPCD for execution: CPSIR: ...cmp. string, inc. & repeat: HL->text, DE->DEFT 'str', BC count ...returns: HL 1 past beginning of string in text; Z=1 if found JR CPS0 CPSLUP: POP HL; POP DE; POP BC if R.B|R.C zero then INC A else begin CPS0: INC DE LASTDE: WORD DATA1 NEXTDE: WORD DATA1 FREE: WORD STACK STACK: DEFS 080H ...user stack (variable length char. strings) TMPSP: EQU STACK+068 ...top of temp. stack used when doing Step MYSTAK: DEFS 080H ...reg. stack MYSP: ...top of stack BUFF: DEFS LINEL .->stack; length of text->HL ERMGET() ...get msg. & put into buffer JR ERR1 ERMGET: PUSH HL ...save ptr. to text of error msg. STARS() ...to put out '***** ' POP HL LD C,(HL); LD B,0 ...put length of message into BC INC HL LDIR ...move text into buff words repeat Outhex(@HL); INC HL OuthxB(@HL); INC HL ...print contents of memory until DEC B zero; R.A->@DE; INC DE; '|'->@DE; INC DE ...OuthxB leaves R.A=' ' POP HL; LD B,16 repeat if @HL>=07F or R.A<020 then '.' R.A- ...to store repeat cnt, inst at, addr, & bk of brkpts S_R: DEFS 16 ...to save stored regs. NXTCNT: BYTE 0 ...count of how many NEXT's to do; also=max. depth (by T cmd), ... & =flag during R, or D, NGFLG: BYTE 0 ...=1 if doing N, 2 if S, 3 if T, 4 if ; @DE; DEC DE; CPIR ...chk 1st char. if zero then begin if @DE-1<>zero then begin ...@DE=length PUSH BC; PUSH DE; PUSH HL; LD B,A; INC DE repeat INC DE; @DE=@HL; JR NZ,CPSLUP; INC HL until DEC B zero; SCF; R.HL-carry-R.DE; JR..output buffer FTYPE: BYTE at BUFF ...where type of input file returned RECLEN: WORD at BUFF+3 ...where record length of file returned SEGDES: EQU BUFF+28 ...start of where segment descriptors returned SegDs2: EQU BUFF+60 ...start of set of seg. des. sayier RET Err0: RET Z ...flag must be not zero (enter here from rst) Err: PROC PUSH DE ...ptr. to error STARS() ...put '***** ' into buffer ERR1: Outmsg() ...add CR & send out LD DE,BUFF ^NUMERR; INC (HL) ...increment error count HLout(W.LSTNCD) >@DE; INC DE; INC HL ...put out ascii until DEC B zero; '|'->@DE; INC DE WSend() until DEC C zero; POP BC; RET MAXNL: EQU 10 ...max. no. letters of name to print Name: PROC ...expects an address in R.HL (call $) ...returns: R.HL=ptr. to symbJ, 5 if G, else 0 R_PC0: WORD 0 ...save prev. PC (during Step) SSP: WORD 0 ...saves Q's SP when set SStep sets sp. brk & goes SAVADR: WORD 0 ...saves addr. after Call inst. (possible spot for sp. bkpt) ...also used to save pos. in screen img. during R Z,CPSLUP; 00 ...don't catch test string POP HL; POP DE; POP BC ...rem. chars. end end end LCPSIR: EQU $-CPSIR DBUG := .DO(LD B,'Q') ResSVs Q := .DO(LD B,'R') DEL .DO(@DE=',';CALL Z,CHGRR;CALL NZ,PRTRRS;CP A) := .DOng where to image from SDDIF: EQU SegDs2-SegDes ...diff. bet. 2 sets of seg descptrs with IMAGE DATA1: DEFS RECL ...low input buffer DATA2: DEFS RECL ...high input buffer MAPTYP: BYTE 0 ...'A'=>do Map alphabetically, else by order of occurrence MAPCMP: BY...put out starting addr. of code for line MOVTXT() ...put out tab + move text to buffer, truncating if too long POP BC ...ptr. to error in text PUSH DE ...pts. after last char. in buffer if R.HL-R.BC>zero ...HL at CR in text, BC at error and beol of greatest value <=$ (call ^LOC), ... BC=$-LOC; Z=1 if found PUSH DE; EX DE,HL; INC DE; W.0->R.HL; PUSH HL; R.HL-R.DE->R.BC 00->R.A while Nxtsym(R.A) zero do begin PUSH HL if @2HL-R.DE=zero and begin LD A,(IY+TYPE); BIT , or D, cmds SBInst: BYTE 0 ...to save inst. at special brkpt. SBAddr: WORD 0 ...to save addr. of special brkpt. BRKEXT: WORD 0 ...if<>0, call this addr. after break, then go DmpAdd: WORD 0 ...pts. to beg. addr. of current dump; updated to 1 past end L(LD B,'R') ShRegs := .DO(LD B,'D') .DO(R.A=0;PUSH AF;CALL Z,CHGMEM;POP AF;CALL NZ,Dump) := .DO(LD B,'N') NS2 .DO(LD (HL),1) := .DO(LD B,'S') NS2 .DO(LD (HL),2) := .DO(LD B,'G') .DO(5->NGFLG) := .DOTE 0 ...used by Map: each bit compared with bit of TYPE byte MAPMSK: BYTE 0 ...used by Map: if bit=0, don't care about result with MAPCMP MAPBEG: WORD 0 ...used by Map: lowest value to be put out MAPEND: WORD 0 ...used by Map: highest value to be put out L gin PUSH HL;LD HL,DATA1-1;SBC HL,BC;POP BC end BC R.DE-1->R.HL ...HL pts. at last char. in buffer LDDR ...shift text that is past error ahead 1 space in buffer enUNDEFB,A end zero and BIT ZAPB,A zero and begin PUSH BC;LD B,0;if BIT BANK2B,A not zero then INC B B.CODEBK=R.B;POP BC end zero then begin R.HL+R.BC->R.BC; POP HL; EX (SP),HL end else POP HL 1->R.A end R.C; CPL; R.A->R.C; R.B; CPL; stDmp: WORD 0 ...pts. to beg. of last line dumped R_AF: WORD; BYTE 0 ...regs. stored here R_A: BYTE 0 R_BC: WORD 0 R_DE: WORD 0 R_HL: WORD 0 R_IX: WORD 0 R_IY: WORD 0 ... no shadow regs saved R_SP: WORD SP2 R_PC: WORD 0 R_F0: BYTE 0 ...prev. value of (LD B,'J') .DO(R.HL->R_PC;4->NGFLG) := .DO(LD B,'B') LSTBRKS := .DO(LD B,'B') GETCNT := .DO(LD B,'X') BRKSOFF := .DO(LD B,'X') ? := .DO(LD B,'T') Tr2 .DO(LastNm: WORD 0 ...last name put out by Map Nxtpos: WORD 0 ...next pos. in buffer (used by Map) HOLE: WORD 0 ...where gets patched PATCHN: BYTE 3 ...no. of bytes patched over (usually moved to patch area) PATCHR: BYTE 0 ...if<>0, indicates should not copyd '?'->@DE ...insert '?' before char. in error POP DE; INC DE ...pts. after last char. in buffer Outmsg() ...add CR & put out to $CON & file if open RESNST() ...res. STACK & NCODE (if error during ORG, DEFS, etc.) W.NCODE->W.LSTNCD if B.LOGUN<>SWCOR.A->R.B POP HL; if R.HL=0 then INC A else CP A POP DE; RET DNAM: PROC ...same as PRTNM except pads with spaces into a fixed format 1+MAXNL+4 PUSH BC; PUSH HL; PUSH HL LD HL,MAXNL+5; R.HL+R.DE; EX (SP),HL PRTNM() POP HL; R.L-R.E->R.B; COPYSP() POPregs. stored here R_A0: BYTE 0 R_BC0: WORD 0 R_DE0: WORD 0 R_HL0: WORD 0 R_IX0: WORD 0 R_IY0: WORD 0 R_SP0: WORD 0 Quit1: PROC ...close any open input files (LOGUN>SWCON) @^LOGUN=SWCON; RET Z CLOSFL(R.A) DEC (HL) JR Quit1 Quit: PROC ...close files D (HL),3) := .DO(LD B,'H') NS2 HISTORY := .DO(LD B,'U') (.DO(LD A,(Deasm);R.A=0C3)) UNASM := .DO(LD B,'L') (GETNUM / .DO(W.LstDmp+1;00)) .DO(PUSH HL) "," .DO('H'->@^BUFF;INC HL) $(.DO(R.A->@HL;INC HL) .DO( bytes to patch area RDFLG: BYTE 0 ...set=1 when read with immediate return in progress GTLFLG: BYTE 0 ...set=1 with relation GT, set=0FF with LE, otherwise 0 QOPTS: BYTE 0 ...if bit 0=1, ok to redefine labels ...if bit 1=1, show offset addresses on liN then begin ...check if from $CON or file W.LASTCR; LD BC,RECL; 0D->R.A CPIR; EX DE,HL ...scan to next CR end ST1: LD B,1 ...flag for no QINIT ST2: LD SP,MYSP if W.SAVSP<>0 then LD SP,HL ...chk if were in debugger DEC B; CALL NZ,QINIT ...if  HL; POP BC; RET PRTNM: PROC ...entered with addr. in HL ...prints name of most recent symbol + disp. to current pos. at DE OutSP() ...out 1 sp. PRTNM2: PUSH BC; PUSH HL if Name() and R.B=0 then begin ...Name rets. BC=disp. R.C; PUSH AF ...sav Quit1() ...close any open input files Quit2: PROC; B.DIAGSW if BIT 2,A not zero then begin ...now close output file if open PUTEOF() ...put out eof seq. ... W.FPUTNX; LD (HL),0FF ...put 'FF' for EOF at next pos. in outpt buf. PUTOUT() ...putR.A->@HL;INC HL)) .DO(EX DE,HL;R.HL->NEXTDE) .DO(LD BC,LCPSIR+4;NCODE+R.BC->NCODE;PUSH HL;Out();W.NCODE;POP BC;R.L-R.C->R.A;POP HL;RET Z) LocSub ; A0 := (.DO(R.H=0;R.L)) / IdDEF / .DO(00) ; D2: if GETNUM() <> then begin if @DE<>0D then R.A=','; sting OFFSET: WORD 0 ...if<>0, labels will be defined =NCODE+this DIAGSW: BYTE 0 ... bit 2=1 for file writing ... bit 3=1 for diag output ... bit 6=1 for listing EQUFLG: BYTE 0 ...set=1 if value of equate to be output when listing EQUVAL: WORD 0 ...value oR.B<>1, do init. set-up stuff GetrecD() ...get line of input or jp debugger ST3: JP XMETA ...call parser START: LD B,0; JR ST2 START1: LD SP,MYSP DEL() @DE=0D; JR Z,START; R.A=';'; JR Z,START PUSH DE; LD DE,DATA1; CALL Copy; DEFT '/DO '; POP HL repee displacement on Stack R.HL->R.IY; LD BC,NAME; R.HL+R.BC->R.HL ...HL pts. to name LD C,(IY+LNGTH); if MAXNL0 then begin R.A- out last record CLFPT() ...close file end ZDGSW: 00->B.DIAGSW ...reset DIAGSW to 0 RET STARS: LD DE,BUFF ...start of buffer CALL Copy DEFT '***** ' ...into buffer RET MOVTXT: 9->@DE; INC DE ...put in tab W.LASTCR; PUSH HL ...pos. after last RET NZ; R_PC->R.HL end GETCNT: if @DE=',' then begin INC DE; PUSH HL; A0(); POP HL; RET end 1->R.A; CP A; RET NS2: if B.A0()=0 then INC A; JR NST2 Tr2: if B.A0()=0 then LD A,07F NST2: R.A->B.NXTCNT; ^NGFLG; CP A; RET CHK1PR: LD C,'''; JR $+4 ..."A'"/"af equate kept for listing LINKSW: BYTE 0 ...when=1, Lkup will not link new symbol PAKSW: BYTE 0 ...when=0, pack just globals; when=1, pack all not zapped DOFLG: BYTE 0 ...<>0=>"/GET" cmd. RetQFlg: BYTE 0 ...set when start execution: 1=>imm. ex. & RET, elseat if @HL=';' then 0D R.A->@DE; INC HL; INC DE until R.A=0D; ...put /DO FILENAME into input buffer QINIT() ...put in indr. jps for after rsts., etc. GETRCX(LD DE,DATA1) ...start of input buff.->DE->LASTCR->LASTDE JR ST3 ...call parser QINIT: >R.C; '+'->@DE; INC DE; Outhex(R.C) end end POP HL; POP BC; RET CHGRR: ...change regs. PRTRRS() ...print regs. CHGMRR(1) ...change them; fall thru: ... PRTRRS: 3->R.A ...print all regs. ... PRTRR: ...if BIT 0,A=1, print PC+disp. from closest prevCR in text LD BC,076 ...(LINEL-8-2), limit to search (-2 is for '?' or ' [') 0D->R.A; CPIR R.L-1; POP HL ...R.A=low-order of pos. of CR or end of line; HL=LASTCR R.A-R.L->R.C ...length of line (without CR); B=0 from above RET Z; LDIR ...move text '" CHK1SP: LD C,' ' ..."A "/"a " CHK1C(); RET NZ; INC DE; RET C1SPCRCM: LD C,','; CHK1C(); RET Z CK1SPCR: CHK1SP(); RET Z ..."A " / "A/CR/" CHK1CR: LD C,0D CHK1C: ...enter with R.B=capital letter; R.C=char. to chk. if at 2nd spot ...ret. Z=1 if R.A or 0 CPU: BYTE 0 ...if<>0, then no. of remote CPU CODEBK: BYTE 0 ...bank of memory to put code out on (0=bank 1, 1=bank 2) PROGBK: BYTE 0 ...saves CODEBK for later restoration Skip: BYTE 0 ...if<>0, skip line unless begins with "/" I_SW: BYTE 0 ...if =1, kI_INIT() ...make sure set up right for interrupts BKINIT() ...init. PIO, bank 2 SP, Skip; set brk ret addr (both banks) RSTS() ...set restarts Quit1() ...file would be marked open if Q imaged from file Q_B() ...set breaks->Q RET Get1: PROC ...g . symbol; else not ...if BIT 1,A=1, print other regs. no matter what, except if ... BIT 2,A=1, don't do IX,IY,SP ...if BIT 1,A=0, just print those registers diff. from prev.--also ... store as prev. value for next time--plus print byte @PC ...preserveeat PUSH AF LD DE,BUFF; HLout(); PRTNM() ...put out addr.+ name PUSH HL; Outbuf(); POP HL Deasm(); POP AF ...HL is inc'ed past inst. until DEC A zero; POP DE; RET ShRegs: PROC ...print shadow regs. SAV_R(); PUSH AF; PUSH DE ...save reg. vaore inst. CALL NZ,BRKOFF ...if no FF (possible if overlays) end FNDNXTPC() ...addr next inst->HL $$$ B.RDaHL()->STBINST PutBrkB(); JP NZ,STRET2 R.HL->STBADDR; LD (STSP),SP JP Go2 ... RESRR() ...regs. back, except R.HL=R_SP ... PUSH AF ... if Tppropriate thing R.A->R.C ...ret. R.C=last char. gotten Put1(0D); POP DE; RET CHMCHR: ...chk char. in R.A & do approp. thing R.A->R.E if R.A=8 then begin R.B|R.C; RET Z ...if backspace & not 1st pos. if R.C=0 then begin DEC B; LD C,4 end DEC Cbank, cpu# end CKBRKPT(POP DE); POP AF; R.A->@(R.HL-1) ...store repeat count POP DE; 00; RET BKCPUA: B.CODEBK=0; RET Z; B.CPU+1; RET ...load A with bank+cpu code PutBrkB: ...put out break byte @HL, ret. Z=0 if rom WRaHL(0FF) CKFF: B.RDaHL()=0FF; REs all regs. WSbgn(); LD C,A; PUSH BC if BIT 0,C not zero then begin HLout(R_PC) ...print PC DNAM() ...print disp. from most recent symbol if BIT 1,C zero then begin RDaHL(); Outhex(R.A) ...print byte @R_PC end else COPYSP(LD B,2) endriables if TSTCPU() then begin ...if Q cpu DI; EXX; EX AF,AF'; STRR(); EX AF,AF'; EXX; C_EI() end else begin ...if remote cpu ^SRR_AF; LD A,4 repeat RDa2HL(); PUSH BC; R.HL+2 until DEC A zero; POP HL; POP DE; POP BC; POP AF; STRR() ...storSTCPU() not zero then begin ... POP AF; StepR(); JR S_INTR ...if remote cpu, do Step there ... end ... 087; OUT (CTC2),A ...set CTC control word ... if B.CODEBK=0 then begin POP AF ...test bank ... LD (SvSP1),SP; LD SP,HL ...save SP ......@@@ ...  SCIPOS() ...HL=new screen image pos., DE=old one repeat Put1(8); DEC DE until R.HL=R.DE; RET end R.B=8; RET Z ...if at end of row R.E=' '; JR Z,MVCRS1 if R.A=9 then begin repeat MVCRS() until R.C=0; RET end LD DE,BUFF+79; R.A->@DE ...pt.T BRKSOFF: ...remove all breakpts. LD HL,BRKLST-2; LD B,NBRKS repeat R.HL+2+2 until @HL|@(R.HL+1) not zero or DEC B zero; R.B=0; RET Z B.CODEBK; PUSH AF if @(R.HL+1)<>0 then begin SetCPU(R.A-1); LD A,1 end R.A->CODEBK; DEC HL ...set bank & cpu# for else COPYSP(LD B,MAXNL+11) endif R_A->R.B ...do R.A: if R_A0<>R.B or BIT 1,C not zero then begin R.B->R_A0; PUSH AF CALL Copy; DEFT ' A='; Outhex(POP AF) end else DOTSPS(LD B,3) ...put out " . " endif POP BC; PUSH BC; B.R_AF->R.B ...do R.F: e sh regs. of rem. cpu end PRTRR(6); POP DE; JR RES_R ...print regs. except IX & IY Regs: PROC ...write out registers (saves all regs.) SAV_R() ...save reg. variables R.HL->R_HL; POP HL; LD (R_SP),SP; PUSH HL R.HL->R_PC; R_HL; STRR() ...store reg PUSH AF; ... if IOP=1 then ^S_INT1->I2_JMP ...set to capture int. (bank 1) ... POP AF; ......@@@ ......@@@ ^S_INT1->I2_JMP ... R_PC; PUSH HL; R_HL ...set up for return ... 2; OUT (CTC2),A ...2 means do interrupt after 2*16 clock periods (+2)  DE to free spot Hexd(); RET NZ ...chk if hex digit R.A->@W.SAVADR; PUSH BC ...store in scr. image ^CODEBK; LD D,(HL); PUSH DE ...save bank ASCtoN(); PUSH AF ...A=value of char. W.LstDmp->R.HL ...^memory region to be changed (if not doing regs)  place with brkpt. REMBRK() SetCPU(B.CPU); POP AF; R.A->CODEBK ...restore cpu#, bank JR BRKSOFF BRKOFF: ...remove breakpt. at R.HL PUSH DE; CKBRKPT(EX DE,HL); POP DE; RET NZ ...ret. if not found R.HL+2 REMBRK: ...enter: @2(R.HL-1)=breakpt. addr., @ if R_F0<>R.B or BIT 1,C not zero then begin R.B->R_F0; PUSH AF CALL Copy; DEFT ' F='; Outhex(POP AF) end else DOTSPS(LD B,3) endif POP BC; LD B,C; LD C,0 ...R.B=orig. R.A repeat RRCOPY(R.B); INC C; INC C ...do 2-byte regs. until R.C=12 or R.A=6 s. PUSH AF; PRTRRS() ...print regs. ...cont: RES_R: ...recall register variables ... PUSH AF ...this push done previously here PUSH BC;PUSH DE;PUSH HL ^S_R; LD DE,R_AF; LD BC,16; LDIR POP HL;POP DE;POP BC;POP AF;RET SAV_R: ...save register variable... R_A; EI; EI; RET ...note: this line=31 clock periods ... end ... POP AF; PUSH DE; R.HL-2; EX DE,HL; ^SvSP2 ...bank 2 (R_SP-2->DE) ... WRa2HL() ...store SP-2 at SvSP2 ... R_PC; EX DE,HL; WRa2HL() ...store PC on stack of bank 2 ... POP DE; ^Step2; if NXTCNT<>0 then begin ...if changing regs., must translate B & C, & change ^memory region if R.B=0 then LD B,8; DEC B if begin BIT 1,C; RES 1,C end zero then SET 1,C ...C: 0,1<->2,3 00->B.CODEBK ...set bank 1 ^R_AF->R.HL end LD E,C; SR(R.HL-2)=inst. from breakpt. ...restore inst. & zero breakpt. addr. 00; LD B,(HL); LD (HL),A; DEC HL; LD C,(HL); LD (HL),A @(R.HL-1)->R.A; R.BC->R.HL ...fall thru: ... ResINST: ...if @HL on set bank=FF, restore inst. in R.A, ret. Z=1; else Z=0 R.A->Rand BIT 2,B not zero WSend(); RET RRNMS: DEFM 'BC'; DEFM 'DE'; DEFM 'HL'; DEFM 'IX'; DEFM 'IY'; DEFM 'SP' RRCOPY: ...enter with R.C=disp. from R_BC to R_XX in question; DE->output buf. ...if BIT 1,A=1, print reg. no matter what; else only print if diffs PUSH AF;PUSH BC;PUSH DE;PUSH HL ^R_AF; LD DE,S_R; LD BC,16; LDIR POP HL;POP DE;POP BC;POP AF;RET STRR: PUSH IY; PUSH IX; PUSH HL; PUSH DE; PUSH BC; PUSH AF W.0+R.SP; LD DE,R_AF; LD BC,12; LDIR ...store regs. on stack->variables POP AF; POP BC; POPPUSH HL; R_HL ... JP GOX ...will go to Step2 on bank 2, then execute 1 inst. ...S_INT1: ...control goes here after interrupt when doing Step (bank 1) ... R.HL->R_HL ... POP HL; LD (R_SP),SP ...store SP ... LD SP,(SvSP1) ...restore SP ...S_INT: R.HL->R_L E; R.B*2+R.E->R.E; LD D,0 ...DE=2*B+(C/2) R.HL+R.DE ...pt. to memory byte to be changed POP AF ...A=value to replace in nibble if BIT 0,C zero then begin R.A*2*2*2*2; LD E,0F ...replacing high nibble end else LD E,0F0 ...replacing low nibble .C; CKFF(); R.C; CALL Z,WRaHL; RET CKBRKPT: ...enter with DE=addr. to search for in list of breakpts. (may be 0) ...Breaklist format: repeat count, inst., addr.(2 bytes), bank/cpu ...if found, HL->at inst. (2nd byte of 5), Z=1 ...if not found, HL->2nd . ... from prev.; also copy reg. value to loc. storing prev. value PUSH BC; PUSH DE; LD B,0 ^R_BC0+R.BC; PUSH HL; LD E,(HL); INC HL; LD D,(HL) ...DE=R_XX0 ^R_BC+R.BC; LD B,(HL); INC HL; LD H,(HL); LD L,B ...HL=R_XX if R.HL-carry-R.DE+R.DE<>zero or B  DE; POP HL; POP IX; POP IY ...restore regs., stack RET RESRR: LD HL,0-14; ADD HL,SP; LD SP,HL ...=7 pushes EX DE,HL; ^R_AF; LD BC,14; LDIR ...move regs. in variables->stack POP AF; POP BC; POP DE; POP HL; POP IX; POP IY; POP HL ...regs back, excPC; R_HL ...come here with HL=PC ...S_INTR: STRR() ...store rest of regs. ... 3; OUT (CTC2),A ...reset CTC ...ResFF: LD DE,(R_PC0) ... CKBRKPT(); 0FF; CALL Z,WRaDEi ...if were at breakpt., restore 'FF' ... C_EI() ...conditional EI ... RETI STRET: ... R.A->R.D B.RDaHL()&R.E+R.D->R.A WRaHL(R.A) ...replace byte POP AF; R.A->B.CODEBK ...restore bank POP BC ...fall thru: ... MVCRS: ...move cursor along under memory dump MVCRS1: INC C; if R.C=4 then begin INC B; LD C,0 end SCIPOS() ...HL=new screebyte of last 5-byte spot, Z=0 LD HL,BRKLST-1; LD B,NBRKS CKBP1: repeat R.HL+2+1; DEC B if begin @HL=R.E; @(R.HL+1); INC HL end and R.A=R.D then begin if R.D|R.E not zero then begin B.BKCPUA()=@HL; JR NZ,CKBP1 end JR CKBP2 ...ret. Z=1 if DE=0IT 1,A not zero then begin POP DE; R.L->@DE; INC DE; R.H->@DE ...copy reg. value to store prev. POP DE; PUSH HL ...DE->next spot of output buffer OutSP() ...put out space LD B,0; ^RRNMS+R.BC; LDI; LDI ...move RR name to buffer '='->@DE; ept R.HL=SP RET LocSub: ...enter with HL=addr. to start looking, R.A=len. of string ...BC pts. to string in code area PUSH DE; PUSH HL; LD D,B; LD E,C; DEC DE PUSH DE; WRaDEi() ...put in length at beg. of DEFT 'STR' ^CPSIR; LD DE,(XAdd); LD BC,LCPSIenter here after Step $$$ LD SP,(STSP) RESSTBRK() STRET2: LD DE,(R_PC0) CKBRKPT(); 0FF; CALL Z,WRaDEi ...if were at breakpt., restore 'FF' RET RESSTBRK: ...reset special break used by Step STBADDR=0; RET Z; ResINST(STBINST); W.0->STBADDR; RET FNDNXn image pos., DE=old one PRTIMG: R.HL=R.DE; RET Z Put1(@DE); INC DE; JR PRTIMG ...update scr. from scr. image CHRRTAB: BYTE 0 24 35 43 51 59 67 75 79 ...tab positions for CHGRR CHMTAB: BYTE 20 25 30 35 40 45 50 55 60 ...ditto CHGMEM SCIPOS: ...using  or bank matches end until R.B=0; ...not found INC A ...Z=0 CKBP2: R.HL-2-1; RET MBPERL: EQU 4 ...max. no. of brkpts. to be listed per line LSTBRKS: ...list addresses of all breakpts. + disp. from last label WSbgn() LD HL,BRKLST-1; LD B,NBRKS; INC DE; HLout(POP HL) end ...value of RR->buffer else begin POP HL; POP DE; DOTSPS(LD B,6) end ...put out " ."+6 spaces endif POP BC; RET DOTSPS: OutSP(); '.'->@DE; INC DE ...put out " ." COPYSP: repeat OutSP() until DEC B zero; RET ...R.B spaces->R; WRLDIR() LD (NCODE),DE; OUTRETJ() ...put out CPSIR routine +ret. at XAdd POP DE; POP HL; LD BC,0 GoXX() ...call CPSIR (search text to find string) on set bank R.HL-1; 1; CALL Z,Dump POP DE; 00; RET HISTORY: PROC ...print addr.+last label(+disp)TPC: PROC ...enter with R_PC,etc set; ret. HL=next PC R_PC->R.HL JR_(); RET Z CALLJP(); RET Z RET_(); RET Z JPat(); RET Z RST_(); RET Z if @HL=0DD or R.A=0FD then begin ...if IX/IY R.HL+1 if @HL<02C or R.A=039 or R.A>=0E1 and R.A<0FA then JRB & C, get HL=current pos. in screen image; set DE=old one ^CHRRTAB if begin NXTCNT=0; PUSH AF end then ^CHMTAB ...pt. to approp. tab tbl LD E,B; LD D,0; R.HL+R.DE; LD E,(HL) ...E=tab corres. to B ^BUFF+R.DE; LD E,C; R.HL+R.DE if POP AF not zero andLD C,MBPERL+1 repeat R.HL+2+1 if begin @HL|@(R.HL+1); INC HL end not zero then begin if DEC C zero then begin LD C,MBPERL PUSH HL; Outmsg(); POP HL; Outset() end ...if after MBPERLth brkpt., start another line PUSH HL; PUSH BC@DE+; 0->R.B CHGMEM: ...change memory: enter with HL->1st mem. spot of 16 PUSH HL; Dump(00) ...dump 16 bytes of memory CHGMRR() ...make changes (call with R.A=0); rets. R.C=last input char. Dump(POP HL;00) ...display again R.C=0D; RET Z ...if CR,  of last R.A entries at R_SP W.R_SP repeat PUSH AF; PUSH HL; RDa2HL(); Dump(R.BC;00); POP HL; POP AF R.HL+2 until DEC A zero; RET BRK: PROC ... expects R.HL pointing to brk address; R.A=repeat count ...ret. Z=0 if brks used up or in rom, else Z=1  NXTPC2 BASINST(); R.HL+1 RET end NXTPC2: BASINST() RET BASINST: ...inc HL past inst. if @HL=0ED then begin R.HL+1 @HL->R.A; R.HL+1 if R.A&087=3 then R.HL+2 end else if @HL=0CB or R.A=0D3 or R.A=0DB or R.A&0C7=6 or R.A=0C6 then R.HL+ R.B-1 zero and BIT 1,C not zero then R.HL+2+1 LD DE,(SAVADR); R.HL->SAVADR; RET DEASM: PROC ...disassemble @R_PC ...if full Deasm not patched in, just chk for Call LD A,(Deasm); R.A=0C3; R_PC; JP Z,Deasm Call(); RET NZ ...if Call, print CALL ?"cc,"; LD B,(HL) ...B=bank indicator byte @(R.HL-1); DEC HL; LD L,(HL); LD H,A; HLout() ...put out addr. if B.BKCPUA()=R.B then DNAM() else COPYSP(LD B,MAXNL+5) POP BC; POP HL ...put out last label+disp. if bank & cpu matches R.C-1; CALL done W.DmpAdd; JR CHGMEM ...if LF, repeat with next 16 bytes ...Note: below NXTCNT is used as flag: 0=CHGMEM, 1=CHGRR ... SAVADR is used to store current pos. in scr. image CHGMRR: R.A->NXTCNT; PUSH DE LD DE,BUFF; PUSH DE COPYSP(LD B,79) ...init. s PUSH DE; PUSH AF; PUSH HL if CKBRKPT(EX DE,HL) not then begin ...chk if not already brkpt. PUSH DE; CKBRKPT(LD DE,0) ...if not, look for empty slot POP DE; JR NZ,NOBRK ...err if no empty slot EX DE,HL; B.RDaHL()->@DE ...copy bkpt byte if 2 else if @HL&0CF=1 or @HL&0E7=022 then R.HL+1+2 else R.HL+1 CP A; RET JPat: ...test JP (HL),etc if 0E9=@HL then R_HL->R.HL else if begin R.A=@(R.HL+1); R.HL-1 end then begin if @HL=0DD then R_IX->R.HL if R.A=0FD then R_IY->R.HL end RET CALLSUBR (Call sets HL=R_PC) WSbgn(); CALL Copy; DEFT ' CALL ' ...doesn't clobber R.A or HL if R.A<>0CD then begin CALL Copy; DEFT 'cc,' end RDa2HL(R.HL+1); PRTNM2(R.BC) WSend(); RET UNASM: ...disassemble R.A insts. @HL if R.A=0 then INC A PUSH DE repNZ,OutSP end until DEC B zero; WSend(); RET Step: PROC ...execute next instruction using stored regs.; store new regs. ... R.I must be 13 R_PC->R_PC0 ...save PC if CKBRKPT(EX DE,HL) zero then begin ResINST(@HL; EX DE,HL) ...if at brkpt., restcreen image in buffer with spaces LD C,B ...B=C=0 SCIPOS(); POP DE ...set init. pos. in scr. image (->HL), DE=beg. PRTIMG() ...print scr. image from DE to HL while B.Get1()<>0D and R.A<>0A do CHMCHR() ...get char. from keybd until CR or LF & do aPutBrkB() not zero then begin ...set bkpt NOBRK: POP HL; POP HL; POP DE; RET ...ret. Z=0 if rom end EX DE,HL; INC HL; LD (HL),E; INC HL; LD (HL),D ...save brk address BKCPUA() ...do: if CODEBK<>0 then CPU+1->R.A R.A->@(R.HL+1) ...save  JP: ...test for JP or CALL @HL=0C3; JR Z,CJPT; @HL=0CD; JR Z,CJPT if R.A&0C7<>0C2 then begin R.A=0C4; RET NZ end if TSTCC() then begin CJPT: @2(R.HL+1)->R.HL end else R.HL+1+2 CP A; RET TSTCC: ...test cond. code in bits 3-5 matches flag B.R_AF->R.D B,E ...diff. in stk level WSbgn(); COPYSP() ...put out R.B spaces R.HL->R.IY ...HL pts. to entry in symbol table LD BC,NAME; R.HL+R.BC->R.HL LD C,(IY+LNGTH); LDIR; WSend() ...print subr. name end end else SStep2()  INC DE; @DE='L'; JR Z,FNDHL end end end SWX: POP DE; ENDO(); B.FNDFLG-1; RET ...set Z=1 iff "xHL" found FNDHL: 1->FNDFLG DEC DE; OIXY() ...replace "HL" with "IX" (or IY); DE after R.B='('; JR NZ,SWLUP ...try again in case ADD IX,IX (or IY) ...chk for POP or EX (SP).. etc. PUSH BC; StepSP(); POP BC ...do Step & comp. R_SP to orig. RET NC ...if R_SP>=orig. R_SP until DEC B zero; W.SAVADR; B.RDaHL()->SBInst ...store inst from @(ret. addr.) if PutBrkB() zero then begin ...put out Ff1>) ; ...TESTCJ: RET ... err here if optimizing (don't care) USERCC := ; CtoJ: ...if back 3 bytes=0CD then if addr defined and within 128 bytes then ... change to JR, else change to JP (0C3); Z=1 iff change made @(NCODE-2-1)=0CD; RET NZ INC HL; B ...flag if @HL&038->R.A zero and BIT 6,B zero or R.A=8 and BIT 6,B not zero or R.A=010 and BIT 0,B zero or R.A=018 and BIT 0,B not zero or R.A=020 and BIT 2,B zero or R.A=028 and BIT 2,B not zero or R.A=030 and BIT 7,B zero or R.A=038 and BIT 7,B no end end else Step() LD DE,(R_SP); POP HL ...HL=orig. R_SP until R.HLR.C ...length rem. to "!" in buffer if not zero then begin LD B,0; R.HL+2+1->R.DE+1; EX (SP),HL; DEC HL; LDDR ...shift rem. buffer fwd. 4 places; new end->stack R.HL+1; EX DE,HL ...restore DE end ENDO(); DISP(INCF; Z=0 =>rom R.HL->SBAddr; LD (SSP),SP ...set special brk; save SP JP Go ...go end SStep3: repeat StepSP() until >=zero; ...do Steps until R_SP>=orig. R_SP RET CALLHL: JP (HL) B_RTN: PUSH HL; PUSH BC ...control goes here after break ^D_PC; RPUSH HL; @2HL; PUSH HL if Name() zero and R.B|R.C zero then begin ...chk if addr after 0CD defined POP HL; POP BC SCF; SBC HL,BC ...diff. bet. addr. & $ ->HL INC H; JR NZ,RPLJP BIT 7,L; JR Z,RPLJP R.L->@BC ...disp. is <=128, put it in t zero then CP A else OR 1 RET JR_: ...test for JP or JP cc @HL&0C7; RET NZ if @HL&030 zero then begin OR 1; RET end B.R_AF->R.B; LD A,(R_BC+1); R.A->R.C @HL&038->R.A; R.HL+1 if R.A=018 or R.A=030 and BIT 0,B zero or R.A=038 and BIT 0,B not zeroR Z,Trace JP C,Next ...Next needs NGFLG in R.A if R.A-5 zero then begin ...Z=1 if "G", Z=0 if "J" Go: ...continue execution: if at brkpt, do Step first (restores brkpt) if TSTCPU() not zero then CKStepR() ...if rem. cpu set, all cpu's to go;  DE); BEGO(); JR SWX ...put in "+0dd" OIXY: 'I'->@DE; INC DE; B.IXYFLG->@DE; INC DE; RET OUTIXY: BEGO(); OIXY(); JR OUTX OUTB: B.RDaDE(); JR OUTA DISP: B.RDaDE() if BIT 7,A not zero then begin OUTN(); DEFT '-0'; -R.A end else begin OUTN(); DEFT '+0' enDa2HL(); LD (R_PC),BC ...get & store PC ^D_SP; RDa2HL(); LD (R_SP),BC ...get & store SP POP BC; POP HL B_RTN1: STRR() ...store rest of regs. PUSH DE; PUSH BC LD DE,(R_PC) if SBAddr-R.DE zero then begin ...chk if was spec. brk (used by SStep) Recode DEC BC; 018->@BC ...replace 0CD with 018 (JR) INC BC; INC BC; LD (NCODE),BC ...adjust NCODE end else begin POP HL; POP BC RPLJP: DEC BC; 0C3->@BC ...replace 0CD with 0C3 end CP A; RET C_Bkup: ...if back 3 bytes=0CD then backup NCODE b or R.A=020 and BIT 6,B zero or R.A=028 and BIT 6,B not zero or R.A=010 and DEC C not zero and @HL<>0FE then begin LD C,(HL); LD B,0 if BIT 7,C not zero then DEC B R.HL+1+R.BC->R.HL end else R.HL+1 CP A; RET RST_: ...test for restart @HL&0C7... 2/10/81 last mod (fixed LD (IXY+d),n) ...to use: ... load in Q ... define a label SCRATCH somewhere where 0400 bytes are available during ... the making of DEASM. Default=$+01000 (with error) ... ORG where want DEASM to go ... /DO DEASM ... (uses abd OUTA: BEGO(); Outhex(R.A) OUTX: ENDO(); RET &BYTE := 80 HIGHONES / =76 DEFB / OOTO7F;~ &OOTO7F := 40 .O("LD ") R53 .O(",") R20 / OOTO3F;~ &OOTO3F := 04 OOXXX1XX / 02 OOXXXO1X / 01 OOXXXOO1 / JRETC;~ &JRETC := 20 OO1XX000 / 10 ( 08.O("JR ")/.O("DJNZ ")) sSBrk(); LD SP,(SSP); RET ...reset sp. brk & ret. end STBADDR-R.DE; JP Z,STRET ...if special Step brk $$$ if W.BRKEXT<>0 then begin CALLHL(); JR CONTX end ...chk if to execute procedure & then cont. CKBRKPT(); PUSH AF if zero then begin ...Z=1efore call (so drops thru) @(NCODE-2-1)=0CD; RET NZ R.HL->NCODE; RET EndCC: ...************** ORG Here ...start of permanent part of DEASM Do_it: PROC ...call with HL=addr. to disassemble at R.HL->W.SAVEDE; WSbgn(); ' '->@DE; INC DE; ENDO() P.BYTE;=0C7; RET NZ @HL&038->R.L; 00->R.H RET RET_: ...test for RET @HL=0C9; JR Z,RETT if R.A=0ED then begin @(R.HL+1)=04D; JR Z,RETT R.A=045; JR Z,RETT R.HL-1; RET end @HL&0C7=0C0; RET NZ if TSTCC() then begin RETT: @2R_SP->R.HL end else R.HLout 0B00 bytes) ... if desired, ORG elsewhere; may also image Q+DEASM ... Deasm: EQU Dbug+0C * if B.Deasm<>0C9 then Err; Name: EQU Dbug+9 * if B.Name<>0C3 then Err; ...ENDLINE: EQU XINST+036 ... 3C ...* if B.ENDLINE<>01A then Err; UCCADR: EQU EXTADR+2 ... EPLUS / 08 .O("EX AF,AF'") / DEFB;~ &DEFB := .O("DEFB 0") OUTB;; &OOXXX1XX := 02 LDROT / (01 .O("DEC ") / .O("INC ") ) R53;~ &R53 := 20 R53HI / 10 R53IS23 / 08 .O("C") / .O("B") ; &R53IS23 := 08 .O("E") / .O("D") ; &R53HI := 10 R53IS67 / 08 .O("L") / .O(" indicates was set brkpt. if @(R.HL-1)<>0 then DEC (HL) ...dec. repeat count if @HL<>0 then begin CONTX: LD SP,TMPSP; JP Go ...do Go if repeat count>0 end INC HL; WRaDEi(@HL); DEC DE ...restore inst. for Dump end Dump(EX DE,HL; 00) .. INC DE; BEGO(); WSend(); W.SAVEDE->R.HL; RET SAVEDE: WORD 0 ... next place to de-assemble DEOUT: WORD 0 ... ^BUFF initially IXYFLG: BYTE 0 FNDFLG: BYTE 0 Out1: POP HL;BEGO();LDI;ENDO();JP (HL) OUTN: POP HL;BEGO();LD C,(HL);LD B,0;INC HL;LDIR;ENDO();JP (+1 CP A; RET CkInst0: ...ret. inst. @R_PC in R.A; also set HL=R_PC CKFF(R_PC); RET NZ ...chk if brk byte (FF) CKBRKPT(EX DE,HL); @HL; EX DE,HL; RET Z ...if set brk, R.A=orig. inst. 00; RET ...if not set brk, just set R.A=0 Call: PROC ...tests for deasm needs 0B00 bytes non-optimized TYPE: EQU 4 LNGTH: EQU 5 UNDEFB: EQU 3 Here: ORG SCRATCH ... place for extend code Here1: *^Here1->R.DE; if ^Here-R.DE+R.DE then begin R.H+010->R.H;R.HL->NCODE end ... use one page up ITEM := .SAV(*) .H") ; &R53IS67 := 08 .O("A") / .O("(HL)") ; &R20IS23 := 01 .O("E") / .O("D") ; &R20HI := 02 R20IS67 / 01 .O("L") / .O("H") ; &R20IS67 := 01 .O("A") / .O("(HL)") ; &HIGHONES := 40 C0TOFF / OPS R20;~ &R20 := 04 R20HI / 02 R20IS23 / 01 .O("C") / .O("B") ; &XB.display memory PRTRR(2) ...print regs. PUSH HL; DEASM(); POP HL ...disassemble POP AF; 0FF; CALL Z,WRaHL ...restore 'FF' RESNCD() ...if displaced NCODE, reset it POP BC; POP DE BkDbg: LD HL,0-MYSP if R.HL+R.SP carry or begin LD HL,0-MYSTAK-020; HL) EPLUS: INC DE; EGENSUB(); PUSH HL; HL_NAME(); POP HL; RET Z BEGO(); '0'->@DE; INC DE; HLout() ...fall thru to ENDO: ENDO: LD (DEOUT),DE ; LD DE,(SAVEDE) ; CP A ; RET BEGO: LD (SAVEDE),DE ; LD DE,(DEOUT) ; CP A ; RET RDaDE: PROC EX DE,HL; RDaHL(); EX  a call instruction @R_PC: Z=1 iff true ...(rets. R.A=0CD iff reg. call); also sets DE=R_SP, HL=R_PC CkInst0() ...get inst.->R.A, R_PC->HL LD DE,(R_SP) R.A=0C0; RET C; R.A=0CD; RET Z; R.A&0F=0C; RET Z; R.A=04; RET Pop: PROC ...check for POP -- or EOUT("H06"Re *,"C RDaDE","HA8A0") := .OUT("C " *) := "=" .OUT("C RDaDE","HFE"Re) := "*" .OUT("C RDaDE","HE6"Re) ?("=" .OUT("HFE"Re) ) := "(" $ ")" ; ... := """ """; HEXDD := .SAV(*) .SA := 20(10 DEFB/.O("EX DE,HL"))/10.O("IN A,(")N.O(")")/.DO(INC DE) CBOPS R20;; &OPS := 20 A0TOBF / 10 SUBS / ADDS;~ &ADDS := 08 .O("ADC A,") / .O("ADD A,") ; &SUBS := 08 .O("SBC A,") / .O("SUB ") ; &A0TOBF := 10 ORCP / 08 .O("XOR ") / .O("AND ") ; &ORCP R.HL+R.SP end not carry or B.CODEBK<>0 then LD SP,MYSP ...if SP not in Q's stack or doing bank 2, reset SP W.R_AF; PUSH HL; POP AF; R_HL ...restore A,F,HL JP Debug Next: ...if R.A=1, do NXTCNT insts.; if =2, same but skip proc. calls repeat PUDE,HL; RET GETIT: PROC B.RDaDE()->@(DEOUT) ; R.HL+1 -> DEOUT ; RET EGENSUB: B.RDaDE()->R.L;00->R.H;if BIT 7,L not zero then DEC H; R.HL+R.DE+1;RET DE_NAME: B.RDaDE()->R.L; INC DE; B.RDaDE()->R.H ...HL=LOC for rev. lookup ...note: above also incs. DE HL_X (SP),-- inst. @R_PC CkInst0() ...get inst.->R.A, R_PC->HL R.A=0C1; RET C if R.A=0FD or R.A=0DD then RDaHL(R.HL+1) R.A=0E3; RET Z; R.A&0F-1; RET StepSP: PROC ...do Step, then compare R_SP to orig. DE, preserving DE; ret. C ...also ret. C=1 if R_SPV(Re *) ; ORNC2 := "/" .OUT("H28","A1"#1) .LABEL(#1) Zp ; ...TESTCJ ; ITEM2 := ITEM / OUTPT ; OUTPI := ".OUT(".SAV().SAV() := ".LABEL(".SAV("H014C").SAV("C Copy") ; OUTPT := .OUT("C Outset",Re,Re) $ ")" .OUT("C Out") := ".SAV(".O:= 08 .O("CP ") / .O("OR ") ; &ROT := 20 OO1XX111 / .O("R") (08 .O("R")/.O("L")) (10 / .O("C")) .O("A"); &OO1XX111 := 10 (08 .O("CCF") / .O("SCF")) / 08 .O("CPL") / .O("DAA") ; &LDROT := 01 ROT / .O("LD ") R53 .O(",") N;~ &N := .DO(INC DE) .O("0") OUTB ?(8SH AF if R.A-1 zero then Step() else SStep() PRTRR(1) ...display regs. that change DEASM() ...disassemble POP AF until begin ^NXTCNT; DEC (HL) end zero; ...dec. count BkDbg0: LD SP,(R_SP); JR BkDbg ...set SP & JP Debug Trace: ...traces a NAME: Name(R.HL); RET NZ; R.B=0; RET NZ PUSH BC ... save disp BEGO() ... set up for output LD BC,TYPE;@(R.HL+R.BC)->R.A ...get type LD BC,LNGTH-TYPE; R.HL+R.BC; LD C,(HL) ... get len. of name INC HL ; LDIR ... move name POP BC ;PUSH AF; if R.C<>0 th more than 0100 higher PUSH DE; Step(); POP DE; R_SP-R.DE; RET C 00=R.H; RET ResSBrk: ...reset special break used by SStep W.SBAddr=0; RET Z; ResINST(B.SBInst); W.0->SBAddr; RET SStep: PROC ...steps over subroutines ...specifically if Call skips untiUT("C Outset")$ ")" .OUT("C Sav") := ".O(" """ ( .OUT("C Out1","'"*) / Sr .OUT("C OUTN","'"Count,"'"*)) .DO(INC DE) ")" := ".DO(" $ ")" := TRUEITEM := DEL / XCOMM ; OUTITEM := """ ( .OUT("H3E","'"*,"H1213") / .OUT("C Cop0 / (40/20) .O(" ...'") GETIT .O("'")) ; &OOXXXOO1 := 08 .O("ADD HL,") SS45 / .O("LD ") SS45 .O(",") NN;~ &NN := .DO(INC DE) DE_NAME / .O("0") OUTB .DO(DEC DE) OUTB .DO(INC DE) ; ...note: DE_NAME incs. DE &CDDDEDFD := 10 IXY / 20 ED / .O("CALL ") NN;; &IIXroutine, printing out names of all subroutines it executes ... indenting to depth of stack, up to a stack depth of NXTCNT words R_SP->R.HL repeat PUSH HL ...save orig. R_SP if Call() then begin ...Call sets DE=R_SP if StepSP()@DE ; INC DE '0'->@DE;INC DE;Outhex(R.C) end POP AF ; ENDO() ; RET ... type returned in R.A SWHLIXY: ...search for "HL" preceded by ' ',',' or '(' in previous out buffer ...if found, replace by "IX" or "IY", if "(" before, insert "+0dd"l R_SP>=old Stack Pointer ...note: if subr. pops stack & changes ret. addr., must do POP or ... EX (SP), within 4 insts. or goofs up if Call() not zero then begin ...chk if at CALL Step(); RET end ...note: DE=R_SP, HL=R_PC set in Call R.HL+2+1->Sy","'"Count,"'"*) )""" := ".DO(" $ ")" := DEL ; DOITEM := """ .OUT(*) """ / DEL := / "," ; TRUEITEM := "$" .LABEL(#1) .OUT("H28","A1"#1) Zp .OUT("HBF") := ".EMPTY" .OUT("HBF") / "?" .OUT("HBF") ; ...SRCOX110X := 01 CDDDEDFD / CALLXX;~ &CALLXX := .O("CALL ") CC .O(",") NN;; &IIXXXIXX := 02 (01 DEFB / OPS N) / 08 IIXX110X / 01.O("PUSH ")QQ45 / CALLXX;; &X3ORXB := (08 .O("DEC ")/.O("INC ")) SS45;~ &SS45 := 20 (10 .O("SP")/.O("HL")) / 10 .O("DE") / .O("BC") ; ...do Step, chking if R_SP changes LD BC,(R_SP); POP HL; PUSH HL ...HL=orig. R_SP R.HL-R.BC->R.HL ...get diff. in stack level if NXTCNT*2>=R.L then begin LD E,L if Name(R_PC) and R.B|R.C zero then begin ...if symbol at R_PC L; Z=1 ...if not found, Z=0 00->FNDFLG BEGO(); '!'->@DE; PUSH DE ...'!'->current spot in out buffer Outset() ...beg. buffer->DE SWLUP: while @DE<>'!' do begin INC DE if R.A=' ' or R.A=',' or R.A='(' then begin LD B,A if @DE='H' then begin AVADR ...save ret. addr. for special break if used StepSP(); RET NC ...do Step, chk if R_SP .OUT("C Test","'" Count,"'" *) ; STMT := "&" .LABEL(*) DEL ":=" $ ";" (";"CtoJ /"~"C_Bkup / .OUT("HC9")) ; ORNCL := ( ":=" / "/").OUT("HC8") ; ANDCL := $ ?( .OUT("H20","A1"#1) $ .LABEL(#1) Zp ? GET2N .DO(LD L,C) SAVN ; BCDE := "(BC)".DO(P.SavB;DEFB 0) / "(DE)" .DO(P.SavB;DEFB 1) ; QQ := "AF" .DO(P.SavB;DEFB 3) / SS ; SS := "BC".DO(P.SavB;DEFB 0) / "DE".DO(P.SavB;DEFB 1) / "HL".DO(P.SavB;DEFB 2)TRDY: DEFM 'Z8000 SYS NOT READY'; BYTE 0D 0A 0 INIT: ...init. necessary stuff in ram & elapsed timer ...chk if Z8000 rdy: if in prom, print msg & ret NZ ...start up Z8000; if no ack, print msg & ret NZ 00->R.A->STATUS ...mark file i-o variables free  / .O("LD ") (20 OO1XX010 / 08.O("A,(") SS45.O(")")/.O("(")SS45.O("),A")) ; &OO1XX010 := 08(10 .O("A,(") / .O("HL,(") ) NN .O(")") / 10 .O("(")NN.O("),A") / .O("(") NN .O("),HL") ; &IXY := ?(20.DO('Y'->IXYFLG) / .DO('X'->IXYFLG)) .DO(PUSH DE;INC DE;W.DEOUTnting to CMDSW PUSH HL; NAMEND(^STRBUF); LD HL,STRBUF+1 if OpenF(LD B,LU1) not then begin POP HL; DEC (HL); ERROR(R.A); RET end LD DE,RECLN; W.ENDBUF->W.SVENDB->W.CMFPOS-R.DE->W.ENDBUF ...allocate sp. at top of edit buff. for c!ͽQ!@ء9 s1!C֡sۡA h >1!AP.80 .80.80a!AQ8 Q0!ͽP!@ m8ԡ9"! !ν!Bء1 > MaСe!B *`'"R; if zero then R.HL-1 EX DE,HL POP HL; POP BC CPMEOF->R.A; CPIR; if zero then R.HL-1 if R.HL>=R.DE then EX DE,HL RET GETFIL: ...get a file (name at STRBUF+2) & insert above current line ...enter with DE at beg. of line; ret. Z=1 iff all ok PUSH DER.A->REQFLG->RETFLG->BRKFLG ...->TIMESW->RQTIMFLG->WRCONFLG ^LUFLAGS->R.HL; LD B,NLU repeat R.A->@HL; INC HL until DEC B zero; ...mark all LU's inactive ^KBUF->NXTIN->NXTOUT BASCNTMSK->CNTMSK ^COUNT->R.HL; 00->R.A; LD B,5 repeat R.A->@HL; INC HL unt;PUSH HL) IXY2 .DO(POP HL;POP HL) := .DO(POP HL;R.HL->W.DEOUT;POP DE) DEFB;; &IXY2 := =CB .DO(INC DE;INC DE) CBOPS (*07=06 .O("(") OUTIXY .DO(DEC DE) DISP .O(")") .DO(INC DE) / .DO(RET)) := =E9 .O("JP (") OUTIXY .O(")") := =36 .O("LD (") OUTIXY .DO(INC md file buffer POP HL; RET TXTQUN: DEFB ESC ESC; DEFM 'QU N'; DEFB CR GETCMF: PROC PUSH HL; PUSH DE; PUSH BC ...get char. from cmd. file->R.A LD DE,(SVENDB) if W.CMFPOS=R.DE then begin W.ENDBUF->W.CMFPOS ...if to end of buffer, reset CMFPOS De6e!Bء7 pcugq1ܠ A¡ACs ts`9ݗsѕ xp  `@J     `?J /`   ~#J ` 9J . LYC; ...deft name actually now @STRBUF NAMEND(^STRBUF); LD HL,STRBUF+1 if OpenF(LD B,LU0) not then begin FILERR(R.A); POP DE; RET end if R.C<>0 then LD DE,0FF80 ...fake it if file > 64K LD C,E; LD B,D POP DE; PUSH BC if begin SHil DEC B zero; RELBUK() CKINPRM(); JR Z,PRMSG ...chk if Z8000 in prom GETBUK(); PUT1B(STARTCD); SNDBUK() ...start up Z8000 WAITACK(); JR NZ,PRMSG ...wait for ack CP A; RET PRMSG: PUTSTR0(^NOTRDY) OR 1; RET GETCMD0: ...enter with bucket, 1st byte DE) DISP .O("),") N := BYTE SWHLIXY;; &C0TOFF := 04 IIXXXIXX / 01 IIXXX0X1 / 02 .O("JP ") CC .O(",") NN / .O("RET ") CC;~ &CC := 20 CCHIGH / 10(08.O("C")/.O("NC")) / 08.O("Z")/.O("NZ") ; &CCHIGH := 10 (08.O("M")/.O("P")) / 08 .O("PE") / .O("PO") ; &OO1XX0 EX DE,HL ...->DE ^RECLN->R.HL; if ReadF(LD B,LU1) not zero then begin ...read in 1 record FINCMF: ENDBUF->CMFPOS; EX DE,HL; ^TXTQUN; LD BC,7; LDIR end ...put in "QU N" if error W.CMFPOS->R.HL; end @HL=CPMEOF; JR Z,FINCMF; BIT jYh9p譠 ~~  J 0! !!``Q 8E0[!X 5LX! #*0`>ݐ`>J.` .n >'{)҂!` 8J .LVh8ҏкґݞ __a4o4L9as`9FIFR(); POP BC end not zero then begin CLOS10(); OR 1; RET end ...shift file fwd. EX DE,HL ...DE=beg. pos. for new part if begin PUSH DE; B.ReadF(R.BC->R.HL; LD B,LU0); POP DE; PUSH AF end not zero then begin FILERR(R.A); W.0->R.HL ...CLOS10();in R.A ...get cmd, saving all regs. and keeping bucket PUSH AF; PUSH BC; PUSH DE; PUSH HL; PUSH IY; PUSH IX ^REQFLG; LD (HL),1 GETCMD(); GETBUK() 00->REQFLG POP IX; POP IY; POP HL; POP DE; POP BC; POP AF; RET GETCMD: ...routine to get cmds. from Z8000 := .O("JR ") CC2 .O(",") EPLUS;; &CC2 := 10 (08.O("C")/.O("NC")) / 08 .O("Z") / .O("NZ") ; &CBOPS := 80 CB80FF / 40 CB407F / 20 CB203F / 10(08.O("RR ")/.O("RL "))/08.O("RRC ")/.O("RLC ") ; &CB80FF := 40 .O("SET ") NUM53 / .O("RES ") NUM53;~ &NUM53 := .D7,A; JR NZ,FINCMF RES 7,A; R.HL+1->W.CMFPOS ...char.->R.A; inc. cmd file pos. POP BC; POP DE; POP HL; RET CLSCMF: @^CMDSW-1; RET NZ ...chk if were doing cmd. file R.A->@HL; W.SVENDB->W.ENDBUF ...restore CMDSW, ENDBUF CloseF(LD B,LU1); RET ERRD2: n8LV x  nVҲ!S!V` 9J  ҷxt!30 w!\`!\oBs%߈p!^$!$(aB 8  0 ;;oBnAy aB0oB 5 w!\zy_ $ "  RET ...if error end PUSH HL ...am't read ... ...below moved to ED22: ... LD (BUFPOS),DE; 00->B.CRSCOL ...for printing (beg. of read-in text) ... B.ROWNO->B.CRSROW ...adjust cursor row PUSH DE CLOS10(); POP DE POP BC; R.DE+R.BC->R.HL; PUSH ZZP<^ ^ ^ ^h^ OE \O(RDaDE();RRA;RRA;RRA;AND 7;BEGO();Outhex();','->@DE;INC DE;ENDO());; &CB407F := .O("BIT ") NUM53;; &CB203F := .O("S")(08 .O("R")/.O("L"))(10.O("L")/.O("A")) .O(" ") ; &ED80FF := (40/04) EDBY / 20(02 EDBY/01.O("CP")/.O("LD"))(08.O("D")/.O("I"))?(10.O("R") PROC ... R.C=0D2; CALL Z,CLSFIL ...close file if error was for invalid attr. RET  >@HL; W.SVENDB->W.ENDBUF ...restore CMDSW RET NZ ...chk if were doing cmd. file R.A->@HL; W.SVENDB->W.ENDBUF ...restore CMDSW, ENDBUF CloseF(LD B,LU1); RET ERRD2:   w>`AaB.?7poBL9f_1 _$J#   aB 5 \  `` 904!^    XX!$!>)CLNa 00oBa00ӬRa+̞6 {p {u  ! `.kHL ...BC=len., HL=1st pos. past new part FNDEOF(EX DE,HL); EX DE,HL ...DE=after last valid data of file POP HL; PUSH HL R.HL-R.DE->R.BC ...no. of extra bytes read in POP DE SHFTBK() ...shift back file over excess FIXEOF() POP AF; RET PUTFIL: ..) / EDBY;~ &EDBY := .O("DEFW 0") OUTB .O("ED") ; &EDNN := 04 EDBY / 02 (01 ED437B / ED427A) / EDBY;; &ED := .DO(INC DE) 80 ED80FF / 40 EDNN / EDBY;; &ED427A := (08 .O("ADC HL,") / .O("SBC HL,")) SS45;; &ED437B := .O("LD ") 08 SS45 .O(",(") NN .O(")") / ED),CPMEOF; R.HL+1 if CKINBUF() @HL; INC DE;,<>=* !! ~~ ! TE x  p x     ;;C x   ,,   ;;Cp00 99ݞ x 00 99 p 0 Ҟ 4ϗEsބ03s߁3 9.write to file (deft name at STRBUF) from HL to DE; Z=0 iff fail EX DE,HL ...DE=addr, HL=end PUSH HL NAMEND(^STRBUF) ...preserves DE POP BC WRTFIL(LD HL,STRBUF+1) CALL NZ,FILERR RET WRTFIL: ...enter with HL=addr of name, DE=addr to write from, BCEIRX468271 _ -  ***00@.;KPGWSBMOCLDFQTNJJ|p,pHtJz z468271 _ PFILE TOO BIG NOT ASCI437BP2;~ &ED437BP2 := .O("(") NN .O("),") .DO(DEC DE;DEC DE) SS45 .DO(INC DE;INC DE) ; patch ^Deasm,Do_it() Here2: ORG EndCC ...free area *?" DEASM from ",^Do_it," to ",^Here2 UCC: DEFM 'USERCC ' *begin ...reset USERCC Lkup(^UCC); LD BC,UCCADR; LD (HEAD() ...also RDAHD WRT: RITE() OPN: OPEN() CLS: CLOSE() end end until RETFLG<>0; CLSFILS() ...not really needed RETFLG->R.A=0FF; JP Z,DOCMD0 ...go do Z80 cmd if R.A=2 then CACHEOFF() RET ...ret. to Z80 system CKSTUF: ...may be ca01p3K KQas1L-T:!\.80 5 R-LNLX_$!$їѐL-a4!9.8`: 8 q(0` ;o6p |q xp    ߥJ / x    =end ...ret. Z=0, A=code if err PUSH BC; PUSH DE CreateF(R.HL; LD B,LU0) POP DE; POP HL RET NZ PUSH HL; PUSH DE ...DE=addr, HL=end PUTEOFSQ(R.HL) ...put eof seq., move HL past POP DE ...addr R.HL-R.DE->R.HL ...len WriteF(LD B,LU0; R.HL); POPI NAME? ERROR ERROR NOTFOUND QU N NO ROOMHIT KEYNO CHG ENTER INSERT REPLACE ??? TAG 1 TAG 2 EOF! \!q . ;;   .0 ! $}2?}:]0_   q &! zޡ5aoL+L),C; INC HL; LD (HL),B LD (IY+TYPE),2**UNDEFB; W.0->W.UCCADR end ORG Here2 /PACK LD BC,UCCADR; LD (HL),C; INC HL; LD (HL)..free area *?" DEASM from ",^Do_it," to ",^Here2 UCC: DEFM 'USERCC ' *begin ...reset USERCC Lkup(^UCC); LD BC,UCCADR; LD (Hlled from system specific routines CONIN(); CKCHAR() if TSTBUK() then begin GETCMD() ...if cmd for Z80, get it UPCOUNT() end else INCCOUNT() CKPERINT() RET UPCOUNT: ...round up COUNT to next mult. of 0100 00->@^COUNT; R.HL+1 repeat INC (HL); ߻p3K6 x  ` /  ҩpB`a4o4"n:`9`:n>[p q ph> t Ѝa6D`:n9|`.n:n9K po6Y`9(`:B9n:n9О  HL ...orig end PUSH AF; RESEOFCH(R.HL); CLOS10(); POP AF; RET PUTEOFSQ: ...enter HL=^place to put eof seq. ...save orig. chars., put seq., ret. HL past PUSH HL LD DE,SAVCHBF; LD BC,3; LDIR POP HL LD (HL),CPMEOF; R.HL+1 if CKINBUF() .OUT("HF9") / .DO(P.SavB;DEFB 3) SSNN) := "," ; SSNN := .OUT("HED","O4B"ORe4) / .OUT("O01"ORe4) ; NNREST := .OUT("H22") / "A".OUT("H32") / .OUT("HED","O43"ORe4) ; AREST := . INC HL until not zero; RET INCCOUNT: ...COUNT:+1 ^COUNT->R.HL repeat INC (HL); INC HL until not zero; RET CKINPRM: ...put 0 in bucket & release; chk if Z8000 rets. 3 which means in prom ...leave bucket released with 0 in GETBUK(); RELBUK0() W.100ao1q1psa1qsos9p0aCC qp x  0.8poB.9Ѧ1tѫ! 4Cs 1a0 xp p 00`x4 x󠁩pp x 80gin LD (HL),CR; R.HL+1 LD (HL),EOF; R.HL+1 end RET CKINBUF: ...test HL==ENDBUF-1 LD BC,(ENDBUF); DEC BC R.HL=R.BC; RET RESEOFCH: ...restore @HL chars saved in SAVCHBUF LD DE,SAVCHBF @DE->@HL; INC DE; INC HL if CKINBUF() .OUT("O78"Re) := ( .OUT("H7E") SWTCH / .OUT("H3A") ) := .OUT("H3E") BN ; PP2 := DEL ( / .DO(P.SavB;DEFB 2)) .OUT("OC0"ORe4 Re) ; ADSBC2 := DEL "HL," .OUT("HED","O40"ORe4 Re) / Ig ; IDD :0->R.HL repeat B.GETBUK()->R.B; RELBUK0(); R.B=3; RET Z until R.HL-1=0; OR 1; RET WAITACK: ...wait for ACKCD from Z8000; ret Z=0 if timeout LD HL,MAXLUP repeat TSTBUK(); JR Z,WTA2 until R.HL-1=0; 0FF->R.A WTA2: R.A->R.B RELBUK0() R.B=ACKCD; RET NO `;J!: 8J8(0n;ս`;!: 8*0`n;ΞL;`8J:)LVqa4 G`9B:nYELY jYj8`. L9!\r$4h:L:a4Kpыo4L9L>ӯ` >n :L:j:$L;L:.A while DEC B not zero do R.A/2 R.A->CNTMSK RET PUTSTR0: ...enter with HL=^string to put to console (ends with 0) @HL=0; RET Z; PutC(R.A); R.HL+1; JR PUTSTR0 Z80CMD: ...enter with bucket containing chars of cmd string ending with CR ... for poss. ZA=8 then begin ...if backspace INC C; DEC C; JR Z,GetN PUSH DE; LD C,0 repeat LD B,C if @DE=9 then begin repeat INC C until R.C&7=0; DEC C end INC DE; INC C until R.HL=R.DE; ...get R.B=col. of prev. char. repeat Echo(8); Echo(' '); o6o6^_ Ğֶa43 q0Vޗu_ _ Ğ 4 1!7_ __2!__ _ _ߒ_ Ğ x AAa43 0`.n:L; o4_ )a430֚_ _ L!<`}`UN() POP IX; RET RITE: ...write file GETFPS() ...file pos. requested->AHL EX DE,HL; R.A->R.C; LU0->R.B; 00->R.A Seek_() ...correct zfpos if necessary (CDE=req. fpos) if not zero then begin R.A->CC0; JR RITEX end repeat REQBUFW() ...rets BC=xfl+L;`8n:3` ;DJ `:J8h:n ;F`;L:j:`n;YLNapKLL;j>I!0R!7n@DE; INC DE until DEC B zero; ZC1: RELBUK() 0D->@DE 0FF->RETFLG; RET CANTDO: Echo(8) until R.C=R.B; DEC HL POP DE; 8->R.A end else begin R.A->@HL; INC HL; PUSH AF; Echo(R.A); POP AF end until R.A=0D; RET WSbgn: PROC; EX DE,HL; R.HL->W.LASTDE; EX (SP),HL PUSH DE; PUSH BC; PUSH AF; PUSH IY EX DE,HL; PUSH DE; LD DE,BUFF;_ LXpJ q**13LW_ V0LW_ LN!E_ ,! LN!L_ $(0_ _ܠ_  dW!\poB~ x TTn @_ L@ n ?_ L? x UU_ pph-_  NNh-LN(`.__en, HL=xfadr, sets xflen,xfadr PUSH BC; PUSH HL EX DE,HL; R.BC->R.HL; LU0->R.B WriteF0() ...WRITEFL0() POP DE; POP BC if not zero then begin R.A->CC0; JR RITEX end PUSH DE; PUSH BC XFADR0H->R.A; XFADR0->R.HL GET() POP BC; PUSH BCa6ֈ Jߠ ֗  L@DE; INC DE ...put CR in buffer Outbuf: B.DIAGSW; BIT 2,A ...check if file open for2L,L,__!:_` n .` n /!!)1P SCREEN EDITOR - 11/22/82 ʞdW!\poB~ x TTn @_ L@ n ?_ L? x UU_ pph-_  NNh-LN(`.__ ADJUST() POP BC; POP HL EX DE,HL; R.BC->R.HL; LU0->R.B WriteF_() ...WRITEFL() R.A->CC0; JR NZ,RITEX until XFLEN0=0; RITEX: DUN(); RET CLOSE: ...close file CloseF_(LU0->R.B) R.A->CC0 ...@IY(CC) RELLU() DUN(); RET PUTCONI: ...enter wit 40 8  s01p x xp   x` ;!0 8  LR.HL LU0->R.B if OPNTYP=0 then OpenF_() else CreateF_() R.A->CC0 LD (FNM_POS),DE; R.C->POS_H .. output CALL NZ,PUTREC ...put to file Putcon: PROC ... print from ^BUFF to R.DE ^BUFF LD C,0 while R.HLR.HL; else HL=0 W.0 h bucket containing len. (0=256) + chars. to put to cons. ...put out, rel. bucket, ...set WRCONFLG IN A,(DATA); R.A->R.B ...len. PUSH BC ^WRCONBUF->R.HL->R.DE; LD C,DATA BYTE 0ED 0B2 ...INIR RELBUK() POP BC repeat PutC(@DE); INC DE; CONIN() until.=7 h9!p t ɀȀW[  Lp x  `xw`>  x 11D 226 33'anaL;n x OO)Ӭa6cn ;ә`. !: 8J..file len to send to Z8000 if zero then ACTLU() DUN(); RET GETFNM: ...using FNM_POS & FNM_H, get filename from Z8000->FNMBUF & convert ... to form name+0; ret. HL=^name FNM_POS->R.HL; FNM_H->R.A LD DE,FNMBUF; LD BC,LFNMBUF-1 PUSH DE GET() ...get deat Get1(); P_ESC() until R.A='?' or R.A=0D; RET end P_ESC: R.A=01B; RET NZ ...test for escape Quit1(); RESNST() ...poss. need to close files / res. NCODE/STACK JP BkDbg0 PUTREC: ...puts from ^BUFF to DE to file if open, else to $CON B.DIAGSW BIT 2 while Hexd() do begin B.ASCtoN(R.A)->R.C; LD B,0 R.HL*2*2*2*2+R.BC->R.HL end XOR A; RET Num: PROC ...R.A has digit; get value of digit sequence->R.HL W.0 repeat R.HL*2->R.BC; R.HL*2*2+R.BC R.A&0F->R.C; LD B,0; R.HL+R.BC->R.HL until Digit() DEC B zero; RET GETFPS: ...get requested fpos->FILPOS->AHL FNM_POS->R.HL; POS_H->R.A R.HL->FILPOS; R.A->FILPOSH RET REQBUFW: ...req. buffer for writing ...ret. HL=addr, BC=len=min(xflen0,buff_size) LD BC,BUFEND-BUFBEG if XFLEN0R.(0ՒLN qXp qp`>Jn9թݞs! 10 8 5 p!Zo6ӓRCn ;_ x OOILNԸ!,0oF3p x nnNnI ** NNp!Ԣ1nIoD!H.8 eft fname from Z8000 to FNMBUF POP HL LD A,LFNMBUF-2 if R.A>=@HL then @HL->R.A R.A->R.C; LD B,0 00->@(R.HL+1+R.BC) ...put 0 after name LD HL,FNMBUF+1 RET READ: ...read file GETFPS() ...requested fpos (where want to read)->AHL PUSH AF; PUSH HL ,A; JR Z,Putcon ...test for $CON output ^BUFF PUTFILE: ...below puts from HL to DE ->file PUSH DE EX DE,HL PUTLUP: R.HL-R.DE->R.BC ...BC gets length of text to be transfered W.FPUTRM->R.HL ...space left in buffer if SBC HL,BCR.C if REQFLG=0 then PUTZ() else IN A,(DATA) ...leave in Z80 cmd so Z8000 won't take R.C->R.A if R.A=CONWRCD then begin PUTCONI(); RET end if R.A<>IOCODE then begin if R.A=Z80CD then Z80CMD() else if R.BC ^BUFBEG->R.HL RET REQBUFR_I: ...init for REQBUFR W.0->CURBUF; RET REQBUFR: ...req. buffer<>CURBUF for reading ...ret. HL=addr, BC=len=min(xflen0,RDBLKSZ) ...store CURBUF, BUFFLEN, BUFFDST (from XFADR0), BUFFFPOS (from FILPOS) PUSH IX LD BC,RDBL`̈́.8F q3!"mLJLML9aF 8BnLaCsӞ! 9 8  ILLH**LK 80.xp!q-` LSsַMDaF 80 8.xpLINNo6MDLHnKnJ 8.xLLD DE,(XFLEN0); LD C,0 ADD3(); R.HL->ENDFPOS; R.A->ENDFPOSH POP DE; POP AF; R.A->R.C; LU0->R.B; 00->R.A Seek_() ...correct zfpos if necessary (CDE=req. fpos) if not zero then begin R.A->CC0; JR READX end REQBUFR_I() ...init for REQBUFR W.0->XFBUF ve HL,BC,DE @DE=@HL; RET NZ ...cmp. 1st char. PUSH BC; PUSH DE; PUSH HL DEC HL; DEC DE if @DE>=@HL then @HL; LD B,A ...min. len.->R.B PUSH AF repeat INC HL; INC DE @DE=@HL; JR NZ,CPNX ...cmp. chars. in name until DEC B zero; POP AF; JR NZ,CPNA=QUITCD then begin IN A,(DATA) if R.A<>0 then 1 else 2 ...A=0 =>turn off cache (if ZOOM) R.A->RETFLG ...ret. to Z80 system end else if R.A=TIMERCD then begin IN A,(DATA); TIMER() end JR GETCMDX end ...disk cmd. follows: ...passedKSZ if XFLEN0R.BC LD DE,(CURBUF) ^BUFF1->R.HL; LD IX,BUFF1VC if R.HL=R.DE then begin ^BUFF2->R.HL; LD IX,BUFF2VC end R.HL->CURBUF ...->@2IY(XFADR) PUSH HL LD (IX+BUFFLEN),C; LD (IX+BUFFLEN+1),B XFADR0->R.HL; XFADR0H->R.A R.HL->@2IKjKLI** ԱaLMp0kD 11q7$LJ!"`I ** !9LM*0 9 NNLJԞ--From here: --To here^ LNԆaPR.HL; LU0->R.B ReadF_() ...read file, ret. R.A=CC, Z=0=>err R.A->CC0 ...@IY(CC) if not zero then begin POP BC; JR READX end if DELXFFLG=0 then XFDTA(CURBUF) X2 ...chk length comparison POP HL; POP DE PUSH DE; PUSH HL LD BC,TYPE-NAME EX DE,HL; R.HL+R.BC; EX DE,HL ...DE pts. to TYPE byte R.HL+R.BC ...ditto HL @DE=@HL ...if names equal, cmp. type byte JR CPNX2 CPNX: POP HL CPNX2: POP HL; POP DE; POP BC in bucket: ... iocode,LU,cmd,xfadr[4,otyp=2nd],xflen[2],fnam/fpos[4],bufhdr_id REQVAR() ...get use of disk i-o variables LD C,DATA IN A,(DATA); R.A->LU0 IN A,(DATA); R.A->CMD0 IN A,(DATA); R.A->XFADR0H IN A,(DATA); R.A->OPNTYP IN H,(C); IN L,(C);X(BUFFDST); R.A->@IX(BUFFDST+2) FILPOS->@2IX(BUFFFPOS); FILPOSH->@IX(BUFFFPOS+2) POP HL POP IX; RET REQVAR: ...mark file i-o variables in use if @^STATUS<>0 then stop LD (HL),1; RET RELVAR: ...mark file i-o variables free 00->STATUS; RET DUN: ...ehNaR@LNooP!bq0hNaP LNKP/!: 8J.(0 DqoT`N q22 jNՄUaP q oR!N*0*0aRoRaP aRױFa4so4a6ssso6X else CURBUF->XFBUF POP BC; PUSH BC ADJUST() ...adjust xfaddr0,xflen0 POP HL; INCFPS() until XFLEN0=0; if DELXFFLG<>0 then XFDTA0() READX: DUN(); RET XFDTA0: ...transfer buffer XFBUF (if<>0) to Z8000 ...may be called from READFL (when DELXFF; RET PutOut: ...put out Map entries, starting cols. 0,20,40,60 ...enter with HL pointing to symbol tbl entry PUSH HL LD E,(HL); INC HL; LD D,(HL) W.Nxtpos; EX DE,HL HLout(); OutSP() ...put out value (+space) POP HL; LD BC,TYPE; R.HL+R.BC OuthxB(@ R.HL->XFADR0 IN H,(C); IN L,(C); R.HL->XFLEN0 IN A,(DATA); R.A->FNM_H ...seg. with filename (if open) IN A,(DATA); R.A->POS_H IN H,(C); IN L,(C); R.HL->FNM_POS ...addr of filename if open or file pos. if random access R/W IN H,(C); IN L,(C); R.HLet 1 char. from console->R.A (wait if one not ready) repeat Get1if() until not zero; RET Echo: ...echo char. & keep track of col. in R.C if R.A=9 then begin repeat Put1(' '); INC C until R.C&7=0; RET end if R.A=0D then begin LD C,0; Put1(R.A); 0A end !ֽ֜LN _םשoDo6aR1KPKRLNړ KPaPoPaRoRaDoDaD1pL;aRLNЋaP< y 11 44 11aPasass5 x EELN{կ_lo6LG=1) XFBUF->R.HL=0; RET Z ... XFDTA: ...xfer data from buffer pointed to by R.HL to Z8000 ...if RDAHD, send partdun msg.; preserve IY,IX PUSH IX LD IX,BUFF1VC; LD BC,BUFF2 if R.HL=R.BC then LD IX,BUFF2VC LD C,(IX+BUFFLEN); LD B,(IX+BUFFLEN+1) LD EHL) ...put out type LD BC,LNGTH-TYPE; R.HL+R.BC LD C,(HL); LD B,0; INC HL ...R.C=len. LDIR ...put out name LD HL,BUFF-1; LD BC,20 repeat R.HL+R.BC until R.HL-carry-R.DE+R.DE>=zero; ...note: carry reset repeat OutSP() until R.HL-carry-R.DE+R.DEBUFHDR GETCMDX: RELBUK() ...may be gotten if called by GETCMD0 RET TIMER: ...if R.A=0, restore timer to default interval; if R.A=n=1 to 5, set ... interval to (base=default)*(2**n-1) if R.A=0 then R.A+1 if R.A>=6 then 5->R.A R.A->R.B; BASCNTMSK->Relse begin DEC C if R.A<>8 then begin INC C; INC C; if R.A<' ' or R.A=07F then '#' end end Put1(); RET GetN: PROC ... gets to CR, echoing, backspacing, storing @DE (saves DE) R.DE->R.HL; LD C,0 ...C=col. repeat B.Get1() ...get byte if R.L;` 9n :_ B x EEpLN x TT\О^H`:n:n9L;w 1p 4s_ LNև|_иaRqCPٗa4KPa6KRo6aPso6aRs o4a6o6aPo4a6s,(IX+BUFFDST); LD D,(IX+BUFFDST+1); @IX(BUFFDST+2)->R.A PUSH BC PUT() POP DE; LD C,0 ...bufflen @2IX(BUFFFPOS)->R.HL; @IX(BUFFFPOS+2)->R.A ADD3() ...get end fpos for buff R.A->R.B LD DE,(ENDFPOS); ENDFPOSH->R.C R.B->R.A if CP3() @DE; INC DE; RET Gen: PROC ...GENERATES NEW SYMBOL OF FORM 'NN'# ... CHECKING IF PREVIOUSLY CALLED...move BC bytes from @HL on Z80 to @ADE on Z8000 PUSH AF if R.B|R.C zero then begin POP AF; RET end REQBUK() PUT1B(WRCODE) POP AF; EX DE,HL PUTADL() ...put Z8000 addr & len into bucket R.BC->R.HL; LD BC,BUCKL-6 if begin R.HL-R.BC; PUSH AF end R.A; LD E,0; RRA; RR C; RR D; RR E; ...length*128 POP HL; RET ParseName: PROC ...expects name+delim @HL, FCB @DE returns error A PUSHǩ ;͐^ Ԝ ~( ͔_R. :O802maOC6Pm3{2@R.@2cwԜ~P gVͦΦ(_s(^ &BC  ( DE w( HL_ ~R. A (: O782B.  pOTOFF ...PutIO_: IO_Init(); BYTE PUNCHOFF-WBOOTOFF ...SAVREGS: ...save regs. except AF (clobbers HL) ... EX (SP),HL; PUSH BC; PUSH DE; PUSH IX; PUSH IY; JP (HL) ...RESREGS: ...restore regs. except preserve AF ... POP HL; POP IY; POP IX; POP DE; POP BC; E AT THIS LEVEL POP HL POP BC ...POP PRIOR RETURN ADDRESS PUSH HL ...SAVE RETURN ^GENCLN-R.BC POP HL JR Z,GEN2ND PUSH BC PUSH HL ^TMPTAB; LD B,16 ...16 poss. temp. symbol values repeat ...chk table marking temp. symbols as used or not @HL=0; ro then R.HL+R.BC->R.BC WRTBUK0() POP AF; RET C; RET Z CONIN() while begin LD BC,BUCKL-1; R.HL-R.BC end >zero do begin WRTBUK(); CONIN() end R.HL+R.BC->R.BC ... WRTBUK: REQBUK(); PUT1B(WR2CD) ... WRTBUK0: ...write BC bytes from @DE+ to bucket &  BC; PUSH DE; PUSH HL PUSH DE LD B,FCBSZ; 00->R.A repeat R.A->@DE; INC DE until DEC B zero; ...zero out FCB POP DE ... R.HL+1; ...skip DEFT length $$$ @(R.HL+1)->R.A; R.HL-1 if R.A=':' then begin ...drive given @HL-'@'->@DE ...SAVE DRIVE NUMBEnter with IY at vector REQBUK() DUNCD; OUT (DATA),A ...sending completion msg. LU0; OUT (DATA),A CMD0; OUT (DATA),A BUFHDR->R.HL; R.H->R.A; OUT (DATA),A; R.L->R.A; OUT (DATA),A CC0; OUT (DATA),A if CMD0=OPN then begin POS_H; OUT (DATA),A ...filX (SP),HL; RET ...PutC: PROC ...put out 1 char. (in R.A) to console ... ...save all regs. ... PUSH AF; SAVREGS() ... PutCh(LD C,A) ... RESREGS(); POP AF; RET ...GetC: PROC ...get 1 char. from console->R.A if ready; ret. Z=0 iff got one ... ...save otheJR Z,GENOK ...0 means not used INC HL until DEC B zero; TUDEEP: CALL Errm DEFT 'TOO DEEP' ...nested too deep GENOK: 16-R.B->R.A ...value of temp. symbol LD (HL),3 ...mark symbol used in TMPTAB POP HL ...return address PUSH AF LD BC,GENCLN GEN2send it; save HL, inc DE EX DE,HL; if begin R.C=0; R.B end<>zero then R.A+1; LD B,C; LD C,DATA repeat OTIR until DEC A zero; EX DE,HL; SNDBUK(); RET INCKPTR: ...inc. HL=^ into circular keybd buffer; preserve R.A,BC,DE PUSH BC; LD BC,KBUFEND R.HL+1=R.k., Z=1, R.A=code IN A,(CNTL) if R.A<>0FF then begin IN A,(CNTL) if BIT 7,A not zero and R.A<>0FF then begin CP A; RET end RELBUK() end OR 1; RET GETBUK: ...get bucket repeat IN A,(CNTL) until R.A<>0FF; repeat IN A,(CNTL) until R.A<>0FF; Re length FNM_POS->R.HL; R.H->R.A; OUT (DATA),A; R.L->R.A; OUT (DATA),A end else if R.A=RDAHD then begin FILPOSH->R.A; OUT (DATA),A ...file pos. FILPOS->R.HL; R.H->R.A; OUT (DATA),A; R.L->R.A; OUT (DATA),A end SNDBUK() RELVAR() RET PARTDUN: r regs. ... SAVREGS() ... if B.StatC() <> 0 then begin ... B.GetCh()->R.A; LD B,0; INC B ...Z=0 ... end ... CALL RESREGS; RET ...watch out for Q optimizer making this JP ...PutIO: PROC ...put to serial port (PUNCH) ... PUSH AF; SAVREGS() ... PutIO_(LND: POP AF ...R.A=temp. symbol value PUSH AF PUSH BC ...BC=GENCLN CALL Outhex '#'->@DE; INC DE JP (HL) GENCLN: POP BC; LD C,B; LD B,0 ...clean up stack; temp. symbol value->BC ^TMPTAB+R.BC; RES 1,(HL) ...note: Zp resets bit 0 RET ...note: GENCLN BC; POP BC; RET C; ^KBUF; RET CONIN: ...get char. from console to keybd buffer if one rdy (reset bit 7) ...preserve BC,DE,HL GetC_(); RET Z PUSH HL R.A->@W.NXTIN W.INCKPTR()->NXTIN POP HL; RET CKCHAR: ...send chars. in keybd buffer->Z8000; chk for ET RELBUK0: PUTZ() RELBUK: ...release bucket without causing int. on Z8000 1; OUT (CNTL),A; RET SNDBUK: ...release bucket & cause int. on Z8000 00; OUT (CNTL),A; RET PUTZ: 00 PUT1B: OUT (DATA),A; RET ROM: DEFL $  ...release bucket & cause int. on ...RDAHD sends back msg. saying how much done ...call with AHL=filepos done, IY @VEC R.A->R.B CMD0=RDAHD; RET NZ REQBUK() DUNCD; OUT (DATA),A LU0; OUT (DATA),A CMD0; OUT (DATA),A LD C,DATA LD DE,(BUFHDR); OUT (C),D; OUT (C),E 00; OUT (DATA),A ..D C,A); ... RESREGS(); POP AF; RET ...GetIO: PROC ...get from serial port if ready (READER) ... SAVREGS() ... if B.StatIO() <> 0 then begin ... B.GetIO_()->R.A; LD B,0; INC B ...Z=0 ... end ... CALL RESREGS; RET ...IO_Init: PROC ...replaces CALL in) ...HL=space left after transfer ...if buffer would overflow, BC gets len. of remaining space R.HL->W.FPUTRM; W.FPUTNX->R.HL ...next open buffer space EX DE,HL; LDIR ...text->buffer if zero then PUTOUT() ...if buffer is exactly filled (flag secntl-C LD DE,(NXTIN) W.NXTOUT=R.DE; RET Z repeat if begin @HL->R.B=3; CONINCD->R.A end then BRKCD->R.A INTZ8T() until W.INCKPTR()=R.DE R.HL->NXTOUT; RET CKPERINT: ...if COUNT up to count interval, int. Z8000 B.COUNT&@^CNTMSK; RET NZ INTZ8T(PE ...logical unit RCMD: EQU 1 ...request code RDMA: EQU 2 ...data transfer area RLEN: EQU 4 ...bytes to transfer RRET: EQU 6 ...address to return on completion RCOMP: EQU 0A ...completion code RSUPP: EQU 0B ...pointer to supplemen.0 because not comp. OUT (C),B; OUT (C),H; OUT (C),L ...fposdun SNDBUK(); RET INCFPS: ...enter IX at LUvec, HL=#bytes to inc. fpos: FPOS+HL->FPOS->AHL LD DE,(FILPOS); FILPOSH->R.C ADD3(R.HL;00) R.HL->FILPOS; R.A->FILPOSH RET ADD3: ...AHL+CDE->AHL st of caller with JP to BIOS+3+@retadr ... ...then goes there (preserve C) ... LD HL,(SYSRET+1); POP DE; R.HL+@DE->R.HL; EX DE,HL ... ...DE=addr, HL=retadr ... DEC HL; LD (HL),D; DEC HL; LD (HL),E; DEC HL; LD (HL),0C3 ... JP (HL) ...**********************t in SBC above) else begin EX DE,HL if carry then begin ...if buffer overflows PUTOUT() POP HL; PUSH HL; JR PUTLUP end R.HL->W.FPUTNX end POP DE; RET *ZAP STARS RESNST ERMGET ERR1 ST2 ST3 QINIT Echo P_ESC PUTLUP  TLUP  PUT RINTCD) RET INTZ8T: ...if conin or timer int., tell Z8000 (code in R.A, poss. char in R.B) ...don't do if RETFLG<>0 ...preserve HL,DE R.A->R.C RETFLG=0; RET NZ REQBUK(); R.C->R.A PUT1B(); PUT1B(R.B) SNDBUK(); RET REQBUK: ...request free bucket Btal info  ..address to return on completion RCOMP: EQU 0A ...completion code RSUPP: EQU 0B ...pointer to supplementalRRET: EQU 6 ...address to return on completion RCOMP: EQU 0A ...completion code RSUPP: EQU 0B ...pointer to supplemen R.HL+R.DE; R.A+carry+R.C; RET CP3: ...AHL==CDE R.A=R.C; RET NZ; R.HL=R.DE; RET ADJUST: ...XFADR0+BC->XFADR0; XFLEN0-BC->XFLEN0 XFADR0+R.BC->XFADR0 XFLEN0-R.BC->XFLEN0 RET ACTLU: ...mark LU LU0 active LU0->R.C; LD B,0; ^LUFLAGS+R.BC->R.HL; LD (HL),*********** Disk Interface *************************** ...LUN: BYTE 0 DMABEG: WORD 0 LUOFFSET: EQU 0 ...4 FCBSZ: EQU 36 FCBS: DEFS NLUS*FCBSZ ...File Control Blocks (correspond to LU's 0..NLUS-1) CCPM: PUSH IX;PUSH IY;PUSH BC;PUSH DE;PUSH HL CALL CPM PR_AFpQuitzCopy/{OuthexpErrmqErrerOutmsg{HLoutDELqGet1vPut1IrWSbgnYrWSendqrPutconyTest[{OutOutNjxGetrecxGetconK{OutpywRDaHLyWRaHLQzIdozDigitzHex.GETBUK()=0; RET Z if BIT 7,A zero then begin RELBUK(); JR REQBUK end ...^if cmd for Z8000 in bucket, wait till emptied GETCMD0() ...if cmd for Z80, get it into vector & keep bucket RET TSTBUK: ...test if something for Z80 in bucket; if so, get bucDE s#r+(BC }| ( q utm\"çͿY͏>@()*&p͋z} ͥ(&ĥq(: p=/   (  ( () [_z302o]012oz ɯO~w~3{͟1 RET RELLU: ...mark LU LU0 inactive LU0->R.C; LD B,0; ^LUFLAGS+R.BC->R.HL; LD (HL),0 RET CLSFILS: ...close all open files 00->R.A repeat PUSH AF R.A->R.C; LD B,0 ^LUFLAGS+R.BC->R.HL if 00<>@HL then begin R.A->@HL; CloseF_(LD B,C) end OP HL;POP DE;POP BC;POP IY;POP IX RET DskInit: PROC CCPM(LD C,RESDSK) B.CDISK->R.E CCPM(LD C,SELDSK) 00; RET ...Reset: PROC ... PUSH BC; CCPM(LD C,RESET); POP BC; ... 00; ... RET GetFCB: PROC ...expects LUN A returns FCB DE PUSH HL; ^FCBS->R.HL; dzLatchC{OutsetzCopyinzSrzSr1zCountӔINSTLISTOIgx}lLkupnl}}LkupȀGenZp%SavBReJPp`XcEff1ZDbug6JASMSTZCOMMAND)7LABELCOLhINST*XINSTwCBNmBITOP...System Interface ...set NLUS before compiling ...********* Console ********* PutC: PROC ...put out 1 char. (in R.A) to console ...save all regs. PUSH AF; PUSH BC; PUSH HL LD HL,(SYSRET+1) LD BC,CONOUTOFF-WBOOTOFF; R.HL+R.BC CALLBIOS(LD C,A) POPzͨͳh}~#fo*ejͷ}( ͋8G  Az,Az:#͋8 ~#fo(>>͋ [ej͋*ej>2p÷}Ӫ++x(.ͬyYP## x(ͶyӪ+x(ͪy_# x({ͱy"Qj*Qj++ìyӪ"Qj++ͪy#۪OͪyG3۪OͪyG' POP AF until R.A+1>=NLU; RET GET: ...move BC bytes from @AHL on Z8000 to @DE on Z80 PUSH AF if R.B|R.C zero then begin POP AF; RET end REQBUK() PUT1B(RDCODE) POP AF PUTADL() ...put Z8000 addr & len into bucket SNDBUK() R.BC->R.HL while begin LD DE,FCBSZ; R.A-(LUOFFSET-1) ...LU#'s start at 4 ... INC A; while DEC A not do R.HL+R.DE->R.HL EX DE,HL; POP HL; RET CloseF: PROC GetFCB(R.B); CCPM(LD C,CLOSEF); if R.A < 4 then 00; RET OpenF: PROC ...expects name+delim @HL; LU R.B ...returns 2WN}NumHNumXCOMM-OptmhQBEG]dNEWQBEG]GDEASM%SCRATCHfDeasm{g_ 01#g 00#cSavBReJPp`XcEff1ZDbug6JASMSTZCOMMAND)7LABELCOLhINST*XINSTwCBNmBITOP HL; POP BC; POP AF RET GetC: PROC ...get 1 char. from console->R.A if ready; ret. Z=0 iff got one ...save other regs. PUSH BC; PUSH HL LD HL,(SYSRET+1) PUSH HL LD BC,CONSTOFF-WBOOTOFF; R.HL+R.BC CALLBIOS() POP HL if R.A<>0 then begin LD BC,C۪OͪyG۪_ͪygkPYz(R0+ͻy۪YP+ͬy!xKyKͶyѯ)0۪!x) ۪!B۪ͪy<ͱy+xͱy+++yͱyӪXQͶyѯ!oz {O)))) !)DM)) O _z(3{~#{*Qj+"Qjͪy8 pBIT>7G+ͪyͱy͐*Kj|q*Qj"KLD BC,BUCKL-1; R.HL-R.BC end >zero do begin repeat TSTBUK() until zero; PUT1B(RD2CD) RDBUK(); SNDBUK() CONIN() end R.HL+R.BC->R.BC repeat TSTBUK() until zero; PUTZ() RDBUK(); RELBUK() RET RDBUK: ...read BC bytes from bucket to @DE+; save HL,error A file length CDE GetFCB(R.B); if ParseName() then OpenIT(OPENF); RET CreateF: PROC ...expects name+delim @HL; LU R.B ...returns error A file length CDE GetFCB(R.B); if ParseName() then begin CCPM(LD C,DELETEF); OpenIT(CREATEF); end RETelse uהuBL͸'r(;? A1͸͐:הBL͸o͛ uͽu֟u}͢(elseu͏הuA1͸J3{͸Vand ȡV(ͦor &3{?23{P͕zA1:Yͦ(ҿ3{͸L:ONINOFF-WBOOTOFF; R.HL+R.BC CALLBIOS() LD B,0; INC B ...set Z=0 end POP HL; POP BC RET CALLBIOS: ...save regs.<>AF,BC,HL & call @HL PUSH DE; PUSH IX; PUSH IY JPaHL() POP IY; POP IX; POP DE RET JPaHL: JP (HL) ......the following code gets j*Oj"Qj!"Mj*Kj|"Qjgo"Kj:o:o= *Qj+ͪyO>ͱyy( ͳyͶy##"Qj>ͳyͶyѯ3{[Gj  (H*p:p *Sj:oO(Ko [GjAz "Ij{KIj x(B| }(ͳ}{2pp(NKSj7*QjB8B!kk inc DE EX DE,HL; if begin R.C=0; R.B end<>zero then R.A+1; LD B,C; LD C,DATA repeat BYTE 0ED 0B2 until DEC A zero; ...EDB2=INIR EX DE,HL; RET PUTADL: OUT (DATA),A; R.H; OUT (DATA),A; R.L; OUT (DATA),A R.B; OUT (DATA),A; R.C; OUT (DATA),A; RET PUT:  OpenIT: PROC ...expects DEFT @HL, FCB @DE returns error A file length CDE LD C,A if B.CCPM() < 4 then begin B.CCPM(LD C,FILSZ); LD HL,FCBSZ-3; RanRecF(R.HL+R.DE); 00->@HL->@(R.HL+1)->@(R.HL+1); end if R.A<>0 then FNF_ERR RET RanRecF:= ͭ<>w<=>>=l< \>>o>2oH380028H380220>2oH38H30\3{Pͭo (?̣not ͐͟ocarry\̣H28H20 ԣ̣Îzero͐0 |R.DE RR.BCB modified by IO_Init ...StatC: IO_Init(); BYTE CONSTOFF-WBOOTOFF ...GetCh: IO_Init(); BYTE CONINOFF-WBOOTOFF ...PutCh: IO_Init(); BYTE CONOUTOFF-WBOOTOFF ...StatIO: IO_Init(); BYTE LSTSTOFF-WBOOTOFF ...uses list status ...GetIO_: IO_Init(); BYTE RDROFF-WBO  RET ABTMSG: DEFM 'SYS: Z8000 NOT READY FOR BOOT'; BYTE 0D 0A 0 ABORT: PUTMSG(^ABTMSG); LD SP,(SAVSP); RET PUTMSG: PROC; repeat PUT1(@HL); INC HL until @HL=0; RET PUT1: ...put R.A to console PutC(); RET REQBUK: PROC repeat IN A,(CNTL) until R.A<>0FFq 6 (A  y  R >q> q>qy +>w#q "ejkkcr> :oWĨr!kkR0~q#v?( q͜r?( ͏pp:oW(!kkRDM*jB0Kj"j*j w 0w"j* Os* :;<=>?@ [\]^ ` {|}~Ao>ZSejy08&o 09(SejdzAG8ag8 o g|(=8{N#ͬz*ej:gjO͕'("O"PzpTOO LONGSej ("z:ejG:gj~ {A='^' then CP A else R.A|0FF RET SeekF: PROC ...expects B LUN, CDE=abs. or rel. file pos. to seek to ... R.A=0=>abs., =1=>rel., =2=>rel to eof ...ret. CDE=abs. file pos. PUSH IX PUSH DE; PUSH BC PUSH AF GetFCB(R.B); PUSH DE; POP IX ...DE,IX=^Fh!vzqv~qV2.07. tdd disassemblerWrrdi {i Ói pj j j j" 7k 6 w * KDDDS $OeKKG]G;D DSKD(*** l:KK CLL3HfW""+L $O"  K; IN A,(CNTL) R.A=0; RET Z RELBUK(); JR REQBUK RELBUK: PROC 1; OUT (CNTL),A; RET SS: PROC LD (SAVSP),SP ...in case abort GETPARM() LOAD(^"S"); RET NZ LD BC,(PROGLEN); LD DE,(S__BEG); LD A,(S__SEG); LD IX,0FFFF BOOT(^BUFF) if SCRFLG<>0 then begis(  s!s]> 1p*n|(~svW1QD COM,YZ,,QD M DEASM S IQRSII( 8 >#dmbk͍s 6 (A  y  R >͓s> ͓s>͓sy O#~ {#A8|${}${͗zH}-{'@Sgjkk> ͨrJ{|${:o_(or>;v> !kk~#= Kgj>!Kij#ȔDKB[Qj͙{SQj[gj"  ' ~͸y#B C >͸yA\|~1#(TKKjx(~A8 m} u8sr}( ͸y͸y~͸y#~͸y8CB POP AF if R.A<>0 then begin if R.A<>1 then B.CCPM(LD C,FILSZ) LD HL,FCBSZ-3; RanRecF(R.HL+R.DE) ...CDE=file pos. (current/end) end else R.A->R.C->R.D->R.E ...CDE=0 POP HL; R.L->R.A; POP HL ...AHL=entered offset R.HL+R.DE; R.A+carry+R.C 1* O9* 9(  9Gwk~kBinfF n:_n!J$=(x͐n0x͐ >x͐ n>On0#n!!w#w#w(>V#N#~n LOAD(^"SCREEN"); RET NZ end else begin W.089E->W.BUFF; W.2->PROGLEN end ...Z8000 "RET" LD BC,(PROGLEN); LD DE,(SCR_BEG); LD A,(SCR_SEG); LD IX,(S__ENT) BOOT(^BUFF) ...starts up "S" LD HL,(1); LD L,0 ...addr BIOS if 'Z'=@HL and R.A=@(R.HL+1) an+>w#͓s "o t:_ t!$s$=(xBt t0xBtͷt >͆txBtͷt  t>͆tO t0# t!!ͦtw#w#w(>V#N#~$#~+: ~@##>t~. #>t> u >Gx( ~v +s#rp MIXED REFr} N#F0v(r+s*o `iF} s#røyp NOT DEFINEDB #øyH ~ z͸yO ~ (zGxøyV m}8 ~͸yD ͱyYP L*or}8 }w#w+|N#Fr+svx  4`i|ͱyͻ R.HL->R.DE; R.A->R.C ...CDE=new abs. offset PUSH BC 00; R.HL*2->R.HL; RL C; RLA; LD L,H; LD H,C ...offset/128->AHL POP BC ...CDE preserved R.HL->@2IX(FCBSZ-3); R.A->@IX(FCBSZ-1) POP IX 00; RET ReadF: PROC ...expects B LUN, DE=buffer addr, HL len$#~+: ~@##>G~. #>G>Y >Gx( ~e #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ x͐((#n!!OW_}T]Oů)lau!t"w#x( >!3  dd R.A=@(R.HL+1) then begin ...chk if have ZOOM BIOS DELAY() ...wait for Z8000 to get bucket & keep until init'd R.HL-2 LD BC,ZOOM&0FF; R.HL+R.BC PUSH HL JPaHL(ZOOM_RDY) ...notify ZIOS Z8000 system is loaded POP HL if SCRFLG<>0 theoint) commands). 4. If a user's program uses some routines in Q also used by QBUG (in par- ticular those associated with the `write' statement), a potential conflict exists. This would generally arise when stepping through that part of the program (iny:oGkk D pREDEFINED LABEL`iF}ͱyͶyyy( #KoB7R}$ }% }p OUT OF RANGE>2pT]> +ͼ}N#F+ѷRs#rx(`iRDMqp=~(#<_* p{GNͨ}^Vz(Cy x ( #fgth ...returns A=err code (Z=0=>err), HL amount read PUSH IX InitRW(); while R.B|R.C not and RanRW(READR) do DEC BC ExitRW(); POP IX; RET WriteF: PROC ...expects B LUN, CDE file address, HL length, IX DMA address ...if R.C=0FF then write sequentix( >"3  dSH)lgx͐!!GnHn 4 # (  >>KHB`!PO>(G (+| |ʣ>}aiaiQY{Gz(<= B0 KB! DM#| >>2n JPaHL(SCREEN_RDY) ...notify SCREEN loaded end RET JPaHL: JP (HL) DELAY: ...give Z8000 time; preserve HL PUSH HL; W.01000 repeat until R.HL-1=0; POP HL; RET GETPARM: ...get arg. (if any) from cmd line and poss. adjust SCRFLG ^INPTR; LD C,(HL); Lcluding when using the "T" command). 5. If necessary, QBUG's stack pointer can be reset by doing "Q", then "/*". 6. Normally when an instruction list is typed following the "*" (for immediate execution), the code goes at the next code location. Ho(:p n K^(]?Y:p R* p^#V+H ["p7R0?q!Ͳ~~ͨ}̓}:p w#w:p(>w>2ppTOO MANY SYMBOLS* pN#F+ DMB * pBp#w#* pRs#r@* p#ͫ~ ͓~0A~O^ f :p ~(n ally ...returns HL amount written, CDE, IX updated PUSH IX InitRW(); while R.B|R.C not and RanRW(WRITER) do DEC BC ExitRW(); POP IX; RET ...GetRRP: PROC ...expects A LUN; returns FCB @DE; Random Record Pointer @HL ... GetFCB(R.A); LD HL,FCBSZ-3; RW B>^w#>w#zw#>w#xw#yw#zbk`iG | ! T]xoyG>O!P>y +| ʣy>g( ͣ:gͣSYS: Z8000 NOT READY FOR BOOT !ͮ{y~͸#~ (>syhS͸K{[q:s!!c:(D B,0; R.HL+1->R.DE+R.BC; 00->@HL while @DE=' ' or R.A=9 do INC DE if @DE&0DF='S' then 1->SCRFLG else if R.A='N' then 00->SCRFLG RET FILNAM: DEFS 33 LOAD: PROC ...load file with deft name @HL; set length->PROGLEN; Z=0=>err LD DE,FILNAM; @HL->R.C; L wever, if a "/" is typed first, it will be put at an out-of-the-way location instead. This might be necessary if there was code at the next code location still to be executed, as in the following situation: *B ^ABC *CALL ABC (this actually generates ~ͨ}̓}Ͳ~ѯŷ 2Dj* p##*EjN#F+ "Ejx :Dj 0<2Dj !kk"o:oA(* pB ͓~0fm N !"o m[o!kkRcr͚z Rem Space=͓~*"pB .O("(") NN .O("),") .DO(DEC DE;DEC DE) SS45 .DO(INC DE;INC DE) ; patch ^Deasm,Do_it() Here2: ORG EndCC ...free area *?" DEASM from ",^Do_it," to ",^Here2 UCC: DEFM 'USERCC ' *begin ...reset USERCC Lkup(^UCC); LD BC,UCCADR; LD (H)+R.BC-1 R.DE->@2IYSCREEN͸ !"c!"{K{[v:x*t!c*.>Z ## # ]++3 >\:(>\!+| !N#T] w ( S >2N 2 (>.~ (# ps/DO Csmm~O#!ͱ("bk"{c( ͢"͢'S' NOT FOUND D B,0; INC HL; LDIR; 00->@DE ...move name if OpenF(^FILNAM; LD B,0) not then begin ERR(); RET end R.DE->PROGLEN->R.HL; LD DE,BUFF if ReadF(LD B,0) not then begin PUSH AF; CloseF(LD B,0); POP AF; ERR(); RET end CloseF(LD B,0); RET SNFMSG: DEFM "'SCALL ABC; JP Debug) After the break at ^ABC, there still remains the code "JP Debug" to be executed when ABC eventually returns. Thus, to execute something else at this point, one should do: */TEST(2) (or whatever) 7. The following procedures in Q{cr͏ [o?0 PY?8DM>Co!B ,! +8~G#   ^#V*o{͸ ~͵ N#!jk R8͸R0!kR0crkkSo${> !B($!p~(#pTOO DEEP>6${>#H!p (4) ORG DEASM /DO DEASM.S ORG 0100 /?"/IMAGE QD.COM ",begin LD BC,0B0E end,^Q-R.BC," 0",@2(TABBSE->R.BC)F / 40 EDNN / EDBY;; &ED427A := (08 .O("ADC HL,") / .O("SBC HL,")) SS45;; &ED437B := .O("LD ") 08 SS45 .O(",(") NN .O(")") / ED437BP2;~ &ED437BP2 := 'SCREEN' NOT FOUND ERROR  :! !)!????098(w#098(w!ͮGr͚z/IMAGE SYS.COM !{S >2N 2 (>.~ (# ps/DO Csmm~O#!ͱ("bk"{c( ͢"͢'S' NOT FOUND ' NOT FOUND"; BYTE 0D 0A 0 SCRNFMSG: DEFM "'SCREEN' NOT FOUND"; BYTE 0D 0A 0 ERRMSG: DEFM 'ERROR ' ERRCD: BYTE ' ' ' ' BYTE 0D 0A 0 ERR: PUSH AF if R.A=FNF_ERR then begin LD A,(FILNAM+1) ^SCRNFMSG if R.A=0 then ^SNFMSG end else begin PUSH BUG may be called from a user's program if it is in bank 1 (referenced via the global symbol Dbug): Regs: EQU Dbug+6 writes out the current value of the registers (preserves registers) Dump: EQU Dbug+3 displays memory starting at R.HL with R.A=nˎ~ {OG!p ˆ{!kk#Ó{{O[ij(SijDKK"ij*ij+NGB77PY##7bkz${*Qj+~+~ "Qj x <! =(G #7R(ٯQU  hRK ͕,bjR?؆DK Ϸ .O("(") NN .O("),") .DO(DEC DE;DEC DE) SS45 .DO(INC DE;INC DE) ; patch ^Deasm,Do_it() Here2: ORG EndCC ...free area *?" DEASM from ",^Do_it," to ",^Here2 UCC: DEFM 'USERCC ' *begin ...reset USERCC Lkup(^UCC); LD BC,UCCADR; LD (H [FD; OUT (C),A; OUT (CNTL),A IN A,(CNTL) until R.A<>0FF or R.HL-1=0; ...get bucket JP Z,ABORT ...HL=0 POP HL 00; OUT (C),A ...put in 0 2->R.H while DEC B not do begin PUSH BC; BUKLD(); LD DE,BUCKL-16; POP BC end GOBUK->R.H; BUKLD() RELBUK()AF; ^ERRCD if R.A/2/2/2/2+'0'>'9' then R.A+7 R.A->@HL; INC HL POP AF if R.A&0F+'0'>'9' then R.A+7 R.A->@HL ^ERRMSG end PUTMSG(R.HL) POP AF; RET  HL; INC HL POP AF if R.A&0F+'0'>'9' then R.A+7 R.A->@HL ^ERRMSG end PUTMSumber of 16-byte lines to display (if R.A=0 then does 1 line) (preserves registers other than HL and AF) Also, the global symbol R_AF points to the registers stored in Q after a break (or after the "N", "S", or "T" commands). These are stored in the[bNQ &6SQ &6GU >2apJC ͧ"p>2apBỦBC ͧŇXUXC ͧETQ /6HQ &ͯUK :[ͻLC Eͧ(*op#,>H!kkw#tz w#tzw#("gj1*Qj "QjP{*Qj}́} |}kk(+H_O>cv!v~v5͏p:oW( vwMw2okk͚z***** > *Gjv> }=O!kj"ij*ejq͚z ERROR ${*ejkcq:v:Cj(Gr͚z ERROR TOTAL=${Wr!v~v5~(my!%jO ^Vn f~x:v *Mj|(:v(S!m Rny x xR8 $ DM!mB*#j" j:%j2"jx DMbk> ny>-v2CjkqSGjSej2Aj"?jxx*?j" j:Aj2"jky*?j"#j:AjET MoveTxt: PROC ...while characters valid move R.A->R.B while R.B<>0 and ValidChar(@HL) do begin R.A->@DE; INC HL; INC DE; DEC B; end R.B->R.A ... MoveSp: PROC ...R.A spaces->@DE R.A+1->R.B; ' '->R.A while DEC B not zero do begin R.A->@DE;  following order: R_AF, R_BC, R_DE, R_HL, R_IX, R_IY, R_SP, R_PC. Also note: to add extensions to the debug commands, the place to patch in is at ^Dbug. This would be called immediately before the debug commands are parsed. Differences when debugging Пȯͧ(  (,*p, > < >2`p!ap' W,WC ߸"mpO  Gr*mp"op{͸ky"mp~${#~͵#>|~0 0>.#>|Wr !RDM 5~#foR0&B8!~_ o g(:p  DMqʹpN#ʹpcrkk!Cj4*Sj{pշB8(!kB0bk+>?crp*Qj"Sj:v( *Gj> 1kk*Mj|(ijqUxa1kk͕ (;(k͚z/DO ~; > # ͳqkxvpv|v͏pyv( > v y v>  ( 8 >#vbk2%jmO:vGUu:vG!͘u"?j2AjNyy z`8>:vG͘u ͜p:Bjo !k"Gj6 pREAD:o ^#V#N#F#x>iw!kuybk*wMw͗zQ VERS !h@{~N#F+ws#r+q#p+>> 2cvɿN#( ASej#([ejH INC DE end RET ValidChar: PROC if R.A>='@' and R.A<='Z' ...includes A-Z or R.A>='`' and R.A<='}' ...includes a-z or R.A>='/' and R.A<='9' ...includes 0-9 or R.A>='!' and R.A<=')' ...includes "#$%&'( or R.A='+' or R.A='-' or R.A='\' or R.in Bank 2: All memory and symbol references are for the currently set memory bank. Thus, to be referenced in bank 2, a symbol must have been defined there. (Symbols with the same name in different memory banks are considered different symbols.) This r >y/Ox/G| <!.}GU͸ 'x #y N> 0O( O>+y${j>q>GrOA(*p{I ͯy${UU:rpG:p I(x2p͚z A=${N:qpG:p I(x2p͚z F=${NAx y ( P(WrBCD x2 pTHENELSE ! p>wENDIF 2 pBRKS-> Q y( P yRESET +͕EXTEND!p~6*ejͼ}$pq#p62pIMAGE <͕Sv ( w!"$h!"h!8h"hÒ(!DMӭ̀y/ ͜pyͬy* EOFxSTART ͜p*Qjnfr(͙d ~#fo# ͉ē,P. Fzϯ(FzkC ͤzU Ȕ[Ͽ8{7W. FzFz>sB. FzFz>sFz!ì!õHLDE bkBC`i+carry+-carry-= ::͕-> jͳ ë( ͽ ë + et͕" z >͋x* C Copyin#1 C GenRFzC ͤz.DO(͕; (["zzC Copy'z'ͤz"Htzz{o),͗zHF#~${#P{(ڍ 2 ((% A1ͽ8{7(Lͽ͆( :ͤ [>l͕͊( ٜ ëOC0n7͕HL, ͕O40n7DFzdzy$͵i(BC) ë(DE)ëAF ëBC ëDE ëHL ëSPëIX(IY ëÕHLIX IYO86rU (EHLIXIYSP!p ^#V!sp F#fhR O(}|͸! >={N͸>.͸bqby *mp2`pkkOUHY;q ( (͞O> v_ xy  Y>vR x{ (h /y ktz*fpw!pV {*op:`p(x Iˉ ͝óCLEAR̤~DIAG !oaLOAD >;DO 2pSv͎ͻåw!"o+"op̟(2o̟(:o 2o͕R=ͧ "o, ͧ"oͲALL K͏ ^ >!o2pgo"Ij͕E= ͧ"$hRL=80 !"h!"h͕R  }/o|/g#"ѩ <(ë- ѩ =(ëǦ & ë( | ë( .XOR. ë *2 /2?͕-> ˨ͳ ë( ͽ ë ͕R.͕O42nr+ - )Ǧ ٣*2 )/2<͕ѩ #֩ estricts somewhat the use of routines and variables from Q when in bank 2. Certain routines, however, in particular those required to do the `write' statement, may be reached via other routines with the same name defined in bank 2. in particular those reٜ,[͕( ٜ ëO03nr͕+( ͉ ë O7rO06͊r͕ft,08{7Ы͒ , DNZ ëZ ëNC ëC ëPO ëPE ëP ëMëC, ëNC, ëɯ2p!qpY;x_A WͯyͶy2p y YRv#+3;CKO#(-27ͱy##= hͧͧέ͕...̎Fz !8{ͤz;: (͕MEL7Ͳ(EQU9D>WORD ͜ >( E>ͬ(BYTE ͜ >( E>(PROC ͜ >(E> ͕; DEFL \9>͕at F~*pI{I h!Êl_BiBi~!rh Ti di {i Ói pj j j j" 7k 6 w * KDDS\LDDDS $OeKKG]G;D DSKD(*** l:KK CLL3HfW""+L $O"  Kquired to do the `write' statement, may be reached via other routines with the same name defined in bank 2. efined in bank 2. "T" command). 5. If necessary, QBUG's stack pointer can be reset by doing "Q", then "/*". 6. Normally when an instructZ, ëNZ,ëFz A1ͤz$;(*Qj+"Qj͕A,+ O807r ͊OC6r0*Qj+"QjFz y "oͬ *oI{͑*FzA2ͤzП̬2** ͵Z( - ͵g}į('   o&' I{UL>l8"wps}p"p*wpLj!Ppqp!qpPp!9qp !9!qpPY͸y![p-ySQjK͞+>bѯ*}pͱy`ib##= a("a ͯy(#s#r#wa+wѯ:p:ͬ( *o I{ĝD7ͭwD1. (2. >( s. : p /G:p̃0 D?>2pnf"pFz!p~/w[x2p*͕at9D>+Fz*ej}͕*Qj"cjܔ͕; ܔ(ןן;*$p͐z;Ͳ>.;KPGWSBMOCLDFQTNJj6vl]NV4o<468271 _ K*B (+~# (#KB 8`i+"6+6 *+6 :+2 (yͧ> :6G:7:U:QO˹x ŁG:S( :R(  :T~ #!+!UT] ͏w 0[$Ko*cj I{͵;U(I{ FzM|+ ͵-͵& ͵* ͵2/͵0 ͛dzí͕dz ͖͛H }͎͂value(*cjmCcj) ͎Fz[͕͠Ġwpatch #!owr 4ͧp<>Ͷyͯy!&p####~#  x:p#~(=a>2p+N:pa2pa##Fw+Nw+~`iO y̶y!'p###~#~#  z( x <+++Gr!'p###~##(/ cr8{F+~+ng{ Uy=ĸWr*p"bpa ~XE%ͯy2"sÝ{Kʇ™͙LD ͕͋JP 0͕ OC2r͝(U Ԝ[(͝JR ͕ O20r(CP ë=EX 5͕DE,HL ( AF,AF' ((SP), HLٜOR ë=RL ë( RR ë -EI DI # +R(+  x FILE TOO BIG NAME? ERROR ERRORO!3y͠ͅ>  O͠!:͇>Iͧy͠͠bk> :5GyͧRy ! :<G yP0 x   :;(yO:;0 G> P ' ~'#'yP O!5"o>2o͵,Ustop ?C WSbgnI, I(C WSend͕͠ C HLout͕ C Outhex" xbegin͉endȔ̞( ͧ ( ͻ*Qj"Sjgx!ovĔif $ġ^thenzܔźOendifwhile )ġ^[bpa≯y*|:X!"*p/͓͆͡~( #~,8 9(80^#~ #~# ##/~((( ( ##~(~" ####> *wp#+ ~ *yp *{p~(~(( #~#fo###:qpG~8 p(8 p 0 @(  IN >͕A,( C) x( l [(8 O40r,(C)RET ͕͒ OC0rGPOP ëINC ë( DEC ë ͕SUB ë( AND ë( XOR ë =ADD $͕Ԝ ,O09n(ë@ADC ë 7(~ !T~ <54x ÉG~( ؿ yPx NO ROOMHIT KEYNO CHG ENTER INSERT REPLACE ??? TAG 1 TAG 2 !0!>!7>I>Aͧ~ #͠!S6:S!0͇v5EOF͕O2:(8s!:(6,:5= ͠w__[0S0>25*:524GdozܔA1U7Orepeat ͉͕kendrcaseܔzofendLU7until 3zͨ A17(ġ^A2U7D7DEC B ͕ѣ͕; Ϳ8{7DA1?*!A2ͽz% ͕; ( @ P(( P 0 x(8 x(~~0 :qpG:tpO~8#(,0 @($8 @  p(( p   (~( Ny(# #~~8og~( #~M(E( +~ *}p~#fo#*p a~ȯͿ[}p Ϳ( #ͯy=ë@SBC ë7(ë@BIT ëbSET ëbRES ëbLDI LDD CPI CPD ORG xت`iRLA RRA RLD oRRD gDAA 'CPL /NEG DCCF ?SCF 72Q 2Qͧ!:5O%͠ɯAͧ y>  F#fhp_!U>?ͅ!U"=}!9!9*=~ #; "=2?J{ 0*=+"=6 ͕ zUyͧy>_ > ͠7(4i z +͍:?M8!*=sT]S=25>_ y=͈͠_ ((else zܔzGLͽ,w(ëD A1ͽ͕:ܔGLͽt͠ z£z۟z͂ͧ(elsez͔ܔzA1ͽO8{ͽ[and ͡[(ͫor &8{D78{U͚zA1?#^ͫ(ҿ8{ͽ*}pRد*ip|:hpX!"ipϊ(ш###"fp( *fpͯy2hp "ipsdpÉ8!dvͱyCp!fvͱyC}pL[p*ipR  {dp*R*kp|(ba +~(5~(1jÉ#~͸yb>l͇>̶y!98 !90:p(1kk*qp*wpOUT /͕UC), 8O41r(l ),ARLC ë( RRC ë( SLA ë( SRA ë( SRL ë -EXXPUSH ëWORD̬BYTECALL ͕ OC4r(͝LDIR LDDR DJNZ ͕CP *=6 ͕{`8˯N#! ( X(!!a̓:J * |(pS= *|pWE([  (q (; ɿ , (; ͩ'@ 09(͵AF(!)DM)) O ͵(!A8O)))) (L?= Ͳ<>|<=C>=q< a>Ct>2oH380028H380220>2oH38H30a8{UͲt (Dѣnot ͕ͤtcarryaѣH28H20 ٣ѣÓzero͕0 |R.DE RR.BC= ш>l͇!`p5 {}p*}pϊ ?08K}pB:`p8%]*p x CGrU NWr1ш[}pR01j:ap( y(a [paшi:p *p*wp!:p(!jvͻy*p*wpó:p :pay͏p1kksMj >*IR CPDR DEFS ͤت*Kj DEFT ͱz̈́DEFM ͱz͋RLCA RRCA RETI MHALT vOTIR OUTI DEFBDEFW͕ ̛Ĩ(WRITE%GLOBAL͕Fz(͕l ̺([0E~Xx <͉ +EOX NyF#~*R8*R0*RB DM (_  O ~#~ (; > ͯNH%RDPSD͇MsS1D( > &D y &D>  ( B ͕̩ ë͕c ٜ ̓( ͙dR. ?O807rfOC6Ur8{7@R.@2h|ٜ~U l[ͫӦ(dx(c &BC  ( DE |( HLd ~R. A (? O787B. %x2ap/ V("pO  :ap(!x*Kj"Qj"pȔΌ !ȁb Zw͔  p ̈́< E>[ FzC Latchͬ]UͲ[/ (A1ͽLͽ%(ݿ͔ H13m8{z͔ ]+ O04r7O347Ê(HL) ëͲ =B ëC ëD ëE ëH ëL ëAëԜ !,( *ͤ[( , !ͤq O02n,AA, ԛ+ 8,+ O407r( O46r͊(= &E:=(/  (G;* (/ O(Ȕ VmMAP A 2oK͝ZAP ͕͎(͕Fz 3(PACK ͕ALL >(2pK;~LIST :͕OFF !o˶(ON̴( ͟pEND(ʹX [ejZw͖y͎BANKyIF u :ͬ- !} }Do>{P{( ͫ D0 ̩( U ͕[f>8{7R. ͙( ٜ (^ '͉(p C ͽ̈́LͽēW. %( Fz *ͬē,l *ͬU ͠[n -DE ^#V+( v m z.OUT( ͪ.LABEL( LԎ.SAV( ([C SavR{ Ͳ}E$ Lͽb(A1ͽ?b" z ͋(͔ M={##P{[(ͪ([( , ͪp ̈́C Outs O06rlU L ",+ O707͊( 6͊l("X *ejͩ,Ͱͤ[SP, Ԝ (ë͉͕,͉U O4Bnͤ[O01nͤԜ "A 2͕O43nq O0An+ O787U  ~ ]!v")]Gr> []e^e]Wr*)]e][]e]N#[]́]͘]e]>0{S+][)]S)][+]ͯyo]*+]w#"+]o]og}(%#o]oo]gXxe] ~ N#y( >+>0y${[]ɯ2.]e]>!8{!( (,(( GH L( []:.]=>RDYERR: EQU 0C2 NOTFNDERR: EQU 0C7 EOFERR: EQU 0C9 NOTOPNERR: EQU 0CB TUMNYERR: EQU 0CF WRGTYPERR: EQU 0D2 ...******* ORG ROM0 ...sets asm & runseg RAM: ADDR RAM2 ROM: ADDR ROM0 /DO ZSYS /DO ZSYSLIB /DO SHELL ENDROM: ADDR ROM ENDRAM: ADDR RAM /MAP  if not zero then ERR() R8:=R3 R13:=R9; R12:=MYSeg RL0:=@R8&0DF ...1st char made upcase if RL5=1 and RL0='X' then begin DEL() LDL RR10,LSTENT if CPB @R9,#'*' then R9:+1->R13 else begin if GETADR() zero then begin ..cr. bottom before done, else Z=1 EX DE,HL; PUSH HL ...save last char. to print POSCRS(B.ROWNO->R.B;R.C) ...pos. cursor to start PRTLUP: POP HL; R.HL-R.DE; RET Z ...test if done R.HL+R.DE; PUSH HL ...save last print char. R.C=0; CALL Z,ERASL ...if ...SHELL CONLU: EQU 2 MAXS_ARGS: EQU 10 ...max. no. args to shell script EOFCH: EQU 01A ...eof char (CPM) EOFCH2: EQU 0FF ...RIO MAXFNML: EQU 32 HDRSIZ: EQU 24 MAXNSEGS: EQU 12 SEGENTSZ: EQU 8 LHDRBUF: EQU HDRSIZ+MAXNSEGS*SEGENTSZ MAGIC1: EQU 0E007 .( $ QH2@o\E U9]+0e]${[]o] `o]v  _@o] 9]LD B_/],`o] _o] co] a o] Ϳeo] o]EIRX468271 _ - ]]d+FUNDEF /if ^ENDRAM1>^PSA then ?"ENDRAM1 OVERFLOW->PSA"; /if ^ENDROM>^RAM2 then ?"ENDROM OVERFLOW->RAM2"; /if ^ENDRAM>^FREE then ?"ENDRAM (RAM2) OVERFLOW->FREE"; /WRITE"Type in:" /WRITE"/IMAGE S ROM: ",^ROM0," ",^ENDROM-1," ...E=",^START0 .../IMAGE S ROM: .get addr to RR2 LDL RR10,RR2 R13:=R9 end end end else begin if RL5=1 then begin RL0=='I'; JR Z,CMDZ80 end ...test for "I" LDFIL(R8; R5:) ...if Z8000 file, load file, ret. RL3=1, RR10=entry ... pt; if Z80 file, ret. RL3=-1;in 1st col., erase line while @DE=0 do INC DE ...go past nulls case R.A of TAB:begin ...if tab B.SHOWTB->R.B TBLUP: if begin INC C; R.C=NCOL end 0, ptr. to curr. pos. in system cmd line FILDRV: BYTE 0 ...for drive# ...(or start of name) BYTE '/' FILNM: DEFS MAXFNML+1 ...filename or drive+fname BYTE 0 HDRBUF: DEFS LHDRBUF MAGICNO: WORD at HDRBUF SCd+Fi{t5.;KPGWSBMOCLDFQTNJE|:&f3468271 _ K*B (+~# (#KB 8`i+"6+6 *+6 :+®  (yͧ> :6G:7:U:QO˹x ŁG x :S( :R(  :T~ #!0!UT] ^ROM0 ^ENDROM-1 ERFLOW->FREE"; /WRITE"Type in:" /WRITE"/IMAGE S ROM: ",^ROM0," ",^ENDROM-1," ...E=",^START0 .../IMAGE S ROM: ^ROM0 ^ENDROM-1 OM-1 OINPRGB: EQU 7 DELWRB: EQU 5 ...delayed write GDDTAB: EQU 4 RDB: EQU 0 ...1=read, 0=write RDAB: EQU 1 A if shell script, load into ... (requested) memory buffer, ret. RL3=0 ...LDFIL calls ERR.. if err if RL3=-1 then begin CMDZ80~ TOTRM(); R9:->CMDPTR ...go till @R9=";" or CR & set CMDPTR Z80CMD(R8) ...send cmd string @R8 to Z80, temp(R.B); LD B,' ' ...1st 'space'=B.SHOWTB JR NZ,TBLUP ...put out spaces until at tab pos. end end CR:begin ...if CR R.A->R.B if B.SHOWCR<>0 then begin ...if showing CR with another char. if begin R.C=LCOL; B.SHOWCR end O͗!>~>Iͧy͗͠bk> :5GyͧRy ! :<G yP0 x  G:;(yO:;0 GP  ~#yP O!5~ !T copyright(c) 1977, digital research $Error On Line $SUBNo 'SUB' File Present$Disk Write Error$Command Buffer Overflow$Command Too Long$Parameter Error$Invalid Control Character$Directory Full$Cannot Close, Read/Only?$!9"!͇͊!p+q*orarily quitting ...doesn't ret. end if RL3=0 then begin ...if shell script GETARGV(R3:=^S_ARGV; R5:=MAXS_ARGS)->S_ARGC ...store ^'s to args. & cnt (needed by GETSCRPT) TOTRM(); R9:->CMDPTR0 ...save level 0 CMDPTR LVLro then PUT1(R.A) else R.A->R.B end ... PUT1(CR) ...print CR LD C,NCOL end P.ASCPRT:begin ...if is printable ascii char. (>=020) P.CHRPRT ...print it (note: R.B was set = the char. in ASCPRT) end CR2: CHRPRT(LDabove buffer SCRPTPTR: LONG 0 ...ptr.->current spot in above S_ARGV: WORD ARRAY 0[MAXS_ARGS] ...gets ^'s to args of script file S_ARGC: WORD 0 ...no. of above INBUF2: DEFS 144 ...input buffer used with shell script LINBUF2: EQU $-INBUF2 INBUF: DEFS 14~ <54x ÈG~( ؿ yPx NO ROOMHIT KEYNO CHG ENTER INSERT REPLACE ??? TAG 1 TAG 2 !'!5!.>I>Aͧ~ #͠!S6:S!'~m5EOFO2:(8r!:(6,:5= ͠w[0S0>25*~:524G2Q 2 ͊!p+q*͍2!p+q*͍2!p+q*͊!p+q*͍!p+q*͍!p+q*͍2!s+p+q+p+q:=2ʦ** w*#"*#"!p+q(+*DM*p*& 6:ep\:=:+1; RET end end LDL LSTENT,RR10 DEL() if CPB @R9,#',' not and BIT R11,0 zero then begin CKREDIR() ...poss. redirect i-o TOTRM(); R9:->CMDPTR ...go till @R9=';' or CR & set CMDPTR R0:=flag; SET R0,15; R0:->flag /SEG P B,'~') ...stands for CR in LOCATE cmd. else begin ...if any other kind of char. CHRPRT(LD B,SHOWCH) ...print SHOWCH in place of actual char. end end ...end of case statement if R.C-NCOL zero then begin ...check if last col. LD C,A 4 LINBUF: EQU $-INBUF DBGSTK: DEFS 0C0 ...stack for debugger DBUGSP: DBGBUF: DEFS 80 LDBGBUF: EQU $-DBGBUF ORG $+0F&0FFF0 RRS: WORD [16] ...save regs. here if no other brk handler RRN4: WORD [1] RRFC: WORD [1] RRPC: WORD [2] WORD [4] ...left empty EQͧ!~:5O͠ɯAͧ y>  F#fhg_!U>?|!U"=t!0!0*=~ #; "=2?J{ 0*=+"=6 ͕ zU̖yͧy>_ > ͠7(4i z +:?M8!*=sT]S=25~>_ y=̪͈͠_ ( *=6  ͧ!t6>!t%\= >!t6:t<2t=O! ~2u b:<2O>9b!60+~9b!60+4:uat:u_2u:uMʉSͧ!v6!"v!|6:|Ҁ!x6 2}:} Hk:} h:}$6 2}$*}M3:}02}O> ͧ3!zUSHL RR12 ...also on stack CALL @RR10 ...RR12 pts. to del. after filename EXIT_() ...system call to close files; setup default LU's 0,1,2 ... again & reenter shell /NONSEG end TOTRM() ...if just loading file end RET DEL: ...test...Bucket Equates (ZOOMA) BUCKET: EQU 0FF ...(07B on ZOOMB) CNTL: EQU BUCKET DATA: EQU BUCKET-2 BUCKL: EQU 0100  (07B on ZOOMSPLIT COM.SSYS COMGHNSTPC S /0NXTPC S1 5zNDRAM: RAM: ADDR $ ...******** ORG ROM ...the following is actually initialized ram: LSTENT: LONG RESHELL ...entry addr of last file loaded or last addr 'X'ed PROMPT: BYTE ':' DPROMPT: BYTE '<' /SEG ...enter shell seg'd; for now, assume in MYSeg and͕{`8˯N#! ( X(!!Xz:J * |(gS= B*|gW<([d  (h (; ɿ , (; ͠'@ 09(ͬAF(!)DM)) O ͬ(!A8O)))) ͸(<~6ͭ:}"!}5́ͭ́3*yM"h:}^a a2}O>Vͧ^:}>*z& ~ !z4í!{q*v#"v͙dͧ*vv :{w:x<2xO>}|ͧ Using ZOOMSYS To start, hit Reset or power up. When CPM's (or RIO's) prompt (on the Z80) appears, do the following: (On RIO, substitute % for A> below.) A>SYS (on RIO, this can and is recommended to be in OS.INIT, in which case it would not be donin shell PSA: ADDR PSASEG.0300 ...needs 023C if allow space for all vectors MYSP: ADDR MYSEG.0800 ...top of stack; free down to 0.53C ...RAM1: ADDR MYSEG.0540 ROM0: ADDR MYSEG.0800 in ASMSEG RAM2: ADDR MYSEG.03700 ...part used by SHELL FREE: ADDR MYSEG. can use MYSP SHELL: CMDPTR:=0; LVL:=0 RESHELL: LDL RR14,#MYSP ...set SP R3:=flag; RES R3,15; R3:->flag /NONSEG if R9:=CMDPTR=0 then begin ...if not in middle of cmd string SHELLP: GETLIN() ...get line of data (R9 ret'd pointing to) end CMD() JR Ox <  +<OO eNy͖F#~*R8*R0*RB DM (* O͛* ͛(  ͛ͩfo] /](7^D^/])(o] 9]JP (7^/])o]6 9]LD (-!6]:ͧz2~e:~2O! 6*~& 6$>!~_z*~& w!~5Bx:yͧ*v+"vv ~_{ozg001 $$$$ SUBe here) -- This downloads the Z8000 system. A>G -- Starts up and transfers control to the Z8000 system. : -- (Prompt on Z8000) At this point, any filename that is typed will be loaded and run (if it is of appropriate format), the same as on the Z04200 SCREEN: PROC at MYSEG.06000 ...addr of hi-res screen handler MYSeg: EQU MYSEG*0100|08000 ...system calls (basic inst orred in): SC_IO: EQU 07F00 SC_SETTMR: EQU 07F01 SC_ACT: EQU 07F02 SC_SEEK: EQU 07F05 SC_FSTAT: EQU 07F07 SC_GETTM: EQU 07F09 SCSHELLP ERRRST: R15:=^MYSP; JR SHELLP GETLIN: ...get line of input & pt. R9 at beg.; make sure CR at end if LVL=0 then begin GETCON(B.PROMPT,^INBUF,LINBUF) ...from console end else begin GETSCRPT() ...from shell script end RET CMD: while begR 0 ...LF 0 TXERR1: DEFM 'ERROR '; DEFB 0 TXERR2: DEFM ' ERROR' ERROR: ...write "ERROR ##", where "##"=R.A in hex, on current line; ret. Z=0 LD C,A; PRT0(^TXERR1); PUTHEX(R.C) ... ERRD2(); PUT1(CR); OR A; RET ... OUTTWO(CR;LD B,LF); OR A; RET FILERR: v:5O͠ɯAͧ y>  F#fh__ !U>?t!U"=l !(!(*=~ #; "=2?J{ 0*=+"=6 ͕ zUHyͧy>_ > ͠7(4i z +:?M8!*=sT]S=25v>_ y=M͈͠_ ( *=6 ͕{80. In addition, multiple names may be separated by ";"s or ","s (in the latter case, the preceding file is only loaded, not run). In addition, typing "X" causes the last loaded file to be executed, and "X n.nnnn" (where "n.nnnn" is an address in hex_Z80: EQU 07F0C SC_EXIT: EQU 07F0D SC_RESTRT: EQU 07F0E SC_QUIT: EQU 07F0F SC_MREQ: EQU 07F10 SC_MREL: EQU 07F11 SC_RDBKH: EQU 07F12 SC_WRBKH: EQU 07F13 SC_XFSEG: EQU 07F14 SC_RETSEG: EQU 07F15 SC_CHGM: EQU 07F16 SC_BKR: EQU 07F3E SC_INTR: EQU 07F3F ...lin CMDPTR:=0; DEL(); RL0:=@R9==0 end <> do begin if RL0=';' or RL0=0D then begin R9:+1; JR CMD end ...$$$ 0 ends if RL0='/' then begin R9:+1 if CPB @R9,#'/' <> then ERR() ...if LVL<>0 then RELBUF(LDL RR2,SCRPT) ...not needed QUI...write "ERROR ##" on cmd. line; R.A=error no.; ret. Z=0 LD C,A; BLCMR(); PRCMR1(^TXERR2); POSCRS(LD A,NCOL-7;LD B,0) PUTHEX(R.C); P.RETCRS; OR 1; RET PRLIN: ...print from R.DE, row ROWNO, col. R.C up thru a CR ...set Z=1 if all printed; Z=0 if got to`8˯N#! ( X(!!Pr:J * |(_S= *|_W4([  (` (; ɿ , (; ͘'@ 09(ͤAF(!)DM)) O ͤ(!A8O)))) Ͱ(4~Gx <, the first "n" being the segment number) causes execution to begin at that address. There can also be input-output redirection (see below) and disk initialization (by typing "I"). :EE FILE1 -- Example of loading editor to edit FILE1. :Y FILE2 -- ibrary functions in range 040..07F ...i-o cmds.: OPN: EQU 0 CLS: EQU 1 RD: EQU 2 WRT: EQU 3 RDAHD: EQU 0A ...special read ahead cmd. ...i-o completion codes: OK: EQU 080 NOCHAR: EQU 0 GENERR: EQU 0C0 ...errors have bit 6 set INVLDERR: EQU 0C1 NOTT(RL0:=1) ...tell Z80 to ret. to RIO and goto SLEEP end if RL0='#' then begin repeat R9:+1 until B.@R9=0D; JR CMD end ...if comment R8:=R9 ...save beg. of name GETFNM() ...test if legal filename ...if so, Z=1, R3=^beg, R5=len, R9 past  screen bottom R.DE->R.HL; CR; PUSH BC; LD BC,0; CPIR ...find next CR POP BC; EX DE,HL ...R.DE=char. after CR ...cont: CONOUT: ...print to console from HL to DE, but not past bottom of screen ...start at row=ROWNO, col.=R.C ...return Z=0 if got to sͽ +4OG NyHF#~*R8*R0*RB DM (* O͓* ͓(  ͓ͯ͡NH%RDPSD͇MsS1D( > &D y &D>  (    Example of loading Y and having it compile FILE2. :// -- Return to Z80. >A (The Z8000 may be reentered by typing "G" again.) **************************************************************************** Miscellaneous 1. Hitting 'ctl-C' ca .xpa!v 41a11pCMP_v 00oP$a-_Z ERROR _Z -NOT FOUNDa- H 901pR !hP3aP&LP!o .[[ !s09p?.xp-[aP$oP&LPФLP5a! tpJqs 8 KK1p? ^^11// ~~0 &$ ++B --B &&SB ||SB **@ //@K.xp0贫p {p sp zp rp.rp.zp.sp.{pjЮ^\ߧߟߦ_gb߭ TAG 1 endif LD BC,LTAG1; W.TG2POS-R.BC->W.TG2POS ...correct TG2POS LD DE,(TG1POS); JR TAGOFF ...remove TAG 1 TG2OFF: LD C,LTAG2; LD DE,(TG2POS) ...remove TAG 2; drop thru: ... TAGOFF: ...enter with DE=either TG1POS or TG2POS; R.C=LTAG1 or LTAG2 . u po! .xp(PONеH!100 80<fP4^;ԧ u ! 80 ==a xpaPۂ_gbrqTP" '' 8̩0oP$0 80oP$!1aP",4a CC5Œ ^] LP !KP uses a break on the Z8000. Hitting 'ctl-S' stops console output; it can be started up again by hitting any key. 2. If no other break handler is present, the system has a small monitor which is entered upon a break. This monitor has the following comma!LPa߷^q! }2?}:]      ;;ʽ x   ;;!  ! }2?}:]!_Z/DO !ogP"oP"oP LP5   騐      #ߵE։+Y^Uf( _k)U#_[v=#-_e}܁܄;[܉;?ܐ~n P2ܔܗ:_ܛܞ;_ܦ/ܩ*s q شsܶDO LܽLOAD LēڻW_UpPACK ALL sp or tab if RL0:=@R9<>' ' then begin RL0==' '; RET NZ end repeat R9:+1 until RL0:=@R9<>' ' and RL0<>' '; R0==R0; RET TOTRM: ...go till @R9=';' or CR; if ';', change to CR while RL0:=@R9<>';' and RL0<>0D do R9:+1 B.0D->@R9; RET GETFNM: ...test if v_ a30C_aP LP ; JJ"ꠀ0 ^]> a`0ނ^D AA^^Z 80 11% 334 LLL 44.1a߰SsTS ލ0߲1s]sqJ aɡS0mS҅nds: (Below, "n.nnnn" refers to an address in hex. The "n." is the segment number; if left off, it defaults to the segment of the PC prior to the break. Also, the commands may be typed in either capital or small letters.) D n.nnnn,mm ... display mm lin!4Ps  x  psL NP0.80Z  Ԟ .xp!s 8j0@ ??  L ??   ѐP^ݞfP4E!ss1aPaPoPaPs1ңҤIMAGE" xp    p_S!oorMtޯޱ05AW_Wnm EOF_USTART e_X>BRKS-> !Y_Xt'P-RESET03EXTEND ӯ;CLEARCSEGLPKNONSEGLPTMAP xalid filename @R9, incing R9 ...if true, ret. Z=1, R3=beg, R5=len VALIDCHR(B.@R9); RET NZ PUSH R9 repeat R9:+1 until VALIDCHR(B.@R9) not; POP R3 if R5:=R9-R3<=MAXFNML then R0==R0 RET INVCHS: DEFM ';,<>=*' LINVCHS: EQU $-INVCHS VALIDCHR: PROC ...te\ aۡSsހSڽ01s0ҧґpwTޘDC@SB޻ _QP MIXED REFe] HHѓю OO ќї֞ WW Ѩѣѥs֩q RR& 80ў01s 11N^] 440^]s 339^^es of memory starting at address n.nnnn . ",mm" may be left off, with mm defaulting to 1. If mm=0 or there is a "," with nothing following, one line of memory is displayed which may then be changed a word at a time by typing in the new value for p s!oPfP4!CPMP!oPa`LLP4_QWRITE`LdP4n߼!6` "(`P5c!!!Bء7 ^VcD4!u߽0 1` AApnuҰbZAP d;gגچUqLISTtwOFFbP4~ON?_P݆END GS_T\݅_XְۆݖIF ٠ݜTHEN݈n P0ݤELSEBP0nP0ݰENDIFLP0ݹWRITE 6ݿ,:ݻߞGLOBALDIAGst if RL3=valid char. for filename RL3==021; RET ULT; RL3==07E; RET UGT R5:=^INVCHS; R1:=LINVCHS; CPIRB RL3,@R5,R1,EQ; COMFLG Z RET ERRCEX: ERRMSG(); JR ERREX2 ERREX: QSTION() ERREX2~ CMDPTR:=0; EXIT_() ...exit to system, which will restart shell ERR`^`*^] DD ٠۠ݠߠ LLaP 9ec57<J . > Vt5 sl0sSF;GLDDS  K_QPREDEFINED LABELsǭs}z^`*s߸s0}il R.A=' '; ...C=0 from above repeat INC C; DEC DE until @DE<>' '; INC DE if R.C->R.A=1 then begin 0D->@DE; INC DE end else NEWSTR(R.A;^TXTCR) JP L1 *ZAP CMDTYP EOFSTR EEXA ECODEA *ZAP EEXJ ECODEJ NC NR TXTCR NULSTR SP L1 L2 L3 DE; INC DE end elseP54jP5_QOPENaF !1p.{ {p {u5  ;,<>=* !! ~~ !U2TEU 8  0P` P5 ^dhP5!ҁpT /g7bДD]LP3L aPNҷ !q^TLdP4*_P^/_XZMP,MP.TMPS@UNDEFo0s!oP(=oP*R=܅oP,,܌oP.aP,oP.޿ 2ALLL͞ { 00 zz odP4LMJX ovܯ)ܲ>aC: PUSH R0; CLSFIL(); POP R0 ...RH0=LU#, RL0=err code ... ERRCC: ...RL0=error code to put out ERRMSG(); ERRRST() ...doesn't ret. ERR: QSTION() ...print "???" ERRRST() ...abort cmd line (doesn't ret) ERRMSG: if RL0=NOTFNDERR then ?"FILE NOT FOUND" v0t1wqt1awDB_QP OUT OF RANGE9_QP ODD DISP. 008820s``??`n`aoLTAG1); RET NZ ...shift rem. file fwd. 13 sp. if room R.HL->W.TG1POS; PUSH HL ...TG1POS pts. to 1st spot opened up EX DE,HL; ^TXTFRH; LD BC,LTAG1; LDIR ...put in "--From here:" ^TAGFLG; INC (HL) ...1->TAGFLG POP DE; JR TAGX ...print "TAG 1", fill  ^TLPߓ!^Q`P3 !_Z ERROR TOTAL=9Z!P5 X*PLP Y !ҁ!g5d]LP5LPa^"LP5%! q^U q^Uuss0!1Q0TԖ]`PLP3!oo4 9!=GvۮCZ]E=aP orN;o/oravorsvT=Ncr_rBvUݐFރ _Zppލޒ_Shw2  ިEQUݳޕw b޲WORDx eu< ?wBYTEߍ ܣߊ\ _ else if RL0=WRGTYPERR then ?"WRONG FILE TYPE" else ?RL0:,"???" RET QSTION: ?"???"; RET GETADR: ...get hex addr from @R9->RR2; inc R9, Z=1 if succeed LD R2,LSTENT ...default=seg. of last entry ... GETADR2: ...enter here with R2=default seg. HNUM();`oTc     E_QP NOT DEFINEDLP 8 AAa!PJoMU QP7 x   ,,p ߗ!1שs7/7qo 808aPFsQP6Xu5 :43=screen, get allow. cmds. TAG2: B.TAGFLG-1; JP NZ,QSTION ...tag 1 must be already set but not tag 2 P.FNDPSB ...find pos. (->DE) & ROWNO of beg. current line W.TG1POS-R.DE; JP NC,QSTION ...must be after TAG 1 pos. SETTG2(); RET NZ ...put in tag 2 (Z ɞ2_QREAD! U!Ae hX@b5j i afa3 5aa˩!71!11ߴMrߵߦMara;]/oMMM!! P! ]4!7ooߌLONGߢߍWߚPROC߰ߤߝߧADDR!۬ ߴinŤn! $n( ۠?1 /aP ' Lo>Aat).IARRAYLP2aP$ RET NZ if CPB @R9,#'.' then begin R9:+1; PUSHL RR2 HNUM(); POPL RR0 if not zero then LDL RR2,RR0 else begin RH2:=RL1; RL2:=0; SET R2,15 end end R0==R0; RET HNUM: ...get value of hex digit string @R9->R3; preserve R2 HEXD(); RET NZ R3:=0 aw}Kө9gQp6~gg aPF==שxsSKPHnapppԡC\ӒoCӗ_QPTOO MANY SYMBOLSaPF!11aPF!B/11.80aPF7/7n!@aPF=;( `g ߼L$ =0 if no room); TG2POS->DE TAGX: if @^CRSROWR3 until HEXD() not zero; R3==R3; RET HEXD: RL0:=@R9=='0'; RET C; RL0=='9'; JR ULE,HDX RL0=='A'; RET C; RL0=='F'; JR ULE,HDX RL0=='a'; RET C; RL0=='f'; RET UGT HDX: R9:+1; R0==R0; RET ASCtoN: ...convert ascii hex dig`ө8Юл-ޡ9naPF1a!1o`  C naPF3=3aaP(IGP*KP.KP,;MLAAa PF BН )ߥ`Mc߳a _Sbԣn ..."O2" means OFF2 R.A=2; JP NZ,QSTION ...check if a TAG 2 DEC (HL); P.FNDPOS; P.TG2OFF ...remove TAG 2 end else begin R.A=0; JP Z,QSTION ...check if any tags P.FNDPOS; P.TGSOFF ...remove tags end FNDCH0(); PRSCRN(); RET ...find CRSRaP"aP"q }R_}Z (}R_}Z.(}R_}Z!! }R_}Z/!}R_}Z!`_}Z!1 y0^8rpo^816~o0038'008 :;<=>?@ [\]^ ` {|}~Z'_[.'۩pwAP$oP$gP$zero^YJ^Z^Z^Z^Z^[^\^\^e:^eD^d^e$^Ql0_Zj_Z _ZBCF_Y6A27.XB,.ԉ)HH_[@_YQALRgit (in RL0) to its value if RL0>='A' then RL0:-7; RL0:&0F; RET LDFIL: ...enter with filename @R3, len=R5 (may be qualified) ...if Z8000 file: load the file, ret. RL3=1, RR10=entry addr ...if shell script, ret. RL3=0; if Z80 file, ret. RL3=-1 ...if er Rem Space=пaPH6_Sb!cC ө8a1o cE x 80p q 1 10p x 8 a`s A_SbMgYZԇ\aԋ`ө81p!sk7 Mp_Sbpo e!OW of new BUFPOS; print scr. ...OFFERR: P.QSTION; RET ..."???"->cmd. line PLTAG2: LD DE,(TG1POS); P.NXTLIN ...find place for TG2POS if no TAG 2 @DE=EOF; CALL NZ,NXTLIN; LD (TG2POS),DE; RET ...end of 1 tagged line TGSOFF: ...remove & shift file back o x AA ZZ o!Y`p x 00 8 x 00 99 op  AA FF aa ffS""$%B *WS"'߉%W!!3 >CY- 901p00-aa11p x    p x   Ibnbh2** ei^cx- tx~rߧpЌ$T}Ж' x  p q''pwЏޗЫ$TޛLе(߿Ск)Фо@ ^Ъ}/aP"_Y޹()6w*PPw*Y VERS 1.00 -* `P5`n LP`P5 jP5 a `P4!P7r{Y5 LP4ALP4!_Z***** P6 4 0_QP OVER NESTED 5!e!Ը#.xp8bP6e` 堉bP6!^\Ԯq1aP1p.xpoP1poPCaP0 9,/^\ !7qsG3ver tags; correct BUFP0, TG2POS, BUFPOS ...at least tag 1 must be on when come here ^TAGFLG; DEC (HL) if not zero then begin ...if there is a tag 2 DEC (HL); P.TG2OFF ...remove TAG 2 end else P.PLTAG2 ...if no TAG 2, TG2POS=end of line marked by x '' ""p q""p"PTOO LONGo x  p xaC.{p 8   ,, 80 80 AA#8 uHHp00 99.xp(00 99.xp..xp+ successive words in hex, each value separated by a space from the preceding one, and hitting return when finished. R ............. display memory where the registers prior to the break have been saved. The format is R0..R7 on line 1, R8..R15 on lin and length 00->R.A; end if R.A<>0 then if R.A=1 then EOF_ERR else 0FF POP BC; OR A; RET ExitRW: PROC PUSH AF; ... LUN->R.B; ... RanRecF(R.HL); ...get file address in CDE ... PUSH BC LD BC,(DMABEG); R.IX-R.BC->R.HL ...len->HL ... POP BC; ... BYTE -1 ...name length set to -1 because ASSIGN handles name ... THE OUTPUT WRITE VECTOR FOLLOWS ...FILPUT: BYTE 4 ...unit no. ... BYTE 0EH ...write binary, wait ...FPUTAD: WORD FPUTBF ...file output buffer ...FPUTL: WORD RECL ...length ... WORD 0 0 A='^' then CP A else R.A|0FF RET SeekF: PROC ...expects B LUN, CDE=abs. or rel. file pos. to seek to ... R.A=0=>abs., =1=>rel., =2=>rel to eof ...ret. CDE=abs. file pos. PUSH IX PUSH DE; PUSH BC PUSH AF GetFCB(R.B); PUSH DE; POP IX ...DE,IX=^F OUT (CTC0),A ...program CTC int. vector reg. ... IV; DEFB 0ED 047 ...013->R.I ... DEFB 0ED 05E ...set IM 2 RET Put1: PROC ...put out 1 char. (in R.A) to console PUSH AF; PutC(); POP AF; RET Get1if: PROC ...get 1 char. from console->R.A if ready; e 2, and N4, FC, and PC on line 3. G ............. resume execution where left off (or at current value of the stored PC) J n.nnnn ...... jump to address n.nnnn and resume execution SH ............ restart system and reenter shell, first closing fil POP AF; RET ...*ZAP SAVREGS RESREGS GetCh PutCh GetIO_ PutIO_ IO_Init *ZAP CALLBIOS JPaHL *ZAP DMABEG LUOFFSET FCBSZ FCBS CCPM GetFCB OpenIT RanRecF *ZAP ParseName MoveTxt MoveSp ValidChar InitRW RanRW ExitRW *PACK ALL *ZAP DMABEG LUOFFSET FCBSZ FCB... BYTE 0 ...completion ... THE UPDATE VECTOR FOLLOWS ...UPDATE: BYTE 5 ...unit no. (used only when imaging) ... BYTE 02C ...update ... WORD FPUTBF ...loc. of attributes ... WORD 116 ...no. of bytes of attr. ... WORD 0 0 ... BYTE 0 ...CC ... THE CLOSE VCB POP AF if R.A<>0 then begin if R.A<>1 then B.CCPM(LD C,FILSZ) LD HL,FCBSZ-3; RanRecF(R.HL+R.DE) ...CDE=file pos. (current/end) end else R.A->R.C->R.D->R.E ...CDE=0 POP HL; R.L->R.A; POP HL ...AHL=entered offset R.HL+R.DE; R.A+carry+R.C ret. Z=0 iff got one JP GetC; START0: PROC LD SP,MYSP ^INPTR->R.HL LD C,(HL); LD B,0 ...len. R.HL+1->R.DE 0D->@(R.HL+R.BC) ...make sure CR at end of input in sys cmd buff JP START1 ... LD DE,05D ...DEF FCB ... if @DE=020 then JP START ... PUSH Des. This is a good way to get back to normal command mode after breaking (with cntl-C) from a program. PR ............ quit to Z80 (closes files and shuts off timer) and jump to boot prom in preparation for reloading SYS (Z8000 system) from Z80 ( bytes to patch area RDFLG: BYTE 0 ...set=1 when read with immediate return in progress GTLFLG: BYTE 0 ...set=1 with relation GT, set=0FF with LE, otherwise 0 QOPTS: BYTE 0 ...if bit 0=1, ok to redefine labels ...if bit 1=1, show offset addresses on liECTOR FOLLOWS ...FILCLO: BYTE 4 ...unit no. ... BYTE 6 ...CLOSE ... WORD 0 0 0 0 ... BYTE 0 ...completion code CLOSFL: PUSH DE; PUSH HL CloseF(R.A->R.B) POP HL; POP DE 00; RET ...CLOSFL: R.A->B.FILCLO ...logical unit no. ... LD IY,FILCLO ...SYSTEM: . R.HL->R.DE; R.A->R.C ...CDE=new abs. offset PUSH BC 00; R.HL*2->R.HL; RL C; RLA; LD L,H; LD H,C ...offset/128->AHL POP BC ...CDE preserved R.HL->@2IX(FCBSZ-3); R.A->@IX(FCBSZ-1) POP IX 00; RET ReadF: PROC ...expects B LUN, DE=buffer addr, HL lenE;^SLSHDO;LD DE,DATA1;LD BC,4;LDIR;POP HL ... LD B,8 ... repeat ... if @HL<>020 then begin R.A->@DE; INC DE end ... INC HL ... until DEC B zero; ... if @HL<>020 then begin ... '.'->@DE;INC DE ... LD B,3 ... repeat ... if @HL<>020 then begin R.A->@not generally needed) 3. In order for a file to be loadable and runable on the Z8000, it must be an object file in the format described below, with header and segment table sections at the beginning. (The relocation information and symbol table sectio...8-17-82 LSTLU: EQU 0 ...list file log. unit IMGLU: EQU 1 ...image file log. unit EOF: EQU 0FF ...2nd type of eof char. ...RECL: EQU 0200 ...DATE: EQU 013AB ...where date stored ...COMMON: EQU 0FA80 ...start of common code area for both banks (need 01.. fake entry ... DI; EX AF,AF'; EXX ...shadow regs. saved for QBUGing progs. using them ... PUSH HL; PUSH DE; PUSH BC; PUSH AF ... EXX; EX AF,AF'; P.C_EI ... PUSH HL; PUSH DE; PUSH BC; PUSH IX ... CALL SYSTM ...@1403 ... POP IX; POP BC; POP DE; POP HL .gth ...returns A=err code (Z=0=>err), HL amount read PUSH IX InitRW(); while R.B|R.C not and RanRW(READR) do DEC BC ExitRW(); POP IX; RET WriteF: PROC ...expects B LUN, CDE file address, HL length, IX DMA address ...if R.C=0FF then write sequentiDE; INC DE end ... INC HL ... until DEC B zero; ... end ... JP START2 ...SLSHDO: DEFM '/DO ' ... THE ASSIGN VECTOR FOLLOWS ...FILASN: BYTE 4 ...logical unit no. ... BYTE 02H ...ASSIGN FILNM: WORD 0 ...points to filename ... WORD 0 0 0 ... BYTE 0 ...CCns are not needed.) The segment table specifies where the file is to be loaded; the entry_pt is specified in the header. Exception: if the file is marked as runnable in any Z8000 segment, the segment number given in the entry_pt is used for loading the f00) ...SP2: ...@@@ EQU 0FC00 ...top of bank 2 stack (must leave room below here) ...ASkip2: EQU 0101C ...addr. of Skip2 (in prom's stack below what's used) STAK2: DEFS 040 SP2: ...init'n for R_SP ATMPCD: EQU STAK2 ...@@@01098 ...temp. code area (in prom'.. DI; EX AF,AF'; EXX ... POP AF; POP BC; POP DE; POP HL ... EXX; EX AF,AF' ... LD A,(IY+10) ...CC ... CP 080H ...check if call was successful ... ... C_EI: PROC ...do EI iff I_SW=0 PUSH AF; if B.I_SW=0 then EI; POP AF; RET EOFSEQ: BYTE CPMEOF 0D EOF ally ...returns HL amount written, CDE, IX updated PUSH IX InitRW(); while R.B|R.C not and RanRW(WRITER) do DEC BC ExitRW(); POP IX; RET ...GetRRP: PROC ...expects A LUN; returns FCB @DE; Random Record Pointer @HL ... GetFCB(R.A); LD HL,FCBSZ-3; R ... WORD ASNSUP ...ASNSUP: BYTE 0 ...indicates system will parse filename and put in vector ... DEFS 1 ...for drive no. ...FNML: DEFS 1 ...for file name length ...FNAME: DEFS 020 ...for filename ... THE INPUT OPEN VECTOR FOLLOWS ...FILINO: LOGUN: BYTE SWile. Programs are called as subroutines from the system, and are started up in segmented mode, with register RR12 and also the stack above the return address containing a pointer to the rest of the command line (after the filename) which invoked the p s stack below what's used) ...IV: EQU 0FF ...value of I reg. (high-order of int. vectors) ...CTC0: EQU 070 ...CTC channel 0 ...CTC2: EQU 072 ...CTC channel 2 ...I2_JMP: WORD at 0FFF4 ...@@@ at 013E6 ...CTC2 int. vec. loc. BRKFLG: BYTE 0 ...@@@ at 013CD ...LEOFSEQ: EQU $-EOFSEQ PUTEOF: ...put out eof seq. to list file PUSH DE ^EOFSEQ->R.HL; LD DE,EOFSEQ+LEOFSEQ; PUTFILE() POP DE; RET FINBUF: ...if list file open, fill rem. buffer with spaces +CR at end & put out B.DIAGSW; BIT 2,A; RET Z LD BC,(FPUTRM).HL+R.DE->R.HL; ...Rec_Ptr->HL ... RET InitRW: PROC ...enter B LUN, DE=buffer addr, HL len. ...returns IX=addr, BC record count, FCB @DE, Random Record Pointer @HL ... R.B->LUN LD (DMABEG),DE; PUSH DE; POP IX LD DE,07F; R.HL+R.DE; 00; R.HL*2; RLA; LD CON ...unit 5 (actually will be put in range 6-10 when used) ... BYTE 04H ...OPEN ... WORD BUFF ...where attributes returned ...FOPNLA: WORD 96 ...get 96 bytes of attribute info ... WORD 0 0 ... BYTE 0 ...completion code ... WORD FOPNSP ...FOPNSP: BYTE 8 .rogram. This can contain arguments to be passed to the program and is terminated by a carriage return (hex 0D). (If additional commands follow on the command line, a carriage return is inserted at the end of the first program's argument list.) As no=1xxxxxxx if BRKRTN jumped to (else=020) BRKJMP: BYTE at 066 BRKRTN: WORD at 067 ...@@@ at 013CE ...RIO jump address if BRKFLG set D_PC: WORD 0 ...@@@ at 012D5 ...RIO saves PC here D_SP: WORD 0 ...@@@ at 012D7 ...RIO saves SP here RR_AF: WORD 0 ...@@@ at 0; W.FPUTNX->R.HL repeat LD (HL),' '; INC HL; DEC BC until R.B|R.C zero; DEC HL; LD (HL),0D ...fall thru: ... PUTOUT: LD BC,RECL; LD (FPUTRM),BC; ^FPUTBF->W.FPUTNX PUTO2: PUSH DE EX DE,HL; R.BC->R.HL WriteF(B.FILPTO->R.B) POP DE ... LD (FPUTL),BC; RL,H; LD H,A; ...(HL+127)/128 PUSH HL; GetFCB(R.B); LD HL,FCBSZ-3; R.HL+R.DE->R.HL; ...Rec_Ptr->HL ... GetRRP(R.B) POP BC; RET ...InitRW: PROC ...returns BC record count; FCB @DE; Random Record Pointer @HL ... R.B->LUN; LD (DMABEG),IX; ... R.HL+07F; ..open for input and random access ... BYTE '*' ...DRIVE ADDRESS (not needed if use ASSIGN) ... BYTE -1 ...because ASSIGN handles filename ... THE READ & WAIT VECTOR FOLLOWS ...FILRD: BYTE 5 ...logical unit ...RDTYP: BYTE 0A ...read binary or read direct ted above, programs which are started up by the system must begin in segmented mode. If they are to run nonsegmented at any time, they must first set up a stack in the segment they are running in, possibly saving the original stack pointer to switch back 1000 ...start of stored regs on remote cpu (AF,BC,DE,HL,IX,IY) RR_SP: WORD 0 ...@@@ at 0100C ...stored SP on remote cpu RR_PC: WORD 0 ...@@@ at 0100E ...ditto PC SRR_AF: WORD 0 ...@@@ at 01010 ...start of stored shadow regs. on remote cpu ...IOP: BYTE 1 ...HL->W.FPUTAD ... SYSTEM(LD IY,FILPUT) RET Z WRTERR: PUSH AF B.FILPTO=LSTLU; CALL Z,ZDGSW ...if list file, zero DIAGSW CLFPT() ...close output file without trying to empty buffer POP AF CALL ERRMCC; DEFT 'WRITE' CLFPT: CLOSFL(B.FILPTO) ...close fi00; R.HL*2; RLA; LD L,H; LD H,A; ...HL/128 ... PUSH HL; ... if R.C<>0FF then begin ... 00; R.DE*2->R.HL; RL C; RLA; LD L,H; LD H,C; ...CDE/128 ... PUSH HL; PUSH AF; GetRRP(R.B); POP AF; POP BC; ... PUSH DE; PUSH HL; ... LD (HL),C; INC HL; LD ((022) ... WORD DATA1 ...read into low buffer ...FILRDL: WORD RECL ...bytes to read ... WORD 0 0 ... BYTE 0 ...completion code ... WORD RCADR1 ...3-byte area for disk address ... THE READ & NO WAIT VECTOR FOLLOWS ...FILIN: BYTE 5 ...log. unit ... BYTE 0B .R R.HL+2->R.HL ...GO PAST DRIVE ID end ...else current drive INC DE ...GO TO NEXT PART OF FCB PUSH DE MoveTxt(8) if @HL='.' then begin R.HL+1; MoveTxt(3) end else MoveSp(3) POP DE if @DE=' ' then 0FF else 00 POP HL; POP DE; POP BC OR A; R.1 if IOP; 0 if not BKINIT: 0C3->BRKJMP; ^NMI_Rtn->W.BRKRTN; RET ...set brk ret addr RSTS: PROC 7; LD BC,3; ^JPR; LD DE,8 ... repeat PUSH BC;LDIR;PUSH HL ...move jump into place W.5+R.DE;EX DE,le; ret. Z=1 ... LNEWLU: LSTLU->R.A ...restore list file LU# ONEWLU: R.A->B.FILPTO; CP A; RET ... R.A->B.FILASN->B.FILPTO->B.FILPUT; CP A; RET ...set LU#->outpt vectors LFILOPN: ...open list file; DE pts. to filename followed by a delimiter LD (FILNM)HL),B; INC HL; LD (HL),A; ... POP HL; POP DE; ... end else GetRRP(R.B) ... POP BC; ... RET RanRW: PROC ...enter IX=^buffer, A=CPM code (READR/WRITER), ... DE=^FCB, HL=^Random Record field ...read record; ret. A,Z=err code, IX updated, BC,DE,HL pre..read binary, return immediately ... WORD DATA2 ...read into high buffer ...FILINL: WORD RECL ...bytes to read ... WORD 0 ...RDDUN ...completion return address ... WORD 0 ...FILINC: BYTE 0 ...completion code ... WORD RCADR2 ...3-byte area for disk addressET MoveTxt: PROC ...while characters valid move R.A->R.B while R.B<>0 and ValidChar(@HL) do begin R.A->@DE; INC HL; INC DE; DEC B; end R.B->R.A ... MoveSp: PROC ...R.A spaces->@DE R.A+1->R.B; ' '->R.A while DEC B not zero do begin R.A->@DE; HL ...advance to next rst loc. POP HL;POP BC until DEC A zero RET JPR: JP Err0; JP Test; JP Icopy; JP Out; JP OutN; JP BrkRtn; JP BrkRtn NMI_Rtn: PROC EI; EX (SP),HL; JR BrkRtn2 ... BrkRtn: PROC ...*****temporary ,DE OFILOPN(LSTLU) ...open output file with LU=LSTLU ^DIAGSW; SET 2,(HL) ...mark for file output ...(ret. HL=^DIAGSW) RET OFILOPN: ONEWLU(R.A) CreateF(FILNM->R.HL; R.A->R.B) RET Z ... ...OFILOPN: ONEWLU(R.A) ...store log. unit # (in R.A)->output served PUSH BC; R.A->R.B; PUSH DE; PUSH IX; POP DE; CCPM(LD C,SETDMA); POP DE; if B.CCPM(LD C,B)=0 then begin PUSH HL; while INC (HL) zero do R.HL+1; ...increment record count POP HL; LD BC,080; ADD IX,BC; ...increment DMA address ... THE OUTPUT OPEN VECTOR FOLLOWS FILPTO: BYTE 4 ...logical unit ... BYTE 4 ...open code ... WORD 0 0 0 0 ...use default attributes ... BYTE 0 ...completion code ... WORD FILPSP ...^supplemental ...FILPSP: BYTE 1 ...open output, overwriting ... BYTE '*'INC DE end RET ValidChar: PROC if R.A>='@' and R.A<='Z' ...includes A-Z or R.A>='`' and R.A<='}' ...includes a-z or R.A>='/' and R.A<='9' ...includes 0-9 or R.A>='!' and R.A<=')' ...includes "#$%&'( or R.A='+' or R.A='-' or R.A='\' or R.break routine******** EX (SP),HL;R.HL-1; BrkRtn2: R.HL->D_PC; PUSH AF; W.4+R.SP->D_SP; POP AF; EX (SP),HL JP B_RTN I_INIT: PROC ...make sure set up right for interrupts ... BYTE 0ED 057; ...LD A,I; ... if R.A=0FF then 1 else 0; ... R.A->IOP; ... 0E0; vectors ... SYSTEM(LD IY,FILASN); JR NZ,RESLLU ...assign ... SYSTEM(LD IY,FILPTO) ...open output file ... RET Z RESLLU: LNEWLU(); JR OPNERR ...restore LU=list file in output vectors FILOPN: ...enter with FILNM=^filename +delim.; open file for input ..L0=='>'; RET Z R9:+1 end RESFLG Z; RET SETREDIR: ...get filename from @R9, close LU R3 & open (approp. type) to file ...call ERREX or ERRCX if err PUSH R6; R6:=R3 DEL(); if GETFNM() not then ERREX() ...get filename R1:=^FILNM; LDIRB @R1,@R3,R5;R11:+1 PUTCON: ...print from ^DBGBUF to @R11 PUSH R7 R7:=^DBGBUF; RL1:=0 while R7R.A->R.H->R.L ...init. file pos. $$$ READFL() ...read binary into low buffer, waiting; then into high buffer, not waiting RGC:=1 ...1st arg (name) not used while ARGC@ARGV'; ARGC:+1 R9:+1 while ARGTRM(RL0:=@R9) not do R9:+1 end R3:=ARGC restore R6,R7 RET GETCON: ...enter with RL3=prompt char. (0=>non.ret. R.A=080 if "LOAD" file, else 020 ("DO"); CDE=file len. OpenF(FILNM->R.HL; B.LOGUN->R.B) JR NZ,RESLU if B.DOFLG=0 then 020 else 080 RET ...FILOPN: SYSTEM(LD IY,FILASN); JR NZ,RESLU ...assign ... SYSTEM(LD IY,FILINO); JR NZ,RESLU ...open input f B.0->@R1 close(R6) R5:=R6 ...open type happens to equal LU if open(^FILNM,R5,->RL0)=-1 then ERRCEX() POP R6; RET ...header offsets: H_SEGT: EQU 10 H_ENTRY: EQU 12 H_FLG: EQU 16 RELOSEGB: EQU 1 ...bit of H_FLG saying code may run in any seg. ...segtd if RL3=0D then RL1:=0 else begin RL1:+1 if RL3<' ' or RL3>=07F then RL3:='#' end PUTCHAR(RL3); RET PUTCHAR: PROC ...put out 1 char (in RL3) to console; preserve regs. PUSHL RR0; PUSHL RR2; PUSHL RR4 R5:=R15+7 write(CONLU,R5,1) POPL RR4; Pr, abort to ERR.. save R6..R8 OPNFIL() ...ret. R3=^attr., RH0=LU; if err, Z=0, RL0=cc if not zero then ERRCC() RL7:=RH0; RH7:=0 ...R7=LU R8:=read(R7,^HDRBUF,LHDRBUF,->RL0)==1; JR LT,LDFX if R8>HDRSIZ and MAGICNO=MAGIC1 then begin LDIMG(R7,R8); RH6:e), R5=^buffer, R1=len buffer ...get line of input, make sure CR at end; ret. R9 at buffer if RL3<>0 then PUTCHAR(RL3) R9:=R5 read(CONLU,R5,R1-2)+R9->R3; RL0:=0D->@R3'; RL0:=0->@R3 ...$$$ was R1-1 ...0 at end RET GETSCRPT: ...get line of input fromile ... B.DOFLG->R.B ... B.FLTYP(); BIT 7,A; RET NZ ...chk if proc. type ... if BIT 5,A not zero then begin INC B; DEC B; RET Z end ... ...check if file type ascii and not doing "/GET" ... CLOSFL(B.LOGUN) ...close file if not ascii or proc. ... 0D2->R.ab offsets: SG_ADDR: EQU 0 SG_LEN: EQU 4 SG_TYP: EQU 6 LDIMG: ...load image with magic no. MAGIC1, R3=LU ...already have 1st R5 bytes of file (header+segtab) loaded into HDRBUF ...ret. RR10=entry pt., RL0=cc, Z=0 iff err PUSHL RR6; PUSHL RR8 R7:=R3; ROPL RR2; POPL RR0 RET /SEG DEBUG: ...debugger; entered after break LDRL RRS,RR0 ...store regs. @RRS: LDCTL R0,NSPSEG; LDR RRN4,R0 LD R0,RR14[2]; LDR RRFC,R0 LDL RR0,RR14[4]; LDRL RRPC,RR0 R15:+8 LDM RRS+4,R2,14 LDL RR14,#DBUGSP ...set SP R1:=04=1 end else begin SEEK_(R3:=R7; SUBL RR4,RR4; R1:=0) ...set file ptr back to 0 if TSTASC(^HDRBUF,R8) then begin if SCRPTCD='#' and LVL=0 then begin ...before test RL6=028 LDSCRPT(R7); RH6:=0 ...if shell script (ascii subtype 8) e shell script; ret. R9 pointing to ...if done, dec. LVL and restore CMDPTR from CMDPTR0 LDL RR4,SCRPTPTR if CPL RR4,ENDSCRPT >=zero then begin ...if done RELMEM(LDL RR2,SCRPT); LVL:-1 R9:=CMDPTR0 RET end save R6..R8 R0:=flag; SET R0,15; R0:A ...error code for invalid type RESLU: PUSH AF; @^LOGUN-1->@HL; NEWLU(); POP AF ...restore old log. unit no. ... ^FOPNLA; LD (HL),96 ...reset no. bytes of attributes to get OPNERR: CALL ERRMCC; DEFT 'OPEN' ...MVDATA: ^DATA1; if B.DOFLG<>0 then LDIR; C6:=^HDRBUF R1:=HDRSIZ+@R6[H_SEGT] RL0:=WRGTYPERR; R5==R1; JR ULT,LDIMGX R8:=R6+R1 ...end of segtab SEEK_(R3:=R7; R5:=R1;R4:=0; R1:=0) ...seek to start of image LDL RR10,R6[H_ENTRY]; R6:=@R6[H_FLG] R9:=^SEGTAB while R9flag /NONSEG OUTSET(); COPY(); DEFT 'BREAK AT '; OUTADR(LDL RR2,RRPC) OUTMSG() DBUGLP: ...get line of input & do cmd GETLIN_D(B.DPROMPT) ...get line of input->DBGBUF, R9=^ case RL0:=@R9'&0DF of 'G': GO() 'J': JUMP() 'D': DUMP() 'R': Rnd ...else begin RL0:=0D2; JR LDFX end ...Z=0 end RL0:=WRGTYPERR; RESFLG Z end LDFX~ RH0:=RL7 ...for ERRC,CLSFIL if not zero then ERRC() ...if error on loading file or invalid type SET R10,15; R10:&0FF00 CLSFIL() RL3:=RH6 restore R6..R8 RET->flag /SEG LDL RR8,RR4; LDL RR6,#INBUF2; R1:=LINBUF2-2 ...$$$ was LINBUF2-1 repeat ...move next line of script from system buffer->local buffer RL0:=@RR8'==0D; JR Z,GTS3 if RL0='$' and RH0:=@RR8>='1' and RH0<='9' then begin if R3:=RH0-'0'R.A CP SWCON+5; JP NC,TUDEEP ...files go from log. units 6-10 R.A+1->@HL ...increment log. unit no. NEWLU() ...store=0 then begin ...if code segment LDL RR2,R9[SG_ADDR]; if BIT R6,RELOSEGB not zero then R2:=R10 R1:=@R9[SG_LEN]; RH0:=RL7 SYSTEM(RL0:=RD); JR NZ,LDIMGX end R9:+SEGENTSZ end R0==R0 LDIMGX~ POPL RR8; POPL RR6 RET LDSCRPT: ...enter wiEGS() 'S': REINIT() 'P': RESET() else ERR_D() end JR DBUGLP GETLIN_D: GETCON(B.(),^DBGBUF,LDBGBUF); RET ERR_D: PUTCHAR(B.'?') R15:=^DBUGSP ...set SP JR DBUGLP GETADR_D: ...get addr from @R9 to RR2 DEL(); LD R2,RRPC ...default seg. GETAD TSTASC: ...enter R3=^1st R5 bytes of file; chk if all ascii before EOFCH ...(chk both FF & 1A) while R5<>0 do begin RL0:=@R3==EOFCH; RET Z RL0==EOFCH2; RET Z BITB RL0,7; RET NZ R3:+1; R5:-1 end RET OPNFIL: ...enter with filename @R3, len_ARGC then begin R5:=S_ARGV[R3]; R4:=MYSeg ...get RR4=^arg #n if R5<>0 then begin while ARGTRM(RL0:=@RR4') not do begin RL0:->@RR6'; R1:-1; JR Z,GTS2 ...replace '$n' by arg. end end end R9:+1 end else begin  new log. unit no. in vectors LD IY,RECPTR-SWCON-1 R.A->R.C; LD B,0; ADD IY,BC ...position IY INC DE; SCF ...move DE past CR if ^DATA2-carry-R.DE0 or REQMEM(R3:R2(); RET RESET: ...if "PR", do Quit, go to boot prom B.@R9&0DF=='R'; JR NZ,ERR_D QUIT(RL0:=0) ...doesn't ret. REINIT: ...if "SH", restart shell (closes files & reinitializes stuff) B.@R9&0DF=='H'; JR NZ,ERR_D SC (SC_RESTRT & 0FF) ...doesn't return=R5 (may be qualified) ...open file for input; ret. R3=^attr, RH0=LU; if err, Z=0, RL0=code PUSHL RR6 R6:=R5; R7:=^FILNM->R4 LDIRB @R4,@R3,R5 B.0->@R4 R4:=0FFFF; R1:=0 if R6<3 or RL0:=@R7[1]<>'/' and RL0<>':' then begin R5:=^FILDRV RL0:='0'->@RL0:->@RR6'; R1:-1 end until R1=0; GTS2~ repeat until B.@RR8'=0D; GTS3~ B.0D->@RR6'; B.0->@RR6 R0:=flag; RES R0,15; R0:->flag /NONSEG LDL SCRPTPTR,RR8 restore R6..R8 R9:=^INBUF2 RET CLSFIL: ...RH0=LU R1:=0; RL0:=CLS ...drop thru: ... SYSTEM: buffer, pt. DE to same rel. pos. in low W.RCADR2->R.HL; B.RCAD2H->R.A end ...addr. of record in high buffer else begin W.RCADR1->R.HL; B.RCAD1H->R.A end ...addr. of record in low buffer endif LD (IY+0),E; LD (IY+5),D ...store old DE (normally p+1)=-1 then begin ...1 extra for poss. CR RL0:=04A; RESFLG Z; JR LDSX ...err if can't get buffer to hold script end LDL SCRPT,RR2; LDL SCRPTPTR,RR2 ...beg. of buffer for script R1:=R6; RH0:=RL7 SYSTEM(RL0:=RD) ...read script->buffer (saves RR2=be JUMP: ...get addr, do go GETADR_D(); JR NZ,ERR_D ...RR2=addr LDL RRPC,RR2 ... GO: ...restore regs. & go R0:=flag; SET R0,15; R0:->flag /SEG R0:=RRN4; LDCTL NSPSEG,R0 LDM R0,RRS,16 WORD 07900 MYSeg RRN4 ...LDPS RRN4 /NONSEG REGS: ...dump memory R5; RL0:='/'->@R5[1] SYSTEM(R0:=0+OPN) ...RH0=0 =>open for input (preserves regs<>R0) if RL0<>NOTFNDERR and RL0<>NOTRDYERR then begin RL0==OK; JR OFILX end end R5:=R7 SYSTEM(R0:=0+OPN) OFILX~ POPL RR6; RET CKREDIR: ...enter with R9 after filenamsave R1..R5 SC (SC_IO & 0FF) ...SC 0 restore R1..R5 RL0==OK; RET Z80CMD: ...send cmd string @R3 to Z80 for execution R2:=0FFFF; SC (SC_Z80 & 0FF) ...doesn't ret. REQMEM: SC (SC_MREQ & 0FF); RET RELMEM: SC (SC_MREL & 0FF); RET SEEK_: SC (SC_SEEK & ts. after CR) LD (IY+10),L; LD (IY+15),H; R.A->@IY(20) ...store disk addr. of record FILOPN() ...open file (rets. R.A=FTYPE, CDE=len.) R.A->B.FILTYP ...save for RDERR if BIT 7,A not zero then begin ...if procedure (instead of ascii) type LOADFL(g. buffer) if not zero then begin PUSH R0; RELBUF(); POP R0; RESFLG Z; JR LDSX end if R6<>0 then begin R0:=flag; SET R0,15; R0:->flag /SEG RL0:=0FF; CPIRB RL0,@RR2,R6,EQ; if zero then R3:-1 if RL0:=@RR2[-1]<>0D then begin LDB @RR2,#0D; R3:+1where regs. stored DUMP2(LDL RR2,#RRS; RL0:=3); RET DUMP: ...get addr, dump memory GETADR_D(); JR NZ,ERR_D PUSHL RR2 R3:=1 if CPB @R9,#',' then begin R9:+1 if R3:=HNUM() not zero then R3:=0 end RL0:=RL3; POPL RR2 if RL0=0 then begin DUMP2(RLe; chk for '<' or '>' followed by ... file (or device) name; setup for i-o (LU's 0 & 1) redirection TOREDIRC() ...go to '<' or '>'->RL0; NZ =>to ';' or CR instead RET NZ PUSH R6 R6:=0; if RL0='>' then R6:=1 ...set R6=LU for i-o redirection LDB @R9,0FF); RET QUIT: ...tell Z80 to ret. to RIO, closing any open files first SC (SC_QUIT & 0FF); RET ...SC 0F EXIT_: ...closes files, then resets default devices for LU's 0,1,2 & reenters ... shell (doesn't ret.) SC (SC_EXIT & 0FF) ...SC 0D OUTSET: R11) JR FILDN2 end ... ^SEGDES ...start of segment descriptors ...NXTSEG: LD E,(HL); INC HL; LD D,(HL); INC HL ...DE=beg. seg. addr. ... LD C,(HL); INC HL; LD B,(HL) ...BC=seg. len. ... R.B|R.C; JR Z,FILDN2 ...test done ... B.DOFLG=0; CALL N end ...make sure CR at end R0:=flag; RES R0,15; R0:->flag /NONSEG end LDL ENDSCRPT,RR2; R0==R0 LDSX~ POPL RR6; RET GETFLEN: ...ret. RR2=len of file of LU RL3 R15:-6 R5:=R15; R4:=0FFFF; SC (SC_FSTAT & 0FF) LDL RR2,R15[2] R15:+6; RET ARGLTRM: .0:+1); CHGMEM() end else DUMP2() RET DUMP2: ...print RL0 lines starting at RR2; ret. RR6 at beg. of last line repeat PUSH R0; OUTSET() LDL RR6,RR2 OUTADR() ...address out RH1:=6; RL0:=' '; repeat RL0:->@R11' until RH1:-1; ...spaces RH1#0D ...for program looking at cmd line R9:+1 SETREDIR(R6) ...get filename, close LU R6 & open to filename ...calls ERREX or ERRCX if err TOREDIRC() ...look for another '<' or '>' if zero then begin R5:=R6 R6:=0; if RL0='>' then R6:=1 ...set:=^DBGBUF; RET COPY: ...DEFT to copy @R11 follows call R3<->stk; PUSH R1 RL1:=@R3; RH1:=0 ...get count R3+1; LDIRB @R11,@R3,R1 POP R1; R3+1; RES R3,0; R3<->stk RET OUTADR: ...put addr in RR2 (incl. seg.) @R11 RL0:=RH2&0F+'0'; if RL0>'9' then RL0:+Z,SETTB0 ...if "/GET", bank 1 NCODE->DE ... INC HL; PUSH HL; PUSH BC; W.0; PUSH HL ...initialize len. read to 0 ...CNTSEG: RDREC() ...read in one record ... POP BC; W.RECLEN ...BC=len. read prev. ... R.HL+R.BC->R.HL ...new len. read (also rese..chk if RL0=char which terminates arg list (CR,';','<',or '>') ...execute both seg'd/nonseg'd; preserve regs. if RL0<>0D and RL0<>';' and RL0<>'<' then RL0=='>'; RET ARGTRM: ...chk if RL0=char which terminates arg. ...execute both seg'd/nonseg'd; pres:=8 ...count of words repeat RDAT(); OUTHEX() RDAT(); OUTHEX() ...print contents of memory RL0:=' '->@R11' until RH1:-1 zero; RL0:='|'->@R11' R3:=R7; RH1:=16 repeat RDAT() if RL0>=07F or RL0<020 then RL0:='.'  LU for i-o redir. if R5=R6 then ERREX() ...must not be same dir. as before R9:+1 SETREDIR(R6) end POP R6; RET TOREDIRC: ...go to '<' or '>'->RL0; ret NZ if to ';' or CR instead while RL0:=@R9<>0D and RL0<>';' do begin RL0=='<'; RET Z R7 RL0:->@R11' RL0:='.'->@R11' ... OUTHEXW: ...put out R3 in hex @R11 OUTHEX(RL0:=RH3) RL0:=RL3 ... OUTHEX: ...put out RL0 in hex @R11 PUSH R0; RL0:/16; HBTHEX(); POP R0 HBTHEX: if RL0:&0F+'0'>'9' then RL0:+7 RL0:->@R11'; RET OUTMSG: LDB @R11,#0D; ts carry) ... EX (SP),HL; POP BC ...HL=len. of segment, BC=len. read ... PUSH HL; PUSH BC ... if begin SBC HL,BC; LD BC,(RECLEN) end >zero then begin ... MVDATA(); JR CNTSEG ...segment not done; transfer data ... end ... R.HL+R.BC->R.BC ..erve regs. RL0==' '; RET Z; RL0==9; RET Z; ARGLTRM(); RET GETARGV: ...enter R9 after filename ...get vector of pointers to 1st R5 args to @R3 ...ret. R3=arg cnt, R9 at arg. list terminator register ARGV:R6, ARGC:R7 save R6,R7 R3:->ARGV; 0->@ARGV'; A  RL0:->@R11' ...put out ascii until RH1:-1 zero; RL0:='|'->@R11' PUSHL RR2; OUTMSG(); POPL RR2 POP R0 until RL0:-1 zero; RET CHGMEM: ...change up to 16 bytes of memory @RR6 RH1:=12; repeat PUTCHAR(B.' ') until RH1:-1; GETLIN_D(B.0) ...getom M_BUFF during M_INIT (at start/restart) DI_FLG: BYTE 0FF ...FF=>NMI enabled, FE=>disabled, 7E=>disabled & NMI came DB_FLG: BYTE 0FF ...ditto for break STARTSW: BYTE 0 ...if=1 when started up by Z80, don't do all reinitting N_IOINPRG: BYTE 0 ...gets BUFF,RR4; LDR M_BUFSZ,R1 RET ...BUCKET ROUTINES (should run both seg'd & nonseg'd): REQBUK: ...request free bucket while begin GETBUK(); RL0==0 end <> do begin RELBUK(); WORD 08D07 end RET ...delay (NOP) added to give Z80 more time when also wants bthe bucket (for ZIOS) UNLOCK: EQU 2 ...unlock the bucket (for ZIOS) ...disk parameters MAXTRK5: EQU 160 ...maximum number of tracks per disk MAXTRK8: EQU 76 CPM: EQU 5 ...CPM entry point SYSRET: EQU 0 ...system reentry point (CPM warm boot) CDISK: EQU 4IT() ...init. buffer pool BUFHDRI() ...init. buffer headers 0FFFF->BRKRTNO->SC_RTNO->TI_RTNO ...no brk, special SC, or timer int. handler yet INIT2() JP SHELL INIT2: ...initing common to START & REENT2 SPsI() ...init. default SPs for each seg.  input (0=>no prompt), R9=^ LDL RR2,RR6; RH1:=8 repeat DEL(); PUSH R3; R5:=HNUM(); POP R3; JR NZ,CHMX WRTAT(RL0:=RH5); WRTAT(RL0:=RL5) until RH1:-1; CHMX~ DUMP2(LDL RR2,RR6; RL0:=1) RET RDAT: ...do RL0:=@RR2' PUSH R5; R5:=flag; SET R5,15; R5:->cnt of no. of active disk i-o reqs. to Z80 INTCNT: LONG 0 ...count of periodic ints. ...following used by XFSEG: SPs: ;WORD 0[MAXNSEG] ...SP for each segment saved; default=top of memory SPsBASE: ADDR SPs-(FRSTSEG*2) SVRRS: ;WORD 0[5] ...prog. status vucket CHKBUK: ...wait till bucket not busy; if something for Z8000 in bucket, get 1st ... byte->RL0, Z=1; else Z=0; save regs<>RL0 GETBUK() if RL0<>0 then begin BITB RL0,7; RET Z end RELBUK() RESFLG Z; RET GETBUK: ...wait till bucket ready, then get ...current disk INPTR: EQU 080 ...addr of CPM buffer containing len + cmd line after ... filename TBASE: EQU 0100 ...base of user programs ...BDOS function calls RESET: EQU 0 ...system reset CONIO: EQU 6 ...direct console I/O RESDSK: EQU 13 ...reset dto top of memory FILTABI() ...clear file table; open LU's 0,1,2 to default device RET MEMINIT0: ...clear R1 words starting at RR2 R5:=0 repeat R5:->@RR2' until R1:-1; RET SPsI: ...init. default SPs for each seg. to top of memory MEMINIT0(LDAR RR2,Sflag /SEG RL0:=@RR2; JR RWATX ... /NONSEG WRTAT: ...do RL0:->@RR2' PUSH R5; R5:=flag; SET R5,15; R5:->flag /SEG RL0:->@RR2 RWATX~ R3:+1; RES R5,15; R5:->flag /NONSEG POP R5; RET ENDROM: ROM: ADDR $  5:=flag; SET R5,15; R5:->flag /SEG RL0:->@RR2 RWector used by XFSEG to start up new segment: PSFCW: WORD 0 PSSEG: WORD 0 0 PSTAT: ADDR PSFCW-2 LNAMBUF: EQU 33 ...max len filename+1 NAMBUF: DEFS LNAMBUF SCRFLG: BYTE 0 ...set=1 if have screen ...following belongs to CONsole driver: PRTSW: BYTE 0 .. it repeat INB RL0,CNTL until RL0<>0FF; repeat INB RL0,CNTL until RL0<>0FF; RET ...INITBUK: RELBUK(); GETBUK() ...fall thru: ... RELBUK0: ...release bucket, first storing a 0 PUTZ() RELBUK: ...release (reset) bucket RL0:=1 OUTB CNTL,RL0; RET SNDBisk system SELDSK: EQU 14 ...select disk OPENF: EQU 15 ...open file CLOSEF: EQU 16 ...close file DELETEF: EQU 19 ...delete file CREATEF: EQU 22 ...create file SETDMA: EQU 26 ...set DMA address READR: EQU 33 ...random read WRITER: EQU 34 ...random write FILPs; R1:=MAXNSEG); RET FILTABQ: ;WORD 0[NLUs] ...for quicker access to FILTAB /begin LDAR RR4,FILTABQ; R3:=^FILTAB; R1:=NLUs repeat R3->@RR4'; R3:+LULEN until R1:-1; end FILTABI: ...init. file table with default device open for LU's 0,1,2 ...(later coerve regs. RL0==' '; RET Z; RL0==9; RET Z; ARGLTRM(); RET GETARGV: ...enter R9 after filename ...get vector of pointers to 1st R5 args to @R3 ...ret. R3=arg cnt, R9 at arg. list terminator register ARGV:R6, ARGC:R7 save R6,R7 R3:->ARGV; 0->@ARGV'; A.printing stopped if <>0 (note: also 0'ed by B_RTN1) PUTBFLOCK: BYTE 0 ...=1 says PERINT should leave PUTBUF alone PUTBUFCNT: WORD 0 ...cnt. of chars. in PUTBUF KBUF: DEFS 50 ...circular buffer for keybd input KBUFEND: NXTIN: WORD KBUF ...place for neUK: ...send bucket with cmd for Z80 (same as RELBUK on present system) RL0:=0; OUTB CNTL,RL0; RET PUTZ: RL0:=0 PUT1B: OUTB DATA,RL0; RET ...INTERRUPT ROUTINES: /SEG B_RTN: PROC ...handle inst break PUSH R0; LD R0,RR14[8]; R0:-2; LD RR14[8],R0; POP SZ: EQU 35 ...compute file size ...BIOS entry offsets WBOOTOFF: EQU 3 CONSTOFF: EQU 6 CONINOFF: EQU 9 CONOUTOFF: EQU 0C PUNCHOFF: EQU 012 RDROFF: EQU 015 LSTSTOFF: EQU 02D ...ZDOS error codes EOF_ERR: EQU 1 ...end of file error FNF_ERR: EQU 2 ...file notuld possibly actually call device's 'open' routine) MEMINIT0(LDAR RR2,FILTAB; R1:=LFILTAB/2) LDAR RR4,FILTAB; LDL RR2,DEFDEV; R1:=3 repeat SETB @RR4,LUOPNB; LDL RR4[DEVADR],RR2; R5:+LULEN until R1:-1; RET BUFHDRI: ...init. buffer headers; also set N_IRGC:=1 ...1st arg (name) not used while ARGC@ARGV'; ARGC:+1 R9:+1 while ARGTRM(RL0:=@R9) not do R9:+1 end R3:=ARGC restore R6,R7 RET GETCON: ...enter with RL3=prompt char. (0=>nonxt char. going into KBUF NXTOUT: WORD KBUF ...ditto next char. out BUFS: DEFS NBUFS*BHLEN ...buffer headers SPBUFHDR: DEFS BHLEN ...special bufhdr (must be adjacent to BUFS) SPBUFF: DEFS BLKSZ RAM: ADDR $ ...***************** ORG ROM ...START & IR0 ...adj. PC on stk B_RTN1: ...come here after NMI PRTSW:=0 ...enable printing if BIT BRKRTNO,0 zero then begin PUSHL BRKRTNA; RET end ...if have addr of brk handler, go there B_RTN2: JP DEBUG INTRTN: PROC ...handles NMI; enter with FCW=0C000 (se found error FALSE: EQU 0 TRUE: EQU 0FF CPMEOF: EQU 01A  U 1 ...end of file error FNF_ERR: EQU 2 ...file not found error FF: EQU 012 RDROFF: EQU 015 LSTSTOFF: EQU 02D ...ZDOS error codes EOF_ERR: EQU 1 ...end of file error FNF_ERR: EQU 2 ...file notOINPRG=0 MEMINIT0(LDAR RR2,BUFS; R1:=(NBUFS+1)*BHLEN/2) ...includes sp. bufhdr LDL RR2,#SPBUFF; LDRL SPBUFHDR+BUFADR_,RR2 N_IOINPRG:=0; RET ADT0: ...resident device(s) as goes in ADT on init. WORD MYSeg CON DEFT 'CON'; BYTE 0[ADTWIDTH-8] ADTINIT: .e), R5=^buffer, R1=len buffer ...get line of input, make sure CR at end; ret. R9 at buffer if RL3<>0 then PUTCHAR(RL3) R9:=R5 read(CONLU,R5,R1-2)+R9->R3; RL0:=0D->@R3'; RL0:=0->@R3 ...$$$ was R1-1 ...0 at end RET GETSCRPT: ...get line of input from  NIT: REENTRY: PROC; JR REENT1 ...reentry pt. START0: PROC; JR ST0 ...entry pt. when first loaded DEFM 'V1.00 ' ... DEFDEV: WORD MYSeg CON ...default device for LU's 0,1,2 ... /SEG ST0: ...initialization done when first loaded R3:=0C000->flag LDL RR1g'd) if BITB DI_FLG,0 zero then begin RESB DI_FLG,7; IRET end ...if NMI "disabled", wait till "enabled" PUSHL RR0 CHKBUK() ...get bucket, 1st byte->RL0; Z=1 if msg. for Z8000 JR NZ,I2 ...shouldn't happen PUSHL RR2; PUSHL RR4 case RL0: of PERI active device table: ADTWIDTH: EQU 16 ...size of each entry in ADT NDEV: EQU 8 ...max # devices active at once NRESDEV: EQU 1 ...# resident devices (always active) ...***************** ORG RAM1 PRTBUF: DEFS 256 ...used by printf library func. & WR..init. active device table LDAR RR4,ADT; LDAR RR2,ADT0; R1:=ADTWIDTH*NRESDEV/2 LDIR @RR4,@RR2,R1 ...resident device(s) R1:=NDEV-NRESDEV+1; LDL RR2,#0FFFF,0FFFF while R1:-1 not zero do begin LDL @RR4,RR2; R5:+ADTWIDTH end RET DEFDEVI: ...call op shell script; ret. R9 pointing to ...if done, dec. LVL and restore CMDPTR from CMDPTR0 LDL RR4,SCRPTPTR if CPL RR4,ENDSCRPT >=zero then begin ...if done RELMEM(LDL RR2,SCRPT); LVL:-1 R9:=CMDPTR0 RET end save R6..R8 R0:=flag; SET R0,15; R0:4,#MYSP ...set SP (in MYSeg) GETBUK() ...prevent Z80 from interrupting till init'd ...set stuff in prog. status area R3->PSANMIF->PSA_SCF->PSABRKF->PSAPRVF ...FCWs LDL RR2,#MYSeg,INTRTN; LDL PSANMI,RR2 ...my NMI handler R3:=^SYSTM; LDL PSA_SC,RR2 .NTCD: begin PERINT() if BIT TI_RTNO,0 zero then begin RELBUK() POPL RR4; POPL RR2; POPL RR0 PUSHL TI_RTN; RET end end WRSCRCD: WRSCR() WR2CD: WR2() RD2CD: RD2() RDCODE: READM() WRCODE: WRITEM() DUNCDSCR PRTBUFEND: PUTBUFSZ: EQU 144 ...254 ...(must be <=BUCKL-2) PUTBUF: DEFS PUTBUFSZ ...buffers console printing ENDRAM1: ...***************** ORG RAM BRKRTNA: WORD 0 ...goes with BRKRTNO BRKRTNO: WORD 0FFFF ...addr of brk handler if any SC_RTNA: en routine of default device to init. LDRL RR2,DEFDEV; RL1:=OPN; CALL @RR2; RET TSTMEM: ...count (->RL3) segments of ram memory present starting at FRSTSEG ...also set LSTSegt=last segment (word form) ...in addition, set SCRFLG=1 if screen present, els->flag /SEG LDL RR8,RR4; LDL RR6,#INBUF2; R1:=LINBUF2-2 ...$$$ was LINBUF2-1 repeat ...move next line of script from system buffer->local buffer RL0:=@RR8'==0D; JR Z,GTS3 if RL0='$' and RH0:=@RR8>='1' and RH0<='9' then begin if R3:=RH0-'0'RL1; RELBUK0() if RL1=BRKCD then begin POPL RR0; BITB DB_FLG,0; JP NZ,B_RTN1; RESB DB_FLWORD 0 ...goes with SC_RTNO SC_RTNO: WORD 0FFFF ...addr of special SC handler if any TI_RTN: WORD 0 ...goes with TI_RTNO TI_RTNO: WORD 0FFFF ...addr of timer int. handler if any ...list of active devices ADT: WORD MYSeg CON ...addr DEFT 'CON'; BYTE e 0 save R6..R9 R9:=MAXNSEG/2; R8:=0; LDL RR6,#FRSTSeg,0FFFE repeat if MTST(LDL RR2,RR6) then R8:+2 RH6:+2 until R9:-1 zero; SCRFLG:=0 if MTST(LDL RR2,#SCRSeg,0FFFE) and SCRDRVR() then SCRFLG:=1 R3:=R8 R1:=FRSTSeg-0100; RH1:+RL3; R1:->LSTSegtMSIZE: EQU 0E000 ...56K BSIZE: EQU 0600 ...size of BIOS ...BUCKET: EQU 07B ...0FF ...@@@ 07B modified for ZOOMA ZIOS: EQU 0F800 ...origin of ZIOS BOOT0: EQU 080 ...load trk 0 sec 1 here and execute BIAS: EQU MSIZE-05000 CCP: EQU 03400+BIAS BDOS: EQU CCP=0 ...so do regular startup RL3:=TSTMEM() ...count #segs present, also set SCRFLG if have screen SETMBUF(RL3) ...determine where to put buffer pool B.0FF->DI_FLG->DB_FLG ...NMI, break "enabled" DEFDEVI() ...init. default device SUBL RR2,RR2; LDRLG,7; IRET ...if break "disabled", wait till "enabled" end I2~ POPL RR0 JP B_RTN2 ...shouldn't come here end end POPL RR4; POPL RR2 RL0:=1; OUTB CNTL,RL0; POPL RR0; IRET ...release bucket IODUN: ...get id & comp. code; execute comp.0[ADTWIDTH-8] ...1 resident device^; if more, include them here BYTE 0FFFF[(NDEV-NRESDEV)*ADTWIDTH] ...note on i-o handler: ... ret. RL0=CC ... on entry: R1=orig. R0, R13=orig. R1=len, RR2=addr, RR4=alt addr FILTAB: ;BYTE 0[NLUs*LULEN] LFILTAB: EQU $-F restore R6..R9 RET MTST: ...enter with RR2=addr to test if mem. at; ret. Z=1 if so R1:=@RR2; LD @RR2,#05555 if CP @RR2,#05555 then begin LD @RR2,#0AAAA CP @RR2,#0AAAA end R1:->@RR2 RET SCRDRVR: ...test if screen driver in place @SCREEN LD +0806 BIOS: EQU CCP+01600 ENDCPM: EQU BIOS+BSIZE-080 ...BIOS1: EQU BSIZE-080 ...Interrupt Vector Table IVT: EQU 0FF00 ......Bucket Equates ...BUCKL: EQU 0100 ...CNTL: EQU BUCKET ...DATA: EQU BUCKET-2 ...cache parameters CBLKSZ: EQU 01000 ZOOM: PROC at B INTCNT,RR2 ...init. periodic int. count RELBUK0() ...INITBUK() ...put 0 in bucket & release SLEEP: LDL RR14,#MYSP JR $ REENT2: ...come here after 'exit' to reenter shell (assumes files closed) INIT2() REENT1: ...JP 0.800 goes here to reenter with no rout. if any; release id ...in comp. rout.: RL0=CC, R0-R5 free to use PUTZ() INB RH1,DATA ...LU INB RL1,DATA; RL1:&0F ...cmd INB RH3,DATA; INB RL3,DATA ...^bufhdr if read/write INB RL0,DATA ...cc PUSHL RR10; FNDLU_() if RL1=OPN then begin ...ILTAB RWADR: WORD 0 0 ...addr for RD2 or WR2 cmd RWLEN: WORD 0 ...ditto len. LSTSegt: WORD 0 ...last seg. have M_BUFF: LONG 0 ...addr of buffer pool M_BUFSZ: WORD 0FE00 ...size of buffer pool; must be multiple of 16 M_BUFFAD: LONG 0 ...gets value frR3,SCREEN; R3==05E08; RET ...test for JP inst ...(later test for ident string) SETMBUF: ...enter RL3=#segs in mem.; set M_BUFF,M_BUFSZ LDL RR4,#MYSeg,FREE; R1:=0FE00-FREE if RL3>=4 and R4<>MBUFSeg then begin LDL RR4,#MBUFF; R1:=MBUFSZ end LDRL M_IOS+033 ...additional ZOOM BIOS entry ...codes for ZOOM entry ZOOM_RDY: EQU 0 ...zoom system loaded CACHE_OFF: EQU 1 ...turn cache off CACHE_ON: EQU 2 ...turn cache on SCREEN_RDY: EQU 3 ...screen loaded (also for SysRdy in ZIOS) LOCK: EQU 1 ...lock  reiniting 0C000->flag; LDL RR14,#MYSP ...shell also sets SP JP RESHELL START: PROC ...entry pt. when started up by Z80; come here with flag=0C000 STARTSW==0; JR NZ,REENT2 ...reentering after Z80 cmd START2: LDL RR14,#MYSP ...set SP (in MYSeg) M_IN! if open MRKCPL() ...mark complete, setting COMPB, poss. ERRB,ERRCD INB RL0,DATA; INB RH1,DATA; INB RL1,DATA; RH0:=0 LDL RR10[FLEN],RR0 ...store file len. end else begin if RL1=CLS then MRKCPL() else begin PUSHL RR8 R9:=R3; R8:=R end R9:=R10 while RL1:-1 not zero do begin LDL RR6,@RR8 if BIT R7,0 not zero then begin MTREPL~ if R2=0FFFF then R2:=R12 LDL @RR8,RR2 ...store addr R9:+4; RL7:=@RR4+1; RH7:=0 LDIRB @RR8,@RR4,R7 ...move deft name RL0:=o wait for PUTBUF to be emptied ...preserve regs.<>RL0 repeat until PUTBUFCNT=0; REQBUKW2: repeat until N_IOINPRG=0; REQBUK() RET TIMEROFF: RL0:=0 ... SETTIMER: ...start or stop timer ints. (R12=calling seg,RR12 free to use) ...RL0: =0,stop; =1-5,s5; RL1:=WRT ... CALL SCREEN ... restore R6..R13 end else begin if N_IOINPRG<>0 then begin PUTZ(); JR PERINTX end ...don't send to Z80 if file i-o in progress PUTBUFBUK() ... R4:=DATA ... RL0:=CONWRCD; OUTB @R4,RL0 ... OUT do if NEXT() not then BREAK : while BIT R7,EMPTY not or R6@RR8[CCD] else begin SETERRCD() if BIT @RR8,GDDTAB zero then RELBUF() end end else begin ...RD or RDAHD if RL1=RDAHD then OK; JR MTX end R9:+ADTWIDTH end end end RL0:=GENERR MTX~ LDM R1,@RR14,10; R15:+20; RET FIXNAME: ...if name @RR4=string+'0', convert to deft form ...preserve all regs. except RR4 pointed to new string save R0..R3 if RL0:=@RR4>020tart them,1=slower,5=faster ...RR2: addr of routine to execute upon int. R0:->R13; REQBUKW() RL0:=TIMERCD; OUTB (DATA),RL0 R0:=R13; OUTB (DATA),RL0 PUSHL RR2 if R2=0FFFF then R2:=R12 if RL0=0 then R3:=0FFFF LDRL TI_RTN,RR2; SNDBUK() POPL RR2; R0:=B @R4,RL5 ... OTIRB @R4,@RR2,R5 ... SNDBUK() ...not really necessary end ... PUTBUFCNT:=0 end PERINTX~ RET INKEY: ...next byte in bucket=char. from console; put->circular buffer ...R0..R5 free to use PUTZ() INB RL0,DATA if RL0=STOPCH tR7:=R6; R6:=R3; R3:=R5; R5:+R7; LDL @RR4,RR6 R5:+R6+2; R7:=@RR4&0F+R6->@RR4; R5:=R3 end ...TRUE() : R3:=R5+4; R2:=R4; R3==R3 MREQX: EI_(); POPL RR6; POPL RR4; RET M_REL: PROC ...expects RR2 pointing to buffer to be released (now ignores R2) ...Bbegin if BITB RL0,7 not zero then begin ...(read ahead rets. bit CC,7 zero when not all dun) RL0:->@RR8[CCD]; RESIOINPG() end INB RL2,DATA; INB RH3,DATA; INB RL3,DATA; RH2:=0 ...get new fpos ADDL RR2,#BLKSZ-1; SRLL RR2,#BLKSZPWR R2:=@ then begin LDAR RR2,NAMBUF+1; RH0:=LNAMBUF; RL1:=0 while RL0:=@RR4<>0 and RH0:-1 not zero do begin RL0:->@RR2'; R5:+1; RL1:+1 end LDAR RR4,NAMBUF RL1:->@RR4 end restore R0..R3 RET CPNAME: ...compare name @RR4 with name @RR8[4] (namR13; RET GETTIME: ...get count of periodic ints. since startup->RR2 LDRL RR2,INTCNT; RET CLSFILS: ...close all open files LDAR RR10,FILTAB; RL7:=0 repeat if BITB @RR10,LUOPNB not zero then begin R1:=0; RH0:=RL7; RL0:=CLS; IOREQ() end R11hen COMB PRTSW ...reverse print toggle else begin if PRTSW=0 then begin LDR R3,NXTIN R2:=MYSeg; RL0:->@RR2 INCKPTR(R3)->R3->NXTIN ... if R3<>NXTOUT then LDR NXTIN,R3 ... ...don't take new char. if would overtake NXTOUT if R3=NUFFER_JOIN() save R2..R9 LDRL RR4,M_BUFFAD; R4:->R8 ...segment of buff. R5:=R3-4; DI_() LDL RR6,@RR4 R7:&0FFF0; R9:=R5-R7; LDL RR2,@RR8 if R7<>0 and BIT R3,EMPTY then begin ...join below R6:+R2; R7:=R3; R5:=R9 end R9:=R5+R6; LDL RR2,@RR8 ifRR8[BLKNO]; R3:-R2 ...R3=(new fpos+(BLKSZ-1))/BLKSZ-BLKNO=no. blks done end else begin RL0:->@RR8[CCD]; RESIOINPG() R3:=1; if BITB RL0,6 not zero then R3:=0 end R3->@RR8[NBLKSDUN] end POPL RR8 end end POPL RR10; es in DEFT form) ...name @RR4 not longer than ADTWIDTH-5 to match; R6 free to use PUSH R1; PUSH R5; PUSH R9; R9:+4 if RL1:=@RR4=@RR8 then begin R5:+1; R9:+1; RH1:=0 CPSIRB @RR4,@RR8,R1,NZ COMFLG Z end POP R9; POP R5; POP R1; RET ISDEV: ...ch:+LULEN until RL7:+1=NLUs; RET EXIT: ...close files, do some reiniting, & reenter shell CLSFILS() REENT2() ...doesn't return RESTART: ...close files and jump to where first started up by Z80 CLSFILS() TIMEROFF() ...make sure (fast) timer off STAXTOUT then begin INCKPTR(R3); LDR NXTOUT,R3 end ...if overtake NXTOUT, move it fwd (skip oldest char) end PRTSW:=0 end RET INCKPTR: ...inc. R3=^ into circular keybd buffer R3:+1==^KBUFEND; RET C; R3:=^KBUF; RET WRSCR: ...write to screen;  BIT R3,EMPTY then begin ...join above R6:+R2; R9:+R2; LDL RR2,@RR8 end R3:=R3&0F+R6; LDL @RR8,RR2 LDL @RR4,RR6 EI_(); restore R2..R9; RET ...Note: I will probably remove this: ...use of XFSEG: ... Proc() ... ...Proc: SC XFSEG; LONG Proc_; RETRET MRKCPL: ...enter RR10=^LUvec, RL0=CC; mark complete SETB @RR10,COMPB; N_IOINPRG:-1 SETERRCD: if BITB RL0,6 not zero and BITB @RR10,ERRB zero then begin RL0:->@RR10[ERRCD]; SETB @RR10,ERRB end RET RESIOINPG: RES @RR8,IOINPRGB; N_IOINPRG:-1; REk if name @RR4=device; if so, Z=1, RR8=^ADT entry ...R12=calling seg.; save regs<>RR8 PUSHL RR4; PUSHL RR6 LDAR RR8,ADT repeat LDL RR6,@RR8 if BIT R7,0 zero then begin CPNAME(); JR Z,ISDEVX end until R9:+ADTWIDTH=^ADT+(NDEV*ADTWIDTH); RESFLG Z RT2() ...doesn't ret. Z80CMD_: ...@RR2=cmd string to send to Z80 (if R2=0FFFF, R2=R12=calling seg) ...temporarily quits and will be restarted if R2=0FFFF then R2:=R12 PUSHL RR2 CLSFILS() TIMEROFF() STARTSW:=1 ...mark not to reinit everything when len+data in bucket; R0..R5 free ...uses PRTBUF PUTZ() if SCRFLG<>0 then begin save R6..R13 R1:=DATA INB RL0,@R1; RH0:=0 if R0<>0 then begin LDAR RR4,PRTBUF R13:=R0; LDL RR2,RR4 INIRB @RR4,@R1,R0 RL1:=WRT CALL SCREEN  XFSEG: ...at ret. addr is long addr of procedure to call with same seg. mode ...meant so can do nonseg'd ...up to 10 words of params. on stack may be passed (assumed to start ... 1 word (2 if seg'd) above saved prog. status) LDM SVRRS,R1,5 ...save RT READM: ...send requested data to Z80 INB RL0,DATA ...leave code in 1st bucket pos. GETADL() ...get addr->RR4, len->R3 RELBUK(); GETBUK() JR RD2A RD2: GETADL2() ...addr->RR4, len left->R3 RD2A: RL0:=RDBKCD; OUTB DATA,RL0 if R3-(R1:=BUCKL-1)RR2 ...if R5=4, ditto SC (bit 7=1) handler LDL RR2,BRKRTNA[R5]; RET WRBRKHDL: ...if R5=0, RR2->addr of break handler ...if R5=4, ditto SC (bit1..R5 LDL RR4,RR14[4] ...ret. addr LDL RR2,@RR4 ...addr to call R5:+4; LDL RR14[4],RR4 ...update ret. addr. LDRL PSSEG,RR2; R1:=@RR14[2]; LDR PSFCW,R1 ...set for later LDPS LDL RR4,RR14 RL3:=RH4; R3:&07F; R3:*2 R5:->SPsBASE[R3] ...save SP abov then R1:+R3 ...R1=min(R3,BUCKL-1); R3=R3-R1 ...write R1 bytes @RR4 to bucket: R2:=DATA OTIRB @R2,@RR4,R1 ...WORD 03A42 0120 STADL() ...store updated RR4 & R3 ... SNDBUK() ...because cmd for Z80 (not really necessary) RET GETADL: R2:=DATA INB RHt sys restart ...rets. RR2=addr & R5=len of new buffer, or R3=-1 if can't fit (so not ... changed); also, if entry R5=0, ret. RR2,R5=current addr,len if R5=0 then begin LDRL RR2,M_BUFF; R5:=M_BUFSZ; RET end R5:+R3&0FFF0 ...hi_add=(addr+len) rounded doret. to RIO, closing any open files first ...if RL0=0 then goto boot prom, else goto SLEEP PUSH R0 CLSFILS() TIMEROFF() STARTSW:=0 POP R1 REQBUKW(); PUT1B(RL0:=QUITCD); PUT1B(RL0:=RL1); SNDBUK() if RL1<>0 then SLEEP() ...doesn't ret. WORD 07900 0 7=1) handler ...enter with R12=calling seg. if R2=0FFFF then R2:=R12 case R5: of 0: LDRL BRKRTNA,RR2 4: LDRL SC_RTNA,RR2 end RET ACTIVATE: ...activate (RL0<>0FF) / deactivate (RL0=0FF) device ...enter R12=calling seg. ...RR4=^DEFT NAME, e saved regs RL3:=RH2; R3:&07F; R3:*2 R3:=SPsBASE[R3] LDL RR14,RR2 ...SP on other seg. PUSHL RR4 ...SP for when later ret. PUSH #SC_RETSEG ...code to do SC to ret R5:+(8+2+18) ...go past prog status, ret addr, 10 (-1) poss. args. R3:=R15; R15:-24,@R2; SETB RH4,7; RL4:=0 INB RH5,@R2; INB RL5,@R2 ...addr->RR4 INB RH3,@R2; INB RL3,@R2 ...len->R3 RET GETADL2: LDRL RR4,RWADR; LDR R3,RWLEN; RET STADL: LDRL RWADR,RR4; LDR RWLEN,R3; RET WRITEM: ...write data from Z80 to memory PUTZ() GETADL() .wn to mult. 16 SETB RH2,7; RL2:=0 if R2=MYSeg and R3=R5 or R4:=R5-R3LSTSegt then R3:=-1 else begin LDRL M_BUFF,RR2; R5:-R3->M_BUFSZ end RET ...manag ...LDPS 0.0 SC_RTN0: ...if have special SC handler addr, go there if BIT SC_RTNO,0 zero then begin R15:-4; PUSHL RR2 LDRL RR2,SC_RTNA; LDL RR14[4],RR2 POPL RR2; RET end IRET SYSTM: PROC ...new FCW set=0C000 (seg) ...saves regs. except RL0RR2=addr ...ret. RL0=OK if succeed, else =GENERR (not found/no room) ...note: max. device name length=11 R15:-20; LDM @RR14,R1,10 ...save R1-R10 if R4=0FFFF then R4:=R12 FIXNAME() ...make sure name in deft form LDAR RR8,ADT+NRESDEV*ADTWIDTH; RL1:=N; R2:=10 if BIT R1,15 not zero then begin ...if seg'd R5:+2 ...because longer ret. addr LDDR @RR14,@RR4,R2 ...move args R3:->@RR14 ...ret addr=^SC_RETSEG code PUSH R14 ...seg'd part of ret. addr end else begin LDDR @RR14,@RR4,R2 ...m..get addr->RR4, len->R3 R1:=BUCKL-6; JR WR2A WR2: PUTZ() GETADL2() ...addr->RR4, len rem->R3 R1:=BUCKL-1 WR2A: if R3-R1@RR14 ...ret addr=^SC_RETSEG code end LDM R1,SVRRS,5 ...restore R1..R5 LDPS PSTAT ...start up in new seg. XFSEGRET: ...XFSEG sets up so return here & then back LDM SVRRS,R1,3 ...save R1..R3 R1:=@RR14[2] ...flag R15:+(8+20+2); P140 STADL() ...store updated RR4 & R3 RET PERINT: ...do periodic int. stuff ...if PUTBUFCNT<>0, put buffer to screen or in bucket with CONWRCD ... (unless file i-o in progress) ... 0->PUTBUFCNT if empty PUTBUF ...inc INTCNT ...R0..R5 free to use  M_INIT: PROC ...initializes the buffer area LDRL RR4,M_BUFF; LDRL M_BUFFAD,RR4 LDR R6,M_BUFSZ; R6:-010; R7:=0 LDL @RR4,RR6 R7:=R6; R6:=0; R5:+R7; SET R7,EMPTY; LDL @RR4,RR6 RET M_REQ: PROC ...expects R3 with size ...if succeed, rets. RR2 with pt_INTR; JP Z,INTRTN ...03F CP @RR14,#SC_BKR; JP Z,B_RTN1 ...03E PUSHL RR12; LD R13,RR14[4] ...id->R13 LD R12,RR14[8] ...calling seg->R12 case R13: of SC_SEEK: SEEK() ...5 SC_FSTAT: FSTAT() ...7 SC_MREQ: M_REQ() ...010 SC_MREL: M_REL() ...if act. if RL7:=@RR4<=ADTWIDTH-5 then begin RH1:=RL1; R10:=R9 while RH1:-1 not zero do begin LDL RR6,@RR8 if BIT R7,0 zero then begin CPNAME(); JR Z,MTREPL ...if already mounted, replace addr end R9:+ADTWIDTH OPL RR2 ...RR2=saved SP R1:->@RR2[2] ...xfer flag R1:=R14; RL1:=RH1; R1:&07F; R1:*2 LD SPsBASE[R1],R15 LDL RR14,RR2 ...SP=prev. SP LDM R1,SVRRS,3 ...restore R1..R3 IRET REQBUKW: ...request bucket after waiting for last file i-o to finish ...alsLDRL RR2,INTCNT; ADDL RR2,#1; LDRL INTCNT,RR2 ...count periodic ints. if PUTBUFCNT=0 or PUTBFLOCK<>0 then PUTZ() else begin ... LDAR RR2,PUTBUF (R5:=PUTBUFCNT) if SCRFLG<>0 then begin PUTZ() PUTBUFSCR() ... save R6..R13 ... R13:=Rr. to buffer, Z=1; else R3=0FFFF, Z=0 ...save other regs. PUSHL RR4; PUSHL RR6 R3:+19&0FFF0 ...add space for links and make multiple of 16 ...FIRST_BUFFER()->RR6 : LDRL RR4,M_BUFFAD DI_() ...DI NMI LDL RR6,@RR4 ...while NOT_EMPTY() or TOO_SMALL()" ..011 SC_GETTM: GETTIME() ...9 SC_RDBKH: RDBRKHDL() ...012 SC_WRBKH: WRBRKHDL() ...013 SC_SETTMR: SETTIMER() ...1 SC_ACT: ACTIVATE() ...2 SC_EXIT: EXIT() ...0D SC_Z80: Z80CMD_() ...0C SC_RESTRT: RESTART() ...0E SC_QUIT: QUI1 LD A,NCOL-R1 ...R1=15 PRCMD7: POSCRS(R.A;LD B,0); LD B,7 repeat PUT1(@HL); INC HL until DEC B zero; P.RETCRS ...return cursor ^BLCMRF; LD (HL),1; RET ...flag msg. in rt. part cmd line ... ...NOCHG: ^TXTNCH; JR PRCMR1 ...print "NO CHG" on cmd. lin where MAGICNO=magic number IMGSZ=image size UDATASZ=size of uninitialized data SEGTABSZ=size of following SEGTAB (segment table) ENTRY_PT=entry point HDRFLG=flag: bit 0=1 =>reloc. info + symtab stripped (execution addr fixed) bit 1=1 =>stri2 if RL1=1 then LDL RR2,RR10[FPSREQ] if begin RL1==2; LDL RR0,RR10[FLEN] end then LDL RR2,RR0 ADDL RR2,RR4 if CPL RR2,RR0 >zero then LDL RR2,RR0 LDL RR10[FPSREQ],RR2 end POPL RR10; RET FSTAT: ...enter RL3=LU, RR4=^buffer to put file type to before returning (also done in segmented mode). As an alternative to ending with a RET, the program may execute an EXIT system call (see below) or jump to the system reentry point at 0.800. 4. A 'shell script' file can also be executed. This type oT_() ...0F SC_CHGM: CHGMBUF() ...016 end POPL RR12; IRET IOREQ0: ...enter with stack as after SC save R2..R5 if R2=0FFFF then R2:=@RR14[12] ...[14] if R4=0FFFF then R4:=@RR14[12] ...[14] IOREQ() restore R2..R5 IRET IOREQ: ...i-o request; entee BLCMR: B.BLCMRF=0; RET Z PRCMR1(^TXTBL7); BLCMR0() ...blank all right part cmd line DEC (HL) ...reset BLCMRF marking rt. part cmd line blank RET TXTEOF: DEFM 'EOF' PRNWFB: P.PRTB ...print rem. screen starting beg. curr. line PRNWF0: 00->R.C ...pped plus may run in any Z8000 segment (uses segment of ENTRY_PT) RELOCSZ=size of relocation information SYMTABSZ=size of symbol table SEGTAB: ...segment table ...each entry=description of 1 code or uninit'd data region long START_ADDR; word LENGTH(device or file) & length ...format: type=word (0 if file, 1 if device), len=long ...if R4=0FFFF, use caller's segment (in R12) ...ret. R3=0 if succeed, else -1 (RL5=code) PUSHL RR10 if FNDLU2(RL3:->RH1) not zero then begin R3:=-1; RL5:=RL0 end elf file contains a list of commands that would otherwise be typed in from the console. Up to 9 arguments provided upon invocation of the shell script can be referenced inside (referenced by '$n', n=1..9). There can also be comments (indicated by '#' at thr with RH0=LU / open type, RL0=cmd, R1=len ... RR2=addr, RR4=alt. addr (^filename with open) save R6..R13 R1:->R13; R0:->R1 case RL0:&0F of WRT: WRITE() RD: READ() OPN: OPEN() CLS: CLOSE() end RH0:=RH1; R1:=R13 restore R6..R13 RET FNDLDE must be at beg. of a row R.A->B.CRROW0 ...to assure printing full screen PRNEW: ...print from R.DE, row ROWNO, col. R.C to end of line ...if end of line on a diff. row from prev., print till screen ... full & update CRROW0 @DE=EOF; JR Z,PRFIN ...i,TYPE ...TYPE=0 =>code, 1 =>uninit'd data repeat entries until SEGTABSZ (max 12 entries) IMAGE: <-------------------> (length=IMGSZ=total of code lengths in SEGTAB) RELOC: ...relocation information long ADDR; word FLAG bit FLAG,15=0 =>local sse begin if R4=0FFFF then R4:=R12 R3:=1 if BITB @RR10,ISFILB not zero then R3:=0 R3->@RR4 LDL RR2,RR10[FLEN]; LDL RR4[2],RR2 R3:=0 end POPL RR10; RET SNDFILIO: ...send file i-o req.->Z80 ...enter: R1=LU,cmd, RR2=addr (RL2 poss. open te beginning of a line, and continuing to the end of the line). NOTE: There MUST be a comment (or a single '#') on the first line of the file. The system uses this to recognize the file as a shell script. See this example: CMDFILE contains: # COPY $1.SU_: ...get RR10=^entry in FILTAB for LU RH1 PUSH R3; RL3:=RH1; RH3:=0; R3:*2 R11:=FILTABQ[R3]; R10:=MYSeg POP R3; RET FNDLU2: ...if LU RH1 not open, ret. Z=0, RL0=NOTOPNERR FNDLU_() RH1==NLUs; JR UGE,NOTOPN; BITB @RR10,LUOPNB; JR Z,NOTOPN R0==R0; REf at EOF P.PRLIN ...print till CR ^CRROW0->R.HL if not zero then begin ...Z=0 means line went to scr. bottom LD (HL),LROW; JR PRFIN ...save last print line info end if B.ROWNO-1=@HL then begin P.RETCRS; RET end ...check if CR on same row as pymbol: bit 0=0 =>code ref, 1=>udata ref =1 =>external symbol: bit 12=1 =>initialization ref bits 0-11 = SYMTAB ordinal repeat entries until RELOCSZ SYMTAB: ...symbol table long ADDR; byte TYPE; byte NAME[9] TYPE=0 =>undefined, ype), RR4=addr/fpos ... R13=len, RR8=bufhdr ...bucket must already be gotten ... REQBUKW() ...wait for prev. i-o to finish; then get bucket when free SNDFIO2: ...enter here with bucket already gotten PUSHL RR6 R7:=DATA RL0:=IOCODE; OUTB @R7,RL0 OUTB $2; EE $2 #this is a comment Y $2 Now, if the following is typed: :CMDFILE ABC XYZ the following sequence of commands will be executed: COPY ABC.S XYZ; EE XYZ; Y XYZ 5. Input-Output Redirection: Whenever a program is started up by ZOOMSYS, 3 logical T NOTOPN: RL0:=NOTOPNERR; RESFLG Z; RET WRITE: READ: ...enter with RH1=LU, RR2=addr, R13=len ...get RR10=^entry in FILTAB (^LUvec) for LU RH1 ... FNDLU2() ...get RR10=^FILTAB entry (done below:) RL7:=RH1; RH7:=0; R7:*2 R11:=FILTABQ[R7]; R10:=MYSeg Rrev. R.A->@HL; JR PRSCR ...update CRROW0; print rest of screen ... PRSCR0: ...do PRSCRF + pos. cursor at home pos. P.CRSHM; JR PRSCRF PRSCRH: ...do PRSCRN + cursor home CRSHM() PRSCRN: ...set DE=BUFP0 before doing PRSCRF LD DE,(BUFP0) PRSCRF: ...fro1=>absolute, 2=>proc, 3=>init'd data, 4=uninit'd data if name length>9, 1st byte=length|080, name follows, 0 padded to whole entry repeat entries until SYMTABSZ **************************************************************************** ZOO @R7,RH1; OUTB @R7,RL1 ...LU,cmd OUTB @R7,RH2; OUTB @R7,RL2; OUTB @R7,RH3; OUTB @R7,RL3 ...RR2 R6:=R13 OUTB @R7,RH6; OUTB @R7,RL6 ...R13 OUTB @R7,RH4; OUTB @R7,RL4; OUTB @R7,RH5; OUTB @R7,RL5 ...RR4 R6:=R9 OUTB @R7,RH6; OUTB @R7,RL6 ...R9 SNDBUunits are pre-opened and normally set to the console. Logical unit 0 is considered standard input, and logical unit 1 is considered standard output. These may both be redirected to/from files or other devices instead of the console. Logical unit 2 is usH1==NLUs; JR UGE,NOTOPN; BITB @RR10,LUOPNB; JR Z,NOTOPN PUSH R1 LDL RR8,RR10[DEVADR]; CALL @RR8 POP R1; RET CLOSE: FNDLU2(); RET NZ PUSH R1 LDL RR8,RR10[DEVADR]; CALL @RR8 POP R1; RELLU_() RET REQLU_: ...get LU#->RL0, ^entry in FILTAB->RR10; prese" m row 1, print till screen full starting at R.DE in buffer ...R.DE should be 1st char. in a line ...cursor returned to CRSROW, CRSCOL LD (BUFP0),DE; 1->B.ROWNO; LD C,0 ...BUFP0=1st printed char. PRSCR: ...print starting at R.DE, row ROWNO, col. R.C, tiMSYS System Calls (Note: The following is valid for ZOOMSYS Version 1.00 of 11/17/82.) Unless otherwise stated, registers >=R6 are preserved through a system call. ------------------------------------------------------------------------- General I/ ...C=0 if @^ROWNO=LROW then begin if @^SCLFLG=0 then begin INC A; POP HL; RET end ...if last row & not scrolling, ret. Z=0 DEC (HL) ...dec. SCLFLG end else INC (HL) ...inc. ROWNO endif PUT1(R.B) ...put out char. in R.B ended as a convention for error or other special i-o for which it is desired always to be connected to the console. To cause a program to start up with either the standard input or standard output or both redirected to a file or another device, the followingrves other regs ...if succeed, Z=1, entry 0'ed except LUOPNB set; else Z=0 LDAR RR10,FILTAB; RL0:=0 repeat if BITB @RR10,LUOPNB zero then begin PUSH R1; R1:=LULEN/2 repeat CLR @RR10; R11:+2 until R1:-1; R11:-LULEN; SETB @RR10,LUOPNB ll screen full W.ENDDAT; EX DE,HL; P.CONOUT ...print till screen full or EOF ...note: if CR on last row, R.DE will not be incremented to next char. PRFIN: B.ROWNO->B.LSTROW->R.B ...last printed row (may be "EOF") 00->B.EOFFLG ...reset flag if @DE=E LD DE,DATA1 ...pt. DE to start of buffer JP ST1 ...reset SP, get line of input & start parsing FILDN0: LOGUN=SWCON; RET Z FILDUN: if B.NUMERR<>0 then ?"ERROR TOTAL=",R.A FILDN2: CLOSFL(@^LOGUN) ...close input file DEC (HL) ...decrement logical unit  INC DE; JP PRTLUP ...go to next char. ASCPRT: ...return Z=1 if R.A>=020 and <07F, else Z=0; R.B=R.A R.A->R.B=07E; if not zero then RET NC ...sets Z=0 if R.A=07F R.A=020; RET C ...sets Z=0 if R.A<020 CP A; RET ...Z=1 CHRPRT: ...print R.B unless a syntax is used on the command line: :PROGNAME ARG1 ARG2 ..ARGN FILEOUT This opens FILEIN for input, first closing logical unit 0. Since logical unit 0 is then free, FILEIN gets logical unit 0 and becomes the standard input. In the same way, FI POP R1; R0==R0; RET end R11:+LULEN until RL0:+1=NLUs; RESFLG Z; RET RELLU_: ...release LU RH1 PUSHL RR10; FNDLU_(); CLRB @RR10; POPL RR10; RET OPEN: ...assign LU, do open; enter R1=orig R0, R13=orig R1, R0 diff. ...ret. RH1=LU if REQLU_() nOF then begin ...chk if EOF R.A->B.EOFFLG ...set flag POSCRS(00) ...make sure of pos. ^TXTEOF; LD DE,TXTEOF+3; LD C,0; P.CONOUT ...print "EOF" BLNKLS(B.ROWNO->R.C) ...blank rem. lines end P.RETCRS; RET ...return cursor to prev. pos. BLno. if @HL<>SWCON then begin ...check if back to $CON or still a file NEWLU() ...store revised logical unit nos. LD IY,RECPTR-SWCON; R.A->R.C; LD B,0; ADD IY,BC ...position IY to pt. to stored old DE & record addr. LD E,(IY+0); LD D,(IY+5) ..t last col. (R.B saved) INC C; R.C=NCOL; LD A,B; CALL C,PUT1; RET TXTBL7: DEFM ' ' ...7 spaces TXTNRM: DEFM 'NO ROOM' TXTHTK: DEFM 'HIT KEY' TXTNCH: DEFM 'NO CHG ' TXTENT: DEFM ' ENTER ' TXTINS: DEFM 'INSERT ' TXTRPL: DEFM 'REPLACE' TXTQST: DEFM 'LEOUT is opened for output after closing logical unit 1 and thus gets logical unit 1 and becomes the standard output. In the above syntax example, the arguments ARG1..ARGN are of course optional; the spaces before '<' and '>' are also optional. If it is ot zero then begin RL0:=TUMNYERR; RET end ...RL0=LU, RR10=^entry in file table RH0:=RH1; RL0:->RH1 ...RH1=LU, RH0=open type PUSH R1 FIXNAME() ...if name=string+'0', change to deft if ISDEV() then ...chk if name=device name (RR8=^entry ADT) LDL RNKLS: ...erase rem. rows on screen after R.C POSCRS(00;LD B,C) INC C; R.C=NROW; RET NC PUT1(CR); ERASL(); JR BLNKLS ... PUT1(LF); ERASL(); JR BLNKLS CMD: ...routine to select a subroutine(R.A) from jump table @HL ...if no routine is found returns NZ .recall old DE LD L,(IY+10); LD H,(IY+15); @IY(20)->R.A ...get old record address ... R.HL->W.RCADR1; R.A->B.RCAD1H ... RDFL2(022) ...read direct RECL bytes starting at record with stored address; then fill high buffer, not waiting READFL() .. ??? ' TXTTG1: DEFM ' TAG 1 ' TXTTG2: DEFM ' TAG 2 ' BLCMR0: ^TXTBL7; JR PRCMR0 ...blank rightmost 7 spaces on cmd line HITKEY: ^TXTHTK; JR PRCMR0 ...print "HIT KEY" on cmd. line ... NOROOM: ^TXTNRM ...print "NO ROOM" on cmd. line, ret. cursor; fall desired to only redirect standard input, '>FILEOUT' would be left off (and vice versa). 6. When a filename has been entered, without a drive qualification, on the command line for the system to load, the system looks for it first on drive A (or 0), theR8,@RR8 ...get device addr else begin SETB @RR10,ISFILB LDL RR8,#MYSeg,FILES ...file handler end LDL RR10[DEVADR],RR8 ...store addr of LU handler ...else file handler->addr for LU CALL @RR8 ...init. open POP R1 ...RH1=LU if RL0<>OK then...otherwise the selected subroutine is executed returning Z=1 ...jump table structure: ...n CMD1 CMD2 -- CMDn ADDn -- ADD2 ADD1 CKCMDT(); RET NZ ...no routine found R.HL+R.BC+R.BC+R.BC->R.HL ...pt. to subroutine addr. LD B,(HL); INC HL; LD H,(HL); .$$$ end ... B.DOFLG=0; CALL NZ,GETSUB ... GetrecD: ...test if to jp to debugger or do Getrec if B.LOGUN=SWCON and W.SAVSP<>0 then begin LD SP,HL; JP DBUG2 end ... Getrec: PROC ...enter with DE pointing after CR (or START) ...assure another CR in bufthru: ... PRCMR0: ...enter with R.HL->7-byte string; print top row, right corner ...ret. with HL at BLCMRF, (HL)=1 LD A,NCOL-7; JR PRCMD7 ... PRCMR1: ...enter with R.HL->7-byte string; print top row, 15 cols. from right ...ret. with HL at BLCMRF, (HL)=n on the currently-set default drive. ----------------------------------------------------------------------------- Object file format HEADER: word MAGICNO=0E007; long IMGSZ,UDATASZ; word SEGTABSZ; long ENTRY_PT word HDRFLG,RELOCSZ,SYMTABSZ,UNUSED  RELLU_() RET SEEK: ...set FPSREQ of LU RL3 from RR4; R1: 0=>abs, 1=>from curr., 2=from end ...ret. RR2=new pos., -1 if err (RL5=code) PUSHL RR10 if FNDLU2(RL3:->RH1) not zero then begin LDL RR2,#0FFFF,0FFFF; RL5:=RL0 end else begin SUBL RR2,RRLD L,B ...@2HL->R.HL=subroutine addr. ...note: R.A transmitted thru to routine P.JPHL; CP A; RET ...call subroutine; Z=1; return FILCML: ...fill cmd. line buffer, at same time printing out on cmd. line ...go to routine according to 1st char. (R.DE p# fer if B.LOGUN<>SWCON then begin ...chk if getting from file or console ^DATA2 if @DE=0A then INC DE ...skip linefeeds $$$ R.HL-R.DE; CALL Z,CHKRD ...if at 1st spot in high buffer, call CHKRD @DE=EOF; JP Z,FILDUN ...check if at EOF (RIO) .) ------------------------------------------------------------------------------ Activate/Deactivate Device (System Call 2) ------------------------------------------------------------------------------ (Devices must be able to handle OPEN, CLOSE, RE system calls of value >=080 (if odd, then none). ----------------------------------------------------------------------------- Change Buffer Pool Location (System Call 016) ----------------------------------------------------------------------------- E to console, currently CR's are echoed as CR/LF and LF's are ignored. Devices may also be opened and closed, although this is not usually necessary since logical units 0, 1, and 2 are always pre-opened when a program is started up, usuall---------------------------------------------------------- Closes all open files and does system reentry, restoring default standard i-o definitions. May be called to exit a program without restoring original stack pointer and segmentation mode. This ca R.A=CPMEOF; JP Z,FILDUN ...check if at EOF (CPM) $$$ if R.HL+R.DE-R.DE<=zero then begin ...chk if DE in hi or low buffer LD BC,RECL; R.HL+R.BC->R.BC ...in high buffer PUSH DE; ^DATA2-R.BC; EX DE,HL; POP HL PUSH DE; LDIR; POP DE AD, and WRITE as described above under the General I-O System Call (except OPEN is passed the logical unit number). Exact registers passed at present slightly different: i.e., RR2=addr, R13=length, RL1=command, RH1=logical unit.) Call with registers set  Change location in Z8000 memory of system buffer pool (used with the Request Memory and Release Memory System Calls above, as well as for system i-o functions). The change takes effect upon the next system restart (either by being started up by the Z80 oy set to the console. To open a device, give its name which must be a name the system knows about. (The name of the console is "CON".) Example -- The following sequence will open a file, read it into a buffer, and close the file: LDL RR4,#0FFFll doesn't return. ------------------------------------------------------------------------------ Restart (System Call 0E) ------------------------------------------------------------------------------ Closes all open files, shuts off timer, and does ...move remaining portion of high buffer to same rel. pos. in low W.RCADR2->W.RCADR1; B.RCAD2H->B.RCAD1H ...move record address ... GETFIL() ...fill high buffer, returning immediately RDFIL2() ...$$$ end else begin ...in low buffer as follows: RL0: =0FF if want to deactivate device; anything else if activate RR2: =entry address of device driver RR4: =pointer to DEFT 'DEVICE_NAME' or 'DEVICE_NAME'+0 (device name limited to <=11 characters) If R2 or R4=0FFFF, segment of cr by the Restart System Call). Call with registers set as follows: RR2: =address of new buffer pool location R5: =size of new buffer pool, or, if =0, says want location and size of current buffer pool returned instead Actually, the low address andF,FILNAM ...FILNAM = address where have drive/filename R1:=0; RH0:=0; RL0:=0; SC 0 ...open for input LDL RR2,#0FFFF,BUFF R1:=BUFLEN; RL0:=2; SC 0 ...read max. of BUFLEN bytes into BUFF R1:=0; RL0:=1; SC 0 ...close Further note: The library i-o system restart, simulating startup from Z80. (This includes reinitializing a number of things.) This call doesn't return. ------------------------------------------------------------------------------ Quit (System Call 0F) ----------------------- R.HL->R.BC; R.DE->R.HL 0D->R.A; CPIR ...check if CR before end of buffer CALL NZ,CHKRD ...if no CR, wait for high buffer to be full end end else begin GETCNS: ...reads in a line from $CON, 1st char.->R.DE LD A,'-' Getcon: PROC .aller will be used. Returns: RL0=080 if succeed; =0C0 if not found/no room. ------------------------------------------------------------------------------ Seek (System Call 5) ------------------------------------------------------------------------ high address of the new buffer pool area will be modified to go on mod-16 boundaries within the region specified by RR2 and R5; also, if the specified region sits over top of part of the system, the low address will be moved up so it doesn't. In addition functions described below (System Calls 040-047) may be used instead of this system call and are generally easier to use. I-O Completion Codes: (bit 6 set implies an error) 0: no character ready on console read with request length 0 080: ------------------------------------------------------- Return control to Z80, first closing files and shutting off timer. Then go to either bootstrap in prom or infinite loop to await reactivation by Z80. If called with RL0=0, go to bootstrap to await O - (System Call 0) ------------------------------------------------------------------------- Call with registers set as follows: RL0: =command 0=OPEN 1=CLOSE 2=READ 3=WRITE RH0: =open type if OPEN 0=input (i.e. file must exist) 1=output ------ This call sets the read/write pointer (position for next read or write) for a file. Call with registers set as follows: RL3: =logical unit number of file (as returned from OPEN) RR4: =position or relative position in file (depending on R1) t, it is required that the buffer pool be of a certain minimum size, around 1K bytes. Returns: RR2=address of new buffer pool (current one if initial R5=0) or R3=-1 if specified and (possibly) adjusted region too small R5 =size of new buffer poolsuccessful operation 0C0: general (unspecified) error 0C1: invalid request 0C2: device not ready 0C7: file not found 0C9: end of file reached before requested length was satisfied 0CB: file not open 0CF: too many files open (maxsystem reboot. If RL0=1, go to infinite loop to await startup interrupt. This call doesn't return. ----------------------------------------------------------------------------- Request Memory (System Call 010) ------------------------------------(i.e. create file) Else it is the logical unit number (returned by OPEN) R1: =length of data to be transferred (may be adjusted; see below) RR2: =pointer to memory where data is to be transferred (if R2=0FFFF, segment of caller will be used) R# o set read/write pointer to R1: if =0, RR4=absolute position in file (in bytes) if =1, RR4=relative offset to be added to current position if =2, RR4=offset relative to end of file Returns: RR2=updated value of read/write pointer or -1 i (current one if initial R5=0) Note that system disk i-o performance will degrade fairly significantly if the buffer pool size is made too small. ----------------------------------------------------------------------------- Library Functions (System Cimum 16 logical units; this also includes those set to the console or other devices) 0D2: wrong file type or format In addition, there may be other codes returned from the drivers or operating system on the Z80. ------------------------------------------------------------------ Request a memory buffer. Call with R3=number of bytes requesting. Returns with RR2 at start of buffer, or R3=-1 if one big enough not available. -----------------------------------------------------------------R4: =On OPEN, points to a string containing a DEFT 'FILENAME' (possibly qualified with the drive number); else not used (if R4=0FFFF, segment of caller will be used) Notes: String may also be in form 'string'+0 DEFT 'string' means a length byte (f error (logical unit not open; RL5=code) ------------------------------------------------------------------------------ File Statistics (System Call 7) ------------------------------------------------------------------------------ Get filalls 040-058) ----------------------------------------------------------------------------- SC 040 = OPEN: On entry: R3=pointer to DEFT 'FILENAME' (i.e. length byte first) or 'FILENAME'+0 (currently assumes in caller's segment), R5=open type ---------------------------------------------------- Set Periodic Interrupts - (System Call 1) ----------------------------------------------------------------------------- Can vary rate of periodic interrupts of Z8000 and in addition set up for a spec------------ Release Memory (System Call 011) ----------------------------------------------------------------------------- Release a memory buffer. Call with RR2 pointing to start of buffer to be released (as returned from Request Memory system cnot counting itself) comes first On return: RL0: =a completion code (=080 if successful, bit 6 set =>error (see list of error codes below)) RH0: after OPEN, =logical unit number to use for subsequent operations R1: on READ or WRITE, =length reade statistics of an open file, currently: file type=regular file/device file length Call with registers set as follows: RL3: =logical unit number of file (as returned from OPEN) RR4: =address of where to put the following 6-byte structure (if R4=(0=file must exist, 1=create file) Returns: R3=logical unit number for subsequent calls; if error, R3=-1, RL5=error code Preserves registers>=R6. SC 041 = CLOSE: On entry: R3=logical unit Returns: R3=0 if successful, else R3=-1, RL5=error code ified routine to be called on every interrupt. Call with registers set as follows: RL0 =1 to 5 - set rate of periodic interrupts to approximately default*(2**n-1) where n=RL0 RL0 =0 - set rate of periodic interrupts to default and disable caall). ----------------------------------------------------------------------------- Read Break Routine (System Call 012) ----------------------------------------------------------------------------- If R5=0, returns address of current break-handle or written (may be less than requested amount if end-of-file reached, disk full, error, etc; can also be different for console read, as noted below) Registers >=R6 are preserved. Notes: Special Cases on READ from console: if 0FFFF, segment of caller is used): word FTYPE ...0=file, 1=device long FLEN ...file length in bytes Returns: R3=0 if all okay or -1 if error (logical unit not open; RL5=code) --------------------------------------------------------------------Preserves registers>=R6. SC 042 = READ: On entry: R3=logical unit, RR4=data transfer address (if R4=0FFFF, segment of caller is used (currently also if called from nonsegmented mode)), R1=transfer length Returns: R3=length read; if end-of-file,lls to interrupt routine RR2 =address of interrupt routine (if R2=0FFFF, caller's segment used) if R3 is odd, then no interrupt routine is to be called Registers >=R6 are preserved. The interrupt routine should be written in segmented mode, preservr in RR2 (will be odd if system is taking breaks). If R5=4, returns address of current handler of system calls of value >=080 (odd if none). ----------------------------------------------------------------------------- Write Break Routine (System requested length=0, console status will be tested. If a character is ready, RL0 will be set to 080 and the character will be read in (note that you must have a space for it); otherwise, RL0 will be set to 0. if requested length=1, 1 character w---------- Get Interrupt Count (System Call 9) ------------------------------------------------------------------------------ Returns RR2=count of periodic interrupts which have occurred since system startup. This value can be used for timing (pos R3=0; if error, R3=-1, RL5=error code Preserves registers>=R6. Also note special cases when reading from console: if request length 0, a character is returned if and only if one ready (the returned length indicates whether one was or not); e all registers, and end with an IRET. (The default rate for periodic interrupts is on the order of 50/second but depends on the particular hardware and system software. It may also vary somewhat during i-o. See the Get Interrupt Count system call belowCall 013) ----------------------------------------------------------------------------- If R5=0, the address in RR2 will be made the destination for breaks (if odd, system will again handle breaks). If R5=4, the address in RR2 will be made the handler ofill be returned as soon as available. if requested length n>1, a maximum of n characters or up to a carriage return will be returned, with input editing done on the line entered; also a control-D will terminate input at any point. On WRITsibly with calibration) or random numbers. (Note that the exact interval of periodic interrupts may vary somewhat during i-o.) ------------------------------------------------------------------------------ Exit (System Call 0D) --------------------$ K() ...send bucket POPL RR6; RET DI_: PROC ..."disable" NMI RESB DI_FLG,0; RET EI_: PROC ..."enable" NMI; preserve Z-flag TSETB DI_FLG; RET MI SC (SC_INTR & 0FF); RET ...if was NMI, do it DIS_BRK: PROC ..."disable" NMI break RESB DB_FLG,0; REet. RL3=char, RL0=OK repeat CONINIF() until RL0=OK; RET STOPCH: BYTE CTLS ...print toggle char. EOTCH: BYTE CTLD ...ends line input from console CON: ...console i-o handler ...R1=orig R0, R13=orig R1 (len), RR2=xfadr, other regs free ...ret. RL0=comZPWR; R3->R0 ...R0=FSTBLK POPL RR4 ...XFADR PUSH R13 ...requested len. R13:=0; R6:=R0 ...TOTLEN:=0; I:=FSTBLK repeat PUSH R1; PUSHL RR4; PUSH R1 ...R1=LSTBLK B_READ(R6;RL5:=RH7) ...rets. RR8=^bufhdr (buffer has data); RL0=CC if BITB RL0,sters. SC 045 = PUTCHAR: On entry: RL3=a character which will be printed on standard output Preserves all registers. SC 046 & 047 = PRINTF: Formatted printing which preserves all registers. (Used by "Y") Example: printf("string",arg1,arg2,etc.) T: WRITEF() OPN: OPENF() CLS: CLOSEF() else INVALID() end RET FILIO_W: ...enter regs set, RR10=^LUvec, do FILIO & wait for comp. REQBUKW() ...get bucket after waiting for prev. i-o to finish N_IOINPRG:+1 RESB @RR10,COMPB SNDFILIO() repeat uT EN_BRK: PROC ..."enable" NMI break; preserve Z-flag TSETB DB_FLG; RET MI SC (SC_BKR & 0FF); RET ...if was NMI break, do it ...DEVICE DRIVERS: PUTBUFSCR: ...put PUTBUF->screen; 0->PUTBUFCNT save R6..R13 R5:=PUTBUFCNT->R13 LDAR RR2,PUTBUF; RL1:=p. code; on read/write: R13=no. bytes transferred if RL0:=RL1&0F=WRT then begin ...WRITE_CON: ... repeat until PRTSW=0; ...chk if printing stopped WRCON(R5:=R13) RL0:=OK; RET end if RL0=RD then begin ...READ_CON: LDL RR6,RR2 6 not zero then begin ...if err POP R3; POPL RR2; POP R3; JR RDFX end POP R1 ...LSTBLK if R6=R1 then R1:=R12 else R1:=BLKSZ ...if I=LSTBLK then TOP:=LSTBLKTOP else TOP:=BLKSZ R3:=R6; R2:=0; SLLL RR2,#BLKSZPWR LDL RR4,RR10[FPSREQ] ...puts out string; in string: "\n"=CR, "\t"=tab, ...if "%" in string, next character says format for next argument in ... list of arguments (use "%%" for "%"): "%w": put out word in hex "%b": put out byte in hex "%c": put out ascii character ntil BITB @RR10,COMPB not zero; ...or could chk N_IOINPRG=0 & don't need COMPB RET CKERRCD: ...if ERRB & ERRCD say err, ret. Z=0, RL0=code; else Z=1, RL0=OK RL0:=OK if BITB @RR10,ERRB not zero then RL0:=@RR10[ERRCD] RET OPENF: ...open file with LUWRT CALL SCREEN PUTBUFCNT:=0 restore R6..R13 RET PUTBUFBUK: ...put PUTBUF in bucket, 0->PUTBUFCNT if R5:=PUTBUFCNT=0 then PUTZ() else begin R4:=DATA RL0:=CONWRCD; OUTB @R4,RL0 OUTB @R4,RL5 LDAR RR2,PUTBUF OTIRB @R4,@RR2,R5 PUTBUFCN case R13: of 0: begin RL3:=CONINIF() if RL0=OK then begin RL3:->@RR6; R13:=1 end end 1: RL3:=CONIN1()->@RR6 ...get single char (no echo) else begin R13:=GETLINE(R5:=R13) ...get line to @RR2 (R5=max len) ... rets. R3=l; SUBL RR4,RR2 R0:=R5 ...BOTTOM:=FPSREQ-I*BLKSZ R1:-R0; R13:+R1 ...LEN=TOP-BOTTOM; TOTLEN:+LEN LDL RR2,RR10[FPSREQ]; R5:=R1; R4:=0 ADDL RR2,RR4; LDL RR10[FPSREQ],RR2 ...FPSREQ:+LEN R3:=R6; R5:=@RR8[BLKNO]; R3:=(R3-R5)*BLKSZ; R0:+R3  "%s": put out ascii string (DEFT pointed to) "%d": put out word in decimal "%f": put out floating-point number (uses 2 arguments=high and low words of 32-bit floating-point number) (above small letters may be capital) Specific example: pr RH1; ret. RL0=CC PUSH R2; RL2:=RH0 FILIO_W() POP R2 CKERRCD() ...if err, errcd->RL0, else OK->RL0 RET CLOSEF: ...close file with LU RH1; ret. RL0=CC FNDLU_() ...RR10 at LUvec RH7:=RH1 ...LU save R1..R3,R13 NXTBUFI() while NXTBUF() zero do beT:=0 end RET WRCON: ...enter with RR2=xfadr, R5=no. bytes to write to console ...currently ignores LFs save R6..R11 R7:=R5; LDL RR10,RR2 while R7<>0 do begin repeat until PRTSW=0; DIS_BRK() PUTBFLOCK:=1 ...DI_() LDAR RR8,PUTBUF R6:=Pen. (to CR or EOT or max len) RL0:=OK end end RET end ...OPEN,CLOSE_CON: if RL0=OPN then begin INITCON() if SCRFLG<>0 then CALL SCREEN RL0:=OK; RET end if RL0=CLS then begin repeat until PUTBUFCNT=0; INITCON() RL0:=O ...OFFSET:=(I-BLKNO)*BLKSZ+BOTTOM POPL RR4 ...XFADR MOVDTA_(LDL RR2,RR8[BUFADR_]; R3:+R0) ...move R1 bytes from @RR2 to @RR4; RR4 updated POP R1 until R6:+1>R1; ...until I:+1>LSTBLK RL0:=OK RDFX~ POP R12 ...requested len. if R12>R13 intf("2+2=%w\n",2+2) Note: floating-point format=ffffffee where ffffff=fraction part with high-order bit=sign (1=neg) and ee=exponent (excess 128); 0=all 0 Code generated for printf: SC 046 ...saves registers expression to load arg1 PUSH arggin if RH7=@RR8[LU_] then begin ...find buffers belonging to LU FINBUF() ...release buffer, first writing out if necessary if BITB RL0,6 not zero and BITB @RR10,ERRB zero then begin ...if err (if >1st, keep 1st error code) RL0:->@RRUTBUFCNT; R9:+R6 R1:=0 ...will be set=1 if buffer full or CR repeat if RL0:=@RR10'<>0A then begin RL0:->@RR8'; R6:+1 end if RL0=0D then begin B.0A->@RR8'; R6:+1; R1:=1 end if R6>=PUTBUFSZ-1 then R1:=1 until R7:-1 zero oK; RET end RL0:=INVLDERR; RET ...invalid INITCON: PUTBUFCNT:=0; PUTBFLOCK:=0 PRTSW:=0; ^KBUF->NXTIN->NXTOUT; RET GETLINE: ...get line of input to @RR2, R5=max len., echoing, backspacing, etc ...ret. R3=len. (to CR or EOT or max len) register COL:RLand BITB RL0,6 zero then RL0:=EOFERR RET MOVDTA_: ...move R1 bytes from @RR2 to @RR4; update RR2,RR4 R0:=R1|R3|R5 if BIT R0,0 zero then begin SRL R1; LDIR @RR4,@RR2,R1 end else LDIRB @RR4,@RR2,R1 RET B_READ: ...enter with R3=block no., RL5=LU, RR10=1 expression to load arg2 PUSH arg2 ...etc PUSH size of above pushes SC 047 ...does printing and restores registers DEFT "string" ...at return address of SC 047 ............................................................................... 10[ERRCD]; SETB @RR10,ERRB end end end restore R1..R3,R13 FILIO_W() CKERRCD() ...if err, errcd->RL0, else OK->RL0 RET READF: ...enter R1=orig R0=LU,cmd, R13=orig R1=xflen, RR2=xfadr, R4-R12 free R13==0; RL0:=OK; RET Z FNDLU_() ...get RR10r R1<>0; R6:->PUTBUFCNT if R1<>0 then begin if SCRFLG=0 then begin PUTBFLOCK:=0 EN_BRK() REQBUKW2() PUTBUFBUK() SNDBUK() JR WRCONX end else PUTBUFSCR() end PUTBFLOCK:=0 ...EI_() EN_BRK() end WRCONX~ restore R6.$ 6, PRVCOL:RH6, BUFPTRL:RR8, BUFPTR:R9 register BUFBEG:R12, BUFEND:R13 ... save R6..R13 LDL BUFPTRL,RR2; BUFBEG:=R3 BUFEND:=R3+R5-1 COL:=0 GETLLP~ repeat RL3:=CONIN1() ...get char. RL3==EOTCH; JR Z,GETLX if RL3=8 then begin ...if backspace ^filetab ...ret. RR8=^bufhdr with data (unless error); RL0=CC GETBLK() ...pass block no., LU; rets. RR8=^bufhdr if RL0=0 then begin ...if data not in buffer (& no error) SETXFCNT() SET @RR8,RDB; FILIO_() RL0:=@RR8[CCD] if BITB RL0,6 not ze PUTBUFSZ ...value(R3:=0100;if R3>BUCKL-2 then R3:=BUCKL-2) ...WRCON: ...enter with RR2=xfadr, R5=no. bytes to write to console ... ...currently ignores LFs ... PUSH R6 ... R1:=R5+1; LDL RR4,RR2; R6:=0 ... while R1:-1 not zero do begin ... R6:+1 ... i=^LUvec if BITB @RR10,RDAFLGB zero then begin ...if no read-ahead prev. done SETB @RR10,RDAFLGB ...only try once save R1..R3,R13 RDAHD_() restore R1..R3,R13 end READF2(); RET RDAHD_: ...do read-ahead; enter RR10=^LUvec, RH1=LU LDL RR2,RR.R11 RET ...WRCON: ...enter with RR2=xfadr, R5=no. bytes to write to console ... ...currently ignores LFs ... PUSH R6; PUSHL RR8 ... R1:=R5; LDL RR4,RR2 ... while R1<>0 do begin ... repeat until PUTBUFCNT=0; ... LDAR RR8,PUTBUF; R6:=0 ... DI_() ... COL==0; JR Z,GETLLP R11:=BUFBEG; R10:=R8 ...RR10=BUFPTRA COL:=0 repeat PRVCOL:=COL UPDCOL(RL3:=@RR10) ...update COL by size of char expanded until R11:+1=BUFPTR; ...get PRVCOL=col. of prev. char. repeat ECHO(RL3:=8); EC :_!$=(x 0x ͋ >Z x ͋ >Z O0#!!z w#w#w(>V#N#~$#~+: ~@##> ~. #> >  >Gx( ~ #x (@8Z80(.`8}8&($f RL0:=@RR4'=0D then R6:+1 ... if RL0=0A then R6:-1 ... end ... while R6>MAXCNT do begin ... R5:=MAXCNT-1 ... R6:-R5 ... WRCON2() ... R6:+R5 ...R5=-1 if extra LF done, else 0 ... end ... if R6<>0 then WRCON2(R5:=R6) ... POP R6; RET ...WRCON2: .10[FLEN]; LDL RR4,#0E000 if CPL RR2,RR4 >zero then LDL RR2,RR4 PUSH R3 R3:+(BLKSZ-1)&(0-BLKSZ) ...round up to mult. of BLKSZ ADDBUF(R3; RL5:=RH1) ...add buffer of size R3 POP R3 if zero then begin ...if got buffer R3->@RR8[XFCNT]; 0->@RR8[BLKNO repeat ... if RL0:=@RR4'<>0A then begin RL0:->@RR8'; R6:+1 end ... if RL0=0D then begin B.0A->@RR8'; R6:+1 end ... until R1:-1 zero or RL0=0D or R6>=PUTBUFSZ-1; ... R6:->PUTBUFCNT ... EI_() ... end ... POPL RR8; POP R6; RET ...MAXCNT~ EQUHO(RL3:=' '); ECHO(RL3:=8) until COL=PRVCOL; BUFPTR:-1 RL3:=8 end else if BUFPTR@BUFPTRL'; PUSH R3; ECHO(RL3:); POP R3 end until RL3=0D; GETLX~ R3:=BUFPTR-BUFBEG restore R6..R13; RET UPDCOL: ...enter /898(!8)8(+( -(\(^ x ((#!!z OW_}T]Oů)lau!t"w#͞ x( >!͹   ͞ x( >"͹   S)lgx !!GH 4 # (  >>KBo] ..wait till buffer (PUTBUF) has room, then add to buffer ... DI_() ... if R0:=R5+PUTBUFCNT>PUTBUFSZ then begin ... EI_() ... repeat until PUTBUFCNT=0; ... DI_() ... R0:=R5 ... end ... PUSHL RR6 ... LDAR RR6,PUTBUF; R7:+PUTBUFCNT ... R0:->PUTBUFCNT ] SET @RR8,RDB; SET @RR8,RDAB ...mark for rdahd FILIO_() end RET READF2: ...enter RR2=xfadr, R13=xflen, RH1=LU, RR10=LUvec ...do read, xfdta, update fpsreq, ret. RL0=CC, R13=len read ...register LU:RH7, TOTLEN:R13, LSTBLKTOP:R12, FSTBLK:R0, LST if request length 1, 1 character is returned as soon as available; if request a length n>1, a maximum of n characters or up to a carriage return is returned, with input editing being done on the line entered; also a control-D will terminate with RL3=char, update COL (RL6) by size of char when printed if RL3=9 then begin ...if tab repeat COL:+1 until COL&7 zero; end else begin COL:+1 if RL3<020 or RL3=07F then COL:+1 ...if ctl char. end RET ECHO: ...echo char. in RL3 & keep tra>g(ok > k}͈(ɯ21:((Ì *."i!N#T]> wh  ͪ !+~|  DM*` "W ( ! >2( ͧ:*=H ̓,̆> <2+( ͽ *d~#bk̓{8>(O ! ... repeat ... if RL0:=@RR2'<>0A then begin ... RL0:->@RR6'; R5:-1 ... if RL0=0D then begin RH0:=0A->@RR6'; R5:-1 end ... end ... until R5<<=0; ... EI_(); POPL RR6 ... RET CONINIF: ...get 1 byte from cons.->RL3 if one rdy ...ret RL0=OK if so,BLK:R1, ... I:R6, TOP:R1, BOTTOM:R0, LEN:R1, OFFSET:R0 PUSHL RR2; RH7:=RH1 ...RH7=LU LDL RR2,RR10[FPSREQ]; LDL RR4,RR10[FLEN] if CPL RR2,RR4 >=zero then begin POPL RR2; R13:=0; RL0:=EOFERR; RET end R12:=0; ADDL RR2,RR12 if CPL RR2,RR4 >zero then LDLinput at any point (the control-D is not passed on); in any case, the actual number of characters read is returned SC 043 = WRITE: On entry: R3=logical unit, RR4=data transfer address (if R4=0FFFF, segment of caller is used (currently also ck of col. in COL (RL6) if RL3=9 then begin repeat PUT1C(RL3:=' '); COL:+1 until COL&7 zero; RET end COL:+1 if RL3=8 then COL:-2 else if RL3=0D then COL:=0 else if RL3<020 or RL3=07F then begin PUSH R3; PUT1C(RL3:='^'); POP R3 if RL3=07F th! 7 ( !E yK *BR0 !" PYl (E ( ~ +> +R8!R !7 (Wy(KB͖(ͽ `il (W!ͽ bk ` RDMeW!R ! WF   else=NOCHAR ...save regs>R3 DIS_BRK() if R3:=NXTOUT=NXTIN then begin RL3:=0; RL0:=NOCHAR end else begin PUSH R2 R2:=MYSeg RL0:=@RR2 INCKPTR()->NXTOUT RL3:=RL0; RL0:=OK POP R2 end EN_BRK(); RET CONIN1: ...get 1 char from console; r RR2,RR10[FLEN] PUSHL RR2 ...fpos at end of request SUBL RR2,#1; SRLL RR2,#BLKSZPWR; R3->R1 ...R1=LSTBLK SLLL RR2,#BLKSZPWR; POPL RR4 ...RR2=beg last blk, RR4=end of req. SUBL RR4,RR2; R5:->R12 ...R12=LSTBLKTOP LDL RR2,RR10[FPSREQ]; SRLL RR2,#BLKSif called from nonsegmented mode)), R1=transfer length Returns: R3=length written; if error, R3=-1, RL5=error code Preserves registers>=R6. SC 044 = GETCHAR: Returns: R3=next character from standard input (-1 if end-of-file) Preserves other regien RL3:='?'-'@' RL3:+'@' COL:+1 end ... PUT1C: ...put out char. in RL3 to console save R6..R13 PUSH R3 LDL RR2,RR14; R3:+1; R13:=1; RL1:=WRT CON() POP R3 restore R6..R13 RET FILES: ...file i-o handler case RL0:=RL1&0F of RD: READF() WR% ѷRͅ 6 ͽ  6#, 06 #6#K B  w#, 0! [K E!f ͏ HIT KEY TO REENTER:!R !7 (5E*",".R"QU N [,*.R #*".!l (*".! *.~( ˿#".!+~=w*,"([0|(+>2627lS0[0|(+)[0*R( |( +oB_͗!B>E|>2S(*(* ++|(2RS+:R  ( :J!_~!'=(!fz4r͈Omy2RUS=T>~ 2<> 2<2; console); preserves registers note: a carriage return (hex 0D) also goes to the next line LU:=open(^FILENAME,flag,->comp_code) ...^FILENAME=pointer to DEFT 'FILENAME' flag (word): 0=input, 1=output (create) comp_code (byte): 080=ok, else erroULT MOV M,A ;IF -1 RZ ;YES, NO MORE ANI 03H ;MOD 4 MOV M,A CALL GT.BB0 ;TEST IF DELETED CPI 0E5H ;DELETED? XCHG LHLD ARGADR ;MATCH ALL? JRZ ..DLF ;ALLOW TO PASS BIT 7,M JRNZ ..OK ;GO DO IT ;**** CALL GTJGPC ;GET JOBS GROUufhdr (& buffer) @RR8, first writing out if necessary ...ret. BIT RL0,6 set if err, else RL0=OK repeat until BIT @RR8,IOINPRGB zero; RL0:=OK if BIT @RR8,ALLOCB not zero then begin ...otherwise rel'd in int. rtn. if BIT @RR8,DELWRB not zero then B_W( ɯ2*>T !Uw#6 ͈_:J̗:SĪ{!0@:*([0>!5w:6( |4:7O͖S2B+> ##( A  >O0Ax iyMO oOG*2R O  yP8O>[0S0ʹx<26:62:| !2;U*!*4h N 4:J(ͧP(͠ 21:1A YA *T]~ # ͖* ~# >  !V  J͗ͬ}2,ͬ}2>Jo::O  2!5y(&:=(bk#~ ( (> r code LU (word): logical unit to use for subsequent calls read(LU,^BUFFER,LEN,->comp_code) ...LU from open LEN bytes of data to be put at BUFFER write(LU,^BUFFER,LEN,->comp_code) close(LU,->comp_code) Write Statement This is similar to th yP8 O:4G!6~4y27͠:7 !6~=5>P=27͠:J[*Rw>E28!C~By27( (;͠>*2 +6 ͪ=>I!J>R!Q28:J~B ͗*y27͠:8I [2> _*2 ͈_(:PG{( t 2 :8E '~ ( (:8I >RITE() PUSH R0; RELBUF(); POP R0 end RET SETXFCNT: ...calc XFCNT & store @RR8 (bufhdr); RR10=^LUvec LDL RR2,RR10[FLEN] R5:=@RR8[BLKNO]; R4:=0; SLLL RR4,#BLKSZPWR ...RR4=blk fpos (blk no.*BLKSZ) SUBL RR2,RR4 ...RR2=flen-blk fpos R5:=@RR8[NBLKS:4> yOB[2ʹ:625o>26=25*R(S2ʹ :50:5G:62625o xB*B"R#DMx*R#DM"#[*RB0w~G( (#w S=qt!ͬt!Ͳ~ !  yO0y    ( !5  (y > !: 2 ͌ͧ͘!!H SCREEN EDITOR - 11/22/82 Gr͚z /IMAGE E.COM !{͚z !+{Wrx*?j" j:Aj2"jky*?j"#j:Aj[NBLKS] R3:-R3->@RR8[NBLKSDUN] ...Z=1 end JR ADDBX end until R9:+BHLEN=^BUFS+NBUFS*BHLEN; RESFLG Z ADDBX~ EN_BRK() POPL RR6; RET RELBUF: ...release buffer & bufhdr @RR8 DIS_BRK() if R9<>^SPBUFHDR then M_REL(LDL RR2,RR8[BUFADR_]:9(w:8R( ~ # ~ ( #e29͗>*KBOB0 DM!96x 4~6T] x((F~ :8ET]R ~#~( (x(bk#   ȯ!6:7O7+~ :8E:6="2ʹ!6:7 5y27:8R ͠[2~25Ͳ]; R4:=0; SLLL RR4,#BLKSZPWR ...RR4=NBLKS*BLKSZ if CPL RR2,RR4 @RR8[XFCNT] RET ADDBUF: ...add buffer of size R3, LU RL5; ^bufhdr->RR8; ret. Z=1 iff succeed ...init. BUFADR,LU,NBLKS,NBLK#(=(G #=:7

P=27͠ɯ27͠:4!6 N:QB[0:5!62T!T~(5!45ͧ> 25U|~ͪ4͠:6= [*0R!=!6~=5͠ɯ27<26͠ɯ27:426͠:7O*B~!02HK*BDM~!N~ ({: N~ :D*( :G(~#(:H/o8%#R0w!"@*B~(G#~:EN S2!"@2D>2G2F~!G~(5:E* or(>2I*@+"@|#(~'RDMe:F:E* !5:I ) ...assumed R8=MYSeg CLR @RR8 EN_BRK(); RET FILIO_: ...enter bufhdr @RR8; send to Z80 ...set up for SYSIO: PUSH R13 if BIT @RR8,RDB not zero then begin RL1:=RD if BIT @RR8,RDAB not zero then RL1:=RDAHD|080 end else begin RL1:=WRT if BÌ!9~5m:7O{ O  :6GyP8:6!6F4!7Nw#"2+{ xFs!5w 4(!B0>@ͭͲx :8RH>!: ( >P0WzyFͧ>  ͠1ʚ2ʿ3[[)27OB[2ʹy27o> +SDUN PUSHL RR6; R6:=R3; RH7:=RL5 LDAR RR8,BUFS DIS_BRK() repeat if BIT @RR8,ALLOCB zero then begin if M_REQ(R3) zero then begin LD @RR8,#2**ALLOCB; LDL RR8[BUFADR_],RR2; RH7:->@RR8[LU_] R3:=R6; R2:=0; SRLL RR2,#BLKSZPWR; R3:->@RR8 SCs 048-058 are floating point functions: Argument(s) are in RR2 and RR4 (if 2 arguments), results are returned in RR2. Registers R6 and above are preserved. Floating-point format=ffffffee where ffffff=fraction part with high-order bit=sign (1=neg5NN :Fhͪ:J=* *K R* #oe R8 *0R8 "0ͪSOd ͖"M! !J4ѯ--From here: --To here^ :J* ͖"K! !J4:J=**KR*e!6~04ͪͭBSO2!J~ *5BT @RR8,ASYNCB not zero then SETB RL1,7 end RH1:=@RR8[LU_]; LDL RR2,RR8[BUFADR_]; R13:=@RR8[XFCNT] R5:=@RR8[BLKNO]; R4:=0; SLLL RR4,#BLKSZPWR ...RR4=fpsreq REQBUKW() ...wait for prev. i-o to finish, then get bucket SET @RR8,IOINPRGB; N_IOINPRG:+1 if!6~0(4:J*B**e::25H*!~G># 6 S2(y27͠Oʥ:J*t*!Ͳ*# "BͲ &n >N2E*(N !ͬ h!2E"@!Dw: wB(| !<zɯ2F2I<25 Y DOCUMENTATION (Part 2) SPECIAL INSTRUCTIONS Built-in "C" like I/O functions: printf("string",arg1,arg2,etc.) ... formatted printing which preserves all registers ... puts out string; in string: "\n"=CR (new line), "\t"=tab, if "%" ) and ee=exponent (excess 128); 0=all 0 SC 048 = Floating ADD: RR2:=RR2+RR4 SC 049 = Floating SUBTRACT: RR2:=RR2-RR4 SC 04A = Floating MULTIPLY: RR2:=RR2+RR4 SC 04B = Floating DIVIDE: RR2:=RR2*RR4 SC 04C = Floating COMPARE: if RR22G2F~!G~(5:E* or(>2I*@+"@|#(~'RDMe:F:E* !5:I in string, next character says format for next argument in list of arguments (use "%%" for "%"): "%w": put out word in hex "%b": put out byte in hex "%c": put out ascii character "%s": put out ascii string (DEFT pointed to) "%d": put out wof RR2=RR4, RR2:=0 if RR2>RR4, RR2:=1 SC 04D = FLOAT: Entered with RR2=integer; return RR2=equivalent floating-point number. SC 04E = FIX: Entered with RR2=floating-point number; return RR2=integer (truncated). SC 04F = SQUARE ROOT: RR2:=Sqrt(RR2) SR8*K "K*M "M*@ "@*@x|27[M:J= *K 18'40#1O!K ^#V*R8*R8dE ':J !͂ ~ S227:526ͪ*E :J(T B lʹ:6262527GOz( ~(> !BDMeͭ:J(͂ Bn repeat until BIT @RR8,IOINPRGB zero; POP R13; RET WRITEF: ...enter R1=orig R0=LU,cmd, R13=orig R1=xflen, RR2=xfadr, R4-R12 free ...do `write', update fpsreq, ret. RL0=CC, R13=no. bytes written R13==0; RL0:=OK; RET Z FNDLU_() ...RR10=^LUvec if CKER5NN :Fhͪ:J=* *K R* #oe R8 *0R8 "0ͪSOd ͖"M! !J4ѯ--From here: --To here^ :J* ͖"K! !J4:J=**KR*e!6~04ͪͭBSO2!J~ *5Brd in decimal "%f": put out floating-point number (uses 2 arguments=high and low words of 32-bit floating-point number) (above small letters may be capital) ... arg1,arg2,etc are arithmetic expressions Examples: printf("2+2=%b\n",B.2+2) C 050 = Ascii string-to-float conversion: Enter with RR2 pointing to ascii string (either in DEFT (length byte first) form or in form "string"+0), e.g. "2.36E-4" (if R2=0FFFF, uses segment of caller) Returns RR2=number in floating-point form SC 05ro then begin PUSH R0; RELBUF(); POP R0 end end RET GETBLK: ...enter with R3=block no., RL5=LU ...ret. RR8=^bufhdr of block; ... RL0=CC: 80=good, 0=not in memory, bit 6 set=err PUSHL RR6; R6:=R3; RH7:=RL5 NXTBUFI() while NXTBUF() zero do begin ...RCD() not zero then begin R13:=0; RET end ...if prev. err, Z=0, code->RL0 PUSHL RR2; RH7:=RH1 LDL RR2,RR10[FPSREQ]; R12:=0; ADDL RR2,RR12 PUSHL RR2 ...fpos at end of request SUBL RR2,#1; SRLL RR2,#BLKSZPWR; R3->R1 ...R1=LSTBLK SLLL RR2,#BLKSZPWR;I *B([KSM!J5(5I *MB"M[K [M͗ͪ*0R8(B"0*2R8B0bk"2 e̓t!#w  (;( q:J*͂ ' ̪'"@lS2*MBDM*KR0*MR8 :J=(*͖*K printf("RR2=%w%w",R2:,R3) Notes: Floating-point format=ffffffee where ffffff=fraction part with high-order bit=sign (1=neg) and ee=exponent (excess 128); 0=all 0. Registers are not preserved between the evaluation of consecutive argu1 = Float-to-ascii string conversion: Enter with RR2=floating-point number, RR4 pointing to buffer to put string (necessary length=14) (R4=0FFFF implies use caller's segment) Puts ascii string representing number in buffer in form "string"+0 SC 05get next buffer of device if BIT @RR8,GDDTAB not zero and RH7=@RR8[LU_] and R1:=R6-@RR8[BLKNO] >=zero and R1<@RR8[NBLKS] then begin repeat RL0:=@RR8[CCD] until R1<@RR8[NBLKSDUN] or BIT @RR8,IOINPRGB zero and BITB RL0,6 not zero; if R1<@RR POPL RR4 ...RR2=beg last blk, RR4=end of req. SUBL RR4,RR2; R5:->R0 ...R0=LSTBLKTOP LDL RR2,RR10[FPSREQ]; SRLL RR2,#BLKSZPWR ...R3=FSTBLK R6:=R3; R13:=0 ...I=FSTBLK; TOTLEN:=0 POPL RR2 ...XFADR WRTLUP~ ...repeat PUSHL RR0; PUSHL RR2 R12:=BLR8*K "K*M "M*@ "@*@x|27[M:J= *K 18'40#1O!K ^#V*R8*R8dE ':J !͂ ~ S227:526ͪ*E :J(T B lʹ:6262527GOz( ~(> !BDMeͭ:J(͂ Bments. Code generated for printf: SC 046 ...saves registers expression to load arg1 PUSH arg1 expression to load arg2 PUSH arg2 ...etc PUSH size of above pushes SC 047 ...does printing and restores registers DEFT "string" ...at retur2 = SIN: RR2:=sin(RR2) SC 053 = COS: RR2:=cos(RR2) SC 054 = TAN: RR2:=tan(RR2) SC 055 = ARCTAN: RR2:=arctan(RR2) SC 056 = LOG: RR2:=log(RR2) (base e) SC 057 = EXP: RR2:=exp(RR2) (e raised to a power) SC 058 = POWER: RR2:=RR2**RR4 (RR2 raise8[NBLKSDUN] then RL0:=OK JR GETBLKX end end ADDBUF(R3:=BLKSZ; RL5:=RH7) ...allocate a buffer and bufhdr for block if not zero then begin ...if no bufhdr or buffer avail. LDAR RR8,SPBUFHDR ...use special buff if BIT @RR8,ALLOCB not zero theKSZ if R6=R1 then R12:=R0 ...if I=LSTBLK then TOP:=LSTBLKTOP else TOP:=BLKSZ R3:=R6; R2:=0; SLLL RR2,#BLKSZPWR LDL RR4,RR10[FPSREQ]; SUBL RR4,RR2 ...BOTTOM:=FPSREQ-I*BLKSZ ...here: R5=BOTTOM; R0=LSTBLKTOP; R12=TOP; R1=LSTBLK; R13=TOTL' (KK*MT]BDMe*0R0"[2*MR0 B"2 *KR0"23[MR8B"0*2B"2*K"0DM*2R0C2 "2( (,l[0|( (+B(> ~( oɯͧ rͧAn address of SC 047 getchar() ... returns next character from standard input (usually console) in R3 (preserves other registers); return value of -1 implies end-of-file. putchar(arg) ... puts out character in RL3 to standard output (usually d to the power RR4) p(RR2) (e raised to a power) SC 058 = POWER: RR2:=RR2**RR4 (RR2 raised to the power RR4) = LOG: RR2:=log(RR2) (base e) SC 057 = EXP: RR2:=exp(RR2) (e raised to a power) SC 058 = POWER: RR2:=RR2**RR4 (RR2 raisen begin FINBUF() ...write out buffer if necessary BITB RL0,6; JR NZ,GETBLKX ...if err end LD @RR8,#2**ALLOCB RH7:->@RR8[LU_]; 1->@RR8[NBLKS]; 0->@RR8[NBLKSDUN] end R6:->@RR8[BLKNO] RL0:=0 GETBLKX~ POPL RR6; RET FINBUF: ...release b& EN PUSH R5 if R5=0 then begin ...if BOTTOM=0 R3:=R6; R2:=0; SLLL RR2,#BLKSZPWR; LDL RR4,RR10[FLEN] if CPL RR2,RR4 zero and R12=BLKSZ then begin ...if BOTTOM=eof and TOP=BLKSZ then: R3:=R1-R6; if R0=BLKSZ then R3:+1 ...R3:=Lthere may be multiple statements on each line separated by ";"s, and that comments consist of three dots ("...") followed by the body of the comment and running to the end of the line. Y runs under the ZOOMSYS operating system. USING Y AND COMMANDS To ionally preceded by "n." where n is a segment number) or constant expressions. If the entry point is included, a header is prepended to the file which enables it to be loaded and run by the system; otherwise just a straight memory image is made. Adding "TBUFSEG.0 ...default beg. buffer MBUFSZ: EQU 0FE00 ...must be multiple of 16 ...& have room for 2 words after ...1st byte of BUFHDR) repeat R9:+BHLEN R9==^BUFS+(NBUFS+1)*BHLEN-1; RET UGT until BIT @RR8,ALLOCB not zero; R0==R0; RET ROM: ADDR $  ions, debugging, etc.) The symbol table can be altered with the following commands: /CLEAR clears symbol table /ZAP list of symbol names e.g. /ZAP SYM1 SYM2 effectively deletes (zaps) those symbols from table (although they still take up space in memSTBLK-I; if LSTBLKTOP=BLKSZ then R3:+1 R3:*BLKSZ; PUSH R3 ADDBUF(R3; RL5:=RH7) ...try to get buffer for all rem. whole blks POP R3; JR NZ,WRFT1 R12:=R3 ...TOP:=(LSTBLK-I(+1))*BLKSZ R6:->@RR8[BLKNO]; RL0:=OK end elseinvoke Y, type Y or Y filename In the first case the system will respond with the prompt "-" awaiting the first line of input from the console. In the second case, an automatic /DO filename is generated and executed first (see below). The following =N" simply marks the file as being able to run in any Z8000 segment (the compiler does not check this); in this case, the system will use the segment number of the entry point when loading the file, rather than that in the load-address information. If the1󪀞ҹU_N x ::p q== p == >> <<dAPPCaLq--Lq>>_p _g__N xp ]]_e q((_tԞ߾ ۽؈W0C01_؆opw ؈_eory) /ZAPALL [mask] zaps all symbols not masked out (see below) /PACK [mask] packs symbol table into minimum space saving only global symbols (not zapped or masked out) and undefined symbols /PACK ALL [mask] packs symbol table saving all symbols not  begin WRFT1~ if R12=BLKSZ or begin R3:=R6; R2:=0; SLLL RR2,#BLKSZPWR; R5:=R12; R4:=0; ADDL RR2,RR4 LDL RR4,RR10[FLEN]; CPL RR2,RR4 end >=zero then GETBLK(R3:=R6; RL5:=RH7) else B_READ(R3:=R6; RL5:=RH7) ...if TOP=BLKSZ or TOP>=eis a list of commands which may either be entered from the con- sole or be in a file (either a program or a DO-file). Note that they all must start with either a "/" (as shown) or a "*", and that this must be the first character on a line. ("/" and "*" a entry point is set to an odd number, the system will not start up the program after loading it. The region_name would mainly be used in the case where code is assembled in one segment but is to be executed in another (see below under 'Assembly Language aؓ|Ȁؖ{ بW0C04_ئ؏س҅_p _e_gX_rE x ++ -- || &&.XOR.<->М x ** // %%_rL_e_Z,Аӣ^D Ğ_r  Tzapped or masked out. (Use after ZAPs to actually reclaim space in symbol table.) Note: undefined symbols cannot be zapped or eliminated through packing. The form and meaning of the mask allowed in some of the commands above is as follows (where the braof then GETBLK() else B_READ() end end else B_READ(R3:=R6; RL5:=RH7) if BITB RL0,6 not zero then begin ...if error POP R3; POPL RR2; POPL RR2; JR WRFX end POP R0 ...BOTTOM R1:=R12-R0 ...LEN:=TOP-BOTTOM LDL RR2,RR10[FPSREQ]; Rre generally interchangeable except during conditional assembly, described below.): To assemble a file (and/or execute commands from it), enter /DO source-file name (The file may also be an object file, provided it is of the appropriate format and a specnd Symbol Types' in connection with the "ADDR" pseudo-op). The region_name would normally be the symbol (of 'ADDR' type) which defines the run- and compile-segments of the region. If this is not present, then if addr1 includes a segment number (this incl 3 aP _e_raP _r6["+՞C]-ߚ߉Ӣߪ]-ߛߦް?<+ߪߵߠN߲ߴ45n[_a>Sb_rak^D_a>q QKٓ]}نوٗW8100قٕckets indicate optional constructions): mask=[c [m]] [R=[n1][,n2]] c, m, n1, and n2 are one-word hex numbers or constant expressions (described below). c is compared with the 'type' word with m used as a mask. A symbol is accepted if the bits of c which5:=R1; R4:=0; ADDL RR2,RR4 LDL RR10[FPSREQ],RR2 ...FPSREQ:+LEN LDL RR4,RR10[FLEN] if CPL RR2,RR4 >zero then LDL RR10[FLEN],RR2 ...poss. update flen R13:+R1 ...TOTLEN:+LEN POPL RR2 ...XFADR MOVDTA_(LDL RR4,RR8[BUFADR_];R5:+R0) ...ial linking program has been compiled first (see 'Miscellaneous Notes').) To obtain a source listing with generated object code, first enter /LIST listing-file name before entering /DO. (Note: If listing-file name already exists, it will be written over;udes labels) then that segment number is used, otherwise the IMAGE command uses the current run-segment and compile-segment to determine where to image and what to store for where the image should be loaded. Examples: /IMAGE FILEX START END E=START+2 /IמȀٙN!>1P!>0ӂ7yӆtC ܬ߃0ߺߡܹ==b͊0+h-j 6Wޗ_e_o& _g?_eek _ are '1' in m agree with the corresponding bits in the 'type' word. If m is not given, it is set equal to c; if neither c nor m is given, they are by default 0 (and thus all symbols would be accepted). "R=n1,n2" specifies that the symbol must be within tmove R1 bytes from @RR2 to @RR4; RR2 updated PUSHL RR2 SET @RR8,GDDTAB if BIT @RR8,RDAB zero then @RR8[NBLKS]->@RR8[NBLKSDUN] ...mark good data in buffer if R12>BLKSZ then begin ...if did big buffer R3:=R12; R2:=0; SRLL RR2,#BLKSZPWR&  it thus must be different from the source-file name.) /LIST without a name will display on the console. (To get a printed listing, first list to a file, then print the file.) /LIST OFF turns the listing off but leaves the listing-file open /LIST ON turMAGE FILEY ROM: ROMBEG ROMEND IRAM: IRAMBEG IRAMEND E=ROMBEG (Also see description of Object File Format under 'Miscellaneous Notes'.) /IF relation.block THEN sets a conditional assembly state according to the result when `relation.block' is executed,  Y DOCUMENTATION [PART 1] SECTIONS: Part 1: Y Overview Using Y and Commands Assembly Language and Symbol Types Extended Expressions Control Structures Part 2: Special Instructions Meta-Compiler Debugging Miscellaneous Notes Y OVERhe range n1-n2 (inclusive, and in the current segment) to be accepted. (n1 defaults to 0 and n2 to 0FFFF if a "," is present, else to n1.) Examples: /MAP 10 will produce a map just containing all the undefined symbols. /MAPA 2 0F R=,5000 will prod R6:+R3-1 ...adjust I to last blk of buffer (I:+TOP/BLKSZ-1) end if R12LSTBLK RL0:=OK WRFX~ RET B_WRITE: ...write out block with bsses (or defined values) plus a word in hex representing the type and state of the symbol on the console (and in a file if open for listing). (/MAP prints symbols in the order of their occurrence, while /MAPA prints them alphabetically.) The bits in the 's (except for statements beginning with "/") are skipped. (This is the differ- ence between "/" and "*"; a command starting with "*" may be skipped, while those starting with "/" are always done.) In addition to /IF, the conditional assembly state may ald a descriptive compiler compiler language. The different levels may, for the most part, be freely mixed. The Y compiler features direct code generation into memory (with one pass), immediate execution of statements, conditional compilation, user-definedsaving only global symbols which have been referenced (as well as any undefined symbols). Note: "TMPS" may be used to stand for the mask for temporary symbols and "UNDEF" to stand for the mask for undefined symbols, e.g. /ZAPALL TMPS , /MAP UNDEF . More ufhdr @RR8, waiting for comp. (LUvec @RR10) RES @RR8,ASYNCB RES @RR8,RDB; RES @RR8,DELWRB; SETXFCNT() FILIO_() RL0:=@RR8[CCD] RET B_AWRITE: ...write out block with bufhdr @RR8, but don't wait for comp. RES @RR8,GDDTAB B_ANWRITE: ...same as B_AWRITE type' word currently have the following meaning: low-order nibble = symbol type (if defined): 0=regular label, 1='BYTE', 2='WORD', 3='PROCedure', 4='LONG' 5=based BYTE, 6=based WORD, 7=register 9=BYTE array, 10=WORD array, 11='EQUate', 13='so be changed by the following: /ELSE reverses the conditional assembly state; /ENDIF resets the state to unconditional assembly. Note that the effect of these commands is independent of any nesting. Example: OPTIONS EQU 2 /IF OPTIONS=3 or OPTIONS& extensions to the language, and symbolic debugging. Examples: if SWITCH=0 or CNT>100 then begin SWITCH:=1; GODOIT(2, VAL&0F) end else begin R3:=^ABC; R5:=@R9[2]; R1:=CNT/2 LDIR @R3,@R5,R1 end ABC:=2+XYZ*3/(NUM%4)+B.@R7 repeat XX(R7)->YY; R7commands: /IMAGE filename $(?(region_name:) addr1 addr2) ?("E="addr3 ?("T=N")) This saves a memory image onto file 'filename' (writing over if filename exists) and is usually used to save programs once compiled. The IMAGE command as shown here, where $but don't rel. buffer on comp. (GDDTAB set) SET @RR8,ASYNCB RES @RR8,RDB; RES @RR8,DELWRB; SETXFCNT() FILIO_() RL0:=OK; RET B_DWRITE: ...mark block with bufhdr @RR8 as needing writing, but don't write ... out yet SET @RR8,DELWRB RL0:=OK; RET INVALADDR' (These are described in more detail below.) bit 4=1: symbol is undefined bit 5=1: symbol is defined but not referenced bits 8,9,10 = chain type (if symbol undefined): 0=none, 1=relative 8 bits, 2=absolute 16 bits 3=relative 12 bits, 4=r8 not zero THEN ...result is false R3:=R4 ...this statement is skipped *DO FILE2 ...this statement is skipped /ELSE R3:=R5 ...this statement is compiled /ENDIF ...restores unconditional assembly state To change between generating code i:+1 until RH6:+1>=RL6 and YY<>0 AA: PROC ...rets. Z-flag=1 if true PROC1(R3); FUNC(01000,VAL,^ABC+2)+2==100 RET while BITB RL7,0 not zero do begin ADDL RR2,RR4 if R2<>0 then begin FLAG:=16; JP ERR end ...test overflow XYZ() end Note that (--) and ?(--) mean `some no. of' and `optional', respectively, will image to a file of name filename from between memory addresses addr1 and addr2 (with up to 12 sets of addr1,addr2 pairs) with the entry point set to addr3. addr1,2,3 are hex numbers (optID: RL0:=INVLDERR; RET NXTBUFI: LDAR RR8,BUFS-BHLEN; RET NXTBUF: ...get ^next bufhdr of device ->RR8; Z=0 if no more (incl. SPBUFHDR) repeat R9:+BHLEN R9==^BUFS+(NBUFS+1)*BHLEN-1; RET UGT until BIT @RR8,ALLOCB not zero; R0==R0; RET ROM: ADDR $  elative 16 bits 5=absolute 32 bits high 2 bits = scope: 0=regular, 1=temporary, 2=local, 3=global The symbol information is stored in a `symbol table' in memory. (This table initially contains global symbols from Y which may be used for extens' n segmented or nonsegmented mode use: /SEG to generate segmented code for the following code, or /NONSEG to generate nonsegmented code for the following code. Example: ...start nonsegmented (blah, blah, blah) 0C000->flag ...code to set seout generating any code, e.g. BYTE [20] The BYTE and WORD ARRAY types are defined similarly as in the following: AA: BYTE ARRAY [10] ...reserves 10 bytes BB: WORD ARRAY 0[50] ...reserves 50 words initialized to 0 These are currently limited to one dim ...GETFIL: 1->B.RDFLG ...set RDFLG to indicate reading in progress ... ^RECL->W.FILINL ...len. to read ... SYSTEM(LD IY,FILIN) ...read binary into high buffer, not waiting ... 00; RET ...RDREC: RDFIL(0A; W.RECLEN) ...read binary 1 record ... RET Z; Jst say LD R3,#5 . R15 (or RR14) is default in PUSH/POP instructions; don't need to say PUSH @R15,R3 . Segmented addresses may be written n.addr as opposed to <>addr where n is the segment number, e.g. JP 2.ABC . DEFM 'ssss' or DEFM "ssss"|), negation (-n), and exponentiation by powers of 2 (2**n). Negation and exponention have the highest priority (not counting parentheses), followed by multiplication and division, with the others equal. Special constants which may be used include "$", gmented /SEG ...tells compiler to generate segmented code R5:=@RR6 04000->flag ...code to set nonsegmented /NONSEG (blah, blah, blah) /WRITE string or constant expression $("," (string or const. expr.)) where $(--) means `any no. of', will ension. Example of use: R8:=BB[2] ...gets 3rd word of array (first=index 0) The "PROC" pseudo-op simply defines a symbol as a 'PROCedure' type, which enables a call to the procedure just by stating the name. Example: PROC1: PROC (statements of the R RDERR2 LOADFL: ...load proc. file into memory; CDE=len if R.C<>0 or R.D>=060 then begin 0FF; JR RDERR2 end ...chk too big EX DE,HL ...len->HL ReadF(LD DE,TBASE; LOGUN->R.B) JR NZ,RDERR2 RET RDERR: R.A=EOF_ERR; RET Z ...if EOF error, return $$$ , to generate an ascii string in memory; DEFT 'ssss' or DEFT "ssss", to generate a string preceded by a count byte (count doesn't include count byte); and DEFS n, to reserve n bytes of memory, are valid constructions. BYTE n, WORD n, and LONG n expreswhich is the value of the location counter at the beginning of the instruction or pseudo-operation, "'n'" (example BYTE 'A'), which is the ascii value of the character in single quotes, and "value(-----)", where inside the parentheses is an instruction_lwrite strings or word values in hex on the console (and in a file if open for listing). Example: /WRITE "Enter: /IMAGE ABC ",START," ",END," E=",ENTRY displays as "Enter: /IMAGE ABC nnnn mmmm E=xxxx" /LOAD object_file_name loads the object file (wprocedure) WORDs, BYTEs, LONGs, and PROCs normally receive the value of the current location counter. However, it is possible to define them to be at an arbitrary position in memory as follows: ABC: BYTE at 02000 XYZ: WORD at ABC+10 etc. In this case nless it starts with '0', in which case it is considered hexadecimal. An exception is when it is known that the number must refer to an address, as in JP 5000 , in which case the number is always considered hexadecimal. REGISTER TYPES Symbols may be gsions, as described below under `Symbols', where they immediately follow a label, may also be used other places to simply generate data into the code. (In this case they do not define symbol types.) Instructions must be in uppercase. Changing the list (instructions separated by ";"s) which is executed immediately (at compile time) to put a value in R3 which becomes the value of the constant. See example above. In addition, a "^" may optionally be prefixed to a symbol name, or the prefix "@" may be hich must be of the format described under 'Miscellaneous Notes') into memory at its specified run-address(s). Care should be taken that the file does not load on top of Y. /GLOBAL list of symbol names e.g. /GLOBAL AA BB sets the scope of the symbols no data can be assembled following the BYTE, WORD, LONG, or PROC definition. The following examples demonstrate the use of EQU and ADDR pseudo-ops: VAL: EQU 22 ...defines VAL as a constant with value 22 AAA: ADDR 01000 ...defines AAA as the address 01iven a "register" type by including them in a statement like in the following example: register CAT:R10, DOG:R11, MOUSE:RL7, HORSE:RR12 Then, any reference to the symbol name will reference the corresponding register instead, i.e. MOUSE:=@CAT is the saocation counter: Examples: ORG 02000 ...causes the following code to be assembled at address ... 02000 in the current segment. ORG 2.ABC ...causes the following code to be assembled at address ABC ... in segment 2 (which becomes the new 'curused to indirectly reference a word in memory (at the time the expression is compiled), e.g. @0F000 . Notes: 1. If symbols are used in an expression containing more than one term, they must be defined. 2. Numeric data is generally considered decimal ulisted to global. /START addr causes all files that have been opened by Y to be closed and control transfered to the given address. (addr is a hex number or constant expression.) Note: for debugging, there are other ways to start programs which leave 000 in the current segment BBB: ADDR 2.2100 ...defines BBB as the address 02100 in segment 2 ROM: ADDR 2.XXX in 1 ...defines ROM as address XXX in segment 2; however, ... "in 1" says that a subsequent ORG ROM (see above) will cause ... the followme as RL7:=@R10 . Symbols defined in this way are given temporary scope (except when defined at the beginning of a Special Procedure (see below), where they are made local). EXTENDED EXPRESSIONS Extended expressions are arithmetic or logical expressionsrent segment'). ORG XYZ ...causes the following code to be assembled at address XYZ ... where XYZ includes a segment number. (Also see below in connection with the "ADDR" pseudo-op.) Symbols A symbol in Y consists of one or more letters (upper a..come here with R.A=prompt char. Put1(R.A) 00->B.NUMERR ...zero error count GetN(LD DE,DATA1) ...get new chars; DE pts. to beg. of buffer end GETRCX: LD (LASTCR),DE; LD (LASTDE),DE ...LASTDE needed in case Errm before set RET ...READFL: 0A->Y in operation; see below. /* closes any input files which have been opened by Y and enters debug mode (see below under 'Debugging'). /BRKS->Y and /BRKS->P control the destination for breaks (to the Y debugger or to wherever they were sent prior to Y' ing code to be generated into segment 1, although the ... code will be made for running in segment 2. This state can be ... changed by another ORG to a symbol defined this way or an ORG ... with a specified segment number, e.g. ORG 0.ABC . ABC: A which can include loading, modifying with different operations, comparing, and storing data. Register names used in extended expressions are exactly as in Zilog assembly language. Word registers are R0,R1,...R15. Byte registers fill up R0...R7. The leand lower case) and digits (or "_"), of which the first character is an upper case letter. Labels are usually defined by a symbol appearing at the very beginning if a line (option- ally followed by a ":" or "~", the latter indicating that the symbol is to R.A ...read binary ...RDFL2: RDFIL(^RECL) ...read into low buffer, waiting ... CALL Z,GETFIL ...if no error (such as EOF), fill high buffer, returning immediately ... CALL NZ,RDERR ...if error ... RET READFL: ...read in file, LU LOGUN, starting from f being entered). /RESET EXTEND causes any extensions which have been made to that point using the label EXTEND (see below under 'Extensions') to be cleared. /EOF (in a file) marks end of file. (It will be closed at that point.) // exits the prograDDR XYZ ...defines ABC to have the same (32-bit) value as XYZ. ... If XYZ is an 'ADDR' which may specify run- and compile-time code ... segments (as above), this property is transfered to ABC. CCC: ADDR DDD+4 in 2 similar to ROM above, but with segst significant byte of register Rn is RLn, and the most significant is RHn. Double registers are RRn (n = even). In addition, the Flag and Control Word (or Byte) can be referred to in extended expressions as "flag", and some stack operations use the term have temporary scope (so it may be eliminated by a "/ZAPALL TMPS" statement)). In addition, a "type" (BYTE, WORD, LONG, BYTE ARRAY, WORD ARRAY, PROCedure, ADDR, or EQUate) may be assigned to the symbol when it is defined in this manner, using "BYTE", "WORpos AHL; also set FPOS,FPOSH R.A->FPOSH; R.HL->FPOS RDFIL1() RDFIL2() RET RDFIL1: ...read RECL bytes @file pos. FPOS,FPOSH to @DATA1, LU LOGUN ...set RCADR1,RCAD1H; update FPOS,FPOSH FPOS->RCADR1->R.HL; FPOSH->RCAD1H->R.A READFIL(LD BC,DATA1) RET m, closing files and returning to wherever Y was called from (usually the monitor). In addition, any instruction or instruction list may be executed immediately (from the console or during compilation) by entering /instruction.list e.g. /SETUP(3); INIment number taken ... from DDD. Notes: 1. Symbols defined by 'ADDR' may be redefined; other symbols may only be redefined by first ZAPping them. 2. When an 'ADDR' symbol which was defined with "in n" is redefined without using "in n", its property"stk". Expressions sometimes have an item on the left side followed by ":=" or ":" (this is currently limited to registers and BYTEs and WORDs). The ":=" means the item on the left (n) will get the final result of the expression, while ":" is equivalent D", "LONG", "BYTE ARRAY", "WORD ARRAY", "PROC", "ADDR", and "EQU" pseudo-operations. Example: BYTE1: BYTE 5 0 BYTEVAL+3 This defines BYTE1 as a 'BYTE' variable and in addition assembles and stores the BYTE expressions which follow (constant expression RDFIL2: ...read RECL bytes @file pos. FPOS,FPOSH to @DATA2, LU LOGUN ...set RCADR2,RCAD2H; update FPOS,FPOSH FPOS->RCADR2->R.HL; FPOSH->RCAD2H->R.A LD BC,DATA2 ... READFIL: ...enter with AHL=file pos. to read at, BC=^dest., LU=LOGUN, len=RECL ...do rT() ASSEMBLY LANGUAGE AND SYMBOL TYPES Comparison to Zilog Assembler: Y supports most instructions in Zilog mnemonic Z8000 assembly language (a few of the less common are currently unimplemented; for these, the equivalent binary WORD(s) can be used, e. of being able to specify run- and compile-time code segments (the same ones) is preserved, as long as it is being redefined in the same segment. Example: AREA1: ADDR 1.0F000 in 2 ORG AREA1 ...code AREA1: ADDR $ ORG AREA2 ...other code ORG AREA1 ..to ":=n"; that is, n:+3*4 produces the same result as n:=n+3*4 . At present, word and byte extended expressions are implemented. The type (word or byte) is determined by the first item in the expression, like a register name or a BYTE or WORD. Numbers s truncated to one byte, see below) in the following bytes. If now a statement is used like RH1:=BYTE1 (see 'Extended Expressions' below) RH1 would get the value 5. It works similarly for word and long (4-byte) quantities, e.g.: WORD1: WORD 999 998+Vead, update FPOS,FPOSH; call RDERR if err PUSH DE PUSH BC R.A->R.C; EX DE,HL ...CDE=fpos POP HL PUSH BC; PUSH DE PUSH HL SeekF(LOGUN->R.B; 00->R.A) POP DE ...^dest. ReadF(LOGUN->R.B; ^RECL->R.HL) POP DE; POP BC PUSH AF 00->R.A; R.HL+R.DE; R.Ag. LDCTL REFRESH,R3 = WORD 07D3B). A few modifications are as follows: Hex numbers are distinguished by a leading "0" as opposed to a "%". In addition, numbers that are known to be addresses may usually omit the leading "0". 32-bit constants m.code following will be assembled in segment 2 for ... running in segment 1 3. Pseudo-ops (and any label definition) may optionally be followed by ";". Constant expressions Constant expressions are evaluated at compile-time. Examples are: LD Ror indirect references (i.e. @R4) or function calls are considered words unless preceded by "B.", or unless the expression type has been previously determined in the expression. (There may also be "W." prefixes.) Expressions of different type may also beALUE 0B40 LONGVAL: LONG ABC+2 There may be repeat counts (indicated by [n]) following any of the word or byte expressions, e.g. WORD 0[10] 0800[5] . In addition, a repeat count with no preceding expression will just reserve that many words or bytes with+carry+R.C ...AHL=updated file pos. R.HL->FPOS; R.A->FPOSH POP AF POP DE CALL NZ,RDERR RET ...RDFIL: R.A->B.RDTYP ...type of read (binary or direct) ... R.HL->W.FILRDL ...len. to read ... SYSTEM(LD IY,FILRD); RET ...read into low buffer, waiting ay be written as 2 16-bit parts, e.g. LDL RR2,#08000,MYSP . Indices or offsets may be enclosed in square brackets instead of parentheses, e.g. LD R3,R5[R7] . "#" sign not necessary in cases where no ambiguity exists, e.g. BIT R4,5 is okay, but mu3,100+3*VAL/(XX+2) ORG $+0FF&0FF00 BYTE 2**N-1 /MAP R=^ABC+2,^XYZ ABC: EQU value(LD R3,ABC;LDB RL3,RH3) Operations which may be used in constant expressions include addition (+), subtraction (-), multiplication (*), division (/), and-ing (&), or-ing ((  nested inside one another. R3 is assumed as the default accumulator in word expressions (RR2 in the case of multiplies and divides) and RL3 is the default byte accumulator. In addition, in more complicated expressions, R5 (or RR4) and RL5, respectively,n are separated by a "/". Example: number := ?("+"/"-") $(digit) reads "A number is an optional plus or minus sign followed by any number of digits." expression := right_expr / left_item ":" / left_item ":=" right_expr / left_item ":" op $(e (not counting R13) will be automatically saved at procedure entry (and restored at exit). Calling special procedures: The procedure in the above example could be called as follows: ABC(1,R9+2,B.@R8,X*2,->NNN,R11,@R12[2]) There should be the same numb above, the register named is used without loading the default. BYTEs and WORDs may also appear on the left of a ":=", ":", or compare operand. In the case of loads or compares with constants, or increments, a register does not have to be used; otherwise,rocedure is distinguished by a "(" immediately following the name. Following this is the list of parameters, starting with the input parameters. The output parameters follow the "->". Inside the special procedure, parameters and local variables may be r might be used as default secondary accumulators (so be careful). Also, R1 (RR0, RL1) might be used for parameter passing to procedures (used for the third parameter; see below). In addition to the defaults, any register may be specified to be used as anxpr_mod) / left_item compare_op right_expr where left_item := word_reg / byte_reg / defined_var right_expr := item $(expr_mod) expr_mod := op item / store_op store_item op := "+" / "-" / "*" / "/" / "%" / "&" / "|" / ".XOR." store_op := "<->" / er of input and output parameters, with matching types as in the definition. (It is not necessary for a definition to precede references to it.) What happens here is as follows: 1 is loaded into R3. R9+2 is loaded into R5. B.@R8 is loaded into RL1. the default register is used with the final result ending up in the BYTE or WORD. *,/, and % (mod) have precedence over +,-,&,|,.XOR.,== etc. Also note that a whole double register (e.g. RR2 when the accumulator is R3) will be used unless the multipliereferenced just as if they had been regular (static) variables. If it is desired to return a value from the procedure (besides output parameters), it should be put in R3 if word or RL3 if byte before reaching the closing "}". (Since these are the defaults accumlator. This is done by starting the expression with "Rn:=" (or "Rn:" before first operator). In general, spaces are allowed between items in an expression. Examples of Y extended expressions: generates: R5/4 ................................ "->" compare_op := "==" word_reg := R0 / R1 / R2 / etc. byte_reg := RL0 / RH0 / RL1 / RH1 / etc. long_reg := RR0 / RR2 / RR4 / etc. defined_var := static_var / variable used in special procedures static_var := symbol defined as WORD or BYTE item  R15 is decremented enough to make room for all the other input parameters and all the output parameters starting with the third. R3 is pushed, then loaded with X*2 and stored @R15[2], then popped. (If there were more input parameters, they would be stor or divisor is a constant which is a power of 2. (The power of 2 case is the only one valid for bytes.) Function calls within expressions are assumed to return a value in R3 if word or RL3 if byte. "->" refers to storing, "<->" refers to doing an EXchan, the register need not be mentioned.) The expression "return(---)" where "---" is an expression loading the value to be returned (if any) may also be used to return from inside the procedure. Upon exit from the procedure, the symbols for the parametersLD R3,R5; SRA R3,2 R4:=R5+1-ABC (ABC is WORD) .......... LD R4,R5; INC R4; SUB R4,ABC ^ABC+@R8*3->R9 ...................... LD R3,#ABC; LD R5,@R8 MULT RR4,#3; ADD R3,R5; LD R9,R3 PROC(7)->@R13[2] .................... LDK R3,#7 CALR PROC (or := ?(type_prefix) (item0 / constant / string_ptr / "-" item / "(" expression ")") store_item := ?(type_prefix) item0 type_prefix := "B." / "W." constant := number / symbol defined by EQUate / symbol prefixed by "^" / regular label or ADDR or array wed above X*2 on the stack.) Next, the procedure is called. Upon return, R15 is incremented past the input parameter on the stack; then the first output parameter, which is in RL5, is stored into NNN (a BYTE), and the second output parameter, which is in ge. "flag" can be used to refer to the Flag Byte in byte expressions, and to the Flag & Control Word if in word expressions. "stk" can be used to refer to either a PUSH, POP, or EX with the stack, depending on the context (e.g. R3->stk = PUSH R3, R3:=st and local variables (including register variables) are made reusable (that is, they were defined with local scope). The following takes place upon entering a special procedure: (The first three parameters are in the registers R3, R5, and R1, respectiCALL PROC) LD 2[R13],R3 RH2:=RL7+@(R5:+2) ................... LDB RH2,RL7; INC R5,2 ADDB RH2,@R5 FLAG:=2 (FLAG is BYTE) .............. LDB FLAG,#2 FLAG==0 (FLAG is BYTE) .............. TESTB FLAG R4==^ABC+1 .......................... CP R4,ith no following "[" and no type_prefix string_ptr := ascii string within double quotes; value=addr of DEFT 'string' item0 := word_reg / byte_reg / "()" / defined_var / indexed_var / other_var / proc / "@" indirect_reg / "stk" / "flag" iR1, is stored into R11. The third output parameter is then popped into R5 and stored @R12[2]. It is noted that procedure calls with multiple parameters do not have to reference procedures defined as special procedures; a regular-type procedure that knows k = POP R3, R3<->stk = EX @R15,R3). Expressions which are nested within other expressions must be enclosed within parentheses. Automatic conversion between bytes and words within expressions may be done. In segmented mode, indirect references must be mvely (RL3, RL5, and RL1 in the case of bytes). The other parameters are on the stack above the return address.) First, R13, which is used as the frame pointer, any registers (>=R6) which are to be used as local register variables within the procedure,#ABC+1 R8:->ABC[R5:+1&0FFFE] (ABC=regular label) ......... INC R5; AND R5,#0FFFE LD ABC[R5],R8 RL7:=ABC[R9:] (ABC=BYTE ARRAY) ...... LDB RL7,ABC[R9] R8:=ABC[2] (ABC=WORD ARRAY) ......... LD R8,ABC+4 B.@R4'<->RH0 ........................ ( ndexed_var := (regular label or ADDR or array) "[" expression "]" other_var := undefined symbol / regular label or ADDR or array with a type_prefix and no following "[" indirect_reg := (addr_reg / item) ?("[" expression "]") ?(postinc) / word_reg<>what it is doing is just as valid. CONTROL STRUCTURES Control structures in Y consist of "if", "while", "repeat", and "case" statements which take the following forms: "if" RELATION_BLOCK "then" INSTRUCTION ?("else" INSTRUCTION) ?("endif") "while" RELAade via double registers e.g. @RR4. "'" postfixed to an indirect reference, e.g. @R9', causes the pointer register to be post-incremented (by 1 if a byte reference, and by 2 if word). "^" before a symbol name causes a reference to the address of the symb and any registers containing parameters (R3, R5, and R1, depending on the number of parameters) are saved on the stack. Then R15 (the stack pointer) is decrement- ed enough to make room for the local storage (if any) plus the first and second output paraLDB RL3,@R4; INC R4; EXB RL3,RH0 RH0:=flag->stk ...................... LDCTLB RH0,FLAGS; PUSH R0 RL6:+3*@R4[6]+(R7:=R9%5+22/RL1) ..... a lot PROC(X*2,Y) ......................... LD R3,X; ADD R3,R3; LD R5,Y CALR PROC (or CALL PROC) VAL:=FUNC(X,Y,R0 (segmented mode) "[" constant "]" addr_reg := word_reg<>R0 (if nonsegmented mode) / long_reg<>RR0 postinc := "'" proc := procsym ?("(" ?(args) ")") procsym := symbol defined as PROC or symbol followed by "(" / name of built-in procedure (smallTION_BLOCK "do" INSTRUCTION "repeat" INSTRUCTION_LIST "until" RELATION_BLOCK "case" INSTRUCTION "of" CASE_OPERAND $("or" CASE_OPERAND) ":" INSTRUCTION CASE_OPERAND $("or" CASE_OPERAND) ":" INSTRUCTION etc. ?("else" INSTRUCTION) "end" Above, "?ol, e.g. ^ABC where ABC is a WORD points to the memory location containing ABC. A string, e.g. "XYZ" (including the quotes), results in the string in DEFT form (i.e. with a preceding count byte) to be assembled in memory and pointed to. "()" refers to meters if they exist. Finally R13 is loaded from R15. When exiting the procedure, the first output parameter (if any) is popped into R5, the second output parameter (if any) is popped into R1, R15 is incre- mented past the local storage and 1st, 2nd aZ,N,->S)+3 ............ LD R3,X; LD R5,Y; LD R1,Z DEC R15,2; PUSH R3; LD R3,N LD R15[2],R3; POP R3 CALR FUNC (or CALL FUNC) INC R15,2; LD S,R5 INC R3,3; LD VAL,R3 PRINT("HI") ......................... JR $+6; DEFT 'HI'; BYTE  letters) args := inst_list / inst_list $("," expression) inst_list := instruction $(";" instruction) instruction := expression / assembly language instruction / control structure / etc. Special Procedures These are procedures which can take any (---)" indicates an optional construction and "$(---)" means "any number of (---)". RELATION_BLOCK is a group of logical TEST's "and"ed and "or"ed together without parentheses, e.g.: X=Y and Y>2 or RL7:-1<>zero . (The TEST's here are "X=Y", "Y>2", and "the default word or byte register. A symbol which is a WORD or BYTE ARRAY, or else a regular label (no special definition) or ADDR, if not followed by "[---]", will be taken as a constant pointing to the beginning of the array. (With a regular label or And 3rd parameters, R13 and any other registers which were saved are restored from the stack, and then a RETurn is made. Notes: 1. In segmented mode, it is currently a requirement that the stack be in the same segment as the special procedure when it is 0 LD R3,$-4 CALR PRINT (or CALL PRINT) @RR8[2]->@R7[4] (segmented mode) .... LD R3,RR8[2]; LD |<>4|[R7],R3 where n=current segment B.2+B.PROC()->@RR8' (segmented) ..... LDB RL3,2; PUSH R3 CALR PROC (or CALL PROC) LDB RLnumber of input parameters, and return any number of output parameters plus a value in a register. The parameters plus local variables of the procedure are kept on the stack and thus the procedure is reentrant. The definition of a special procedure is maRL7:-1<>zero".) Higher priority is given to "and"s. TEST is of the form INSTRUCTION RELATION. INSTRUCTION is any single statement in Y, including assembly language, extended expressions, control structures, and special instructions. Note that the BEGINDDR followed by "[---]", the index is simply added to the label value to reference a word or byte (no doubling for words).) Procedure calls with arguments separated by ","s pass arguments using registers R3, R5, R1 and the stack. These are meant to intercalled. This is because indexed addressing (in which the segment number is in the instruction and R13 is the index) is used to reference the parameters and local variables. 2. It is currently left to the user to specify the registers which are to be use5,RL3; POP R3; ADDB RL3,RL5 LDB @RR8,RL3; INC R9 B.()->ABC ........................... LDB ABC,RL3 R3-(R6+100/R9) ...................... LD R5,R6; PUSH R3; LD R3,#100 EXTS RR2; DIV RR2,R9; ADD R5,R3 POP R3; SUB R3,R5 Notes If an exprede as in the following example: ABC(X,Y,Z,N,->OUT1,OUT2,OUT3) ...note "(" immediately follows name ...all parameters to right of "->" are output parameters byte Z,OUT1 ...define type of parameters, default is WORD {byte A,B word CC,DD ...define a_END construction is considered an INSTRUCTION. RELATION may be of several forms. In all cases a test is made on the Z8000 Flag Byte (sometimes code is generated to set the Flag) and the appropriate jump-on-condition-code (JR CC,---) instruction is generface with the 'special procedures' described below (although they don't have to). Syntax of Expressions In the definitions below, "?(---)" stands for "optional (---)"; "$(---)" stands for "any number of (---)". Different alternatives within a definitiod for register variables. This must be done with a "register" declaration statement prior to the body of the procedure (which may be mixed in with "byte" and "word" declarations of local variables). Note, however, that only registers in the range R6..R14ssion starts with a register name not followed by ":=" or ":" or a compare operand ("==" in isolated expressions or =,<>,<,>,etc. in expressions within control statements), then the default accumulator (R3 or RL3) will be loaded. If followed by one of thend specify type of local variables register DD:R8, C:RL7 ...define local register variables ...body of procedure: A:=2; B:=3; C:=Z&B OUT1:=A+B-C CC:=X+Y; DD:=CC/X-Y OUT2:=CC-DD OUT3:=CC+DD*N DD ...value returned in R3 } Note that the special p) ated. The first form of RELATION is simply "zero", "not zero", "carry", or "not carry". Example: if R3+R5 carry then .... This generates ADD R3,R5; JR NC,$+n . Secondly, RELATION may be "=" (equal) or "<>" (not equal); "<", "<=", ">", or ">=", corresp, the current segment where code is being put out is used. Example: patch ^ABC+012, RL0->@R3; R3:+2 An alternate form of the `patch' statement is: patchr address,instlist This is the same except that the 2 (or 3, or n) bytes of instructions displaced  the stack to be concatenated to the output but left on the stack. 7. Ig causes the string at the top of the stack to be popped off without being put anywhere. Additionally, if characters constituting any other identifier (Id) are found withiAG of 0: AA(); 1: BB() 2 or 3: CC() else DD() end repeat PUSH R1 ABC(1) B.@R8'==@R9'; JR Z,BREAK ...break out of loop if R3>>@R13[2] then CNT:+1 POP R1 until R9>=R10 or R1:+1=20 RL0:=0 BREAK~ ...cont. here cont. here nt. re without testing (to advance R7, which is used as the pointer to the source text, for example) is: COMM := "..." NOTCR; where NOTCR is a routine to advance R7 to a carriage return. Alternatively, the routine could be written within a .DO(----) constronding to unsigned comparisons; or "<<" (less than), ">>" (greater than), "<<=", or ">>=", corresponding to signed comparisons. These may optionally be followed by either "zero" or by a RIGHT_EXPR. In the latter case, the RIGHT_EXPR is evaluated and thenby the JP to the patch area are not copied into the patch area. Note that the `patch' statement must be entered during compile (as opposed to debug) mode. Meta-compiler ------------- An extendable meta-compiler (known as XMETA) is included in Y. Usingn an output-expression, code will be generated to call a user-provided routine of that name. A comma within an output-expression is equivalent to having two .OUT's. That is, .OUT("xxx","yyy") is equivalent to .OUT("xxx").OUT("yyy") Output Code Gee WRITE command. Strings, word values in hex, and byte values in hex can be printed out. (This is often shorter than "printf" above.) The syntax is "?" followed by any number of strings (in double quotes) or word or byte extended expressions, separated uction (putting within the parentheses instructions separated by ";"s which are to be executed immediately) as: COMM := "..." .DO(repeat B.@R7' until RL0=0D; R7:-1==R7); SEMANTICS Constructions to facilitate generation of output code can be inserted a compare between the left and right sides is made. (This is usually done with a CP instruction, but in some cases an OR or TEST instruction is used.) Examples: expression: generates: if PROC() <> then ... CALR PROC; JR Z,$+n if PROC() >= zero this language, syntactic and semantic modifications or extensions to the base language can be developed by the programmer and used in the same source language module. The language consists of a sequence of rules which hierarchically describes the syntax neration: When the result of a series of output-expressions is delivered to the .OUT routine, it then is further processed (according to a rule which depends on the first character in the output area) and produces appropriate code. Some of the possible by ","s. Registers are saved. (Within the statement, registers are saved through strings.) Example: ?"X=",R7+1," Y=",@R9+ABC If R7=0C827 and @R9=04000 and ABC=0800 then this will print as X=C828 Y=4800 (a carriage return is added at the end) Note:  at essentially any point in the syntatic description portion of the rule. Two forms are provided: .OUT(output-expression) generates codes as directed by the result of a sequence of output expressions, and .SAV(output-expression) pushes the results then ... CALR PROC; JR ULT,$+n if RL0<2 then ... CPB RL0,#2; JR ULE,$+n if R1<>0 then ... OR R1,R1; JR Z,$+n if ABC<>0 then ... TEST ABC; JR Z,$+n if ABC>>100 then ... CP ABC,#100; JR LE,$+n if RL6<=RL7+3 then ... LDB RL3,RL7; INCB RL3,3 CPof some target language, together with instructions on what object code should be generated for that language. XMETA converts this sequence of rules into a compiler. The following is a somewhat abridged description of XMETA; for more details, see `Y.XMETfirst characters and their interpretation follows: 1. An initial H causes the next characters, two at a time, to be interpreted as the hexadecimal representation of the code, e.g. .OUT("H9E08") generates code for the Z8000 RET instruction. 2. An because of the way it is implemented, the strings here have same escape characters ("%" and "\") as above in "printf". ("%" has no use here but must nonetheless be doubled to print one of them.) "stop" statement: stop ... generates the word 0E00, whi of the output expressions onto an internal stack. Example: FLAG := ("Z" .SAV("60") / "C" .SAV("07")) .OUT("HAE"Re); Output-expressions: There are several primitives for use in generating data into the output area. (Note: The "output area" is actuallB RL6,RL3; JR UGT,$+n RELATION may also be left blank, in which case "zero" is assumed. BEGIN_END is the sequence "begin" INSTRUCTION_LIST "end". INSTRUCTION_LIST is any number of INSTRUCTIONs separated by ";"s or on different lines and may also includeA.DOC'. SYNTAX Briefly, a rule is an identifier (the NAME of the rule) followed by the characters ':=' followed by one or more ALTERNATIVES to be tested for, each separated by the characters ':=' or '/', and terminated by a ";". The "alternatives" areinitial ' (single quote) causes the following characters to be moved directly to the code area. Thus, .OUT("'ABC") is equivalent to .OUT("H414243"). 3. An initial L causes the following characters to be entered into the symbol table with the cch will cause a break when executed "setseg" and "resseg": These save registers and are meant to be used together. setseg ...generates code to set segmented mode and save previous value ... of Flag and Control Word on stack resseg ...generatesy defined as a buffer where the data is further processed, usually resulting in code put out to the "code area".) 1. "---" will generate code to append the characters within the quotes (at least one) to the current output. For example: INST:="RET" labels (at the beginning of a line) or comments. (Remember that comments must start with "...".) RIGHT_EXPR is a form of extended expression (see above) but without a leading "n:=" or "n:". CASE_OPERAND is usually a RIGHT_EXPR, in which case the result)  denoted by a sequence of one or more ITEMS to be tested for. An "item" can be the name of another rule within carets (i.e. ) a LITERAL surrounded by quotes to be tested (i.e. "DEF"), the characters '?' or '$' followed by an item (which means the iteurrent location counter address as the symbol value, e.g. .OUT("LABC") In addition, prior unresolved references to the symbol are resolved. 4. An initial D (for define), followed by a long word in hex, causes the following characters to be ente code to restore segmentation mode (and rest of Flag and ... and Control Word) from stack Example of possible use: /SEG MOVDATA: PROC ...procedure to move R1 bytes of data from @RR2 to @RR6 ...can be called from either segmented or nonse.OUT("HC9"); 2. * will generate code to append the characters last detected by the prev- ious syntatic test to the output area. For example: NAME:= .SAV(*); Here, * will copy the characters detected by the Id routine (if successful) t of the RIGHT_EXPR is compared with the result from the base instruction of the "case" statement, similar to a TEST. It may also be a BEGIN_END, however, in which case the Flag as it stands is used. In either case, the appropriate jump-on- condition-codem is either optional or that there can be any number of the item, respectively), or one or more "alternatives" each separated by the character '/' all within parentheses. In addition, names of procedures or rules to call without testing or code for immedired into the symbol table with a value equal to the hex long word, e.g. .OUT("D82001234XXX") defines XXX to have the value 082001234. In addition, prior unresolved references to the symbol are resolved. 5. An initial = (equal sign) causes the g'd mode setseg LDIRB @RR6,@RR2,R1 resseg; RET "save Ri,Rm..Rn" and "restore Ri,Rm..Rn": This means save on or restore from the stack all named word registers Ri plus Rm through Rn. There may be any number of Ri's and Rm..Rn sequences, in any o the output area, from where they will be saved on the internal stack. 3. #1 will generate code to produce a unique temporary symbol (which is use- ful for implementing local jumps). The same symbol is generated at each use within a given rul instruction is generated. Further notes: 1. End-of-lines (including possible comments) may go after INSTRUCTION, RELATION, "then", "else", "do", "until", or "of". 2. In the "case" statement, each succeeding case is tested until one is found true. Thate execution can be included. (Rules are actually procedures which return the Z-flag set if true.) Examples: PARAMLIST := $("," ); can be read as "a PARAMLIST is a PARAM followed by zero or more commas each followed by one PARAM". following characters to be pushed onto the SAVE stack and a call executed to the parser, pointing to the first character saved. (Note: for sucsessful parsing, the characters must form valid defined instructions separated by ";"s.) Thus, .OUTorder. Example: ... save R7..R12 ABC() ...clobbers registers restore R7..R12 ... Patch statement To do patching of code, a "patch" statement of the following form is provided: patch address,instlist This inserts at "address" a JP to the ce at a given time, but outside that rule different symbols will be generated. For example, a Fortran-like implementation of logical IF statements could be: IFST := "IF(" ")" .OUT("=JR NZ," #1) .LABEL(#1) Zp; STMT := en that case is executed, and the rest of the statement skipped. 3. In the "case" statement, the various cases may alternatively be separated by ";"s instead of end-of-lines. 4. Special code utilizing the Z8000 DJNZ instruction is generated for "repeat"GROUP := "do" $((";"/",") ) "end" := ; can be read loosely as "a GROUP is the word `do' followed by an arbi- trary sequence of STMT's separated by a semicolon or comma, followed by `end'. Alternatively, a GROUP is a single STMT("=RET") will generate the code for RET. 6. An initial A2 causes the following characters to be interpreted as a 16-bit quantity determined by that symbol's value in the symbol table. If the symbol is undefined, an in-place chain is establisheurrent code area; there the given instruction list is inserted, followed by the 2 (3 if set for segmented mode) words of instructions displaced by the JP, followed by a JP back (to "address"+4 (or +6)). (A JP back to "address"+2*n, where n is a digit in t := ...etc. The above will permit nested IF statements. (Note that the procedure `Zp' should be called immediately after the last reference to the temporary symbol in order to remove it from the symbol table.) 4. Re w loops ending with "until Rn:-1 zero;" ("zero" is optional; "Rn" is any word or byte register). (This is distinguished by the presence of the trailing ";"; if left off, the normal DEC Rn; JR NZ,$-n code will be generated.) Be aware that the zero flag." Note: once a test is made and found true, any following test in the sequence must also be true or it is an error, i.e. if "do" is found above, (and also "end") must follow. POSNUM := ?"+" ; indicates that "a POSNUM is a NUM with an optid or extended for future resolution. 7. An initial C is interpreted as either a CALL or CALR to the following symbol, depending on the relative address of the symbol, e.g. .OUT("CCOPY") 8. An initial J is interpreted as either a JP or JR to he range 3-9, can be generated instead by replacing "address" by "address[n]".) "address" takes the form of a constant expression with an optional "n." prefix, n being a segment number to supercede any gotten from "address". If no segment at all is given,ill generate code to concatenate the string of characters at the top of the internal stack to the current output and erase them from the stack. 5. Xc causes the top two strings in the stack to be exchanged. 6. Pp causes the string at the top of is not automatically set in the DJNZ form of the loop. More examples: if RL0>2 then begin R1:=6 repeat R3+R4 until R1:-1 zero; end else begin RH6:+1 while RH6:-1 not zero and ABC|050=XXX do begin ABC:=FF(Y); Y:+5 end end case FLonal plus sign in front". A number of rules are pre-defined for the convenience of the compiler-writer, e.g.: Digit := "0"/"1"/2"/..../"9"; Id := CAPITALLETTER $(ANYLETTER/Digit/"_"); Hexd := Digit/"A"/..../"F"; As an example of just calling a procedu* ...handle symbols referenced but not used when QTYPE<2 (not QR): OJRetQ: OJRetDbg: CMDR: SETTB0: GETSUB: RDLDIRR: WRLDIRR: RDaHLR: WRaHLR: GOXR: StepR: CKStepR: SetCPU: RET *ZAP MAXCPU DATA1 RR_AF RR_SP RR_PC SRR_AF SBAddr NGFLG ...in MMETA *ZAP R_HL R_S8B!kkG~ x <#R 6 #<@86[#!kR8`iͯy${*QjB >]@{:p(:pay*KjDM|*Qj"Kj^Ȕ^<^͠K"QjCKjͥѿ*p*op>*p2p:p :p yaB#*h!oq#p#*h s#r#q#p#q#p#yhB ~ͨ}̓}Ͳ~ѯŷ 2Dj* p##*EjN#F+ "Ejx :Dj 0<2Dj !kk"o:oA(* pB ͓~0fm N !"o m[o!kkRcr͚z Rem Space=͓~*"pBan instruction could be, e.g. if RL0=0CA then begin ?"ERROR ",RL0; stay_here end The other symbol is USERCC which allows the user to redefine an entire line ending with a carriage return. To allow for further extensions, the following construction can u #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ xBt((# t!!ͦtOW_}T]Oů)lau!t"w#ux( >!u  vux( >"u  vS"s)lgxBt!!G tH t 4 #P R_PC ...in MMETA *ZAP CKBRKPT Step ResFF ...in QBUG ...above 3 rows corresponds to zaps in QBUGR *ZAP OJRetDbg SETTB0 GETSUB RDLDIRR WRLDIRR RDaHLR WRaHLR StepR CKStepR *ZAP SetCPU ETSUB RDLDIRR WRLDIRR RDaHLR WRaHLR StepR CKStepR *ZAP SetCPU *ZAP Se"h [Gj͕R[Gjb';u2QO2hQGjLASTCRQjNCODEejLASTDEgjNEXTDEoQOPTSoOFFSET pI_SW pTABBSE$pEXTADR$pEXTEND&pUSERCCqpR_AFp{cr͏ [o?0 PY?8DM>Co!B ,! +8~G#   ^#V*o{͸ ~͵ N#!jk R8͸R0!kR0crkkSo${> !B($!p~(#pTOO DEEP>6${>#H!p be made. (A symbol enclosed in square brackets is called only if it is defined.): EXTEND := [EXT2] / THIS_EXTEND ; To allow for another extension starting with EXTEND, follow this by: /ZAP EXTEND EXT2 := [EXTEND]; /ZAP EXT2 An additional command is  (  >>K"sB@8Z80(.`8}8&($/898(!8)8(+( >>2f!v"g>!v!= qy×zP{íïvïv+"dv!9"fvcrr1kk!N#T]> w~qkGTtѯ: p  !vv; @DE; DEC DE; CPIR ...chk 1st char. if zero then begin if @DE-1<>zero then begin ...@DE=length PUSH BC; PUSH DE; PUSH HL; LD B,A; INC DE repeat INC DE; @DE=@HL; JR NZ,CPSLUP; INC HL until DEC B zero; SCF; R.HL-carry-R.DE; JRQuitzCopy${OuthexpErrmqErrcrOutmsg{HLoutDELqGet1vPut1GrWSbgnWrWSendorPutconyTestP{OutOutNgxGetrecxGetcon@{OutpywRDaHLyWRaHLFzIddzDigittzHexdzLatcˎ~ {OG!p ˆ{!kk#Ó{{O[ij(SijDKK"ij*ij+NGB77PY##7bkz${*Qj+~+~ "Qj x <! =(G #7R(ٯQU  hRK ͕,bjR?؆DK Ϸalso furnished in Y to allow the user to see on the console the data that is sent to the output area, for use in debugging. This command is /DIAG entered (at the beginning of a line) before starting compilation. (DIAG is turned off by /LIST or /LISTEND.Ͳr:oWKj*j6 # x +6 Cj!h"j`i:vGͱu:v̯pMwpWRITE:vv>2vSv>iw!oUw*vGrtSw$*v:vGct :p > >!v~=wmypOPEN!v~׀ ResSVs Q := .DO(LD B,'R') DEL .DO(@DE=',';CALL Z,CHGRR;CALL NZ,PRTRRS;CP A) := .DOh8{OutsetzCopyinzSrzSr1zCountȔINSTLISTDIgm}lLkupnlr}LkupGenZpSav7Re?PpUXcEff1ODbug+JASMSTOCOMMAND7LABELCOLܔhINSTן*XINSTlCBNbBITOP2WN[bNQ &6SQ &6GU >2apJC ͧ"p>2apBỦBC ͧŇXUXC ͧETQ /6HQ &ͯUK :[ͻLC Eͧ(*op#,>H!kkw#tz w#tzw#("gj1*Qj "QjP{*Qj}́} |}) Note: All extensions should go in the same segment with Y. Debugging --------- Y contains a symbolic debugger. To enter debug mode, type "/*" (this can also be in a file; any open input files will be closed). The prompt is a "*". (To return to nkcq:v:Cj(Gr͚z ERROR TOTAL=${Wr!v~v5~(my!%jO ^Vn f~x:v *Mj|(:v(S!m Rny x xR8 $ DM!mB*#j" j:%j2"jx DMbk> ny>-v2CjkqSGjSej2Aj"?jxx*?j" j:Aj2"jky*?j"#j:Aj(LD B,'R') ShRegs := .DO(LD B,'D') .DO(R.A=0;PUSH AF;CALL Z,CHGMEM;POP AF;CALL NZ,Dump) := .DO(LD B,'N') NS2 .DO(LD (HL),1) := .DO(LD B,'S') NS2 .DO(LD (HL),2) := .DO(LD B,'G') .DO(5->NGFLG) := .DO}NumHNumXCOMM"OptmM-OptmCopyin{Sr{Sr1|CountINSTLIST]Ig~lLkupnl~LkupցGenZp3SavPReXPpnXcEff1hDbugDJASMSThCOMMAND>7LABELCOLhINST*XINПȯͧ(  (,*p, > < >2`p!ap' W,WC ߸"mpO  Gr*mp"op{͸ky"mp~${#~͵#>|~0 0>.#>|Wr !RDM 5~#foR0&B8!~_ o g(:p  DMormal compile mode, type "Q".) From debug mode, any instruction (or instruction list) that is typed will be executed immediately, with registers preserved from one line to the next (including any changes made). All of the commands (beginning with a "/") a2%jmO:vGUu:vG!͘u"?j2AjNyy z`8>:vG͘u ͜p:Bjo !k"Gj6 pREAD:o ^#V#N#F#x>iw!kuybk*wMw͗zQ VERS !h@{~N#F+ws#r+q#p+>> 2cvɿN#( ASej#([ejH (LD B,'J') .DO(R.HL->R_PC;4->NGFLG) := .DO(LD B,'B') LSTBRKS := .DO(LD B,'B') GETCNT := .DO(LD B,'X') BRKSOFF := .DO(LD B,'X') ? := .DO(LD B,'T') Tr2 .DO(L* STCBNBITOP2ğWNͬ}NumHNumǡXCOMMBOptmNumجHNum顡XCOMMdOptPPPHNumPPCOpցGenZp3SavPReXPpnXcEff1hDbugDJASMSThCOMMAND>7LABELCOLhINST*XIN>y/Ox/G| <!.}GU͸ 'x #y N> 0O( O>+y${j>q>GrOA(*p{I ͯy${UU:rpG:p I(x2p͚z A=${N:qpG:p I(x2p͚z F=${NAx y ( P(WrBCD##R. ͕ O09n(ͫo0$͕ѩ +֩ ++R. ͕ O42n(ͫ/o8%#͕c 0BC ( DE ( ٜ w̓( HLd wR. A (? O47ru2ì͕R. *DE T]( BC DM(HL( ٜ :;<=>?@ [\]^ ` {|}~Ao>ZSejy08&o 09(SejdzAG8ag8 o g|(=8{N#ͬz*ej:gjO͕'("O"PzpTOO LONGSej ("z:ejG:gj~ {D (HL),3) := .DO(LD B,'H') NS2 HISTORY := .DO(LD B,'U') (.DO(LD A,(Deasm);R.A=0C3)) UNASM := .DO(LD B,'L') (GETNUM / .DO(W.LstDmp+1;00)) .DO(PUSH HL) "," .DO('H'->@^BUFF;INC HL) $(.DO(R.A->@HL;INC HL) .DO(( !Eþ yK*B BR0 !"û PYo (Eû + ~ +>R8!J !: (Zy(KB~(͵ `io (Z͵ S227:526͵ bk X RDMMWR#!J !I F>EHLIXIYSP!p ^#V!sp F#fhR O(}|͸! >={N͸>.͸bqby *mp2`pkkOUHY;q ( (͞O> v_ xy  Y>vR x{ (h /y ktz*fpw!pV {*op:`p(x Iˉ n -DE s#r+(BC }| ( v utra"ìġ^͔>E()*&p͐zĂ ͪ(+Īq(: p=/   (  ( () [dz302o]012tz ɯO~w~O#~ {#A8|${}${͗zH}-{'@Sgjkk> ͨrJ{|${:o_(or>;v> !kk~#= Kgj>!Kij#ȔDKB[Qj͙{SQj[gj"  ' ~͸y#B C >͸yA\|~1#(TKKjx(~A8 m} u8sr}( ͸y͸y~͸y#~͸y8R.A->@HL;INC HL)) .DO(EX DE,HL;R.HL->NEXTDE) .DO(LD BC,LCPSIR+4;NCODE+R.BC->NCODE;PUSH HL;Out();W.NCODE;POP BC;R.L-R.C->R.A;POP HL;RET Z) LocSub ; A0 := (.DO(R.H=0;R.L)) / IdDEF / .DO(00) ; D2: if GETNUM() <> then begin if @DE<>0D then R.A=','; w͈ p͵ (Z! I "K*#B 06#[R͈ ͵ (E!T ͏ HIT KEY TO REENTER:!J !: (5E*",".R"QU N [,*.R *".!o ( [.! *.~˿#".!+~=w*,"+ ɯ2*>T !Uwɯ2p!qpY;x_A WͯyͶy2p y YRv#+3;CKO#(-27ͱy##= 8{ͤzͭ͸m}~#fo*ejͼ}( ͐8G  Fz,Fz:#͐8 ~#fo(>>͐ [ej͐*ej>2pü}ت++x(.ͱyYP## x(ͻyت+x(ͯy_# x({Ͷy"Qj*Qj++ñyت"Qj++ͯy#ઁOͯyG3ઑOͯv +s#rp MIXED REFr} N#F0v(r+s*o `iF} s#røyp NOT DEFINEDB #øyH ~ z͸yO ~ (zGxøyV m}8 ~͸yD ͱyYP L*or}8 }w#w+|N#Fr+svx  4`i|ͱyͻa symbol. Immediately following the "J" is a condition code in hex followed by the symbol name, e.g. .OUT("J08SYM1") If the symbol is undefined, an in-place chain is established or extended for future resolution. 9. An initial W causes#6 Ͱ͈_:J̚:Să{!3C:*([0>!5w:6( d4:7O~S2*+> ##( A  >O0Ax iyMO WOG*2R O  yP8O>[0S0͜x<26:62:d !:4> yO*L>l8"wps}p"p*wpLj!Ppqp!qpPp!9qp !9!qpPY͸y![p-ySQjK͞+>bѯ*}pͱy`ib##= a("a ͯy(#s#r#wa+wѯ:p:yG'ડOͯyG_ͯygkPYz(R0+yYP+ͱy!xPyPͻyѯ)0!x) !Bͯy<Ͷy+xͶy+++yͶyتXQͻyѯ!tz {O)))) !)DM)) O dz(8{~#${*Qj+"Qjͯy8 pBIT>7G+ͯyͶy͕*Kj|qy:oGkk D pREDEFINED LABEL`iF}ͱyͶyyy( #KoB7R}$ }% }p OUT OF RANGE>2pT]> +ͼ}N#F+ѷRs#rx(`iRDMqp=~(#<_* p{GNͨ}^Vz(Cy x ( #f the following hex characters, taken in groups of 4, to be orred together and the resulting word put out to the code area, i.e. .OUT("W11112222") is equivalent to .OUT("H3333"). Using XMETA: Two global undefined symbols are provided to establish[2͜:625W>26=25*R(S2͜ :50:5G:62625W xB*B"R#DMx*R#DM"#[*RB0zfG( (#w S=qw!ͯw!͚~ <*~ *+G#=(p<>Ͷyͯy!&p####~#  x:p#~(=a>2p+N:pa2pa##Fw+Nw+~`iO y̶y!'p###~#~#  z( x <+++Gr!'p###~##(/ cr8{F+~+ng{ Uy=ĸWr*p"bpa ~XE%ͯy2"sÝ{*Qj"Kj*Oj"Qj!"Mj*Kj|"Qjgo"Kj:o:o= *Qj+ͯyO>Ͷyy( <]}++Ͷy2o*QjȔ*o[Qj:oG:o̯y̸y#>͸yͻy##"Qj>͸yͻyѯ8{[Gj (H*p:p *Sj:oO(Ko [GjFz "Ij{KIj x(B| }(͸}${2pp(NKSj7*QjB(:p n K^(]?Y:p R* p^#V+H ["p7R0?q!Ͳ~~ͨ}̓}:p w#w:p(>w>2ppTOO MANY SYMBOLS* pN#F+ DMB * pBp#w#* pRs#r@* p#ͫ~ ͓~0A~O^ f :p ~(n  linkage to the user's newly defined compiler extension. One symbol is called EXTEND. For example: EXTEND := "stay_here" .OUT("HE8FF"); will cause the compiler to generate the word 0E8FF whenever the string "stay_here" is encountered in places where G #=:7

P=27͠ɯ27͠:4!6 N:Q*[0:5!62T!T~(5!45ͧ> 25Ud́̓4͠:6= [*0R!!6~=5͠ɯ27<26͠ɯ27:426͠:7O yP8 O:4G!6~4y27+ [bpa≯y*|:X!"*p/͓͆͡~( #~,8 9(80^#~ #~# ##/~((( ( ##~(~" ####> *wp#+ ~ *yp *{p~(~(( #~#fo###:qpG~8 p(8 p 0 @(PE) zero then SET ZAPB,(IY+TYPE);1 end;CP A) ; LSTINT : ^DIAGSW;SET 6,(HL); 00->B.EQUFLG->R.H->R.L; R.HL->W.LSTLAB; RET SEG_E_RL := DEL "E=" .DO(R.HL->W.E_ADD) / "RL=80" .DO(W.080->W.F_RL) / SEGADR ; SEGADR := .DO(W.0->W.IOFFSET) {DEL {<SM!J5(5% *MB"M[K [M͚w*0R8(B"0*2R8B0bk"2 A͆w! #w  (;( q:J-^  ̭͡"@HS2*MBDM*KR0*MR8 :J=(-r*KR8*K "K*M "M*@ "@*@xX(LD B,OUT_LU) LD BC,BUFLEN if SIZE=R.BC then begin LD BC,(BUFP2); DEC BC; SAVCH->@BC LD BC,BUFFEND if BUFP0->R.DER.BC; ^BUFF-R.BC->R.HL->BUFP1 EX DE,HL; LDIR ...move part past CR to beforeC,B INC DE; INC B until R.A=0; DEC DE if R.C<>0FF then begin LD B,0; R.HL+R.BC->R.HL if R.E-R.L>=4 then R.HL+2+1->R.DE end else begin '.'->@DE; INC DE end LD (ENDFILNM),DE '0'->@DE; INC DE; 00->@DE RET S_END: BUFOVF: DEFS OVFSIZ BUFF: DEF( @ P(( P 0 x(8 x(~~0 :qpG:tpO~8#(,0 @($8 @  p(( p   (~( Ny(# #~~8og~( #~M(E( +~ *}p~#fo#*p a~ȯͿ[}p Ϳ( #ͯy=LKIDPL> .DO(R.L;CPL;LD L,A;R.H;CPL;LD H,A;R.HL+1->W.IOFFSET)} .DO(INC DE)} .DO(PUSH HL) .DO(POP BC) ; COMM := DEL ?("..." NOTCR) ; LABELCOL := .SAV(*) DSETDLR ?":" {QRULE / DEL EQUWBP / LABLRe}; LABLRe := .LABEL(Re) ; EQU27[M:J= *K 18'40#1O!K ^#V*R8*R8@E :J ^ s ͭ-E :J(T ͪH͐:6262527GOz( ~(> !BDMAͰ:J(^  ͡KK*MT]BDMA*0R0"[2*MSr .OUT("C Copy") SREND ; SREND := .OUT("'" Count) OUTSTARI ; OUTSTARI := .OUT("'" *) .DO(INC DE) ; CHKHSr := ""H" .DO(Hexd();RET NZ;PUSH DE;Sr();INC DE;POP BC;R.E-R.C->R.L;@DE=')';RET Z;R.A=',') ; ...CHKHSr checks for '"H[string of hex digits]") or ,'; S BUFLEN BUFFEND: DEFS 2 ORG S_END /MAP 8 /?"/IMAGE SPLIT.COM ",^S0," ",^S_END ET S_END: BUFOVF: DEFS OVFSIZ BUFF: DEFS BDE end else begin '.'->@DE; INC DE end LD (ENDFILNM),DE '0'->@DE; INC DE; 00->@DE RET S_END: BUFOVF: DEFS OVFSIZ BUFF: DEF*}pRد*ip|:hpX!"ipϊ(ш###"fp( *fpͯy2hp "ipsdpÉ8!dvͱyCp!fvͱyC}pL[p*ipR  {dp*R*kp|(ba +~(5~(1jÉ#~͸yb>l͇>̶y!98 !90:p(1kk*qp*wpWBP := .DO(B.IdLN()=4;JR Z,DFLWBP;R.A=3;RET NZ) "EQU" Ig .DO(SETTYP(EQUT)) ; DFLWBP := ("WORD" { .DO(SETTYP(WORDT)) / LABLRe .DO(SETTYP(WORDT)) WNR} / "BYTE" { .DO(SETTYP(BYTET)) / LABLRe .DO(SETTYP(BYTET)) BNR} / "PROC" {3) ...end funcs. with IRET ORG ROM NFUNCS: EQU 25 FUNCLST: ;WORD Open Close Read Write Getchar Putchar Printf0 Printf1 WORD Fadd Fsub Fmult Fdiv Fcmp Float Fix Sqlen.->L OutN: PROC P.Icopy;DEFT 'H';POP HL;LD B,(HL);INC HL;Outhex(@HL);INC HL;DJNZ $-5;PUSH HL;Out();RET ANDCL := $ ?( { $ / .OUT("H20","A1"#1,Re) $ .LABEL(#1) Zp Eff1}) ; QRULE := "=" LABLRe ANDCL $((":=" / "/") .OUT("HK>26=25*R(S2͐ :50:5G:62625K xB*B"R#DMx*R#DM"#[*RB0zZG( (#w S=qw!ͯw!͎~ <~ *+G#=(G #= ш>l͇!`p5 {}p*}pϊ ?08K}pB:`p8%]*p x CGrU NWr1ш[}pR01j:ap( y(a [paшi:p *p*wp!:p(!jvͻy*p*wpó:p :pay͏p1kksMj >*> .DO(SETTYP(PROCT)) / LABLRe .DO(SETTYP(PROCT))}) DEL ?";" := "DEFL" .DO(SETTYP(DEFLT)) ?(DEL "at" .DO(@IY(TYPE);PUSH AF) DXNCODE .DO(W.EQUVAL) OUTHHL (( .DO(PUSH HL) OUTA2ST .DO(POP HL) / .DO(W.OFFSET)) .DO(PUSH HL) N2INCS .rt Asctoflt Flttoasc WORD Sin Cos Tan Arctan Log Exp Power /SEG LIBFUNC: ...do library funcs. according to id on stack PUSHL RR2 if R2:=@RR14[4]&03F@RR14[2] R2:=MYSeg; R2:<->stk; RET end POPL RR2; IRET OC8") ANDCL) OUTRET ";" ; *ZAP ITEM ITEM0 ORCL ITEM1 ITEM2 OUTPT TRUEITEM SR1S OUTP1 OUTP2 OUTBEG *ZAP OUTITEM DOTDO PROCITEM CHKHSr ANDCL *PACKALL ASMST := (("*" / "/") COMMAND / LABELCOL INSTLIST) COMM / COMM .DO(@DE=0D) ; COMMAND := CMD1 / IMMX ; CMD1 =:7

P=27͠ɯ27͠:4!6 N:Q[0ͽ:5!62T!T~(5!45ͧ> 25UX́w4͠:6= [*0R! !6~=5͠ɯ27<26͠ɯ27:426͠:7O yP8 O:4G!6~4y27͠:7 !6...program to split big file into smaller ones (<=BUFLEN) ... (splits at CR or double CR if can) ... Usage: SPLIT FILENAME ... Result: FILENAME.1, FILENAME.2, FILENAME.3, etc ... (if FILENAME has .TYP, digit added at end or replaces last character if ... DO(POP HL) OUTHHL MIN2 / HXWN) MIN2 .OUT("D"Re PLUSIN) RESNCD .DO(POP AF;R.A->@IY(TYPE)) / Ig) ; DEFIT := DXNCODE (("1.".DO(00)/"2.".DO(1)/"s.".DO(B.PROGBK)) .DO(CPL;R.A&1->R.B;B.CODEBK=R.B;CALL Z,EQOTHR) / NN2I_E) .OUT("D"Pp) .DO(1->B.EQUFLG;@2IY->Wpen: PROC RH0:=RL5; LDL RR4,RR2 R3:=@RR14[2]; if R4=0FFFF or BIT R3,15 zero then R4:=@RR14[4] ...nonseg test only for compatibility, may remove later R1:=0; RL0:=OPN; IOREQ() RL3:=RH0; RH3:=0 JR OPCLX ... Close: PROC RH0:=RL3; R1:=0; RL0:=CLS; IOR:= "MAP" .DO(if @DE='A' then INC DE; R.A->B.MAPTYP) MASK Map := "ZAP" DEL {ZAPALL / $(DEL )} := "PACK" DEL {"ALL" .DO(1) / .DO(00)} .DO(R.A->B.PAKSW) MASK PACK := "LIST" DEL {"OFF" .DO(^DIAGSW;RES 6,(HL)) / "ON" LSTINT / Quit2 {"END" / LSTI1ͺv|qvÀqV2.07. tdd disassemblerYrrdi {i Ói pj j j j" 7k 6 w * KDDDS $OeKKG]G;D DSKD(*** l:KK CLL3HfW""+L $O"  Ktype is full 3 chars.) S0: PROC LD SP,MYSP; SPLIT(); JP SYSRET ORG S0+0100 MYSP: /DO SYS.EQU NLUS: EQU 2 ...for ZDOS.S /DO ZDOS.S BUFLEN: EQU 09000 OVFSIZ: EQU 0400 IN_LU: EQU 0 OUT_LU: EQU 1 SAVCH: BYTE 0 FILNM: BYTE 0[15] OFILNM: BYTE 0[20] ENDF+ .EQUVAL) RESNCD ; EQOTHR := (.DO(@^CODEBK;PUSH AF;CPL;R.A&1->@HL;CHKDEF();POP BC;R.B->B.CODEBK)) OUTHHLI ; DEFAT := DEL "at" ? ; PLUSIN : '+'->@DE; INC DE; RET ...WBP := .DO(IdLN();R.A=4;RET NZ) ... "WORD" .DO(SETTYP(WORDT);LD DE,(LASTDE)EQ() R3:=0 OPCLX~ RL0:->RL5; RH5:=0 if RL5<>OK then R3:=-1 IRET Read: PROC RL0:=RD; JR RW2 ... Write: PROC RL0:=WRT RW2~ RH0:=RL3; LDL RR2,RR4 R5:=@RR14[2]; if R2=0FFFF or BIT R5,15 zero then R2:=@RR14[4] ...nonseg test only for compatibility, maNT ?( .DO(LD DE,(LASTDE)) LFILOPN VDATE NOTCR)}} := "BANK" BK_P2 := "IF " IMMXIF .DO(R.A->B.Skip) "THEN" := "ELSE" .DO(^Skip;1-@HL->@HL;CP A) := "ENDIF" .DO(00->B.Skip) := "BRKS->" ("Q" Q_B / "P" P_B) := "RESET" DEL "EXTEND" .DO(@^CODEBK;PUSH * O0* 0(  0>wk~kBinfFN~h #x ^VBi~ ͉:_͉!A$=(x͉ͫ0xͫ  >xͫ  ͉>O͉0#͉!!ILNM: WORD 0 BUFP0: WORD 0 BUFP1: WORD 0 BUFP2: WORD 0 SIZE: WORD 0 SPLIT: PROC GETFILNM(); RET NZ if OpenF(LD B,IN_LU; ^FILNM) not then begin PRT0(^OPNERR); RET end ^BUFF->BUFP1 LOOP: ...repeat if ReadF(LD B,IN_LU; LD DE,BUFF; LD HL,BUFLEN)->SIZE n) ... := "BYTE" .DO(SETTYP(BYTET);LD DE,(LASTDE)) ... := "PROC" .DO(SETTYP(PROCT)) DEL ?";" ; IdLN := .DO(W.LASTDE;EX DE,HL;R.L-R.E;CP A) ; DSETDLR := DEL .DO(W.NCODE->W.DOLLAR) ; INSTLIST := $(DEL ";" INST) ; INST := SINST / XINST ; QINST := Ry remove later IOREQ() R3:=R1; RL5:=RL0 if RL5<>OK and RL5<>EOFERR and RL5<>NOCHAR then R3:=-1 IRET Getchar: PROC PUSHL RR0; R0:=0*0100+RD; RH3:=0 JR GPCHAR ... Putchar: PROC PUSHL RR0; R0:=1*0100+WRT GPCHAR~ PUSHL RR4; PUSHL RR2 LDL RR2,RR14; R3:AF;LD (HL),0;NLKUP(W.LASTDE);LD BC,EXTADR;LD (HL),C;INC HL;LD (HL),B) .DO(LD (IY+TYPE),2**UNDEFB;POP AF;R.A->B.CODEBK;00->@BC;INC BC;R.A->@BC) := "IMAGE" DEL .DO(LD (FILNM),DE;repeat @DE;INC DE until R.A=' ' or R.A=0D;DEC DE) FINBUF .DO(W.0->W.E_ADD;^w#w#w(>V#N#~$#~+: ~@##>b~. #>b>t >Gx( ~̀ #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ xͫ((#͉!!OW_}T]Oů)lau!t"w#ot then begin if R.A<>EOF_ERR then begin PRT0(^RDERR); RET end end LD BC,BUFLEN if SIZE=R.BC then begin LD DE,BUFFEND; LD BC,OVFSIZ repeat DEC DE until @DE=0D and begin DEC DE; @DE=0D; INC DE end or begin DEC BC; R.B|R.C BUFF end else ^BUFF->BUFP1 end end ... until SIZE0 do begin PutC(R.A); INC HL end RET USGMSG: DEFM 'Usage: SPLIT FILENAME'; BYTE 0D 0A 0 OPNERR:+3 R1:=1; IOREQ(); POPL RR2 if R1=0 then R3:=-1 ...if EOF on read or other error POPL RR4; POPL RR0; IRET FLTPRSZ: EQU 13 ...len of ascii string representing floating pt. no. ...Printf uses PRTBUF Printf0: PROC ...save regs. on stack R15:-28; LDM RECL->W.F_RL;^SegDes->W.SDesPs) $ .DO(W.0->R.HL->R.BC) SDesSb2 IMGSUB := "/" Quit P_B RETSYS := "*" DBUG0 := "EOF" FILDN0 := "START " Quit .DO(W.NCODE;PUSH HL) .OUT("HC3") .DO(JP GOX) := "CLEAR" TABINT := "DIAG" .DO(^DIAGS3x( >!N  3x( >"N  S?)lgxͫ!!G͉H͉ 4 # (  >>K?BP!(!! " !"( (!&*B R end zero; if R.B|R.C zero then begin LD DE,BUFFEND; LD BC,OVFSIZ repeat DEC DE until @DE=0D or begin DEC BC; R.B|R.C end zero; end if R.B|R.C zero then begin LD DE,(BUFFEND); LD (BUFP0),DE; 0D->@DE; INC DE e DEFM 'OPEN ERROR'; BYTE 0D 0A 0 RDERR: DEFM 'READ ERROR'; BYTE 0D 0A 0 CREATERR: DEFM 'CREATE ERROR'; BYTE 0D 0A 0 WRTERR: DEFM 'WRITE ERROR'; BYTE 0D 0A 0 GETFILNM: PROC ^INPTR->R.HL LD C,(HL); LD B,0 ...len. R.HL+1->R.DE 0D->@(R.HL+R.BC) ...make @RR14,R0,14 R15:-10; PUSHL RR2 LDCTL R3,NSPSEG; LD RR14[12],R3 LDL RR2,RR14[46]; LDL RR14[8],RR2 LDL RR2,RR14[42]; LDL RR14[4],RR2 ...move down ret. PC & FCW POPL RR2; IRET Printf1: ...do printf, then restore regs. from stack; must call after PrintfW;SET 3,(HL)) := CMDR := "LOAD " .DO(1) DOSUB2 := "DO " DOSUB ; DOSUB : 00->R.A DOSUB2 : R.A->B.DOFLG; LD (FILNM),DE; NOTCR(); LISTCHK(); JP NEWFIL MASK := .DO(W.0->W.MAPBEG;R.HL-1->W.MAPEND) RANGE {GETA / .DO(00)} .DO(AND value(2**ZAPB;CPL;LD L,A);R.  ( x x  ( x x [S> S2>S K! "K*B(~[9 >@<!(!3K*B[(!Bͽ*B 3K :*T]B 0!⚷RDM! B"! "*B ͽ~(#nd else begin INC DE; LD (BUFP0),DE end @DE->SAVCH; CPMEOF->@DE; INC DE; LD (BUFP2),DE end else begin LD BC,(SIZE); ^BUFF+R.BC->BUFP2 end LD BC,(BUFP1) if BUFP2-R.BC not zero then begin LD DE,(ENDFILNM) if @DE='9' then 'sure CR at end of input in sys cmd buff while @DE=' ' do INC DE if @DE=0D then begin PRT0(^USGMSG); OR 1; RET end SAVE_NAME() ...save input name SAVEONAME() ...save output name 00; RET SAVE_NAME: PROC PUSH DE R.DE->R.HL repeat INC DE until @DE=' '0 ...above on stack: #args*2, args (1st highest), regs, prev prog status LDL RR8,RR14[4]; R15:+8 ...RR8=ret. addr where have string R11:=@RR14 ...stk offset 1st arg. (=#args*2) RL1:=@RR8; RH1:=0; R10:=R1 ...string len. R9:+1 LDL RR2,RR8; R3:+R10+1A->B.MAPCMP) {GETA / .DO(B.MAPCMP)} .DO(R.A|2**ZAPB->B.MAPMSK) RANGE ; RANGE := DEL "R=" { .DO(R.HL->W.MAPBEG)} {"," .DO(R.HL->W.MAPEND)} ; ZAPALL := .DO(B.IdLN()=3;RET NZ) "ALL" MASK .DO(00;while NXTsym() do begin if BIT UNDEFB,(IY+TYUsage: SPLIT FILENAME OPEN ERROR READ ERROR CREATE ERROR WRITE ERROR !N#T]> w  !{͞bk ( {8>(O!!T]. H y( {8###T]>.S>0Irͥz/IMAGE SPLIT.COM !{@' R.A+1->@DE if CreateF(LD B,OUT_LU; ^OFILNM) not then begin PRT0(^CREATERR); RET end LD BC,(BUFP1); BUFP2-R.BC->R.HL if WriteF(LD B,OUT_LU; LD DE,(BUFP1); R.HL) not then begin PRT0(^WRTERR); RET end CloseF or R.A=0D; if R.E-R.L>=15 then 14 if not zero then begin R.A->R.C; LD B,0; LD DE,FILNM; LDIR end 00->@DE POP DE; RET SAVEONAME: PROC ^FILNM->R.HL; LD DE,OFILNM; LD BC,15; LDIR ^OFILNM->R.HL->R.DE LD B,0; LD C,0FF repeat if @DE='.' then LD , re also valid. In addition, there is a set of special debug commands, described below: In all commands below, "address" takes the form of a constant expression with an optional "n." prefix, n being the segment number. If left off, then if the constant ees ahead. This might be necessary if there was code at the next code location still to be executed, as in the following situation: *B ABC *CALL ABC (this actually generates CALL ABC + some code to get back to the debugger) After the break at ^ABCCR P.PRCBL1; R.E=ESC; RET ...blank out "_"; Z=1 if last char.=escape CKCMDT: ...chk if cmd. R.A in table @HL (if R.A=lower case, made upper) if R.A>=060 then RES 5,A LD C,(HL); LD B,0; INC HL; CPIR; RET CHKCMD: ...chk if R.A=valid cmd. starting char. with the values as shown with the "R" command. Note that regular jump or call instructions may also be used to start execution (without initializing the registers). R ............. displays the values of the registers that have been saved followts. to 2nd char.) R.A=ESC; RET Z ...ret. if escape R.A->R.E ...save 1st char. CHKCMD(R.A); RET NZ ...check if char. valid; print "???" if not ^CMDBUF->R.HL; LD D,0 ...init. pos. in cmd. buffer LD A,LCOL-R1-1 ...last col. in cmd. line buffer (leavxpression contains a segment number (from a symbol), then it is used as the segment; otherwise, the current segment where code is to be put out is used. If the constant expression consists of a number, it is assumed hex and no leading "0" is required (unl, there still remains code to be executed when ABC eventually returns. Thus, to execute something else at this point (prior to doing a "Go"), one should do: */TEST(2) (or whatever) 5. When starting execution in the debugger, care must be taken that for on cmd. line CKCMDT(^CMDTB2); RET Z ...chk list of reg. cmd. line cmds. if R.A<>CR and R.A<>'X' then begin CKCMDT(^CMDTBC); RET Z ...chk cursor move cmds. (not CR or 'X') end QSTION: PRCMR0(^TXTQST); OR 1; RET ...print "???" on right part cmding a break or after an "N" or "S" command. See also "R Rn" below. R Rn .......... allows changing of the stored registers. Rn is either one of the word registers R0...R15, or "R FC","R PC", or "R N4". Memory where the registers are stored is disping 1 for CR) P.FILCL2; RET Z ...fill buffer; ret. if not to execute XEQCML: ...execute cmds. on cmd. line ^CMDBUF XCMLLP: R.HL->W.CBUFPS; EX DE,HL ...DE=pos. in cmd. buffer (for parsing) TONOSP() ...rets. R.A=char @DE CHKCMD(R.A); RET NZ ...check ess there is a symbol with a name the same as the number). Also note that in these commands, where an address or count follows the initial command symbol, an intervening space is required. The command symbol may be capital or small. D address,n ... disp the segmentation mode is set right. If starting with a "G" or "J" command, the mode will be taken from the stored Flag and Control Word (FC) (in which bit 15=1 implies segmented). If starting up with an instruction entered for immediate execution, the m. line; Z=0 EXTN: ...do extension B.TAGFLG=0; JR NZ,QSTION ...must not be tags present W.EEX0=0; JR Z,QSTION ...chk if EEX defined P.JPHL; LD (CBUFPS),DE ...call EEX if defined to parse cmd. JR NZ,QSTION ...no valid cmd. P.FNDPOS ...pos. in bufflayed with the cursor underneath that corresponding to the register named, the same as when changing memory with the "D" command. Above: "FC"=flag & control word, "PC"=segmented program counter (long word), and "N4"=nonsegmented/normal R14. H n .if valid char. INC DE ...pt. to 2nd char. of cmd. CMD(R.A;^CMDTB2) ...go to routine according to 1st char. ^CMDTBC; CALL NZ,CMD ...possibly cursor move or mode enter cmd. W.CBUFPS ...char. starting or at end of string in prev. cmd. repeat @HL=CR; lays n lines of memory, 16 bytes per line and showing both hex and ascii, starting at "address". ",n" is optional and defaults to n=1. If "D" alone is typed, one line starting at the value of the stored program counter (R_PC) will be displayed. ode will be set to be the same as the mode currently set for code being compiled. Also note that that in the first case above the stack pointer will be taken from the stored R15 (or RR14), while in the latter case, Y's stack pointer is used if the code iser->DE W.ECODE0=0; CALL NZ,JPHL ...go to ECODE if defined to do cmd. FIXEOF() ...make sure 'FF' at EOF, CR before, & CR before beg. of text if P.CHKIN not zero then LD DE,(ENDDAT) ...make sure DE in buffer P.LOCPRT ...if char. at DE off screen, pri.......... history: displays the last n addresses or values on the stack (including corresponding symbol names if any) following a break (or step, etc.). If n is not given, it defaults to 1. L address,hh .. locate a string in memory, displaying memorRET Z; INC HL until R.A=';' ...find end of prev. cmd. ...if another cmd follows, HL->first char., else ret. JR XCMLLP FILCL2: ...enter with HL=start of cmd. buffer; R.E=1st char. ... R.D=starting col. for cmd. line; R.A=last cmd. line col. ...fil A special case of this command is when either n=0 or there is a comma with nothing following. One line is dumped and the cur- sor positioned under the 1st byte. The cursor may be advanced by typing a space or tab (to advance to the next word) or  in the same segment as Y, else a default stack pointer at the top of memory in that segment is used. Miscellaneous Notes ------------------- 1. Normally written procedure calls in Y, i.e. ABC() as opposed to assembly language CALL ABC or CALR ABC, nt so in middle CALL Z,PRSCRN ...else reprint screen NULL: RET ...null cmd. just rets. JPHL: JP (HL) ...jump to addr. SPC: ...move R.DE past spaces; ret. Z=0 if none, else Z=1; R.A=char. @DE @DE=' '; RET NZ ...no spaces repeat INC DE until @DE<>' y where found; hh is an even-numbered length string of hex digits, each pair representing a byte in the string. The search starts at "address", or, if "address" is left off, after the starting address of the most recent line dumped. Examples: l cmd. buffer, at same time printing out on cmd. line ...return Z=1 if to abort without executing, else Z=0 R.HL->W.CBUFPS; R.A->B.LCMCOL; LD C,D repeat if R.E=BKSP then begin ...if backspace W.CBUFPS-1->W.CBUFPS; LD (HL),CR ...update CBUFPS;  backed up using the backspace. Memory can be changed a nibble at a time by typing the desired hex digit when the cursor is in position. Hitting return or line feed completes the operation and displays the changed line. Line feed additionally caus, where ABC is undefined, normally generate the CALR instruction, which means ABC must be defined within 01000 (hex) bytes. (If ABC is defined, the appropriate call will be generated.) Thus, in large programs, it is recommended that lower-level routines be '; CP A; RET TONOSP: ...enter with R.DE in cmd. buffer; search for 1st char. not space ...return Z=1 if not CR or ";", else Z=0 (R.DE pts. to char; R.A=char) P.SPC ...go to 1st char. not space if R.A=CR or R.A=';' then begin OR A; RET end ...if CR o *D 2.2000 ...display 1 line (16 bytes) starting at address 02000 in segment 2 *D 4010, ...display 1 line starting at address 04010 in current segment and place cursor underneath in position for changing memory *L 5000,313233 .store CR there P.PRCBL1 ...blank out "_" DEC C ...R.C=prev. col. R.D=0; PUSH DE; LD DE,CMDBUF CALL Z,FNDCOL ...if doing main cmd buffer, get R.C=col. prev. char ...note: there should not be any tabs if doing "X" cmd buffer es the operation to be repeated on the next line. B address,n ... sets a breakpoint with a repeat count of n at "address". There may be a maximum of 8 different breakpoints at one time. A repeat count of n means the break will not occur until the placed ahead of higher-level ones. To call ahead >01000 bytes, make sure the first reference to the symbol is absolute, i.e. made with a CALL instruction; then following normal procedure call references to the symbol (before the symbol is defined) will alr ";", Z=0 CP A; RET ...set Z=1 FNDSPC: ...move R.DE to 1st space or "," (put in R.A) ...if CR or ";" found first, ret. Z=0, else Z=1 @DE=' '; RET Z R.A=','; RET Z if R.A=CR or R.A=';' then begin OR A; RET end INC DE; JR FNDSPC PUTHEX: ...R.A conv..search for the string '123' (hex 313233) starting at address 05000 in the current segment *J ABC+2 ...start execution at address ABC+2, restoring registers first *N 4 ...execute next 4 instructions in step mode Notes: 1. Upo POP DE; POSCRS(R.C;LD B,0) if begin R.C=R.D; '_'->R.A end then ' '->R.A PUSH AF; PUT1(R.A) ...delete prev. char.; print "_" if <>col. 0 P.RETCRS; POP AF; RET Z ...return cursor; ret. if 1st col. end else if R.A<>0 then beginnth time the breakpoint is hit. (After the break occurs, the repeat count is left at 1.) ",n" may be left off, with n defaulting to 1. In addition, just typing "B" will cause a listing of all the currently active breakpoints. X address ..... remoso be made absolute. 2. Before a symbol is defined, all references to it must be of the same type; that is, either all 8-bit references, as in JR instructions, 12-bit references, as with CALR, 16-bit absolute references, or 16-bit relative referenceserted to hex & the 2 hex chars. put out PUSH AF; RRA; RRA; RRA; RRA; P.HBTHEX; POP AF HBTHEX: R.A&0F|R.A; DAA; R.A+0F0+carry+040; PUT1(R.A); RET DIGIT: ...test for an ascii digit @DE (returned in R.A); if so, Z=1, DE=DE+1 @DE='0'; RET C; if R.A<>'9' then entering Y, breaks (opcode "0E00") are set to go to the Y-debugger (unless another break-handler, such as another copy of Y, is getting them). This can be overridden with the commands /BRKS->Y to send breaks to Y, and /BRKS->P to send them to wherever th ...ignore null chars. LD L,C if R.A=TAB then begin R.D=0; JR NZ,FILCL3; TABPOS() end ...get C=col. of next tab pos.-1 (no tab allowed if "X" cmd) if begin B.LCMCOL=R.C; LD C,L end >=zero then begin ...check if will fit in space oves breakpoint at "address". "X" by itself causes all breakpoints to be removed. N n ........... execute next n instructions (after a breakpoint has been hit or a previous step) displaying registers that change. If n is not given, it defaults to 1. This is because, depending on the type of reference, a particular type of chain is set up which is used to resolve the references when the symbol is eventually defined. 3. The same copy of Y can be made to run in any segment. To get Y to be loadedn RET NC INC DE; CP A; RET HEXD: ...same as DIGIT, but testing for a hex digit P.DIGIT; RET Z R.A='A'; RET C; if R.A<>'F' then RET NC INC DE; CP A; RET NUMBER: ...enter with a digit in R.A ...get more digits from @DE (incrementing DE) as long as theey were previously going. On leaving Y, breaks are again sent to the previous place. 2. During execution of a multiple step command, e.g. N 255 or S 255, `escape' can be pressed to cleanly abort the operation at that point. 3. If necessary, the den cmd line (not last 15 cols.-1) W.CBUFPS; LD (HL),E ...put new char. in cmd. buffer PUSH DE ...save D R.HL->R.DE; INC DE; LD (CBUFPS),DE ...update CBUFPS 00->B.ROWNO; P.CONOUT ...print out new char. (updates R.C) POP DE; PUT1('_') ...print . S n ........... same as "N" above, but skips over procedure calls. G ............. resume execution after a break--or any time there are valid values for the saved PC, SP, etc. (as shown with the "R" command)--with all registers restored. Note: i into a particular segment, you must change the segment number in the entry_point field in the header (see Object File Format below) to the segment you wish it to run in. (A program may be provided for this purpose.) The most common Y currently is initiare are more ...calculate value of number, return in R.HL; set Z=1 W.0 repeat R.HL*2->R.BC; R.HL*2*2+R.BC R.A&0F->R.C; LD B,0; R.HL+R.BC->R.HL until P.DIGIT not zero XOR A; RET HNUM: ...same as NUMBER but with hex digits W.0 repeat if R.A>='A' thbugger's stack pointer can be reset by doing "Q", then "/*". 4. Normally when an instruction list is typed following the "*" (for immediate execution), the code goes at the next code location. However, if a "/" is typed first, it will be offset 64 bytout "_" as "cursor" R.C-1; CALL Z,TAGSHW ...because CONOUT clears line when col=0 P.RETCRS ...return cursor end end endif FILCL3: until B.P.GETCHR->R.E=CR or R.A=ESC; ...get new char. until CR or esc. W.CBUFPS; LD (HL),CR ...put in f R_PC is at a set breakpoint, a "Next" will be executed first in order to restore the breakpoint; otherwise will just "go". J address ..... sets the stored program counter (R_PC) equal to "address", then begins execution, initializing the registerslized to run in segment 1. 4. Y currently is made to reside in memory from 05000 to about 0C400, with approximately 0C400 to 0F000 allocated for the symbol table and 0F000 to approximately 0FA00 allocated for ram buffers. The initial ORG (place where- en R.A-7 R.A&0F->R.C; LD B,0; R.HL*2*2*2*2+R.BC->R.HL until P.HEXD not zero XOR A; RET LOCSTR: ...enter with DE->pos. in text; HL->DEFT 'STR'; BC=no. bytes to search ...if BC>space in buffer, just search to end of buffer ...ret. HL same; if string m z.OUT( ͪ.LABEL( LԎ.SAV( ([C SavR{ Ͳ}E$ Lͽb(A1ͽ?b" z ͋(͔ M={##P{[(ͪ([( , ͪp ̈́C OutsST ...ST=0 ... PUSH HL ...HI_ADD to be kept on stack (init. set=0) ... R.HL-1->W.LO_ADD ...init. set LO_ADD to 0FFFF ... ^SegDes ... ...get HI_ADD=max of HiAdd's of each seg.; LO_ADD=min LoAdd's: ... ...HiAdd for each segment=BegAdr+((SegLen-1)&(0-RL))+AME() ...if name=string+'0', change to deft if ISDEV() then ...chk if name=device name (RR8=^entry ADT) LDL RR8,@RR8 ...get device addr else begin SETB @RR10,ISFILB LDL RR8,#MYSeg,FILES ...file handler end LDL RR10[DEVADR],RR8 ...store adBBSE+2,#05000 The symbol table may now be re-imaged (along with the rest of Y if desired) between the addresses 02000 and 02000+@02000-1 . 7. Whenever Y is printing to the console, the printing may be stopped/ started by hitting either '?' or RETURN. found, DE->1st char., Z=1 ...if not found, DE->after last char. searched, Z=0 P.CHKIN; RET NZ ...chk if DE in text in buffer @HL=0; RET Z ...str. len=0 PUSH HL; P.MINBC; POP HL ...BC=min.(BC,dist. to EOF) if R.B|R.C zero then begin INC A; RET end et͕" z >͋x* C Copyin#1 C GenRFzC ͤz.DO(͕; (["zzC Copy'z'ͤz"Htzz{o),͗zHF#~${#P{(ڍ 2 ((% A1ͽ8{7(Lͽ͆(RL-1) ... while GET2W() not zero do begin ...go thru segment descriptors ... ...GET2W rets. DE=seg beg adr, BC=seg len ... PUSH HL; PUSH DE ... if W.LO_ADD-R.DE>=zero then LD (LO_ADD),DE ...chk if new LO_ADD ... DEC BC; LD DE,(F_RL); W.0-R.DE ..C (HL); RET ...set BLCMRF (@HL) to 2 WAIT: ...wait for keystroke; if not escape, go do next cmd. on cmd. line ...else return to cmd. mode P.HITKEY ...print "HIT KEY" on cmd. line P.WAITCH ...wait for char. from keybrd; test esc.; blank cmd line msg. In addition, hitting ESCAPE causes the current operation to be aborted with control transferred to the debugger. 8. Object File Format: Note: Y generates the stripped format without any relocation information and symbol table. HEADER: word MAGICNO=...if at EOF EX DE,HL; P.CPSIR; if zero then DEC HL ...do search EX DE,HL; RET NEWSTR: ...enter with DE->text; R.A=no. chars. to delete starting curr. pos. ...(don't del. past ENDDAT); R.HL->DEFT 'STR' to insert at current pos. ...if DE not in text, = &E:=(/  (G;* (/ O(Ȕ VmMAP A 2oK͝ZAP ͕͎(͕Fz 3(PACK ͕ALL >(2pK;~LIST :͕OFF !o˶(ON̴( ͟pEND(ʹX [ejZw͖y͎BANKyIF INST / XINST ; SINST := DSETDLR .DO(W.EXTADR) Latch2 / RINST ; RINST := DSETDLR .DO(R.A=2;JP Z,INST2;R.A=3;JP Z,INST3;R.A=4;JP Z,INST4;R.A=5;JP Z,INST5;R.A=6;JP Z,INST6) ; INST2 := "LD" DEL := "JP" DEL (.OUT("OC2"ORe3) / R.C; P.BLCMR0 ...get char. from cons.; blank "HIT KEY" msg R.C=ESC; RET NZ ...ret. if not escape ABTCML: ...enter here with R.A<>0 R.A->B.ESCFLG ...so XEQ cmd. knows there was escape NXT0E007; long IMGSZ,UDATASZ; word SEGTABSZ; long ENTRY_PT word HDRFLG,RELOCSZ,SYMTABSZ,UNUSED where MAGICNO=magic number IMGSZ=image size UDATASZ=size of uninitialized data SEGTABSZ=size of following SEGTAB (segment table) ENTRY_PT=entry point HDRor after deleting, no room to insert, ret. Z=0 ...do, adjusting ENDDAT; ret Z=1, HL same, DE->after last char inserted P.CHKIN; RET NZ ...chk if DE in text PUSH HL; PUSH DE LD C,A; LD B,0; P.MINBC ...BC=min.(R.A,dist. to EOF) EX DE,HL; R.HL+R.BC; EX x2 pTHENELSE ! p>wENDIF 2 pBRKS-> Q y( P yRESET +͕EXTEND!p~6*ejͼ}$pq#p62pIMAGE <͕Sv ( w!"$h!"h!8h"hÒ(!DMӭ̀y/ ͜pyͬy* EOFxSTART ͜p*QjN>.OUT("HE9") / .OUT("HC3")) := "JR" DEL {.OUT("O20"ORe3) / .OUT("H18")} := "CP" .DO(P.SavB;DEFB 7) := "EX" DEL ("DE,HL".OUT("HEB") / "AF,AF'".OUT("H08") / "(SP)," ("HL"/IXY) .OUT("HE3")) := "OR" .DO(P.SavB;DEFB 6)LIN(LD DE,CMDBUF) DEC DE; LD (CBUFPS),DE; RET ...pt. CBUFPS to end of cmd. line SHOW: ...print screen, either showing CR's as "~" or tabs as "~"+spaces if begin @DE & UPCASE='T'; LD A,'~' end then begin ..."ST"=>show tabs R.A->B.SHOWTB; P.PRSCRN; 'FLG=flag: bit 0=1 =>reloc. info + symtab stripped (execution addr fixed) bit 1=1 =>stripped plus may run in any Z8000 segment (uses segment of ENTRY_PT) RELOCSZ=size of relocation information SYMTABSZ=size of symbol table SEGTAB: ...segment t DE,HL; P.SHFTBK ...delete POP DE; POP HL; LD C,(HL); R.C=0; RET Z ...BC=no. chars. to insert PUSH HL; PUSH DE; P.SHFIFR; POP DE; POP HL; RET NZ ...shift file fwd. LD B,(HL); PUSH HL ...B=no. chars. to insert repeat INC HL; @HL->@DE; INC DE until D͝óCLEAR̤~DIAG !oaLOAD >;DO 2pSv͎ͻåw!"o+"op̟(2o̟(:o 2o͕R=ͧ "o, ͧ"oͲALL K͏ ^ >!o2pgo"Ij͕E= ͧ"$hRL=80 !"h!"h͕R  }/o|/g#" := ("RL" .DO(P.SavB;DEFB 2) / "RR" .DO(P.SavB;DEFB 3)) := "EI" .OUT("HFB") / "DI" .OUT("HF3") := "IN" DEL ("A,(" ("C)" .OUT("HED78") / .OUT("HDB") ) / .OUT("HED","O40"ORe3) ",(C)") ; INST3 := "RET" DEL {.OUT("OC '->B.SHOWTB; RET end R.A->B.SHOWCR; P.PRSCRN; 00->B.SHOWCR; RET QUIT: ...quit edit session @DE & UPCASE='U'; JP NZ,QSTION ...must be "QU" INC DE; ^DUNFLG; INC (HL) ...set DUNFLG=1 if P.SPC and R.A & UPCASE='N' then INC (HL) ...if "QU N", don't RDERR2: PUSH AF; Quit() ...close files (return to console after CALL Err) if begin B.FILTYP; BIT 5,A end zero then begin ^DATA1->W.LASTCR; LD (HL),0D ...for printing if not ascii file end POP AF; CALL ERRMCC; DEFT 'READ' NEWLU: ...puts old (or newEC B; ...move in new string POP HL; RET CHKIN: ...ret. Z=1 if EBUF<=DE<=ENDDAT; else Z=0; save all regs. PUSH HL if W.ENDDAT-R.DE>=zero and W.EBUF-carry-R.DER.BC; RET .- hͧͧέ͕...̎Fz !8{ͤz;: (͕MEL7Ͳ(EQU9D>WORD ͜ >( E>ͬ(BYTE ͜ >( E>(PROC ͜ >(E> ͕; DEFL \9>͕at F~*pI{I 0"ORe3) / OUTRET} := "POP" .DO(P.SavB;DEFB 1) := ("INC" .DO(P.SavB;DEFB 0) / "DEC" .DO(P.SavB;DEFB 1)) DEL := ("SUB".DO(P.SavB;DEFB 2) / "AND".DO(P.SavB;DEFB 4) / "XOR".DO(P.SavB;DEFB 5)) := "ADD" DEL ( "," .OUT("O09write out file (DUNFLG=2) B.TAGFLG=0; CALL NZ,TGSOFF ...remove tags if present POSCRS(00;LD B,LROW); ERASL() ...cursor->last line & clear it RET .TAGFLG=0; CALL NZ,TGSOFF ...remove tags if present POSCRS(00;LD B,LROW); ERASL() ...cursor->last li) logical unit no. in input vectors ... R.A->B.FILINO ...input open vector (comment since ^LOGUN=^FILINO) ... R.A->B.FILASN ...assign vector ... R.A->B.FILRD ...file read & wait vector ... R.A->B.FILIN ...file read & no wait vector RET CHKRD: repeat unti..BC=min.(BC,ENDDAT-DE) LTOCR: LD BC,0; PUSH DE while @DE<>CR do begin INC DE; INC BC end POP DE; RET ...BC=dist. to next CR .... i-o vectors: ...ATTR: ...file attributes returned next 5 bytes ...FILTYP: BYTE 020 ...file type ...NUMREC: WORD 0 ..ͬ( *o I{ĝD7ͭwD1. (2. >( s. : p /G:p̃0 D?>2pnf"pFz!p~/w[x2p*͕at9D>+Fz*ej}͕*Qj"cjܔ͕; ܔ(ןן;*$p͐z;Ͳ"ORe4) / .DO(P.SavB;DEFB 0) ) := "ADC" .DO(P.SavB;DEFB 0A) (ADSBC2 / .DO(P.SavB;DEFB 1) AROP2) := "SBC" .DO(P.SavB;DEFB 2) (ADSBC2 / .DO(P.SavB;DEFB 3) AROP2) := "BIT" .DO(P.SavB;DEFB 8) := "SET" .DO(P.SavB;DEFB 018) := "RES" t when free SNDFIO2: ...enter here with bucket already gotten PUSHL RR6 R7:=DATA RL0:=IOCODE; OUTB @R7,RL0 OUTB @R7,RH1; OUTB @R7,RL1 ...LU,cmd OUTB @R7,RH2; OUTB @R7,RL2; OUTB @R7,RH3; OUTB @R7,RL3 ...RR2 R6:=R13 OUTB @R7,RH6; OUTB @R7,RL6 ...R1l B.RDFLG=0; RET ...loop until last read complete ...RDDUN: ... this routine entered at completion of read & no wait operation ... PUSH HL; PUSH AF ... 00->B.RDFLG ...reset RDFLG to indicate reading complete ... B.FILINC=080; CALL NZ,RDERR ...check CC RH1 ... FNDLU2() ...get RR10=^FILTAB entry (done below:) RL7:=RH1; RH7:=0; R7:*2 R11:=FILTABQ[R7]; R10:=MYSeg RH1==NLUs; JR UGE,NOTOPN; BITB @RR10,LUOPNB; JR Z,NOTOPN PUSH R1 LDL RR8,RR10[DEVADR]; CALL @RR8 POP R1; RET CLOSE: FNDLU2(); RET NZ PUSH code will be generated if no other ORG is done) is set for 0 in the same segment as Y. 5. The following are entry points into Y (referenced to its low address, which is usually 05000): +0: normal entry or reentry +2: entry point when first .DO(P.SavB;DEFB 010) := "LDI" .OUT("HEDA0") / "LDD" .OUT("HEDA8") := "CPI" .OUT("HEDA1") / "CPD" .OUT("HEDA9") := "ORG" DXNCODE .DO(GET2();R.BC) STNCD := "RLA" .OUT("H17") / "RRA" .OUT("H1F") := "RLD".OUT("HED6F") / "RRD".OUT("HED67")3 OUTB @R7,RH4; OUTB @R7,RL4; OUTB @R7,RH5; OUTB @R7,RL5 ...RR4 R6:=R9 OUTB @R7,RH6; OUTB @R7,RL6 ...R9 SNDBUK() ...send bucket POPL RR6; RET DI_: PROC ..."disable" NMI RESB DI_FLG,0; RET EI_: PROC ..."enable" NMI; preserve Z-flag TSETB DI_Ffor error other than EOF error ... POP AF; POP HL; RET GET2W: ...next 2 words @HL go to DE & BC, HL inc'ed; BC tested for 0 LD E,(HL); INC HL; LD D,(HL); INC HL LD C,(HL); INC HL; LD B,(HL); INC HL R.B|R.C; RET IMGSUB: ...do IMAGE PUSH DE OFILOPN(IM R1 LDL RR8,RR10[DEVADR]; CALL @RR8 POP R1; RELLU_() RET REQLU_: ...get LU#->RL0, ^entry in FILTAB->RR10; preserves other regs ...if succeed, Z=1, entry 0'ed except LUOPNB set; else Z=0 LDAR RR10,FILTAB; RL0:=0 repeat if BITB @RR10,LUOPNB zero thloaded (looks at system command buffer (or other buffer @RR12) for file name) 6. It is possible to move the symbol table elsewhere in memory or change the amount of space allocated for it. There is a global symbol TABBSE at which is stored the star := "DAA".OUT("H27") / "CPL".OUT("H2F") := "NEG".OUT("HED44") / "CCF".OUT("H3F") / "SCF".OUT("H37") := "OUT" DEL ("C)," .OUT("HED","O41"ORe3) / .OUT("HD3") "),A") := ("RLC".DO(P.SavB;DEFB 0) / "RRC".DO(P.SavB;DEFB 1) / "SLA".DO(P.SavLG; RET MI SC (SC_INTR & 0FF); RET ...if was NMI, do it DIS_BRK: PROC ..."disable" NMI break RESB DB_FLG,0; RET EN_BRK: PROC ..."enable" NMI break; preserve Z-flag TSETB DB_FLG; RET MI SC (SC_BKR & 0FF); RET ...if was NMI break, do it ...DEVICEGLU) ...open output file (IMGLU=LU#) ^SegDs2 ...beg. of seg. descriptors saying where to image from GET2W() ...look at 1st segment descriptor only ...GET2W rets. DE=seg beg adr, BC=seg len R.DE->R.HL PUTO2() ...put out whole seg. CLFPT() ...clen begin PUSH R1; R1:=LULEN/2 repeat CLR @RR10; R11:+2 until R1:-1; R11:-LULEN; SETB @RR10,LUOPNB POP R1; R0==R0; RET end R11:+LULEN until RL0:+1=NLUs; RESFLG Z; RET RELLU_: ...release LU RH1 PUSHL RR10; FNDLU_(); CLRB @RR10; ting address of the symbol table; in the following word is stored the address 1 past the last location allocated for the table. The first word of the table stores its current size. Simply move the table as desired and patch into TABBSE and TABBSE+2 its nB;DEFB 4) / "SRA".DO(P.SavB;DEFB 5) / "SRL".DO(P.SavB;DEFB 7)) := "EXX" .OUT("HD9") ; INST4 := "PUSH" .DO(P.SavB;DEFB 5) := "WORD" WNR := "BYTE" BNR := "CALL" DEL {.OUT("OC4"ORe3) / .OUT("HCD")} := "LDIR" .OUT("HEDB0") / x2ap/ V("pO  :ap(!x*Kj"Qj"pȔΌ !ȁb gZw͔  p ̈́< E>[ FzC Latchͬ]UͲ[/ (A1ͽLͽ%(ݿ͔ H13m8{z͔ ose file; restore list file LU->vectors; Z=1 POP DE; RET ...IMGSUB: ...do IMAGE ... PUSH DE ... OFILOPN(5) ...open output file (5=LU#); ...rets. HL=^DIAGSW ... 080->B.FTYP; 00->B.FPROPS...->@HL ...set attr.; ...zero DIAGSW ... R.A->R.H->R.L; R.HL->W.F_POPL RR10; RET OPEN: ...assign LU, do open; enter R1=orig R0, R13=orig R1, R0 diff. ...ret. RH1=LU if REQLU_() not zero then begin RL0:=TUMNYERR; RET end ...RL0=LU, RR10=^entry in file table RH0:=RH1; RL0:->RH1 ...RH1=LU, RH0=open type PUSH R1 FIXNew position. Example: Suppose it is desired to move the symbol table from its current position (starting at TABBSE) to between 02000 and 05000. The following code will accomplish this: *R1:=@(R3:=TABBSE); R7:=02000->TABBSE; LDIRB @R7,@R3,R1; LD TA. "LDDR" .OUT("HEDB8") := "DJNZ" DEL .OUT("H10") := "CPIR" .OUT("HEDB1") / "CPDR" .OUT("HEDB9") := "DEFS" DXNCODE .DO(GET2();W.SAVNCD+R.BC) STNCD := "DEFT" SREND := "DEFM" OUTSTARI := "RLCA" .OUT("H07") / "RRCA" .OUT("H0F")  INSTGRP := $( CONTCHK / ?) ; CONTCHK := ? ; XCOMM := COMM ENDLINE ; ENDLINE := .DO(@DE=0D;RET NZ;LISTCHK();INC DE;W.NCODE->W.LSTNCD) Getrec ; LISTCHK := .DO(^DIAGSW;BIT 6,(HL);CALL NZ,LIST) ; XCONTROL := "if" SGEND INSTGRP CONTCHK ENDLINE LISTCHK LABXRZ *ZAP REPTEND DECBZ SSEXPR OUTJRF CASEP2 SELECTST X_R_S XCOMS ELSEST ELSEST2 *ZAP TERM EXPR SVLAB LABSV RELOP QGT QLE QLT QGE EXC QNE RELATION RELEND ZC *ZAP QEQ WRELATION OPTZ HLZ AZ XAROP2 AT QRDOT AT2 AT2IXY LD6) / "M".DO(P.SavB;DEFB 7); C4 := "C,".DO(P.SavB;DEFB 3) / "NC,".DO(P.SavB;DEFB 2) / "Z,".DO(P.SavB;DEFB 1) / "NZ,".DO(P.SavB;DEFB 0); E := .OUT("A1" *) / "$".OUT("HFE") N1INC ; N1INC := .OUT("H00") $ .DO(W.NCODE-1->W.NCODE) ; DAROP2 : DEL() C DE;RET)} := "^" (LDIDVAL / .OUT("C "#1) SREND .LABEL(#1) Zp .OUT("HE1") / LDNN2) := "W." (PROC0 / .OUT("H2A") OUTA2ST / LDNN2) := PROC / .OUT("H2A") OUTA2ST := := ("DE" .OUT("HEB5E23562BEB") / <:= "RETI" .OUT("HED4D") / "HALT" .OUT("H76") := "OTIR" .OUT("HEDB3") / "OUTI" .OUT("HEDA3") := "DEFB" BNR := "DEFW" WNR ; WNR := $(DEL ?( WRG) / IdOUT) ; INST5 := "WRITE" WSUB ; INST6 := "GLOBAL" $(DEL GLBSUB) ; BNR := $(DEL ?(SEXPR LABXRZ "then" XCOMS INST XCOMS ELSEST LABLReZ ?"endif" := "while" LABSV SSEXPR LABXRZ "do" XCOMS .OUT("H18","A1"Xc Re) Zp LABLReZ := "repeat" LABSV DEL ?"endr" := "case" INST XCOMS "of" CASEP2 "end" ; LABXRZ := .LABEL(XcAIXY ATIXY2 AEXP *ZAP LDA LDHL PROC0 PROC WORDID WORDID2 BYTEID LDIDVAL LDNN2 DD *ZAP PcarryP McarryM AMOD HLMOD HLMINUS HLPLUS ASTORE HLSTORE *ZAP LABLReZ LPAREN RPAREN XMETA *PACKALL ...GETCND: B.CODEBK=0; B.Skip; ^Skip2; CALL NZ,RDaHL ...REVA: R.A=0; 1...fall thru: AROP2 := ?"A," .OUT("O80"Re ORe3) := OUTOPaHL SWTCH := .OUT("OC6"ORe3) BN ; BN := .DO(W.NCODE-1->W.NCODE) ; ORGNN := ( .DO(LKIDPL();CALL NZ,ORGOTHR;if zero then R.HL->W.OFFSET) OUTA2ST / DOLLR) N2INCS .DO(W.OFFSETAT2IXY> .OUT("H6E66") AT2IXY2 / (DD/LDHL) .OUT("H7E23666F")) := "#" (LDIDVAL / LDNN2) ; PROC0 := (.DO(R.A=0)) ; PROC := ("P.".DO(00) / CHKP) .DO(PUSH AF) .SAV("C "*) ?( INSTLIST ) .OUT(Re) .DO(POP AF) ; ...note: PROC rets. BRG)) ; RPTCNT := "[" "]" ; INCDEC := := .OUT("O04"ORe3 Re) / .OUT("O34"Re) SWTCH ; RR := "(HL)" .DO(P.SavB;DEFB 6) / R1 ; R1 := ( .DO(R.A-1)) RRS ; RRS := "B".DO(P.SavB;DEFB 0) / "C".DO(P.SavB;DEFB 1) / "D".DO( Re) Zp ; REPTEND := "until" XCOMS { .OUT("H10","A1"Re) / SSEXPR LABXRZ .OUT("A2"Xc Re) Zp .OUT("D"Re)} Zp ; DECBZ := .DO(PUSH DE) "DEC B" DEL OPTZ DEL .DO(if @DE=';' then POP HL) / .DO(POP DE) ; SSEXPR := SVLAB SVLAB EXPR OUTJRF ; OUTJRF := .OUT(Re; RET Z; 00; RET ...A=not(A) ...SKIP: GETCND() ...for compatibility, get Skip from set bank for now ... if R.A<>2 then begin ... R.A-1; RET NZ ...if Skip=0 ... @DE='*'; RET NZ ...if Skip=1 & not at '*' ... end SKIP: B.Skip-1; RET NZ ...don't skip) OUTHHL MIN2 / HXWN ; HXWN := OUTHHLI / WN ; WN := NN2I / IdOUT ; IdOUT := OUTA2ST ; OUTA2ST := .OUT("A2"*) ; NN2 := OUTA2ST := ("2**" EXPSUB / "-" NEGSUB / NBR / VALUE / "'" (.DO(if @DE=0D then OR A else begin INC DE;LD R.A=0 iff ("P."/"(") WORDID := "W." / WORDID2 ; WORDID2 := .DO(CHKTYP(WORDT)) ; BYTEID := "B." / .DO(CHKTYP(BYTET)) ; LDIDVAL := .OUT("H21") OUTA2ST ; LDNN2 := .OUT("H21") NN2 ; DD := "HL" / "DE".OUT("H626B") / "BC".OUT("H60P.SavB;DEFB 2) / "E".DO(P.SavB;DEFB 3) := "H".DO(P.SavB;DEFB 4) / "L".DO(P.SavB;DEFB 5) / "A".DO(P.SavB;DEFB 7) ; TOCODES := (",(" .OUT("H2A") / ",".OUT("H21")) := .OUT("O02"ORe4) ",A" := "A," := "," (  Ig,"A1"Pp) CHKGT ; CASEP2 := .OUT("HE521","A2"#1,"HE3") $(XCOMS DEL ?";") ?("else"XCOMS INST XCOMS) OUTRET.LABEL(#1) Zp ; SELECTST := (PROC / BEGEND / .DO(P.SavB;DEFB 7) XAROP2 / Ig) .OUT("H20","A1"#1) DEL":" INST OUTRET.LABEL(#1) Zp ; TST := < if <>1 if @DE='/' then begin OR A; RET end ...don't skip if at '/' NOTCR: @DE=0D; RET Z; INC DE; JR NOTCR DEL: if @DE<>' ' then begin R.A=' '; RET NZ end ...chk for spaces/tabs repeat INC DE until @DE<>' ' and R.A<>' '; XOR A; RET FNDPAREN: ...searc L,A;LD H,0;if @DE=''' then INC DE end))) OUTHHL := := DOLLR ; DOLLR := "$" .DO(LD BC,(OFFSET);W.DOLLAR+R.BC) OUTHHL ; NN2I := N2INCS ; N2INCS := $(N2INC1 / N2INC2) ; OUTHHLI := OUTHHL N2INCS ; NN2I_E : NN2I(); RET Z; Id(69") ; PcarryP := "+carry+" ; McarryM := "-carry-" ; CP_OP := "=" / "::" ; AMOD := DEL "->" := ( .DO(P.SavB;DEFB 1) / .DO(P.SavB;DEFB 3)) := "+" (.OUT("H3C") / .DO(P.SavB;DEFB 0) XAROP2) := "-" (.OUT("H.OUT("O40"Re ORe3) / .OUT("O46"ORe3) SWTCH / .OUT("O06"ORe3) BN) := ( "," (.OUT("O70"Re) SWTCH / .OUT("H36") SWTCH BN) / .DO(W.LASTDE;PUSH HL) "," .DO(EX DE,HL;EX (SP),HL;EX DE,HL) .DO(PSINST> X_R_S := XCOMS WRELATION XCOMS := SXINST X_R_S ; X_R_S := XCOMS RELATION XCOMS ; XCOMS := $ ; ELSEST := "else" XCOMS ELSEST2 INST XCOMS ; ELSEST2 := .OUT("H18","A1"#1) LABLReZ .SAV(#1) ; TERM := TST $("and" OUTJRF TST) ; EXPR := TERh for ")"; ret. Z=0 if reach CR first repeat @DE=')'; INC DE; RET Z until R.A=0D; DEC DE; OR A; RET PatchN: ...chk for "[n]", n>=3; if ok, n->PATCHN @DE='['; RET NZ; INC DE; Digit(); RET NZ; R.A='3'; RET C R.A-'0'->B.PATCHN; @DE=']'; RET NZ; INC DE; RE); RET NZ; JP NDFERR ...do NN2I, put out error msg. if fail because of undef'd label ...NNTRM := $ ; N2INC1 := "+" PLUS2 / "-" MIN2 ; ...chg. NN2 to NNTRM above to get hierarchy N2INC2 := "&" AND2 / "*" TIMES2 := 3D") / .DO(P.SavB;DEFB 2) XAROP2) := := ("&".DO(P.SavB;DEFB 4) / "|".DO(P.SavB;DEFB 6) / ".XOR.".DO(P.SavB;DEFB 5)) := "*2" .OUT("H87") / "/2" .OUT("HCB3F") ; HLMOD := DEL "->" := (.DO(P.SavB;DEFB 1) / OP DE)) := "SP," ( .OUT("HF9") / .DO(P.SavB;DEFB 3) SSNN) := "," ; SSNN := .OUT("HED","O4B"ORe4) / .OUT("O01"ORe4) ; NNREST := .OUT("H22") / "A".OUT("H32") / .OUT("HED","O43"ORe4) ; AREST := .. M $("or" .OUT(Ig Re,Xc"A1"Pp) CHKLE LABXRZ SVLAB TERM) ; SVLAB := .SAV(#1) ; LABSV := SVLAB .LABEL(Pp) ; RELOP := "=" QEQ / "<>" QNE / "<=" QLE / ">=" QGE / "<" QLT / ">" QGT ; QGT := QLE EXC .DO(1->B.GTLFLG) ; QLE := .SAV("H380028") .SAV("H380220") .DO(0FT JUST0: ...chk for "0" not immediately followed by a hex digit @DE='0'; JR JUSTX JUST1: ...same as above but check for "1" @DE='1'; JR JUSTX JUST2: ...same as above but check for "2" @DE='2' JUSTX: RET NZ; INC DE; if Hexd() then begin DEC DE; DEC DE; "/" DIV2 ; ...WNUM := OUTHHL / DOLLR ; NBR := "0" HNumH / Num ; DHEXN : DEL() ...cont. below with HEXN: HEXN := .DO(DEC DE) HNumH ; ...result in HL; R.A=R.L HNumH := HNum .DO(if @DE='H' then INC DE;R.L;CP A) ; GETNUM := DHEXN .DO(P.SavB;DEFB 0)) DEL "R." .OUT("HED","O42"ORe4 ORe3) := "+" / "-" := := "*2" .OUT("H29") / "/2" .OUT("HCB3CCB1D") ; HLPLUS := DEL .OUT("H23") / .OUT("H2323") := "R." { .OUT("O09"ORe4) / .DO(DEOUT("O0A"ORe4) := .OUT("O78"Re) := ( .OUT("H7E") SWTCH / .OUT("H3A") ) := .OUT("H3E") BN ; PP2 := DEL ( / .DO(P.SavB;DEFB 2)) .OUT("OC0"ORe4 Re) ; ADSBC2 := DEL "HL," .OUT("HED","O40"ORe4 Re) / Ig ; IDD :F->B.GTLFLG) ; QLT := .SAV("H38") .SAV("H30") ; QGE := QLT EXC ; EXC := .OUT(Xc) ; QNE := QEQ EXC ; RELATION := {AZ / Ig OPTZ} / RELEND ; RELEND := "not" DEL ZC EXC / ZC ; ZC := "carry" QLT / OPTZ QEQ ; QEQ := .SAV("H28") .SAV("H20") ; WRELATION :OR A; RET end XOR A; RET SETTYP: ...set lower nibble of type byte to R.A LD C,A; LD A,(IY+TYPE); R.A&0F0|R.C; LD (IY+TYPE),A; CP A; RET GETTYP: ...get lower nibble of type byte ->R.A @IY(TYPE)&0F; RET LKIDPL0: B.GETTYP()=DEFLT; RET NZ LKIDPL: ...look / IMMXHL / VALUE ; VALUE := "value(" .DO(W.DOLLAR;PUSH HL) IMMX (.DO(POP BC;LD (DOLLAR),BC;if @DE=')' then INC DE)) ; GETA := DHEXN / IdDEF ; IdDEF := CHKDEF ; *ZAP QRULE CMD1 DOSUB DOSUB2 MASK RANGE ZAPALL LSTINT SEG_E_RL SEGADR *ZAP EQU DEFL DEFIT C DE;DEC DE)} := .OUT("H856F300124") ; ...NOTE: LDA above may reuse HL HLMINUS := DEL .OUT("H2B") / .OUT("H2B2B") := "R." { .OUT("HB7ED","O42"ORe4) / .DO(DEC DE;DEC DE)} := .OUT("H2F856F38012523") ; ASTORE := DEL ("B= Id / Digit / .DO(P.Test;DEFT '$') ; NVAL := GET2N .DO(LD L,C) SAVN ; BCDE := "(BC)".DO(P.SavB;DEFB 0) / "(DE)" .DO(P.SavB;DEFB 1) ; QQ := "AF" .DO(P.SavB;DEFB 3) / SS ; SS := "BC".DO(P.SavB;DEFB 0) / "DE".DO(P.SavB;DEFB 1) / "HL".DO(P.SavB;DEFB 2)= {HLZ / OPTZ} / RELEND ; OPTZ := ?"zero" ; HLZ := DEL "0" .OUT("H7CB5") := "R.DE" .OUT("HB7ED5219") := "R.BC" .OUT("HB7ED4209") ; AZ := DEL .OUT("HB7") / .DO(P.SavB;DEFB 7) XAROP2 ; XAROP2 := DEL ( OUTOPaHL ATIXY2 / (DD/LDHL) Oup last id+"+" without linking in ...if found, ret. IY at table entry, HL=@2IY PUSH DE; Outset(); PUSH DE; Copyin(); PLUSIN(); OutSP() Lkupnl(POP HL); @2HL; POP DE; RET GLBSUB: if NLKUP(W.LASTDE) not then SET UNDEFB,(IY+TYPE) ...if wasn't in table SEEQOTHR WBP IdLN DSETDLR QINST *ZAP INST2 INST3 INST4 WNR INST5 INST6 BNR RPTCNT *ZAP INCDEC RR R1 TOCODES SSNN NNREST AREST PP2 ADSBC2 IDD BCDE *ZAP QQ PP HLIXY IXYD INCSS DROTOP2 ROTOP2 CCC CC C4 E N1INC *ZAP DAROP2 AROP2 ORGNN HXWN NN2I N2INCS OUTHHLI *ZC".OUT("H02") / "DE".OUT("H12") / .OUT("H77") ATIXY2 / ("HL" / LDHL).OUT("H77")) := "R."("A" / .OUT("O47"ORe3)) / .OUT("H32") OUTA2ST ; ...NOTE: LDHL above may use R.A HLSTORE := DEL "R."("DE".OUT("H545D") / "BC".OUT("H444D") / "HL" / / "SP".DO(P.SavB;DEFB 3) ; PP := ("IX" / "IY") .DO(P.SavB;DEFB 2) / SS ; HLIXY := "HL" / IXY ; IXY := "IX" .OUT("HDD") / "IY" .OUT("HFD") ; OUTOPaHL := .OUT("O86"ORe3) ; IXYD := {IXYD1 / .DO(DEC DE)} ; IXYD1 := .OUT("H00") N1INC ; UTOPaHL) := "R." .OUT("O80"Re ORe3) / .OUT("OC6"Xc ORe3,Re) ; AT := "@" QRDOT ; QRDOT := ?"R." ; AT2 := "@2" QRDOT ; AT2IXY := (.DO(PUSH DE;LDAIXY();POP DE)) LDAIXY ; LDAIXY := .OUT("H7E") ATIXY2 ; ATIXY2 := / .OUT GLOBLB,(IY+TYPE) ...mark as global in symbol table if zero and LKIDPL0() zero then SET GLOBLB,(IY+TYPE) CP A; RET ZAPSUB: LKID(); JR C,NOGD ...look up id, error if ref. but not def'd if zero then begin SET ZAPB,(IY+TYPE) ...mark zapped if LKIDPAP NN2I_E N2INC1 N2INC2 DOLLR DHEXN HEXN HNumH VALUE GETA IdDEF *PACKALL XINST := HLEXP / SXINST ; SXINST := AEXP / XCONTROL / BEGEND / SPCINST ; SPCINST := "patch" .DO(00->@^PATCHR;if @DE='r' then begin INC (HL);INC DE end) .DO(R.HL->W.HOLE;3->B .OUT("HE5") .OUT("HE1")) := ("DE".OUT("HEB7323722BEB") / "BC".OUT("H7D02037C020B") / .OUT("H7574") AT2IXY2) := .OUT("H22") OUTA2ST ; CONDIF := .OUT("HAF") SSEXPR LABXRZ .OUT("HAF") ELSEST2 .OUT("H3E01") LABLReZ ; LABLReZ :=INCSS := (SS / .DO(P.SavB;DEFB 2)) .OUT("O03"ORe4 ORe3) ; DROTOP2 : DEL() ...cont. below with ROTOP2: ROTOP2 := (RR / .DO(P.SavB;DEFB 6)) .OUT("HCB","O"Re ORe3) := .OUT("HCB","O06"SWTCH ORe3) ; BITOP2 := DEL EXC "," T("H00") ; AEXP := $ ; HLEXP := $ ; LDA := ("BC".OUT("H0A") / "DE".OUT("H1A") / LDAIXY / ("HL" / LDHL).OUT("H7E")) := "R." ("A" / .OUT("O78"Re)) := "B." PROC0 .DO(RET Z;DEC DE;DEC DE) := .OUT("H3A") OUTA2ST L0() zero then SET ZAPB,(IY+TYPE) end CP A; RET IdPL: Id(); RET NZ; LKIDPL(); JR CHKX ...chk for id with associated offset IdCOL: Id(); RET NZ; @DE=':'; JR CHKX ...chk for id followed by ':' CHKDEF: LKID(); JR C,NOGD; JR NZ,NOGD ...chk if last id is .PATCHN) PatchN "," Patchsub := "stop" .OUT("HFF") := "?" WSUB ; WSUB := .OUT("C WSbgn") WDATA $("," WDATA) .OUT("C WSend") ; WDATA := DEL .OUT("C HLout") := .OUT("C Outhex") := """ OUTSTR := BEGEND ; BEGEND := "begin" INSTGRP "end" ; LABLRe Zp ; LPAREN := "(" ; RPAREN := ")" ; XMETA := $((.DO(W.UCCADR) Latch2 / SKIP) / CONT / ENDLINE / Err) ; ... END *ZAP SRBEG SREND LABLRe SINST RRS NVAL SS IXY OUTOPaHL OUTA2ST GETNUM NN2 *ZAP NBR *ZAP SXINST SPCINST WSUB WDATA BE.OUT(Re) BITSUB ; CCC := .DO(PUSH DE) {",".DO(POP HL) / Ig} / .DO(POP DE) ; CC := "NZ".DO(P.SavB;DEFB 0) / "Z".DO(P.SavB;DEFB 1) / "NC".DO(P.SavB;DEFB 2) / "C".DO(P.SavB;DEFB 3) := "PO".DO(P.SavB;DEFB 4) / "PE".DO(P.SavB;DEFB 5) / "P".DO(P.SavB;DEFB  := "-" ( .DO(-R.L->R.L;PUSH HL) .OUT("H3E") .DO(POP HL) OUTHRL Out / .OUT("HED44")) := ("0" JUST0 .DO(if<>then DEC DE)) .OUT("HAF") := := .OUT("H3E",Re) ; LDHL := "R." {DD / .OUT("HE5E1") / .DO(DEC DE;DE/ defined LD A,(HL); INC HL; LD H,(HL); LD L,A ...value->HL->A RES AL1B,(IY+TYPE); RET ...mark referenced CHKP: @DE='('; 0; RET Z; PROCT->R.A ...chk if proc.; ret. R.A=0 iff @DE='(' ...note: if CHKTYP(PROCT) zero, R.A gets set<>0 CHKTYP: PUSH AF; LKID(ndif POP DE end HLout(); LD BC,(LSTLAB) POP AF ...Z=1 iff EQUFLG=0 if zero and R.B|R.C not zero then begin R.HL-carry-R.BC if R.H=0 and R.L<>0 then begin ...HL=LSTNCD-LSTLAB=disp. OutSP(); Outhex(R.L) end end end 00->B.E POP AF; RET ...*ZAP SAVREGS RESREGS GetCh PutCh GetIO_ PutIO_ IO_Init *ZAP CALLBIOS JPaHL *ZAP DMABEG LUOFFSET FCBSZ FCBS CCPM GetFCB OpenIT RanRecF *ZAP ParseName MoveTxt MoveSp ValidChar InitRW RanRW ExitRW *PACK ALL *ZAP DMABEG LUOFFSET FCBSZ FCB while Hexd() do begin B.ASCtoN(R.A)->R.C; LD B,0 R.HL*2*2*2*2+R.BC->R.HL end XOR A; RET Num: PROC ...R.A has digit; get value of digit sequence->R.HL W.0 repeat R.HL*2->R.BC; R.HL*2*2+R.BC R.A&0F->R.C; LD B,0; R.HL+R.BC->R.HL until Digit() until R.HL>=R.BC or R.H<(RECL/0100); ...chk if done segment ... end ... POP HL ...HL pts to next seg. des. in buffer ... end ... POP DE; CLFPT(); RET ...close file; restore list file LU->vectors; Z=1 ...LDI_N2: LD BC,02FF ...move 2 chars if no.); POP BC; JR NZ,NOGD B.GETTYP()=R.B ...chk if id=type R.A CHKX: RET Z NOGD: LD DE,(LASTDE); OR 1; RET ...back up over id, set Z=0 CKEQUT: LKID(); RET NZ; B.GETTYP()=EQUT; RET ...chk if last id is EQU type LKID: ...look up Id in symbol table without QUFLG MOVTXT() ...put in tab + move text to buffer, truncating if too long if not zero then begin ...Z=1=>no text LD BC,(LSTNCD); SCF if W.NCODE-carry-R.BC>=zero then begin ^BUFF; 00->R.A; PUSH BC repeat if begin LD B,A; @HL=9; L LDAR RR6,PUTBUF; R7:+PUTBUFCNT ... R0:->PUTBUFCNT ... repeat ... if RL0:=@RR2'<>0A then begin ... RL0:->@RR6'; R5:-1 ... if RL0=0D then begin RH0:=0A->@RR6'; R5:-1 end ... end ... until R5<<=0; ... EI_(); POPL RR6 ... end ... not zero; XOR A; RET SavB: ...save following byte as hex POP HL; Outset(); @HL; INC HL; PUSH HL; Outhex(); Sav(); RET ... used to save string of "0"s &/or "1"s (len=low nibble, value=high): ... R.A->R.C&0F->R.L; LD B,4 ... repeat SLA C; '0'+carry+0->@D, plus '-' ... repeat if @HL&0F0=030 then LDI until DEC B zero; ... '-'->@DE; INC DE; RET VDATE: ...puts out Q version no. & date CALL Icopy; DEFT 'Q VERS ' LD HL,QVERS+1; LD BC,4; LDIR ...version no. ... 9->@DE; INC DE ... LDI_N2(LD HL,DATE+2) ...monlinking in (get flag) W.LASTDE NLKUPNL: 1->B.LINKSW; NLKUP(); RET ...generate repeated copies of word/byte in code area WRG: PUSH DE; GET2(); R.HL-2 ...BC=count, HL->word to be repeated R.B|R.C; JR Z,WBRGX PUSH BC; RDa2HL(); LD E,C; LD D,B; POP BC wD A,B end then R.A|7->R.A INC A; INC HL until R.HL=R.DE; ...R.A=col. corres. to DE in buffer EX DE,HL repeat LD (HL),9; INC HL; R.A|7+1->R.A until R.A>=CdLCol; ...tab until col. CdLCol (nominally 64) LD (HL),'['; INC HL; EKʇ™͙LD ͕͋JP 0͕ OC2r͝(U Ԝ[(͝JR ͕ O20r(CP ë=EX 5͕DE,HL ( AF,AF' ((SP), HLٜOR ë=RL ë( RR ë -EI DIE; if R.L>=R.B then INC DE ... until DEC B zero; ... RRA; RRA; RRA; RRA ... Outhex(R.A&0F); Sav(); RET BITSUB: W.NCODE-1->W.NCODE; if B.RDaHL()>=8 then begin P.Errm;DEFT 'BIT>7' end R.A*2*2*2->R.B; DEC HL; B.RDaHL()|R.B WRaHL(); XOR A; RET ...put bit nth ... LDI_N2() ...day ... LDI_N2(^DATE); DEC DE ...year, delete trailing '-'; continue below: Outp() RET ...*ZAP SYSTM INPTR INDRJP ATMPCD CONIO CONRDY INRDY OUTRDY IV ...*ZAP FILASN ASNSUP FNML FNAME FILINO ...*ZAP FOPNLA FOPNSP FILRD RDTYP FILRDL Fhile begin R.HL+2; DEC BC; R.B|R.C end not zero do WRa2HL()...DE->@2HL JR WBRGX BRG: PUSH DE; GET2(); R.HL-1 ...BC=count, HL->byte to be repeated R.B|R.C; JR Z,WBRGX B.RDaHL()->R.E while begin INC HL; DEC BC; R.B|R.C end not zero do WRaHL(R.E)...E->@HX DE,HL; POP BC repeat LD HL,BUFF+LINEL-4 ...Note: Carry must be reset for SBC SBC HL,DE; JR C,LISTX ...chk if fits in buffer RDaHL(R.BC); Outhex(R.A) ...put in ascii of generated code INC BC until W.NCODE-R.BC zero;  IN >͕A,( C) x( l [(8 O40r,(C)RET ͕͒ OC0rGPOP ëINC ë( DEC ë ͕SUB ë( AND ë( XOR ë =ADD $͕Ԝ ,O09n(ë@ADC ë 7(o. in pos's 3,4,5 of prev. byte DXNCODE: P.DEL ...XNCODE: W.SAVNCD=0; CALL NZ,Err ...no ORG or DEFS during imm. ex. XNCD2: W.NCODE->W.SAVNCD; W.TMPCD->W.NCODE; RET ...get temp. loc. for NCODE ResSVs: W.0->W.SAVSP RESNCD: W.SAVNCD=0; RET Z STNCD: R.HLILIN FILINL FILINC FILPTO FILPSP ...*ZAP FILPUT FPUTAD FPUTL UPDATE FILCLO FPUTBF FTYP FPROPS LO_ADD HI_ADD F_ST ...*ZAP FPUTRM FPUTNX RCADR1 RCAD1H RCADR2 RCAD2H RECPTR NUMERR FILTYP STACK ...*ZAP FTYPE RECLEN SEGDES DATA2 RDFLG ...R_DE R_IX R_IY ...*ZAP L WBRGX: R.HL->W.NCODE; POP DE; RET GET2: RDa2HL(W.NCODE-2); RET ...get 2 bytes from code area->R.BC; HL=NCODE-2 GET2N: GET2(); R.HL->W.NCODE ...get 2 bytes & adjust NCODE RDaHL(R.HL-2); R.HL+1; RET ...R.A=low-order prev. word, HL at hi-order ...PLUS2']'->@DE; INC DE end end LISTX: Outp(); RET OUTRET := .OUT("HC9"); OUTRETJ: ...put out RET or JP to a routine to ret. from bank 2 or remote cpu B.CODEBK=0; JR Z,OUTRET B.CPU=0; JP NZ,OJRetQ DEFB 0EF 3; JP Ret1; RET ...note: 0EF is RST 28, then JP ë@SBC ë7(ë@BIT ëbSET ëbRES ëbLDI LDD CPI CPD ORG xت`iRLA RRA RLD oRRD gDAA 'CPL /NEG DCCF ?SCF 7->W.NCODE; 00->R.H->R.L; R.HL->W.SAVNCD; RET ... CHKLE called after "or"; CHKGT called after "and" or after an EXPR CHKLE: B.GTLFLG=0FF; JR GTLE1 ...check if last relation was LE CHKGT: B.GTLFLG-1 ...check if last relation was GT GTLE1: JR NZ,GTLE2 W.NCLOSFL SYSTEM ZDGSW STARS RESNST ERRMCC ERMGET Err0 ERR1 ST1 ST2 ST3 ...*ZAP START START0 START1 QINIT JPR I_INIT Echo GetN P_ESC ...*ZAP PUTLUP PUTOUT PUTO2 WRTERR CLFPT LNEWLU ONEWLU OFILOPN RESLLU ...*ZAP FILOPN RESLU OPNERR MVDATA NXTSEG CNTSEG FILDN2 adds bytes of form LH,LH->LH: PLUS2: GET2N(); R.A+R.C->R.C ...low byte B.RDaHL()+carry+R.B->R.B ...high byte JR WRBC MIN2: GET2N(); R.A-R.C->R.C ...low byte B.RDaHL()-carry-R.B->R.B ...high byte JR WRBC AND2: GET2N(); R.A&R.C->R.C ...low byte B./ OutN IMMX0: W.SAVNCD->R.BC=0; W.NCODE; RET NZ; R.HL->W.SAVNCD; RET IMMX: IMMX0(); PUSH BC; PUSH HL; INSTLIST(); 00; JR IMMX2 ...imm. execution IMMXIF: IMMX0(); PUSH BC; PUSH HL; CONDIF(); JR IMMX2 IMMXHL: IMMX0(); PUSH BC; PUSH HL; HLEXP() IMMX2: CALL Z,OUT /͕UC), 8O41r(l ),ARLC ë( RRC ë( SLA ë( SRA ë( SRL ë -EXXPUSH ëWORD̬BYTECALL ͕ OC4r(͝LDIR LDDR DJNZ ͕CPCODE-1; B.RDaHL()->R.C WRaHL(0FD) ...point chain to spot 2 bytes back if R.C<>0 then begin ...check if end of chain LD B,2 INC A; CP 080; JP Z,OORERR ...check for out of range DJNZ $-6 ...R.A (=orig. chain value) gets increased by 2 end R. GetrecD GETCNS GETRCX ...*ZAP READFL RDFL2 RDFIL GETFIL RDREC RDERR RDERR2 NEWLU RDDUN GET2W *ZAP LSTLU IMGLU STAK2 BRKJMP BRKRTN FILPTO *ZAP JPR NMI_Rtn BrkRtn BrkRtn2 *ZAP CLOSFL PUTOUT PUTO2 WRTERR CLFPT LNEWLU ONEWLU RESLLU *ZAP FILOPN OPNERR FILDN2 RDaHL()&R.B->R.B ...high byte JR WRBC DIV2: GET2N(); PUSH DE; PUSH HL; R.A->R.E B.RDaHL()->R.H; LD L,E; LD D,B; LD E,C ...HL=dividend, DE=divisor if R.D|R.E<>zero then begin ...if divisor=0, BC(answer)=0 LD BC,0-1; repeat SBC HL,DE; INC BC until cOUTRETJ POP HL; R.HL->W.NCODE; POP BC; LD (SAVNCD),BC; RET NZ PUSH DE; JPHL(); POP DE; CP A; RET GoXX: PUSH HL; W.XAdd; EX (SP),HL; JR GoXB ...GoX: OUTRETJ(); W.XAdd->NCODE->R.HL JPHL: PUSH HL ...will go to (HL) W.LstDmp ...HL set=LstDmp GoXB: PUSH AIR CPDR DEFS ͤت*Kj DEFT ͱz̈́DEFM ͱz͋RLCA RRCA RETI MHALT vOTIR OUTI DEFBDEFW͕ ̛Ĩ(WRITE%GLOBAL͕Fz(͕l ̺([0HL-2; WRaHL() ...put correct value for chain in spot 2 bytes back GTLE2: 00->B.GTLFLG ...zero GTLFLG RET Patchsub: W.NCODE; PUSH HL; INSTLIST(); POP HL; PUSH DE; PUSH HL W.HOLE; PUSH HL; LD DE,(NCODE); B.PATCHN->R.B B.PATCHR=0 ...set Z=1 if to copy READFL RDFIL1 RDFIL2 READFIL *ZAP LOADFL RDERR RDERR2 NEWLU CHKRD GET2W ...symbols common to MMETA & QSYS: *ZAP GetrecD GETCNS GETRCX *PACK ALL  READFIL *ZAP LOADFL RDERR RDERR2 NEWLU CHKRD GET2W ...symbols common to MMETA & QSYS: *ZAP GetrecD GETCNS Garry; end POP HL; POP DE WRBC: DEC HL; WBCa2HL(); XOR A; RET ...BC->@2(R.HL-1); Z=1 TIMES2: GET2N(); PUSH DE; LD E,C; LD D,B; RDa2HL(R.HL-1) ...factors->DE,BC PUSH HL; W.0; MULT(R.B); MULT(R.C); EX DE,HL; POP HL ...DE*BC->DE WRa2HL(); POP DE; XOR A. R.B&R.H->R.H; R.C&R.L->R.L ... R.HL+R.DE-1 ... POP DE; R.HL+R.DE ...HL=HiAdd for this seg. ... POP DE; POP BC; PUSH BC ...BC=prev. HI_ADD ... if R.HL>=R.BC then EX (SP),HL ...compare it ... EX DE,HL ... end ... POP HL; R.HL->W.HI_ADD ... S]+ O04r7O347Ê(HL) ëͲ =B ëC ëD ëE ëH ëL ëAëԜ !,( *ͤ[( , !ͤq O02n,AA, ԛ+ 8,+ O407r( O46r͊(bytes, else Z=0 CALL Z,RDaHL; CALL Z,WRaDEi; INC HL; DJNZ $-7 ...move PATCHN bytes from HOLE to after instlist code WRaDEi(0C3); EX DE,HL; WRa2HL(); R.HL+2->NCODE ...put in JP HOLE+PATCHN POP DE; POP HL; WRaDEi(0C3); EX DE,HL; WRa2HL() ...put JP PatcHL),B; INC HL; LD (HL),A; ... POP HL; POP DE; ... end else GetRRP(R.B) ... POP BC; ... RET RanRW: PROC ...enter IX=^buffer, A=CPM code (READR/WRITER), ... DE=^FCB, HL=^Random Record field ...read record; ret. A,Z=err code, IX updated, BC,DE,HL pre; RET ...DE->@2HL MULT: LD B,8 repeat R.HL*2; if RLA carry then ADD HL,DE endif until DEC B zero; RET ... R.A*R.DE + 256*R.HL -> R.HL EXPSUB: ...exponentiates word at NCODE-2; value->R.HL GET2N() ...#->BC W.1 R.B|R.C; RET Z; R.HL*2; DEC BC; JR $-5YSTEM(LD IY,UPDATE); JP NZ,WRTERR ...attributes to file ... ^SegDs2 ...beg. of seg. descriptors saying where to image from ... while GET2W() not zero do begin ...go thru segment descriptors ... ...GET2W rets. DE=seg beg adr, BC=seg len ... PUSH HL;  O06rlU L ",+ O707͊( 6͊l("X *ejͩ,Ͱͤ[SP, Ԝ (ë͉͕,͉U O4Bnͤ[O01nͤԜ "A 2͕O43nq O0An+ O787U  ~h at HOLE POP DE; 00; RET LIST: ...called when bit 6 of DIAGSW is set; enter with DE pointing to CR Outset(); PUSH DE; LD DE,(LASTCR); COMM() @DE; POP DE if R.A<>0D then begin ...chk not blank or comm. W.EQUVAL ...value of equate in case EQUFLG<>served PUSH BC; R.A->R.B; PUSH DE; PUSH IX; POP DE; CCPM(LD C,SETDMA); POP DE; if B.CCPM(LD C,B)=0 then begin PUSH HL; while INC (HL) zero do R.HL+1; ...increment record count POP HL; LD BC,080; ADD IX,BC; ...increment DMA address ...2**BC->HL NEGSUB: ...negate word at NCODE-2; value->HL GET2N(); W.0-R.BC->R.HL; CP A; RET AT2IXY2: ...fix up @2IXY(n); have in memory @IXY(n),@IXY(n),+ 2 bytes of code ... to be inserted as 2nd byte in respective copy of @IXY(n) GET2N(); WRaHL(B.R.DE->R.HL ... if B.CODEBK=0 then ...do fast way if in bank 1 ... PUTO2() ...put out whole seg. ... else begin ...if in bank 2 ... R.HL+R.BC->R.BC; EX DE,HL ...BC=seg. end addr, HL=start seg. addr. ... repeat ...do records until past e( :ͤ [>l͕͊( ٜ ëOC0n7͕HL, ͕O40n7DFzdzy$͵i(BC) ë(DE)ëAF ëBC ëDE ëHL ëSPëIX(IY ëÕHLIX IYO86rU (0 if begin B.EQUFLG=0; PUSH AF end then begin PUSH DE; W.LSTNCD ...get addr. beg. of line B.QOPTS if BIT 1,A not zero then begin LD BC,(OFFSET); R.HL+R.BC end if begin PUSH HL;Id(LD DE,(LASTCR));POP HL end then R.HL->W.LSTLAB e and length 00->R.A; end if R.A<>0 then if R.A=1 then EOF_ERR else 0FF POP BC; OR A; RET ExitRW: PROC PUSH AF; ... LUN->R.B; ... RanRecF(R.HL); ...get file address in CDE ... PUSH BC LD BC,(DMABEG); R.IX-R.BC->R.HL ...len->HL ... POP BC;RDaHL()+1) ...BC=code bytes; inc. 2nd disp. WRaHL(R.HL-1; R.B); WRaHL(R.HL-2-1; R.C) 00; RET SWTCH: ...swaps bytes in code area GET2(); PUSH DE; LD E,B; LD D,C; WRa2HL(); POP DE; 00; RET HNum: PROC ...checks for hex no.: value->R.HL; else HL=0 W.0 nd of segment ... PUSH BC; LD DE,FPUTBF; ...00->R.A ...DE is ptr. to buffer ... LD BC,RECL; RDLDIR() ...move bytes ->buffer ... PUSH HL; PUTOUT(); POP HL ...put out 1 record (4 if RL=80) ... POP BC ...recall seg. end addr. ... 0 ٜ,[͕( ٜ ëO03nr͕+( ͉ ë O7rO06͊r͕ft,08{7Ы͒ , DNZ ëZ ëNC ëC ëPO ëPE ëP ëMëC, ëNC, ë`  (7f͠( ΫO03y}͠6( ͔ Ϋ OB}O06͕}͠q,;C{B۫͝ , ONZ ΫZ ΫNC ΫC ΫPO ΫPE ΫP ΫMΫC, Ϋalent of "JP Debug" on whichever bank or cpu if CODEBK=0 then begin DEFB 0EF 3; JP Debug; RET end CPU=0; JP NZ,OJRetDbg DEFB 0EF 3; JP Debug2; RET ...note: 0EF is RST 28, then JP OutN DBUG0: Quit1() DBUG1: LD SP,MYSP ...init. SP Debug: PUSH HL; PUSH ##R. ͕ O09n(ͫo0$͕ѩ +֩ ++R. ͕ O42n(ͫ/o8%#͕c 0BC ( DE ( ٜ w̓( HLd wR. A (? O47ru2ì͕R. *DE T]( BC DM(HL( ٜ epeat R.A*2 until DEC B zero; ...R.A*(2^n)->R.A Outhex(R.A); RET Eff1: PROC ...deletes code of form 2000H @(W.NCODE-1)=0; RET NZ @(R.HL-1)=020; RET NZ R.HL->W.NCODE; RET *ZAP DATE FREE Link Hash LastNm Nxtpos TMPTAB ENDTAB PUTREC ...in MMETA *ZAP XZ, ëNZ,ëFz A1ͤz$;(*Qj+"Qj͕A,+ O807r ͊OC6r0*Qj+"QjFz y "oͬ *oI{͑*FzA2ͤzП̬2** ͵Z( - ͵g}į('   o&' I{UNC, ΫZ, ΫNZ,ΫQz A1ͯz$F(*Qj+"Qj͠A,6 O80B} ͕OC6};*Qj+"QjQz  y "oͷ +*oT{͜5'QzA2ͯz̷۟2** e( - rĈĺ('   o&AF; PUSH BC; PUSH DE; PUSH IY DBUG2: LD (SAVSP),SP ...if SAVSP<>0, ret. here after Err RESSTBRK() ...reset special brk used by Step just in case missed ResSBrk() ...ditto SStep brk Getcon('*') 00->B.NGFLG if @DE='/' then begin INC DE; CMD1(); JRn -DE s#r+(BC }| ( v utra"ìġ^͔>E()*&p͐zĂ ͪ(+Īq(: p=/   (  ( () [dz302o]012tz ɯO~w~LAT STARIT RetZ COPYSB SR2 TULONG SRDO HBTHEX LDI_N2 OUTDUN OUTCP CPQ *ZAP ISA2 CPAMIX ISA1 DISP CPB RDFERR CPDL1 CPDL2 CPLLUP AL1 AL1LUP *ZAP CPHLUP LINKER HASHER LKLUP0 LKLUP LKEND LKFIN LKEXIT TUMANY TSTEND *ZAP TBINT2 TABLEN PKLUP PK2 Tstsym *ZAP Nm00  0[$Ko*cj I{͵;U(I{ FzM|+ ͵-͵& ͵* ͵2/͵0 ͛dzí͕dz ͖͛H }͎͂value(*cjmCcj) ͎Fz[͕͠Ġwpatch #!owr 4ͧ' T{` ;f$Ko*cj T{F`(T{+'QzX|+ -& * =/0 ͦozø͠oz ͦ͡H }͙͍value(*cjxCcj) ͙Qzfͫ͠Ϡ͂patch #!ow Z,DBUG2 ...if cmd, don't offset NCODE XNCD2(); JR DBUG3 ...if /instlist, offset NCODE (->HL) end XNCD2(); R.HL->XAdd ...NCODE->SAVNCD; TMPCD->NCODE->XAdd if Dbug() zero then begin ...DBUG cmds use offset NCODE ResSVs() ...reset NCODE, SAVNCD8{ͤzͭ͸m}~#fo*ejͼ}( ͐8G  Fz,Fz:#͐8 ~#fo(>>͐ [ej͐*ej>2pü}ت++x(.ͱyYP## x(ͻyت+x(ͯy_# x({Ͷy"Qj*Qj++ñyت"Qj++ͯy#ઁOͯyG3ઑOͯNmFF GetLNm CPName CPNX CPNX2 PutOut *ZAP TUDEEP GENOK GEN2ND GENCLN SAVX R1 RPI ORe *PACK ALL AB PUTREC ...in MMETA *ZAP XLATL1 AL1LUP *ZAP CPHLUP LINKER HASHER LKLUP0 LKLUP LKEND LKFIN LKEXIT TUMANY TSTEND *ZAP TBINT2 TABLEN PKLUP PK2 Tstsym *ZAP Nm00 "o>2o͵,Ustop ?C WSbgnI, I(C WSend͕͠ C HLout͕ C Outhex" xbegin͉endȔ̞( ͧ ( ͻ*Qj"Sjgx!ovĔif $ġ^thenzܔźOendifwhile )ġ^must preserve Z-flag Zp: PROC SET ZAPB,(IY+TYPE) ...mark zapped in symbol table LD A,(IY+NAME+1) ...low-order no. in name (high-order is 0) ASCtoN() ...convert R.A to its value ...Note: this routine will have to change to include high-order no. in n, SAVSP B.NGFLG=0; JR Z,DBUG2 ...if NGFLG<>0, means N,S,T,J or G cmd ^NSTJG ...where to go end else begin W.SAVNCD->W.NCODE DBUG3: R.HL->XAdd; INSTLIST() PUSH AF; CALL Z,OJPDBG ...put out "JP Debug" or equivalent ResSVs() ...reset NCOyG'ડOͯyG_ͯygkPYz(R0+yYP+ͱy!xPyPͻyѯ)0!x) !Bͯy<Ͷy+xͶy+++yͶyتXQͻyѯ!tz {O)))) !)DM)) O dz(8{~#${*Qj+"Qjͯy8 pBIT>7G+ͯyͶy͕*Kj|qG3몑OͺyG'몡OͺyG_ͺygkPYz(R0+yYP+ͼy!x[y[yѯ)0!x) !Bͺy7G+ͺyydozܔA1U7Orepeat ͉͕kendrcaseܔzofendLU7until 3zͨ A17(ġ^A2U7D7DEC B ͕ѣ͕; Ϳ8{7DA1?*!A2ͽz% ͕; ame if ... no. of temporary symbols increased to more than 16 LD C,A; 00->R.B ...symbol value->BC; 1->Z ^TMPTAB+R.BC ...pt. into table marking temp. symbols as used or not RES 0,(HL) ...note: GENCLN (in Gen) resets bits 1 RET SAVN: OUTHRL() ...saDE, SAVNCD, SAVSP POP AF; JR NZ,DBUG2 ...if no instlist ^GOXX ...GOXX goes to XAdd in bank 2 or remote cpu end POP IY; POP DE; POP BC; POP AF EX (SP),HL; RET ...go execute code Dbug: JP DBUG ...for patch for extensions JP Dump ...call Dump *Qj"Kj*Oj"Qj!"Mj*Kj|"Qjgo"Kj:o:o= *Qj+ͯyO>Ͷyy( <]}++Ͷy2o*QjȔ*o[Qj:oG:o̯y̸y#>͸yͻy##"Qj>͸yͻyѯ8{[Gj (H*p:p *Sj:oO(Ko [GjFz "Ij{KIj x(B| }(͸}${2pp(NKSj7*QjB͠*Kj|q*Qj"Kj*Oj"Qj!"Mj*Kj|"Qjgo"Kj:o:o= *Qj+ͺyO>yy( yy##"Qj>yyѯC{[Gj (H*p:p *Sj:oO(Ko [GjQz "Ij{KIj x(B| }(À}/{2pp((else zܔzGLͽ,w(ëD A1ͽ͕:ܔGLͽt͠ z£z۟z͂ͧ(elsez͔ܔzA1ͽO8{ͽ[and ͡[(ͫor &8{D78{U͚zA1?#^ͫ(ҿ8{ͽ0 ve a one-byte number in R.L on stack; conts. below: Sav: PROC ...puts bytes from ^BUFF to DE, then count, in STACK starting ...at W.FREE; W.FREE updated; DE pointed again to source SAVX(^BUFF) JP OUTDUN ...NEXTDE->DE; 1->Z; RET SAVX: ...saves from Hvia Dbug+3 JP Regs ...call Regs via Dbug+6 JP Name ...call Name via Dbug+9 Deasm: RET;RET;RET ...for patch for DEASM (Dbug+0C) JP LFILOPN ...call LFILOPN via Dbug+0F *ZAP CTC0 CTC2 I2_JMP D_PC D_SP TMPSP MYSTAK MYSP SvSP1 ...in MMETA *ZAP DmpAdd N8B!kkG~ x <#R 6 #<@86[#!kR8`iͯy${*QjB >]@{:p(:pay*KjDM|*Qj"Kj^Ȕ^<^͠K"QjCKjͥѿ*p*op>*p2p:p :p yaB#*h!oq#p#*h s#r#q#p#q#p#yhB NKSj7*QjB8B!kkG~ x <#R 6 #<@86[#!kR8`iͺy/{*QjB >]K{:p(:ply*KjDM|*Qj"KjiӔiGiͫV"QjCKjͰѿ*p*op>*p2p:p :p ylB#*h!oq#p#*h s#r#q#p#q#L?= Ͳ<>|<=C>=q< a>Ct>2oH380028H380220>2oH38H30a8{UͲt (Dѣnot ͕ͤtcarryaѣH28H20 ٣ѣÓzero͕0 |R.DE RR.BCL to DE on STACK R.E-R.L->R.C; LD B,0 ...length->R.BC LD DE,(FREE) ...get dest. if not zero then LDIR ...copy bytes unless BC=0 R.A->@DE; INC DE ...save count LD (FREE),DE RET Re: PROC ...restore last item on stack to @DE+.. Ig() R1: R.A=R.C; Rable ...each entry=description of 1 code or uninit'd data region long START_ADDR; word LENGTH,TYPE ...TYPE=0 =>code, 1 =>uninit'd data repeat entries until SEGTABSZ (max 12 entries) IMAGE: <-------------------> (length=IMGSZ=total of code lengths in"h [Gj͕R[Gjb';u2QO2hQGjLASTCRQjNCODEejLASTDEgjNEXTDEoQOPTSoOFFSET pI_SW pTABBSE$pEXTADR$pEXTEND&pUSERCCqpR_AFpp#yhB "h [Gj͠R[Gjb';u2QO2hQGjLASTCRQjNCODEejLASTDEgjNEXTDEoQOPTSoOFFSET pI_SW pTABBSE$pEXTADR$pEXTEND&pUSERCCqpB ͕̩ ë͕c ٜ ̓( ͙dR. ?O807rfOC6Ur8{7@R.@2h|ٜ~U l[ͫӦ(dx(c &BC  ( DE |( HLd ~R. A (? O787B. %ET Z LDIR; RET Pp: PROC ...effectively pops to @DE+.. & pushes again (leaves on stack) RPI(); JR R1 Ig: PROC ...pop last item from stack without putting anywhere ... ret. BC=len.; Z=0 RPI() R.HL->W.FREE ...adjust stack pointer RET RPI: ...ret. HL SEGTAB) RELOC: ...relocation information long ADDR; word FLAG bit FLAG,15=0 =>local symbol: bit 0=0 =>code ref, 1=>udata ref =1 =>external symbol: bit 12=1 =>initialization ref bits 0-11 = SYMTAB ordinal repeat entries untiQuitzCopy${OuthexpErrmqErrcrOutmsg{HLoutDELqGet1vPut1GrWSbgnWrWSendorPutconyTestP{OutOutNgxGetrecxGetcon@{OutpywRDaHLyWRaHLFzIddzDigittzHexdzLatcR_AFpQuitzCopy/{OuthexpErrmqErrerOutmsg{HLoutDELqGet1vPut1IrWSbgnYrWSendqrPutconyTest[{OutOutNjxGetrecxGetconK{OutpywRDaHLyWRaHLQzIdozDigitzHexu :ͬ- !} }Do>{P{( ͫ D0 ̩( U ͕[f>8{7R. ͙( ٜ (^ '͉(p C ͽ̈́LͽēW. %( Fz *ͬē,l *ͬU ͠[n -DE ^#V+( v =^prev. string, BC=length, R.A=0 (for R1), Z=0 (for Ig) W.FREE-1 LD C,(HL) 00->R.B SBC HL,BC ...HL->first char.; set Z=0 for Ig RET Xc: PROC ...swap top two, DE unchanged PUSH DE; PUSH DE Re() ...1st string out PUSH DE ...^ end 1st Re() ...2nl RELOCSZ SYMTAB: ...symbol table long ADDR; byte TYPE; byte NAME[9] TYPE=0 =>undefined, 1=>absolute, 2=>proc, 3=>init'd data, 4=uninit'd data if name length>9, 1st byte=length|080, name follows, 0 padded to whole entry repeat entries untilh8{OutsetzCopyinzSrzSr1zCountȔINSTLISTDIgm}lLkupnlr}LkupGenZpSav7Re?PpUXcEff1ODbug+JASMSTOCOMMAND7LABELCOLܔhINSTן*XINSTlCBNbBITOP2WNif any at brkpt, step it first else begin CKBRKPT(LD DE,(R_PC)); CALL Z,Step end end Go2: RESRR() ...regs. back except HL=R_SP PUSH AF if B.CODEBK=0 then begin POP AF; LD SP,HL; R_PC; PUSH HL; R_HL; RET end ...if bank 1^ PUSH DE; EX DE,HL; ^SvSnfr(͙d ~#fo# ͉ē,P. Fzϯ(FzkC ͤzU Ȕ[Ͽ8{7W. FzFz>sB. FzFz>sFz!ì!õHLDE bkBC`i+carry+-carry-= ::͕-> jͳ ë( ͽ ë + d string out POP BC ...end 1st POP HL ...beg. 1st PUSH DE ...end 2nd PUSH BC ...end 1st; beg. 2nd LD D,B; LD E,C SAVX() ...save 1st POP HL ...beg. 2nd (this pop & prev. push unneeded with present SAVX) POP DE ...end 2nd SAVX() ...save 2nd  SYMTABSZ 9. There is a program YLINK which, if first compiled, enables Y to link in object files of the above format (such as generated by the "C" compiler) when you "/DO" them. They are relocated (YLINK tries to find a free place for them) and the }NumHNumXCOMM"OptmhQBEG]dNEWQBEG]GDEASM%SCRATCH[Deasm{g_ 01#g 00#XName&p+Re?PpUXcEff1ODbug+JASMSTOCOMMAND7LABELCOLܔhINSTן*XINSTlCBNbBITOP2WNP2 if CPU<>0 then ^RR_SP WRa2HL(); POP DE ...store R_SP at SvSP2 (bank 2) or RR_SP (remote cpu) POP AF R_PC; PUSH HL; R_HL->R.HL JP GOX ...go to R_PC on bank 2 ...note: bank1 SP restored upon break or JP Debug2 (->DBUG1) OJPDBG: ...put out equivѩ <(ë- ѩ =(ëǦ & ë( | ë( .XOR. ë *2 /2?͕-> ˨ͳ ë( ͽ ë ͕R.͕O42nr+ - )Ǧ ٣*2 )/2<͕ѩ #֩  POP DE; RET ...the following do a recall & shift (left) in preparation for orring: ORe4: PROC; LD B,4; JR ORe ...n=no. places to shift=4 ORe3: PROC; LD B,3 ...n=3 ORe: PUSH BC Re(); DEC DE; DEC DE B.Inhex(R.DE)->R.A ...get hex # from @DE POP BC r1 symbols are added to Y's symbol table (possibly modified to make them compatible). 10. This documentation is for Y of 11/15/82 (VERS 0.05).  Y's symbol table (possibly modified to make them compatible). 10. This documentation is for Y of 11/15/8.go execute in bk 2 POP AF; JP GOXR ...go to remote cpu SDesSub: ...store seg. descriptors, chk errors; enter: BC=beg adr, HL=end adr ...as goes on des. record->@SDesPs, where imaged from->@(SDesPs+SDDIF) R.HL-R.BC; RET C ...chk end not before beg.  R13=len, RR8=bufhdr ...bucket must already be gotten ... REQBUKW() ...wait for prev. i-o to finish; then get bucket when free SNDFIO2: ...enter here with bucket already gotten PUSHL RR6 R7:=DATA RL0:=IOCODE; OUTB @R7,RL0 OUTB @R7,RH1; OUTB @R7,RL1 not and RanRW(WRITER) do DEC BC ExitRW(); POP IX; RET GetRRP: PROC ...expects A LUN; returns FCB @DE; Random Record Pointer @HL GetFCB(R.A); LD HL,FCBSZ-3; R.HL+R.DE->R.HL; ...Rec_Ptr->HL RET InitRW: PROC ...enter B LUN, DE=buffer addr, HL len. ..editor for different terminals use: EECONFIG (must have EE on disk)  ams Q.COM -- Z80 extended assembler/debugger use: Q or Q filename E.COM -- full-screen editor use: E filename SYS.COM -- used to download Z8000 system (usually e. HEADER: word MAGICNO=0E007; long IMGSZ,UDATASZ; word SEGTABSZ; long ENTRY_PT word HDRFLG,RELOCSZ,SYMTABSZ,UNUSED where MAGICNO=magic number IMGSZ=image size UDATASZ=size of uninitialized data SEGTABSZ=size of following SEGTAB (segment table) R.HL+1 SDesSb2: PUSH DE ...enter here with BC & HL as going in des. PUSH HL ...seg len->stack W.SDesPs; EX DE,HL; ^SDDIF+R.DE; EX DE,HL ...HL=SDesPs, DE=SDesPs2 LD (HL),C; INC HL; LD (HL),B; INC HL ...store beg. adr. PUSH HL; W.IOFFSET+R.BC EX DE,...LU,cmd OUTB @R7,RH2; OUTB @R7,RL2; OUTB @R7,RH3; OUTB @R7,RL3 ...RR2 R6:=R13 OUTB @R7,RH6; OUTB @R7,RL6 ...R13 OUTB @R7,RH4; OUTB @R7,RL4; OUTB @R7,RH5; OUTB @R7,RL5 ...RR4 R6:=R9 OUTB @R7,RH6; OUTB @R7,RL6 ...R9 SNDBUK() ...send bucket POPBRKS BRKLST S_R NXTCNT R_PC0 SSP SAVADR SBInst ...in MMETA *ZAP R_A R_BC R_F0 R_A0 R_BC0 R_DE0 R_HL0 R_IX0 R_IY0 R_SP0 ...in MMETA *ZAP STSP STBADDR STBINST *ZAP CPSIR CPSLUP CPS0 LCPSIR DBUG A0 D2 GETCNT NS2 Tr2 NST2 *ZAP CHK1PR CHK1SP CHK1CR CK1SPCR C1done at system startup) use: SYS (must have file "S" on disk) G.COM -- starts up Z8000 system and then handles input-output, etc. for it use: G X.COM -- used to reenter E after exit (also works with G) use: X XQ.COM -- used to ENTRY_PT=entry point HDRFLG=flag: bit 0=1 =>reloc. info + symtab stripped (execution addr fixed) bit 1=1 =>stripped plus may run in any Z8000 segment (uses segment of ENTRY_PT) RELOCSZ=size of relocation information SYMTABSZ=size of symbol taHL; LD (HL),E; INC HL; LD (HL),D; INC HL POP DE; POP BC LD (HL),C; INC HL; LD (HL),B; INC HL; EX DE,HL LD (HL),C; INC HL; LD (HL),B; INC HL ...store length POP DE LD BC,SegDes+(4*16)+1 R.HL=R.BC; RET NC ...chk not >16 segments (Z=0) R.HL->W.SDesPsL RR6; RET DI_: PROC ..."disable" NMI RESB DI_FLG,0; RET EI_: PROC ..."enable" NMI; preserve Z-flag TSETB DI_FLG; RET MI SC (SC_INTR & 0FF); RET ...if was NMI, do it DIS_BRK: PROC ..."disable" NMI break RESB DB_FLG,0; RET EN_BRK: PROC ..."enaSPCRCM CHK1C Dump MAXNL Name *ZAP DNAM PRTNM PRTNM2 CHGRR PRTRRS PRTRR RRNMS RRCOPY DOTSPS COPYSP *ZAP CHGMEM CHGMRR CHMCHR MVCRS MVCRS1 PRTIMG CHRRTAB CHMTAB SCIPOS *ZAP DEASM UNASM ShRegs Regs RES_R SAV_R STRR RESRR LocSub HISTORY *ZAP BRK NOBRK BKCPUA Pucceed, Z=1, entry 0'ed except LUOPNB set; else Z=0 LDAR RR10,FILTAB; RL0:=0 repeat if BITB @RR10,LUOPNB zero then begin PUSH R1; R1:=LULEN/2 repeat CLR @RR10; R11:+2 until R1:-1; R11:-LULEN; SETB @RR10,LUOPNB POP R1; R0==R0; RET ble SEGTAB: ...segment table ...each entry=description of 1 code or uninit'd data region long START_ADDR; word LENGTH,TYPE ...TYPE=0 =>code, 1 =>uninit'd data repeat entries until SEGTABSZ (max 12 entries) IMAGE: <-------------------> (length=IMGSZ 00; RET CONT: ...checks if DE not at CR & line up to DE just has DELs if @DE=0D then begin OR A; RET end PUSH DE; LD DE,(LASTCR); DEL(); POP HL PUSH HL; R.HL-R.DE; POP DE; RET NZ LD DE,(LASTCR); RET OPTM: OR 1 ...set Z=0 Optm: RET; RET; RET ...foble" NMI break; preserve Z-flag TSETB DB_FLG; RET MI SC (SC_BKR & 0FF); RET ...if was NMI break, do it ...DEVICE DRIVERS: PUTBUFSCR: ...put PUTBUF->screen; 0->PUTBUFCNT save R6..R13 R5:=PUTBUFCNT->R13 LDAR RR2,PUTBUF; RL1:=WRT CALL SCREEN PUTBUFutBrkB CKFF BRKSOFF BRKOFF REMBRK ResINST *ZAP CKBP1 CKBP2 MBPERL LSTBRKS *ZAP STRET STRET2 RESSTBRK ...S_INT etc *ZAP FNDNXTPC NXTPC2 BASINST JPat CALLJP CJPT TSTCC JR_ RST_ RET_ RETT *ZAP Call Pop StepSP ResSBrk CkInst0 SStep SStep2 SStep3 CALLHL B_RTN  end R11:+LULEN until RL0:+1=NLUs; RESFLG Z; RET RELLU_: ...release LU RH1 PUSHL RR10; FNDLU_(); CLRB @RR10; POPL RR10; RET OPEN: ...assign LU, do open; enter R1=orig R0, R13=orig R1, R0 diff. ...ret. RH1=LU if REQLU_() not zero then begin RL0:=...Editor make file ...to use, /DO E.M, type in image statement as written out when done /DO ED1.S /DO SYS.EQU NLUS: EQU 2 ...for ZDOS.S /DO ZDOS.S /DO ESYS.S /DO ED2.S /DO ED22.S ...extensions go here if assembling with editor (rather than using E.X.M) /r patch OPTM2: RET; RET; RET ... " ...OPTIF: RET; RET; RET ...call before "?endif" ...CHKDE: RET; RET; RET ...call after "^" or "W." GLOBAL Err Errm Quit Getcon Putcon Outmsg Getrec Get1 Put1 GLOBAL Test Id Copy Copyin Sr Sr1 Hexd Digit Count Outhex CNT:=0 restore R6..R13 RET PUTBUFBUK: ...put PUTBUF in bucket, 0->PUTBUFCNT if R5:=PUTBUFCNT=0 then PUTZ() else begin R4:=DATA RL0:=CONWRCD; OUTB @R4,RL0 OUTB @R4,RL5 LDAR RR2,PUTBUF OTIRB @R4,@RR2,R5 PUTBUFCNT:=0 end RET WRCON: .CONTX *ZAP BkDbg Next BkDbg0 Trace NSTJG Go OJPDBG Debug DBUG2 DBUG3 Deasm *PACK ALL GLOBAL R_AF Dbug  B_RTN CONTX *ZAP BkD NXTPC2 BASINST JPat CALLJP CJPT TSTCC JR_ RST_ RET_ RETT *ZAP Call Pop StepSP ResSBrk CkInst0 SStep SStep2 SStep3 CALLHL B_RTN TUMNYERR; RET end ...RL0=LU, RR10=^entry in file table RH0:=RH1; RL0:->RH1 ...RH1=LU, RH0=open type PUSH R1 FIXNAME() ...if name=string+'0', change to deft if ISDEV() then ...chk if name=device name (RR8=^entry ADT) LDL RR8,@RR8 ...get device aDO EEXS.S /DO ED3.S EBUF0: EQU ENDROM&0FF00+0100 ...start of edit buffer (1 free space before) EBUF9: EQU EBUF0+((0F900-EBUF0)/0200*0200) ...end of buffer ... (doesn't matter for CPM) /MAP 8 /?"/IMAGE E.COM ",^EE," ",^ENDE-1 ...E=^EE ((0F900-EBUF01 Lkup Lkupnl GLOBAL Latch Outp Outset Out Sav Re Xc Ig Pp Gen Zp Eff1 GLOBAL OutN Num HNum RDaHL WRaHL ...Skip GLOBAL LASTCR NCODE LASTDE NEXTDE TABBSE QOPTS OFFSET EXTADR I_SW GLOBAL Q WSbgn WSend HLout Optm GLOBAL XINST INST INSTLIST ASMST BITOP2 DEL..enter with RR2=xfadr, R5=no. bytes to write to console ...currently ignores LFs save R6..R11 R7:=R5; LDL RR10,RR2 while R7<>0 do begin repeat until PRTSW=0; DIS_BRK() PUTBFLOCK:=1 ...DI_() LDAR RR8,PUTBUF R6:=PUTBUFCNT; R9:+R6 R1:=YS.S *DO BK1.S *DO MSUB.S *DO QBUG.S *DO UNSYM.S ...handle referenced but unused symbols *DO XX.S CODE: EQU 0100 CODE2: EQU CODE+0400 TABLE: DEFS 2+NHASH*2 ...for len. of symbol table + initial links (32 entries) DEFS 0400 *^TABLE; LD (05002),HL *PACK *ddr else begin SETB @RR10,ISFILB LDL RR8,#MYSeg,FILES ...file handler end LDL RR10[DEVADR],RR8 ...store addr of LU handler ...else file handler->addr for LU CALL @RR8 ...init. open POP R1 ...RH1=LU if RL0<>OK then RELLU_() RET SEEK: ..:pw!~(6ɯ2( >:t:u*|}::u :}*{|} :p*n|}_  G:u ( >:t:u[QYAai_ [n:pOͬ "n2pɹR*v "v*yB"y:tO! 6:tO! 6ɯO! (wA<8x  XCOMM WN BN GLOBAL COMMAND LABELCOL  DE NEXTDE TABBSE QOPTS OFFSET EXTADR I_SW GLOBAL Q WSbgn WSend HLout Optm GLOBAL XINSCODE LASTDE NEXTDE TABBSE QOPTS OFFSET EXTADR I_SW GLOBAL Q WSbgn WSend HLout Optm GLOBAL XINST INST INSTLIST ASMST BITOP2 DEL0 ...will be set=1 if buffer full or CR repeat if RL0:=@RR10'<>0A then begin RL0:->@RR8'; R6:+1 end if RL0=0D then begin B.0A->@RR8'; R6:+1; R1:=1 end if R6>=PUTBUFSZ-1 then R1:=1 until R7:-1 zero or R1<>0; R6:->PUTBUFCCALL 05004 ...move symbol table /MAP 8 /LIST /LISTEND /LISTEND T /LISTEND DEFS 0400 *^TABLE; LD (05002),HL *PACK *CALE+0400 TABLE: DEFS 2+NHASH*2 ...for len. of symbol table + initial links (32 entries) DEFS 0400 *^TABLE; LD (05002),HL *PACK *.set FPSREQ of LU RL3 from RR4; R1: 0=>abs, 1=>from curr., 2=from end ...ret. RR2=new pos., -1 if err (RL5=code) PUSHL RR10 if FNDLU2(RL3:->RH1) not zero then begin LDL RR2,#0FFFF,0FFFF; RL5:=RL0 end else begin SUBL RR2,RR2 if RL1=1 then LDL R( >d T _ `iB8(: >d C _  DM: c C Z yx(d T `iB0 DMͫ B8 (ͣ  DM( >d yx( > Ϳ R List of Programs running on CPM ZOOM System: Z80: All regular CPM command programs Q.COM -- Z80 extended assembler/debugger use: Q or Q filename E.COM -- full-screen editor use: E filename SYS.COM -- used to download Z8000 system (usually NT if R1<>0 then begin if SCRFLG=0 then begin PUTBFLOCK:=0 EN_BRK() REQBUKW2() PUTBUFBUK() SNDBUK() JR WRCONX end else PUTBUFSCR() end PUTBFLOCK:=0 ...EI_() EN_BRK() end WRCONX~ restore R6..R11 RET ...WRCON: ...WSendS^ C HLoutS C Outhex" 0beginGend͆\( e ܐ(ëܐϐ y*n"nu!qvRif $͂then8͚8? endifwhile )͹͂do8͚A1 ~ͻ~ repeat ͹GS)endrR2,RR10[FPSREQ] if begin RL1==2; LDL RR0,RR10[FLEN] end then LDL RR2,RR0 ADDL RR2,RR4 if CPL RR2,RR0 >zero then LDL RR2,RR0 LDL RR10[FPSREQ],RR2 end POPL RR10; RET FSTAT: ...enter RL3=LU, RR4=^buffer to put file type (device or file) & lengt":!>  O:( yd xd _ N  Z ( (Z (c >ɯɯtͩt "t>xtO"t00 DMͫ B8 (ͣ  DM( >d yx( > Ϳ R done at system startup) use: SYS (must have file "S" on disk) G.COM -- starts up Z8000 system and then handles input-output, etc. for it use: G X.COM -- used to reenter E after exit (also works with G) use: X XQ.COM -- used to enter with RR2=xfadr, R5=no. bytes to write to console ... ...currently ignores LFs ... PUSH R6; PUSHL RR8 ... R1:=R5; LDL RR4,RR2 ... while R1<>0 do begin ... repeat until PUTBUFCNT=0; ... LDAR RR8,PUTBUF; R6:=0 ... DI_() ... repeat ... if RL0case͚8of͠endL ~û~until 38f A1~(͂A2 ~ͻ~D~ͻ~DEC B S͏S; ͰͰ}Ͷx~~A1~!A2u~8 S; (else 8͚8Lu~û~5(́ҡ~ A1u~h ...format: type=word (0 if file, 1 if device), len=long ...if R4=0FFFF, use caller's segment (in R12) ...ret. R3=0 if succeed, else -1 (RL5=code) PUSHL RR10 if FNDLU2(RL3:->RH1) not zero then begin R3:=-1; RL5:=RL0 end else begin if R4=0FFFF L,H; LD H,C ...offset/128->AHL POP BC ...CDE preserved R.HL->@2IX(FCBSZ-3); R.A->@IX(FCBSZ-1) POP IX 00; RET ReadF: PROC ...expects B LUN, DE=buffer addr, HL length ...returns A=err code (Z=0=>err), HL amount read PUSH IX InitRW(); while R.B|R.reenter Q (clobbers 100-17F however) use: XQ SPLIT.COM -- splits big file up into smaller ones use: SPLIT filename ECONFIG -- reconfigure E editor for different terminals use: Q ECONFIG (must have E on disk) Z8000: Y -- Z8000 multi-le:=@RR4'<>0A then begin RL0:->@RR8'; R6:+1 end ... if RL0=0D then begin B.0A->@RR8'; R6:+1 end ... until R1:-1 zero or RL0=0D or R6>=PUTBUFSZ-1; ... R6:->PUTBUFCNT ... EI_() ... end ... POPL RR8; POP R6; RET ...MAXCNT~ EQU PUTBUFSZ ...value(R3:=0F; 1->R.A; JR GOXB ... GOXX: PUSH HL; W.XAdd; EX (SP),HL ...put execution addr. on stack GOX: PUSH AF; 00->R.A GOXB: R.A->B.RetQFlg ...R.A=1=>ret. via "RET" if CODEBK=0 then begin POP AF; RET end ...bank 1 if B.CPU=0 then begin POP AF; JP GO2 end ..then R4:=R12 R3:=1 if BITB @RR10,ISFILB not zero then R3:=0 R3->@RR4 LDL RR2,RR10[FLEN]; LDL RR4[2],RR2 R3:=0 end POPL RR10; RET SNDFILIO: ...send file i-o req.->Z80 ...enter: R1=LU,cmd, RR2=addr (RL2 poss. open type), RR4=addr/fpos ...C not and RanRW(READR) do DEC BC ExitRW(); POP IX; RET WriteF: PROC ...expects B LUN, CDE file address, HL length, IX DMA address ...if R.C=0FF then write sequentially ...returns HL amount written, CDE, IX updated PUSH IX InitRW(); while R.B|R.C vel language and debugger use: Y or Y filename EE -- full-screen editor use: EE filename C -- C compiler use: C or C filename COMPARE -- compare 2 files use: COMPARE filename1 filename2 EECONFIG -- reconfigure EE 2 100;if R3>BUCKL-2 then R3:=BUCKL-2) ...WRCON: ...enter with RR2=xfadr, R5=no. bytes to write to console ... ...currently ignores LFs ... PUSH R6 ... R1:=R5+1; LDL RR4,RR2; R6:=0 ... while R1:-1 not zero do begin ... R6:+1 ... if RL0:=@RR4'=0D then R6:DAFLGB zero then begin ...if no read-ahead prev. done SETB @RR10,RDAFLGB ...only try once save R1..R3,R13 RDAHD_() restore R1..R3,R13 end READF2(); RET RDAHD_: ...do read-ahead; enter RR10=^LUvec, RH1=LU LDL RR2,RR10[FLEN]; LDL RR4,#0E000----- register AC_1 : R9 ... ------------------------------------------------- register AC : RR10, AC_2 : R10 ... ------------------------------------------------- register AC_3 : R11 ... ------------------------------------------------- ... ------- R11:=BUFBEG; R10:=R8 ...RR10=BUFPTRA COL:=0 repeat PRVCOL:=COL UPDCOL(RL3:=@RR10) ...update COL by size of char expanded until R11:+1=BUFPTR; ...get PRVCOL=col. of prev. char. repeat ECHO(RL3:=8); ECHO(RL3:=' '); ECHO(RL3:=@RR2,R0 ...FLTPRSZ=len of string (fixed) RET ...FLOATING_POINT_MATH MODULE ... ... ***************************************** ... * * ... * Z8000 FLOATING POINT MATH * ... * * ... * by Joe Huber * ... * * ... ***************************+1 ... if RL0=0A then R6:-1 ... end ... while R6>MAXCNT do begin ... R5:=MAXCNT-1 ... R6:-R5 ... WRCON2() ... R6:+R5 ...R5=-1 if extra LF done, else 0 ... end ... if R6<>0 then WRCON2(R5:=R6) ... POP R6; RET ...WRCON2: ...wait till buffer (PUTB if CPL RR2,RR4 >zero then LDL RR2,RR4 PUSH R3 R3:+(BLKSZ-1)&(0-BLKSZ) ...round up to mult. of BLKSZ ADDBUF(R3; RL5:=RH1) ...add buffer of size R3 POP R3 if zero then begin ...if got buffer R3->@RR8[XFCNT]; 0->@RR8[BLKNO] SET @RR8,RDB; SET @------------------------------------------ ...THE FOLLOWING REGISTER DEFINITIONS ARE USED BY THE CONVERSION ROUTINES ...AND OVERLAP THE DEFINITIONS ABOVE WHICH ARE USED BY THE MATH ROUTINES register CHAR : RH1 register COUNT : RL1 register DEC_EXP : R8) until COL=PRVCOL; BUFPTR:-1 RL3:=8 end else if BUFPTR@BUFPTRL'; PUSH R3; ECHO(RL3:); POP R3 end until RL3=0D; GETLX~ R3:=BUFPTR-BUFBEG restore R6..R13; RET UPDCOL: ...enter with RL3=char, update CO************** ... ...This module provides basic floating point operations for the Z8000, ...either segmented or nonsegmented. ...Floating point numbers are stored in a 32 bit long word. They consist of ...an effective mantissa of 24 bits, 8 bit excess-1UF) has room, then add to buffer ... DI_() ... if R0:=R5+PUTBUFCNT>PUTBUFSZ then begin ... EI_() ... repeat until PUTBUFCNT=0; ... DI_() ... R0:=R5 ... end ... PUSHL RR6 ... LDAR RR6,PUTBUF; R7:+PUTBUFCNT ... R0:->PUTBUFCNT ... repeat ... if RL0:RR8,RDAB ...mark for rdahd FILIO_() end RET READF2: ...enter RR2=xfadr, R13=xflen, RH1=LU, RR10=LUvec ...do read, xfdta, update fpsreq, ret. RL0=CC, R13=len read ...register LU:RH7, TOTLEN:R13, LSTBLKTOP:R12, FSTBLK:R0, LSTBLK:R1, ... I:R6, TOP:R8 register EXP_VAL : R7 register EXP_VALL : RL7 register EXP_VALR : RR6 NORMALIZE_AC PROC ...PUTS AC INTO NORMAL FORM ...BIT 31 WILL BE ZERO ...BIT 30 WILL BE ONE ...IF VALUE IS ZERO THEN ZERO'S EXPONENT ...CHECKS FOR OVER & UNDERFLOW ...IF ACL (RL6) by size of char when printed if RL3=9 then begin ...if tab repeat COL:+1 until COL&7 zero; end else begin COL:+1 if RL3<020 or RL3=07F then COL:+1 ...if ctl char. end RET ECHO: ...echo char. in RL3 & keep track of col. in COL (RL6) 28 exponent, and a sign bit ...which replaces the MSB of the mantissa. This is exactly the same format as ...used in ZILOG BINBASIC. ... ... ie SMMMMMMMMMMMMMMM ... MMMMMMMMEEEEEEEE ... ...This gives an effective range of +/- 1.7014117 E 38 to +/- 2.93=@RR2'<>0A then begin ... RL0:->@RR6'; R5:-1 ... if RL0=0D then begin RH0:=0A->@RR6'; R5:-1 end ... end ... until R5<<=0; ... EI_(); POPL RR6 ... RET CONINIF: ...get 1 byte from cons.->RL3 if one rdy ...ret RL0=OK if so, else=NOCHAR ...save re; RES R3,0 ...RR2=ret. addr after string R12:=R2 ...used below for calling seg. R1:=R11+36 LDL RR14[R1],RR2 ...put ret addr in prog status left from PRINTF0 call ...Printf: (RR8=^string, R10=str len, R11=stk offset 1st arg.) LDAR RR6,PRTBUF ...RR6 IS ZERO THEN ZERO EXPONENT if TESTL AC zero then begin AC_SIGN:=PLUS AC_EXP:=0 RET end ... SHIFT AC LEFT BY 8 UNTIL UPPER BYTE CONTAINS A ONE ... DEC AC_EXP BY 8 EACH TIME. ... GROSS NORMALIZATION while AC_2<0100 do begin SLLL AC, #8 if RL3=9 then begin repeat PUT1C(RL3:=' '); COL:+1 until COL&7 zero; RET end COL:+1 if RL3=8 then COL:-2 else if RL3=0D then COL:=0 else if RL3<020 or RL3=07F then begin PUSH R3; PUT1C(RL3:='^'); POP R3 if RL3=07F then RL3:='?'-'@' RL3:+'873591 E -39. ...The mantissa is calculated to 31 bits internally and rounded to 24 bits when ...stored externally. This gives 9 digit accuracy internally and 7 digits ...externally. The mantissa is always normalized which means that the hidden ...MSB is ags>R3 DIS_BRK() if R3:=NXTOUT=NXTIN then begin RL3:=0; RL0:=NOCHAR end else begin PUSH R2 R2:=MYSeg RL0:=@RR2 INCKPTR()->NXTOUT RL3:=RL0; RL0:=OK POP R2 end EN_BRK(); RET CONIN1: ...get 1 char from console; ret. RL3=char, RL0=OK re=^output buffer while R10>>0 do begin if RL0:=@RR8='%' then begin R9:+1; R10:-1 LD R3,RR14[R11] ...get arg. RL0:=@RR8->RH0; RESB RH0,5 case RH0: of 'B': OutB(RL0:=RL3) 'C': RL3:->@RR6' 'W': OutW() 'S': O AC_EXP:-8 end ...SHIFT AC LEFT BY TWO UNTIL BIT 30 OR 31 IS A 1 ...DEC AC_EXP FOR EACH SHIFT ...FINE TUNE NORMALIZATION while AC_2<04000 do begin SLLL AC, #2 AC_EXP:-2 end ...IF BIT 31 OF THE MANTISSA IS NOT 0 THEN SHIFT AC ONE PLACE@' COL:+1 end ... PUT1C: ...put out char. in RL3 to console save R6..R13 PUSH R3 LDL RR2,RR14; R3:+1; R13:=1; RL1:=WRT CON() POP R3 restore R6..R13 RET FILES: ...file i-o handler case RL0:=RL1&0F of RD: READF() WRT: WRITEF() OPN: OPENssumed to be a 1 unless the exponent is zero in which case the ...number is zero. ... ... 7FFF FFFF 1.701412 E+38 Largest positive value ... 0000 0081 1.000000 E+00 1.0 ... 0000 0001 2.938736 E-39 Smallest value ... 0000 0000 0.000000 E+00 0 ... FFFFpeat CONINIF() until RL0=OK; RET STOPCH: BYTE CTLS ...print toggle char. EOTCH: BYTE CTLD ...ends line input from console CON: ...console i-o handler ...R1=orig R0, R13=orig R1 (len), RR2=xfadr, other regs free ...ret. RL0=comp. code; on read/write: 2 utStr(R2:=R12; R5:=^PRTBUFEND-R7) ...RR2 pts. to DEFT 'D': OutDec() 'F': begin R2:=R3; R11:-2; LD R3,RR14[R11]; OutFlt() end else begin RL0:->@RR6'; R11:+2 end end R11:-2 end else begin if RL0='\' then begin R TO RIGHT ...AND ADD 1 TO AC_EXP if BIT AC_2,15 <>zero then begin SRLL AC, #1 AC_EXP:+1 end ...IF AC_EXP GT 255 THEN EXPONENT OVERFLOW if AC_EXP>>255 then begin ...ERROR %02, SET AC TO MAX VALUE AND REPORT ERROR LDL AC #07FFF,0FFFF AC_EXP:=2F() CLS: CLOSEF() else INVALID() end RET FILIO_W: ...enter regs set, RR10=^LUvec, do FILIO & wait for comp. REQBUKW() ...get bucket after waiting for prev. i-o to finish N_IOINPRG:+1 RESB @RR10,COMPB SNDFILIO() repeat until BITB @RR10,COMPB no FFFF -1.701412 E+38 Largest negative value ...SQR_APPROX REAL := %55F61A7F ! .4178932188 ! SQR_APPROX LONG 05735897F ... .4203303218 ! LOCALVAR: LONG 0 ...CONSTANT PLUS: EQU 0 ...SIGN CONSTANTS! MINUS: EQU 0FF register REG4 : RR4 register R13=no. bytes transferred if RL0:=RL1&0F=WRT then begin ...WRITE_CON: ... repeat until PRTSW=0; ...chk if printing stopped WRCON(R5:=R13) RL0:=OK; RET end if RL0=RD then begin ...READ_CON: LDL RR6,RR2 case R13: of 0: beg9:+1; R10:-1 RL0:=@RR8->RH0; RESB RH0,5 case RH0: of 'N': RL0:=0D 'T': begin RH0:=7; RL0:=' ' repeat RL0:->@RR6; R7:+1 until RH0:-1; end end end RL0:->@RR6; R7:+1==^PRTBUFEND-FLTPRSZ; JR UGT,PFBRK ...chk INF. STORE_AC() RET end AC_3:=AC_EXP-080 EXTS AC IFLOAT() LDL OP,#058B90C00; OP_EXP:=080; OP_SIGN:=PLUS ...OP:=LOG BASE E OF 2=.6931471806 FLOATING_MULTIPLY() LDL TEMP4,AC; TEMP4_SIGN:=AC_SIGN; TEMP4_EXP:=AC_EXP LDL AC,TEMP1; AC_SIGN:=TEMPt zero; ...or could chk N_IOINPRG=0 & don't need COMPB RET CKERRCD: ...if ERRB & ERRCD say err, ret. Z=0, RL0=code; else Z=1, RL0=OK RL0:=OK if BITB @RR10,ERRB not zero then RL0:=@RR10[ERRCD] RET OPENF: ...open file with LU RH1; ret. RL0=CC PUSH PTR4 : R5 ...THE FOLLOWING IS A MAP OF REGISTER ALLOCATION DURING ARITHMETIC PHASE. ...SEE BELOW FOR MULTIPLE USES DURING CONVERSION PHASE. ... ------------------------------------------------- register AC_SIGN : RH0, OP_SIGN : RL0 ... ---------------in RL3:=CONINIF() if RL0=OK then begin RL3:->@RR6; R13:=1 end end 1: RL3:=CONIN1()->@RR6 ...get single char (no echo) else begin R13:=GETLINE(R5:=R13) ...get line to @RR2 (R5=max len) ... rets. R3=len. (to CR or EOT or maxfor buffer overflow if next item=max len (13, when float) end R9:+1; R10:-1 end PFBRK~ LDAR RR2,PRTBUF; R1:=R7-R3; RH0:=1; RL0:=WRT IOREQ() ...print buffer R15:+@RR14+2; POP R3; LDCTL NSPSEG,R3 LDM R0,@RR14,14; R15:+28 ...restore regs. IRET O1_SIGN; ...scale to 1/sqrt(2)<=xRL0, else OK->RL0 RET CLOSEF: ...close file with LU RH1; ret. RL0=CC FNDLU_() ...RR10 at LUvec RH7:=RH1 ...LU save R1..R3,R13 NXTBUFI() while NXTBUF() zero do begin if RH7=@RR8[LU_] ---------------------------------- register OP_EXP: R1, OP_EXPH : RH1 ... ------------------------------------------------- register OP_0: R2, OP: RR2 ... ------------------------------------------------- register OP_1: R3, OP_1L: RL3 ... ---------- len) RL0:=OK end end RET end ...OPEN,CLOSE_CON: if RL0=OPN then begin INITCON() if SCRFLG<>0 then CALL SCREEN RL0:=OK; RET end if RL0=CLS then begin repeat until PUTBUFCNT=0; INITCON() RL0:=OK; RET end RL0:=INVLDEutW: PROC ...put out R3 in hex @RR6 OutB(RL0:=RH3); RL0:=RL3 ... OutB: PROC ...put out RL0 in hex @RR6 PUSH R0; RL0:/16; OutNib(); POP R0 OutNib: if RL0:&0F+'0'>'9' then RL0:+7 RL0:->@RR6'; RET OutStr: ...put out DEFT @RR2 @RR6; R5=max. len. RL0:=@RR=1.0 FLOATING_ADD() LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP LDL AC,TEMP3; AC_SIGN:=TEMP3_SIGN; AC_EXP:=TEMP3_EXP LDL OP,#040000000; OP_EXP:=081; OP_SIGN:=PLUS...OP:=1.0 FLOATING_SUB() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXthen begin ...find buffers belonging to LU FINBUF() ...release buffer, first writing out if necessary if BITB RL0,6 not zero and BITB @RR10,ERRB zero then begin ...if err (if >1st, keep 1st error code) RL0:->@RR10[ERRCD]; SETB @RR10,ER--------------------------------------- ... GENERAL PURPOSE POINTER -- R4 OR RR4 ... ------------------------------------------------- ... ... ------------------------------------------------- register TEMP : R6, TEMPH : RH6, TEMPL : RL6RR; RET ...invalid INITCON: PUTBUFCNT:=0; PUTBFLOCK:=0 PRTSW:=0; ^KBUF->NXTIN->NXTOUT; RET GETLINE: ...get line of input to @RR2, R5=max len., echoing, backspacing, etc ...ret. R3=len. (to CR or EOT or max len) register COL:RL6, PRVCOL:RH6, BUFPTRL:R2; RH0:=0; R3:+1 if R0>R5 then R0:=R5 LDIRB @RR6,@RR2,R0; RET TENF~ ;WORD 10000 1000 100 10 1 ... OutDec: ...put out R3 in decimal @RR6 if R3<<0 then begin RL0:='-'->@RR6' R3:=-R3 end LDAR RR4,TENF; RH0:=0 repeat R1:=@RR4 RL0:='0'-1 rP FLOATING_DIVIDE() LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP FLOATING_MULTIPLY() LDL TEMP2,AC; AC_SIGN:->TEMP2_SIGN; AC_EXP:->TEMP2_EXP ...p polynomial LDL OP,#06A491100; OP_EXP:=07F; OP_SIGNRB end end end restore R1..R3,R13 FILIO_W() CKERRCD() ...if err, errcd->RL0, else OK->RL0 RET READF: ...enter R1=orig R0=LU,cmd, R13=orig R1=xflen, RR2=xfadr, R4-R12 free R13==0; RL0:=OK; RET Z FNDLU_() ...get RR10=^LUvec if BITB @RR10,R ... ------------------------------------------------- register AC_EXP : R7, AC_EXPH : RH7, AC_EXPL : RL7 ... ------------------------------------------------- register AC_Q : RQ8, AC_U : RR8, AC_0 : R8 ... --------------------------------------------R8, BUFPTR:R9 register BUFBEG:R12, BUFEND:R13 ... save R6..R13 LDL BUFPTRL,RR2; BUFBEG:=R3 BUFEND:=R3+R5-1 COL:=0 GETLLP~ repeat RL3:=CONIN1() ...get char. RL3==EOTCH; JR Z,GETLX if RL3=8 then begin ...if backspace COL==0; JR Z,GETLLPepeat RL0:+1 until R3:-R1'0' or R1=1 or RH0<>0 then begin RL0:->@RR6'; RH0:=1 end R5:+2 until R1=1; RET OutFlt: ...put out floating pt. no. in RR2 @RR6 FLTTOASC() ...rets. RR2 @ascii string R0:=FLTPRSZ; LDIRB @RR6,3 :=PLUS...OP:=.41517739 FLOATING_MULTIPLY() LDL OP,#0554DE880; OP_EXP:=080; OP_SIGN:=PLUS...OP:=.6664400777 FLOATING_ADD() LDL OP,TEMP2; OP_SIGN:=TEMP2_SIGN; OP_EXP:=TEMP2_EXP FLOATING_MULTIPLY() LDL OP,#040000200; OP_EXP:=082; OP_SIGN:=PLUS...OP:=2.0 LDL AC,TEMP1; AC_SIGN:=TEMP1_SIGN; AC_EXP:=TEMP1_EXP end ...Q POLYNOMIAL LDL TEMP1,AC; AC_SI FLOATING_SUB() LDL TEMP3,AC; AC_EXP:->TEMP3_EXP; AC_SIGN:->TEMP3_SIGN LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN LDL OP,TEMP2; OP_EXP:=TEMP2_E@RR14,R0,14 R15:-10; PUSHL RR2 LDCTL R3,NSPSEG; LD RR14[12],R3 LDL RR2,RR14[46]; LDL RR14[8],RR2 LDL RR2,RR14[42]; LDL RR14[4],RR2 ...move down ret. PC & FCW POPL RR2; IRET Printf1: ...do printf, then restore regs. from stack; must call after Printf OP_EXP=0 then begin ...DIVIDE BY ZERO - ILLEGAL ERROR(TEMP:=4) RET end ...COMPUTE SIGN AND EXPONENT OF RESULT XORB AC_SIGN OP_SIGN AC_EXP:-OP_EXP+128 ...DIVIDE FRACTIONS LDL AC_U AC SUBL AC AC ...CLEAR LOWER PART OF DIVIDEND SRAL AC_U, #1 ..;,<>=* !! ~~ ! TE x  p x     ;;C x   ,,   ;;Cp00 99ݞ x 00 99 p 0 Ҟ 4ϗEsބ03s߁3 9000008368 FLOATING_ADD() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXP FLOATING_MULTIPLY() LDL OP,#058B90C00; OP_EXP:=07F; OP_SIGN:=PLUS ...OP:=LOG BASE E OF SQR(2)=.3465735903 FLOATING_SUB() LDL OP,TEMP4; OP_SIGN:=TEMP4_SIGN; OP_EXP:=TEMXP; OP_SIGN:=TEMP2_SIGN FLOATING_ADD() LDL OP,TEMP3; OP_EXP:=TEMP3_EXP; OP_SIGN:=TEMP3_SIGN FLOATING_DIVIDE() ...ADD IN FRACTIONAL AND INTEGER POWERS OF 2 case INTER&3 of 1: begin LDL OP,#04C1BF828; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=2^1/0 ...above on stack: #args*2, args (1st highest), regs, prev prog status LDL RR8,RR14[4]; R15:+8 ...RR8=ret. addr where have string R11:=@RR14 ...stk offset 1st arg. (=#args*2) RL1:=@RR8; RH1:=0; R10:=R1 ...string len. R9:+1 LDL RR2,RR8; R3:+R10+1.SHIFT RIGHT INTO CARRY RRC AC_2, #1 ...SHIFT CARRY INTO LOWER 32 BITS DIVL AC_Q OP NORMALIZE_AC() RET ...END FLOATING_DIVIDE SQUARE_ROOT PROC ... INPUT: AC CONTAINS X ... OUTPUT: AC CONTAINS SQR(X) ... ERRORS: X IS NEGATIVE RETURNS SQR(ABS(X))01p3K KQas1L-T:!\.80 5 R-LNLX_$!$їѐL-a4!9.8`: 8 q(0` ;o6p |q xp    ߥJ / x    P4_EXP FLOATING_ADD() RET Exp: PROC LOAD_AC() Exp_() STORE_AC() IRET Exp_: PROC LDL OP,#05C551D94; OP_EXP:=083; OP_SIGN:=PLUS ...OP:=4*LOG BASE 2 OF E=5.770780164 FLOATING_MULTIPLY() LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP 4=1.189207115 FLOATING_MULTIPLY() end 2: begin LDL OP,#05A827999; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=2^1/2=1.414213562 FLOATING_MULTIPLY() end 3: begin LDL OP,#06BA27E65; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=2^3/4=1.681792831 IV1.00 !}:o*oo o ],!l]! j] ]!}[p q ph> t Ѝa6D`:n9|`.n:n9K po6Y`9(`:B9n:n9О BRK() R5:-> INTER if AC_EXP<>0 then AC_EXP:-2 ...EVALUATE RATIONAL APPROXIMATION TO 2^X LDL TEMP1,AC; AC_EXP:->TEMP1_EXP; AC_SIGN:->TEMP1_SIGN LDL OP,#0454AED91; OP_EXP:=084; OP_SIGN:=PLUS ...OP:=8.6615859416262 FLOATING_MULTIPLY() LDL TEMP2,AC; AC FLOATING_MULTIPLY() end end ...add integer part to exponent of result R5:=INTER; SRA R5,#2 AC_EXP:=AC_EXP+R5 RET Power: PROC ...RR2:=RR2**RR4 POW() IRET POW: PROC LOAD_AC() LOAD_OP() LDL TEMP1,AC; AC_EXP:->TEMP1_EXP; AC_SIGN:->TEMP1_SIGN78 88&848B8P8^4.x!p4.nT $G7B]4/!0:870L8CON4-4!@B_5 潒baL8L8!o8r!! %UU !UU % !/!a` ^B!Y IN 3 ITERATIONS OF ... NEWTON'S METHOD. ... ... CHECK VALID ARGUMENTS if AC_EXP=0 then RET ...CHECK FOR ZERO OPERAND if AC_SIGN<>0 then begin ERROR(TEMP:=8) AC_SIGN:=PLUS ...RETURN SQR(ABS(X)) end ... SCALE TO .25 <= X 1 ... GIVE X EITHER ao1q1psa1qsos9p0aCC qp x  0.8poB.9Ѧ1tѫ! 4Cs 1a0 xp p 00`x4 x󠁩pp x 8055 ERROR(TEMP:=02) end ...IF AC_EXP LT 1 THEN EXPONENT UNDERFLOW if AC_EXP<<1 then begin ...ERROR %01, SET AC TO ZERO AND REPORT ERROR SUBL AC AC AC_EXP:=0 AC_SIGN:=PLUS ERROR(TEMP:=1) end RET ...END NORMALIZE_AC FLOATING_ADD PROC ...EXCHA LDL AC,OP; AC_EXP:=OP_EXP; AC_SIGN:=OP_SIGN LDL TEMPP,OP; OP_EXP:->TEMPP_EXP; OP_SIGN:->TEMPP_SIGN BRK() LDL LINTE,RR4 ...for y a noninteger, take exp(y*log(x)) if AC_EXP<>0 then begin LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN Log_()   !7.X3.XC: ::::13L8g7Q7^4Xf8~b8~{

TEMP1_EXP; AC_SIGN:->TEMP1_SIGN end CNT:=32 repeat LDL RR4,LINTE; SLAL RR4; LDL LINTE,RR4 if carry and CNT:-1 not zero then begin repeat NGE AC AND OP IF NECESSARY SO THAT LARGER ONE IS IN AC if OP_EXP>AC_EXP then begin ...EXCHANGE ALL AC & ALL OP EX AC_2 OP_0 ...UPPER MANTISSA EX AC_3 OP_1 ...LOWER MANTISSA EX AC_EXP OP_EXP ...EXPONENT EXB AC_SIGN OP_SIGN ...SIGN end ...CALCU3  LDL OP,TEMPP; OP_EXP:=TEMPP_EXP; OP_SIGN:=TEMPP_SIGN FLOATING_MULTIPLY() Exp_() STORE_AC() RET end ...for y an integer, multiply if TESTL LINTE zero then begin LDL AC,#040000000; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=1.0 STORE_AC() RET end( #    ^h?⠉o  f8^ xb8{^ :{Ѐ:: :4::p ߼:::78 39  '2'@! 2::4:%1#21xponent, restore bias ... CALCULATE INITIAL APPROXIMATION AC_EXP:-1 ... COMPUTE X/2 STORE_AC() ... SAVE X/2, DESTROYS AC LDL LOCALVAR,RR2 ... SAVE LOCAL ON STACK LOAD_AC() ... RESTORE AC LDL RR4,SQR_APPROX LOAD_OP() FLOATING_ADD() ... P LDL TEMP2,AC; AC_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN FLOATING_MULTIPLY() LDL RR4,LINTE; SLAL RR4; LDL LINTE,RR4 if carry then begin LDL OP,TEMP1; OP_EXP:=TEMP1_EXP; OP_SIGN:=TEMP1_SIGN LATE REQUIRED SHIFT TO ALIGN RADIX POINT ...IF GT 30 THEN NO SIGNIFCANT DIGITS TO ADD, RETURN if TEMP:=AC_EXP-OP_EXP>>30 then RET ...IF SIGNS OF OPERANDS DIFFER, NEGATE OP MANTISSA if AC_SIGN<>OP_SIGN then begin ...negate op COM OP_0 ...NO NEGL SO  LDL RR4,LINTE LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN if BIT R4,15 not zero then begin COM R4; COM R5; ADDL RR4,#1; LDL LINTE,RR4 LDL TEMP2,AC; AC_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN LD03$j8&2$#j8:ȃ:!1!:B !<$G<%<-<#<+5+1+7+3+!!1!: @a8U%"4NL8 -]_` L8> AȆ>H>M:"@M85+7+ERFORM 3 ITERATIONS OF NEWTON'S METHOD TEMP:=3 NEWTON_LOOP: repeat PUSH TEMP ... SAVE LOOP COUNT OP_0:=AC_2 ... SAVE LAST APPROX. IN OP OP_1:=AC_3 OP_EXP:=AC_EXP OP_SIGN:=AC_SIGN PUSHL RR2 LDL RR2,LOCALVAR ... GET LOCAL FROM ST FLOATING_MULTIPLY() end until CNT:-1 end until CNT:-1<<=0 STORE_AC() RET ...************ ROM: ADDR $  STO() LDL RR4,LINTE; SLAL RR4; LDL LINTE,RR4 if carry then begin LDL OP,TEMP1; OP_EXP:=TEMP1_EXP; OP_SIGN:=TEMP1_SIGN DO HARD WAY! COM OP_1 ADDL OP #1 end ...ALIGN MANTISSAS THEN ADD NEG TEMP ...NEED NEGATIVE COUNT FOR RIGHT SHIFT SDAL OP TEMP ADDL AC OP ...IF RESULT OF ADDITION IS NEGATIVE AND SIGNS OF OPERANDS DIFFER ...THEN NEGATE AC MANTISSA AND STORE OP_SIGNDe6e!Bء7 pcugq1ܠ A¡ACs ts`9ݗsѕ xp  `@J     `?J /`   ~#J ` 9J . LYCQ:JL8L8 1+!.(K83+L80 8!8wL8< 4 B:@_`TR7 …U7)d 7)\ 4)\  ߲Ȁ($ O  pACK LOAD_AC() ... GET X/2 POPL RR2 FLOATING_DIVIDE() ... DIVIDE X/2 BY LAST APPROX. OP_EXP:-1 ... DIVIDE LAST APPROX. BY 2 FLOATING_ADD() ... CALCULATE NEW APPROXIMATION POP TEMP ... GET LOOP COUNT until TEMP:-1 zero; ... GEEQ() R3:=0 OPCLX~ RL0:->RL5; RH5:=0 if RL5<>OK then R3:=-1 IRET Read: PROC RL0:=RD; JR RW2 ... Write: PROC RL0:=WRT RW2~ RH0:=RL3; LDL RR2,RR4 R5:=@RR14[2]; if R2=0FFFF or BIT R5,15 zero then R2:=@RR14[4] ...nonseg test only for compatibility, ma IN AC_SIGN if <OP_SIGN then begin ...NEGATE AC COM AC_2 ...NO NEGL SO DO OLD WAY COM AC_3 ADDL AC #1 AC_SIGN:=OP_SIGN end end NORMALIZE_AC() RET ...END FLOATING_ADD FLOATING_SUB PROC ...CHANGE SIGN OF OjYh9p譠 ~~  J 0! !!``Q 8E0[!X 5LX! #*0`>ݐ`>J.` .n >'{)҂!` 8J .LVh8ҏкґݞ __a4o4L9as`9p  OAȀ  H  4*Y! H.(0P4*<.I驓 I PNE4(xp 7CU5)a8x5'  B!B>S T4   K8r!T EXPONENT FROM EARLIER CALCULATION POP AC_EXP AC_EXP:+080 ...RESTORE BIAS RET ...END SQUARE_ROOT FLOATING_CMP PROC ...COMPARES TWO FLOATING POINT NUMBERS ...INPUT: NUMBERS ALREADY IN AC & OP ...OUTPUT: S below->AC ...WRITES ( S INTEGER ) @y remove later IOREQ() R3:=R1; RL5:=RL0 if RL5<>OK and RL5<>EOFERR and RL5<>NOCHAR then R3:=-1 IRET Getchar: PROC PUSHL RR0; R0:=0*0100+RD; RH3:=0 JR GPCHAR ... Putchar: PROC PUSHL RR0; R0:=1*0100+WRT GPCHAR~ PUSHL RR4; PUSHL RR2 LDL RR2,RR14; R3:P AND CALL ADD COMB OP_SIGN FLOATING_ADD() RET ...END FLOATING_SUB FLOATING_MULTIPLY PROC XORB AC_SIGN OP_SIGN AC_EXP:+OP_EXP-129 LDK TEMP #0 MULTL AC_Q OP ...MULT AC * OP TEMP:=09E00 SLLL AC_U, #2 ...SHIFT LEFT TWICE AND CORRECT LSB'S RL AC_2,n8LV x  nVҲ!S!V` 9J  ҷxt!30 w!\`!\oBs%߈p!^$!$(aB 8  0 ;;oBnAy aB0oB 5 w!\zy_ $ " 7)p5o8x5)b7)d1)^opFg`upF5)>ݞFp6eFfc0cpFc g6SuFeQ!Gg/G5S3B3ݾ5(H5SFYyw0&7Yi0&)cF\ 85BS77(13(K_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN FLOATING_MULTIPLY() LDL OP,#063F7DF9C; OP_EXP:=085; OP_SIGN:=PLUS ...OP:=24.99206394589LAG:=1 end end else begin+3 R1:=1; IOREQ(); POPL RR2 if R1=0 then R3:=-1 ...if EOF on read or other error POPL RR4; POPL RR0; IRET FLTPRSZ: EQU 13 ...len of ascii string representing floating pt. no. ...Printf uses PRTBUF Printf0: PROC ...save regs. on stack R15:-28; LDM  #2 ...GET 2 MSB INTO 2 LSB AC_2:&3 ...SAVE ONLY 2 LSB AC_1:|AC_2 ...SET 2 LSB INTO NEXT HIGHER WORD LDL AC AC_U ...LOAD AC FROM UPPER HALF OF RESULT NORMALIZE_AC() RET ...END FLOATING_MULTIPLY FLOATING_DIVIDE PROC ...CHECK FOR DIVIDE BY ZERO if  w>`AaB.?7poBL9f_1 _$J#   aB 5 \  `` 904!^    XX!$!>)CLNa 00oBa00ӬRa+̞6 {p {u  ! `.k4 3o58+3a38. *QI/I/\8y8\ 813!o8.\8{M8L89 Ȅ:: „!7&J3О5'4 &&@ ..# ‘JUST DO IT $11: CALL CONST ;GET IO READY INFO SPCRT2: STA RSLT.A ;AS RESULT RET ;RETURN HERE $12: LXI H,ARGADR ;NEW FUNCTION MOV A,M INX H MVI C,0 ;IF TPM CPI 0AAH ;FOR TPM SELECTION JRZ ..TPM MVI C,80H ;IF CPM CPI 0CCH ;FOR CPM 0x X >' x X  >' O 0# !!G w#w#w(>V#N#~$#~+: ~@##>͚ ~. #>͚ >ͬ  >Gx( ~͸ #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ x ^Ȁ###0#%##%Ȁ%Ȁ4 :7 '"Dj!!!""(">"R"f""$$#:&(*R+1?  "a"J3!-{Д$1 ?1Ա Ը0 !{B1 _1СOLD DMA RZ ;ERROR PUSH B ;SAVE IT AGAIN MVI M,0 ;SET OK ; ; NOW WE WANT TO SEE IF WE SHOULD SWITCH GEARS ; INTO CPM 2.2 STYLE OR REMAIN TPM-II. THERE ARE ; TWO WAYS TO DO THIS; EITHER THE "f3" FLAG WAY, ; OR THE ".COM" vs. ".SYS" METHOD. ; 6L8!HȇY (0   ;;b ekT5QL8_ȁpvbyg75%7{ f''^| ^ ^P ?^ >^ x11 '@ ; P6 %1  Ѝ, 3' 4" гSELECTION JRNZ ..NO ;NOT DOING SELECTION ..TPM: CMP M ;BOTH MUST BE THE SAME JRNZ ..NO MOV A,C ;GET SELECTION STA CPMTPM ;DO IT ; ..NO: LXI H,"T" ;FOR "T"PM SHLD RSLT.D LXI H,LVER ;MESSAGE SHLD RSLT.B LXI H,0 ;SAY 1.4 LDA CPMTPM((# !!G OW_}T]Oů)lau!t"w#k x( >!͊  ͻ k x( >"͊  ͻ x2S)lgx !!G H 4 # (  >>KBt́ (A  y21:((7 *."!N   !{!2!{ }63 5.75*7{5! 00,$w4n P %%/q  BB߭ CC.kp WW߻ SS!u߱ FF2q ߱.hp  JMPR ..OLD ;MY WAY (NOP FOR THE NEW WAY) ; ..NEW: MVI A,9 CALL GT.BBA ;GETS HL TO .EXT PUSH H ;SAVE THIS LXI D,..SYS ;TRY THIS FIRST CALL ..CK ;CHECK POP H JRZ ..PLG ;IT IS .SYS LXI D,..COM CALL ..CK JRNZ ..NE ;NOT EITHER CMA /  Д  Д М  ƕ{ 1 1 {   ߨ Ѡ3a;!  &ˍCwa{! &55 ;SEE WHICH WE ARE ORA A ;0=TPM (1.4) JRZ ..TPM2 MVI L,22H ;FOR 2.2 ..TPM2: JMPR HRSLT ; LVER: .ASCII "LIOS V" .BYTE VER!"0",".",REV!"0",MOD!"0" .ASCII "- " .DATE .BYTE 0 SERIAL: .ASCII "#XXXXXX" ; $13: XRA A ;CLEAR FLAGS STA CHRS#T]> wq  w U !+~͚ DM* "W>2(͆qͧ:*=͹ ͌,> <2+ h qbk͌{8>(O ! !   ( !Aq yK*B BR0 !n PY 9 (An  ~\\  NN  TT .hp.hp 4ġq1t}> {8ಁ00 99.hp (0PP!`P !`W5p w @qp  !b paq*; ;MAKE 0FFH JMPR ..PLG ;PLUG IT ..SYS: .ASCII "SYS" ..COM: .ASCII "COM" ..CK: MVI B,3 ..CK1: LDAX D SUB M RNZ INX H INX D DJNZ ..CK1 ; ..OLD: MVI A,3 ;TEST F3 CALL GT.BBA ;FOR CPMTPM CONDX ANI 80H ;0=TPM 80H=CPM ..PLG: STA CPMT4 $&  񃫽$ CJ Ϟ҉_$^7 ꠱^" 5 5B7 ꠱{! Ľ1&0/C57B0qȂ>x>q>y>r>z>s>{>v>~>t>|>u>}>v>~ҕAV ;NO CHARACTER SAVED STA CTL.P ;NO CTL-P STA C.DSK ;DEFAULT TO ZERO LXI B,Z+80H ;DEFAULT DMA ADDRESS CALL SET1ST RESET: CALL %INITD ;INIT SYSTEM LXI H,0 ;INITIALIZE LOGGED IN WORD SHLD LOG.DV LDA C.DSK ;LOG IN CURRENT DISK JMP ONL +>R8! !  (Xy(KB(h `i 9 (Xh S227:526h bk RDMWR#! !  F>w R ph (X!   *T]*#R R h (A!͏ HIT KEY TO REENTER:v  0b/* L$`(! `dO(qwhcvyps3c27p߲]Tic桢qT@x]w PM ;SET FLAG IF CPM 2.2 ..NE: LHLD RSLT.H ;LOAD POINT ..LDLP: PUSH H ;SAVE H MOV B,H MOV C,L ;FOR SETDMA CALL SETDMA ;SET DMA CALL REDFIL ;READ THE SECTOR LDA RSLT.A ;RESULT ORA A POP H ;GET ADDRESS JRNZ ..DONE ;THATS IT LXI D,b8~L8~?b8L8>Q$$M84`" HP  .`   .`   o89ڕ8a8K8 ! (Ӳo8䠋ȀJ  L8WȀ &3 .k %.kINE $14 == SELDSK ;SELECT DISK $15 == OPNARG ;OPEN A FILE $16 == CLSARG ;CLOSE A FILE $17 == SRCARG ;SEARCH A FILE $18 == SRNARG ;SEARCH NEXT FILE $19 == DELARG ;DELETE A FILE $20 == REDARG ;READ A FILE $21 == WRTARG ;WRITE A FILE $22 == C! !  (5A*",".R"QU N [,*.R *".! 9 ( [.!+*.~˿#".!+~=w*," ɯ2*>T !Uw#6 F͈_:J̠:S{!9I:*([0>!5w:6( 4:7OS2+> ##(  * wB1//%w @߳ !      ++ -- 00 99߹ ..128 ;SECTOR SIZE DAD D JR ..LDLP ;CONTINUE ..DONE: LBCD ARGOP ;GET FLAG (B) SHLD RSLT.B ;SAVE END ADDR DCR A ;LOAD OK? STA RSLT.A ;RESULT MOV A,B ;GET OTHER FLAG POP B ;OLD DMA ADDRESS PUSH PSW ;SAVE FLAGS CALL SETDMA ;RESTORE ա=Ȁ  L8_`Ȁ M8ȀM8L8!8o8o8(<=]^J & ˡ ߩ ֊n  . ա      ި4 REARG ;CREATE A FILE $23 == RENARG ;RENAME A FILE $24: LHLD LOG.DV ;GET LOGGED IN VECTOR XRSLT: SHLD RSLT.B HRSLT: SHLD RSLT.H MOV A,L ;FOR CPM SPCRT3: STA RSLT.A ;AS RESULT RET $25: LDA C.DSK ;SELECTED DISK JMPR SPCRT3 ;RETURN IT $26 = A ̍ >O0Ax i͍yMO OG*2R O ̍ yP8O>[0S02x<26:62: !:4> yO[22:625>26=25*R(S22 :50̓:5G:62625 xB*B"R#DMx*VE AS RESULT STA RSLT.B ;FOR CPM CPI 7FH ;RUBOUT RZ ;DONE CPI 20H ;CONTROL? JRNC ..ECHO ;NO, ECHO IT CPI 0DH ;CR? JRZ ..ECHO ;ECHO IT CPI 0AH ;LF? JRZ ..ECHO ;ECHO IT CPI 09H ;TAB? RNZ ;DONT ECHO OTHERS ..ECHO: MOV C,A USER DMA POP PSW ;GET FLAGS RNZ ;LOAD ERROR, RETURN ORA A ;B=ZERO? RZ ;OK, SO RETURN LDA F.DSK ;NEW DISK ORA A LDA T.DSK ;OLD STA ARGVAL ;SAVE IT CNZ SELDSK ;SELECT IT LSPD OLDSTK ;USERS STACK LHLD RSLT.H ;GET START OF LOA      ^  @@0ʗ ߾ f  ݯh8"d&Ȁ&0   0 &2$.&Ȁ-&$= SETARG ;SET DMA $27: CALL %SETUP ;SET IT UP SIXD RSLT.X SIYD RSLT.Y CALL SET.AV LHLD A.ALOC JMPR XRSLT ; .PAGE .SBTTL /TPM EXTENDED CALLS/ ; ; THE FOLLOWING ARE "TPM" FUNCTIONS. ; $T28: CALL CONIN ;GET CHARACTER JMP SPCRT2 ;AS ANSR#DM"#[*RB0̀G( (#w S=q}!͵}!0~ <~ *+G#=(G #=:7

P=27͠ɯ27͠:4!6 N:Q[0̓_;FOR OUTPUT JMP OUTCHR $2 == OUTARG ;OUTPUT CHARACTER $3: CALL %READR ;READ CHARACTER JMPR SPCRT2 ;RETURN IT $4: LXI H,ARGVAL ;GET CHARACTER MOV C,M JMP %PUNCH $5: CALL CONST ;FOR CTL-B LXI H,ARGVAL ;GET CHARACTER MOV C,M JMP %LIST ;D PCHL ;GO TO IT ; $T34 == $12 $T35: LHLD ARGADR ;ARGUMENT MOV A,L ;GET COUNT CPI 8 ;0-7 RNC ;INSURANCE ADD A ;*2 ADD L ;*3 MOV C,A ;SAVE AS OFFSET MVI B,0 LXI H,%HOME ;0 FUNCTION DAD B LBCD RSLT.H ;OLD HL HAS PARAMS 5BB303%%5 5BɞB5%1% $\5 %0Сc}߽)!c % 5 $P5 @B7 c1S9 05 `ȀWER $T29: XRA A ;SHOW THIS IS "GET" CALL %DATE ;GET DATE MVI E,"/" ;DELIMITER JMPR OUTDIG $T30: XRA A ;SHOW THIS IS "GET" CALL %TIME MVI E,":" OUTDIG: LHLD ARGADR ;ADDRESS MOV A,B ;FIRST NUMBER CALL ..DIG MOV A,C CALL ..DDIG MO:5!62T!T~(5!45ͧ> 25U4͠:6= [*0R!Ĭ!6~=5͠ɯ27<26͠ɯ27:426͠:7O͍ yP8 O:4G!6~4y27͠:7 !6~=5>P=27͠:J[*Rʀ>E28!L͇y27( (;͠ͼ*2 +6 ͳ=>I!S>R!Z28 ; CPM 2.2 HAS CHANGED THIS. WE STILL SEND ; B&C BACK WITH SERIAL NUMBER POINTER. ; IF E=FD, WAIT FOR CONSOLE. IF FE, JUST ; STATUS ONLY. IF FF, CHECK ; & MAYBE GET. ANYTHING ELSE GOES OUT. ; $6: LXI H,SERIAL ;POINT TO SERIAL NUMBER SHLD RSLT.B ;CALL ..GO ;GO TO IT STA RSLT.A ;RETURN RESULT SIYD RSLT.Y ;FOR SELECT RET ; ..GO: PCHL ; $T36 == BLDFCB $T37: CALL %TINMS SHLD RSLT.H SBCD RSLT.B RET ; ; - NOTE - $T38 = $C30 ; TPMLEN == .-LIOS ; .PAGE .SBTTL /CPM VERSION 2.2 EXɞ0P!@!@ ߩ%l0|6ފވ '0a1111011'11Ȁ!}4!'閭 213033'Ȁ''ɗ51@E B1@E B53V A,D ..DDIG: MOV M,E INX H ..DIG: MOV B,A RRC RRC RRC RRC CALL ..DG MOV A,B ..DG: ANI 0FH ;JUST DIGIT ORI "0" ;NUMBER MOV M,A INX H RET ;DONE ; $T31: RET ;TRAP CONTROL $T32: LBCD ARGADR ;GET POINTER LDAX B ;GET FLAG :J͇ ͠3y27͠n:8I [2ͼ͈_*2 ͈_(:PG{(  G2 :8E '~ ( (:8I ͼ:9(̀͌:8R( ~ # ~ ( #29͠>*KBOB0 DM!96x 46T] x((F~ :8ERETURN ADDRESS LDA ARGVAL ;FOR I/O MOV C,A CPI 0FDH JC %CONOT ;yw!w~w5͏p:oW( *j6&xZx2okkͱ{***** > *Gjv> }=O!kj"ij1*ejqͱ{ ERROR ;|*e64{' 7 2c %333 :(CґҘ :(5 Ҝ''Ɋ'05 11@E ԃ%h8'%ᢗᦗ'ȀӊщО5 ‘%1% $P5 %6Е!  c % INX B ORA A ;0 = DATE MVI A,1 ;FLAG THIS IS "SET" JZ %DATE ;DATE JMP %TIME ; $T33: LHLD A.DMA ;SAVE USER DMA ADDRESS PUSH H ;ON STACK LHLD ARGADR ;GET FCB ADDRESS LXI D,32 ;TO THE END DAD D LXI D,LOCFCB+32 ; LXI B,33 ;FCB LENT]R ~#~( (x(bk#   ȯ!6:7O7+~ :8E:6="22!6:7 5y27:8R ͠[2~25ͻ!9~5v:7O{ O ̍ :6GyP8:6h!6F4!7Nw#"2+{ xFs!5w 4(!B0>;Ͷͻx :8RIN JMPR SPCRT2 CSTS: LDA CHRSAV ;ANYTHING HERE? ORA A RNZ ;YES JMP %CONST $7: CALL %IIOS ;GET IT JMPR SPCRT2 ;RETURN RESULT $8: LDA ARGVAL ;GET VALUE MOV C,A ;INTO C JMP %AIOS ;SET IT $9 == OTBARG ;OUTPUT BUFFER $10 == INBUFF ;jqͶpN#Ͷperkk!Cj4*Sj*|pշB8(!kB0bk+>?erp*Qj"Sj:w( *Gj> 1kk*Mj|(ĵqdy1kkͳ (;(kͱ{/DO ~; > # ͵qkyw͆w͒w͏pzw( > !$=(x   5 $U3c % 5B c 09 }Н<3Ȁ  c % Ž@B5Bc}c}'c}+A5 @B7 5B75 T%'13 ý %6` 11S06'`GTH LDDR ;MOVE IT INX D ;LOCFCB SDED ARGADR ;SAVE AS FCB ADDRESS XRA A ;CLEAR STA LOCFCB+FCB.EX ;EXTENT STA LOCFCB+FCB.NR ;NUMBER OF RECORDS CALL OPNARG ;OPEN IT LXI H,RSLT.A ;RESULT MOV A,M ;GET IT INR A ;TEST POP B ;REMOVE 5 nH>!: ( >P0WzyFͧ>  ͠12=3d[[ͧ27Oa[22y27> ͩ!6~0(4:J33n3::25H[3!~G># 6 S2[(hy27͠ONONE TO ADD POP H LXI B,128 ;128 PER ..ADD: DAD B DCR A ;ADD EVERY JRNZ ..ADD PUSH H ;SAVE THE COUNT ..GOT: MVI A,FCB.RC ;GET SIZE CALL GT.BBA MOV C,A MVI B,0 POP H DAD B PUSH H CPI 80H ;WAS THIS A FULL EXTENT? JRNZ ..DUN ;E ľ( HLĦ ~R. A (́ O78rB. gͷ :- !Ϳ }Do>Y|͋|( D0 ( ͗ ץͨ͝>s|rR. ۧ(  (^ '˧(ͫ C ͿL>էW. g( ́{ *om here: --To here^ :J3͎ "K! !J4:J=3͎*KR3!6~04ͶͼSO2!J~ 35ͼ 3ͼ͢W[KSM!J5(5͐ *MB"M[K [M͠*0R8(B"0*2R8B0bk"2 ͌,AA, m 8,m O40rͭ(8 O46̬ͭ( O06ͭͮ͗ LD ",m O70r̬( 6̬ͮ("͚ *ej,͝SP,  (˜ם,˜͗ O4Bͩ͝O01ͩ "A &:J3}3!03# "B0 &n >N2E*(N !͵ q!2E"@!Dw: w(| !E̓ɯ2F2I<25*B~!02HK*BDM!N~ ({: N~ :D*( :G(~#z(:H/o8%#R0̀!"@*B~(G#NO CALL SRCNXT ;GET NEXT LDA RSLT.A ;FIND IT? INR A JRNZ ..LP ;YES ..DUN: POP D ;STUFF THE BYTES LHLD ARGADR LXI B,33 DAD B MOV M,E INX H MOV M,D INX H MVI M,0 ;OVERFLOW BYTE RET ;COMPUTE FILE SIZE $C36: LBCD ARGADR LXIէnͮ *͗ ͝Ͱ -DE ^#V+( ͸ nfʹ(ۧĦ ~#fo# ˧էnP. ́{ϯ(́{̭C {U͗  ͝Ͽs|rW. ́{́{>õB. ́{́{>ṍ{!!HLDE bkBC`i+carry+TENSIONS/ ; ; THE FOLLOWING ARE THE CPM TAILPIECES ; $C28: CALL %SETUP RES WRPS,D.USER(Y) ;PROTECT RET ;WRITE PROTECT DISK $C29: LHLD WRP.DV ;GET IT SHLD RSLT.H RET ;RETURN WRITE PROTECTED DISKS $C30: CALL SELCHK ;SET/CLEAR BIT 7'S LH2םO43ͩͳ O0Aͩm O78r͗ D ~̬( : ͝>îת̝(  OC0ͩrתHL, םO40ͩŕ{͟{{$"iR(BC) (DE)AF BC DE HL SP~:EN S2!"@2D>2G2F~!G~(5:E* s(>2I*@+"@|#(~¥RDM:Fm:E* !5:I 5NWN :Fͳ:J=3͒ *K R3 # R8 *0R8 "0SO "M!  !J4ѯ H,FCB.EX ;GET EXTENT NUMBER DAD B MOV D,M XRA A SRLR D ;/2 RAR ;A=0 OR 80H LXI H,FCB.RC DAD B ADD M LXI H,33 DAD B MOV M,A INX H MOV M,D INX H MVI M,0 RET ;SET RANDOM POINTERS $C37: RET ;RESET DRIVE(S) $C38: RET PIP A:=B:E.COM PIP A:=B:E.M PIP A:=B:ED1.S PIP A:=B:SYS.EQU PIP A:=B:ZDOS.S PIP A:=B:ESYS.S PIP A:=B:ED2.S PIP A:=B:ED22.S PIP A:=B:EEXS.S PIP A:=B:ED3.S  IP A:=B:SYS.EQU PIP A:=B:ZDOS.S PIP A:=B:ESYS.S PIP A:=B:ED2.S PIP A:=B:ED22.S PIP A:=B:EEXS.S PIP LD ARGADR JMP XCHFCB ; $T38 == $C30 ; $C31: LDA C.DSK ;GET CURRENT DISK MOV C,A ;INTO C CALL %SELDK SIXD RSLT.H RET ; $C32: CALL %SETUP ;GET CURRENT Y LDA ARGADR ;GET "E" CPI 0FFH ;GET? JRNZ ..SET MOV A,D.JOB(Y) ;GET. ..SET: MIX(IY םHLIX IYO86ͭ͗ D(n͝ם(  O03ͩͭתm( ˧  Orͭ8O06̬ͭתͨͶ,rs|rԞ , NZ Z NC C --From here: --To here^ :J3͒ "K! !J4:J=3͒*KR3!6~04ͶSO2!J~ 35 3ͦ[[K̓ăSM!J5(5͔ *MB"M[K [M͠*0R8(B"0*2R8B0bk"2 ;ACCESS DRIVE (MPM) $C39: RET ;FREE DRIVE (MPM) $C40 == $C34 ;WRITE RANDOM W/ZERO FILL ; CPMLEN == .-LIOS ; WRFLG$: .BYTE 0 ;WRITE TYPE FLAG CPMTPM: .BYTE 0 ;DEFAULT TO TPM ; .PAGE ; PATCH: ;PATCH AREA ; ; ; .LOC .DATA. ; SDATL 0- k *2 )/2<ת # ##R. ם O09ͩ(o0$ת + ++R. ם O42ͩ(/o8%#תͥ 0BC ( DE (  wť( HLĦ wR. A (́ O47ͭOV D.JOB(Y),A ;SET. JMP SPCRT2 ;SET/GET USER NUMBER ; $C33: MVI C,1 ;SHOW READ JMPR RANRW $C34: MVI C,0 ;WRITE RANDOM ; RANRW: PUSH B ;SAVE THE FLAG CALL SELFIL ;SELECT THE DISK LBCD ARGADR LXI H,33 DAD B MOV A,M ;GET LSB ANI 7FHPO PE P MC, NC, Z, NZ,́{ A1{$}(*Qj+"QjתA,m O80rͭ8 .̬OC6ͭr*Qj+"Qj́{ @{ "oN b*ö́|;Ӡl^́{A2{͌}!̈́#w  (;( q:J3 ͨ̀C̳ͨ"@S2*MBDM*KR0*MR8 :J=(3*KR8*K "K*M "M*@ "@*@x27[M:J=̔ *K 18'40#1O!K ^#V*R8*R8E :J  ͒== . ARGOP: .BLKW 1 ;LIOS OP CODE ARGADR: .BLKW 1 ;LIOS ARG ADDRESS ARGVAL: .BLKB 1 ;LIOS ARG VALUE CHRSAV: .BLKB 1 ;SAVED CHARACTER CTL.P: .BLKB 1 ;CTL-P FLAG CHRCNT: .BLKB 1 ;CHARACTER COUNT CHRCSV: .BLKB 1 ;SAVED COUNT INCCNT: .BLKB 1 ;Bͷ2תR. *DE T]( BC DM(HL(  Ͱ -DE s#r+(BC }| ( ͸ utʹͣ"֣͠>͇>()*&p{Ī (fGq(: p=/   (  ( () [͟{ ;JUST LOWER 7 MOV E,A MOV A,M ;GET BIT 7 RAL ;INTO CARRY INX H MOV A,M ADC A ;*2 + CARRY MOV D,A ;SAVE IN D LXI H,FCB.EX ;POINT TO EXTENT DAD B PUSH H ;SAVE THIS POINTER MOV A,CP.EXM(X) ;GET THE EXTENT MASK CMA ;MAKE INVERPIP B:=A:E.COM PIP B:=A:E.M PIP B:=A:ED1.S PIP B:=A:SYS.EQU PIP B:=A:ZDOS.S PIP B:=A:ESYS.S PIP B:=A:ED2.S PIP B:=A:ED22.S PIP B:=A:EEXS.S PIP B:=A:ED3.S  IP B:=A:SYS.EQU PIP B:=A:ZDOS.S PIP B:=A:ESYS.S PIP B:=A:ED2.S PIP B:=A:ED22.S PIP B:=A:EEXS.S PIP 3E :J(T {L2:6262527GOz( ~(> !BDMͶ:J( ͨ̀CͦKK*MT]BDM*0R0"[2*MR0 B"2 *KR0"23[MR8B"0*2B"2*K"0DM*2R0C2 "2[L( [(5 UFFER IN COUNT DIRBYT: .BLKB 1 ;RELATIVE DIRECTORY BYTE DIRCNT: .BLKW 1 ;RELATIVE DIRECTORY ENTRY A.DMA: .BLKW 1 ;CURRENT DMA ADDRESS O.DMA: .BLKW 1 ;SAVED DMA ADDRESS A.ALOC: .BLKW 1 ;ADDRESS OF ALLOC VECTOR T.DSK: .BLKB 1 ;SAVED SELECT DISK 302o]012ͯ{ ɯO~w~4s|{ͨ~~#fo*ej~( : ҫ8G : ́{@,́{:#ҫ8 ~#fo(>>ҫ 4[ejҫ4*ej>2p~++x(.zYP## x(zTED MASK MOV L,M ;PICK UP EXTENT NUMBER MOV H,A ;SAVE THE MASK MOV A,L ;EXTENT NUMBER CMP D ;DO BASIC COMPARE POP H ;RESTORE EXTENT POINTER JRZ ..RD ;SAME LOGICAL EXTENT PUSH B PUSH D PUSH H CALL CLSARG ;CLOSE OLD EXTENT CALL RCcj) Р́{Ýץ͹patch #!owr 4"o>2o,͗stop ?C WSbgn͋, ͋(C WSendת C HLoutץ C Outhex" ͳbeginˡend ( `(G`S *Qj"SjÚy!o,[0|( (+̓_(> ~(z ɯ͓ͧ %{ͧ<A(L[0|(+>2627S0L[0|(+ͧ[0*R( |( +_k_͠!B>Eͅ>2S(*L(* ++|(F.DSK: .BLKB 1 ;SAVED FILE DISK C.DSK: .BLKB 1 ;CURRENT DISK S.DSK: .BLKB 1 ;LAST SELECTED DISK LOG.DV: .BLKW 1 ;LOGGED IN DISKS WRP.DV: .BLKW 1 ;WRITE PROTECT VECTOR RENFCB: .BLKW 1 ;TEMP FCB HOLDER RECCNT: .BLKB 1 ;RECORD COUNT RECNUM: .BLK+x(z_# x({z"Qj*Qj++z"Qj++z#"OzG3"OzG'"OzG"_zgkPYz(R0+z"YP+z!x͒y͒zѯ)0"!x) "!B"z͑repeat =ˡתͭendrcaseͼof$endL͐r>until 3ͼ A1r(͠A2͐r>Dr>DEC B תת;2R\+:R ( :J!h͇!0=(!o̓4{<͈Ovy2RU̓S=T>~ 2<> 2<2;2;U3!*4q N 4:JĦͧA *T]~ # * ~# >  !: <!O1>(>2  %B 1 ;RECORD WANTED C.RLSC: .BLKW 1 ;CURRENT SECTOR C.DINF: .BLKW 1 CMPCNT: .BLKB 1 ;COMPARISON COUNT FCBTMP: .BLKW 1 ;TEMPORARY FCB ADDRESS GRPCOD: .BLKB 1 ;GRP HOLD AREA DELSVC: .BLKW 1 ;DELETED DIR SAVED MARKER DELSVI: .BLKB 1 ;DELETED DIR {(s|~#_|U*Qj+"Qjz8 pBIT>7G+zzת*Kj|q*Qj"Kj*Oj"Qj!"Mj*Kj|"Qjgo"Kj:o:o= *Qj+zO>zy( <ʘ~++z2o*Qj *o[Qj:oG:ozz#>zz##"Qj>zzѯs|[GjS (H*p:p *Sj:oO(Ko CALL OPNARG ;OPEN IT CALL RESDMA LXI H,RSLT.A ;WE OK? INR M MVI M,0 ;FOR LATER JRNZ ..OK ;OPEN OK POP B ;GET R/W FLAG (C) DCR C MVI A,4 ;THE ERROR JRZ ..BYE ;DO IT CALL CREARG ;CREATE NEW EXTENT CALL RESDMA LXI H,RSLT.A ;CRE 44s|rA1zl!A2ͼg ת; (else ͼͼ͉L>nĹ(V A1ת:͉L>,̶ ͼͼͼĤ(elseͼ֣üA1͑s|U͝and ͝(ͧ!S!H !Q ! (AO+| {ZEDITOR 12/21/81 -supports I200,V200 Irͱ{ *4q N 4:JĦͧA *T]~ # * ~# >  !: <!O1>(>2  %SAVED INDEX ; ; SPOOLER STUFF (OFF NOW) ; ;SPLFLG: .BLKB 1 ;SPOOLER FLAGS ;SPLFCB: .BLKB 33 ;SPOOLER FCB ;SPLBUF: .BLKB 128 ;SPOOLER BUFFER ; EDATL == . TDATL == EDATL-SDATL ; ; .LOC .DATA. ; LOCFCB: .BLKB 36 ;LOCAL FCB OLDSTK: .BLKW 1 ; [Gj́{ "IjN|KIj x(B| }(}_|2pp(NKSj7*QjB8B!kkG~ x <#R 6 #<@86[#!kR8`iz_|*QjB >]{|:p(:pœ{*KjDM|*Qj"Kj͠ ͠~̍͠"QjCKjѿ*p*op>*p2p:p ATE GO OK? INR M MVI M,0 ..WRT: JNZ WRTARG ;YES, GO AND WRITE MVI A,5 ;OUT OF DIR SPACE JMPR ..BYE ..OK: POP B ;GET R/W FLAG (C) DCR C JRNZ ..WRT JMP REDARG ;YES ..BAD: POP B ;REMOVE FLAG ..BYE: STA RSLT.A ;BAD RET ;READ RANDOM or &s|rs|͐{A1ze͠4(ҿs|U4Lz= <>̾<=̅>=̳< ͣ>ͅͶ>2oH380028UH380220U>2oH38UH30Uͣs|͐öH F(not תͶcarrỵH28UH23}3!,3# "B, &n >N2E*(N !͵ q!2E"@!Dw: wͼ(| !E̓ɯ2F2I<25*B~!02HK*BDM!N~ ({: N~ :D*( :G(~#v(:H/o8%#R0̀!"@*B~(G#~USER STACK ADDRESS .BLKW 30 ;STACK RSLT.Y: .BLKW 1 ;Y RSLT.X: .BLKW 1 ;X RSLT.H: .BLKW 1 ;H RSLT.D: .BLKW 1 ;D STACK: RSLT.B: .BLKW 1 ;B RSLT.P: .BLKB 1 ;PSW RSLT.A: .BLKB 1 ;A .BLKW 4 ;USERS STACK USRSTK: .BLKW 1 ;FOR RETURN RECOVS:p {ÜB#*h!oq#p#*h s#r#q#p#q#p#yhB "h [GjתR[Gjb';u2QO2hQGjLASTCRQjNCODEejLASTDEgjNEXTDEoQOPTSoOFFSET pI ; $C35: CALL SELCK1 ;SELECT THE DISK MVI C,12 ;FIND ALL EXTENTS CALL SRCDIR ;FIND IT LDA RSLT.A ;FIND IT? INR A RZ ;NO LXI H,0 ;COUNTER PUSH H ..LP: MVI A,12 ;GET EXTENT NUMBER CALL GT.BBA ANA CP.EXM(X) ;"AND" IT JRZ ..GOT ;0UH դzeroת0 |R.DE RR.BCB ת תͥ  .ť( ۧĦ.R. ́O80rͭͨOC6͐ͭs|r@R.@2ê;~͗ ͮ͝(ͦͺ(ͥ &BC  ( D:EN S2!"@2D>2G2F~!G~(5:E* s(>2I*@+"@|#(~¡RDM:Fi:E* !5:I 5NSN :Fͳ:J=3͎ *K R3 # R8 *0R8 "0SO "M!  !J4ѯ--Fr: .BLKW 1 ;FOR RECOVERY ; .RELOC ; ENDPRG: .BLKB ((.-LIOS+255)/256)*256-(.-LIOS) ENDIT: ; .END : RSLT.B: .BLKW 1 ;B RSLT.P: .BLKB 1 ;PSW RSLT.A: .BLKB 1 ;A .BLKW 4 ;USERS STACK USRSTK: .BLKW 1 ;FOR RETURN RECOVS6 PIP B:=A:Q.COM PIP B:=A:QD.COM PIP B:=A:Q.M PIP B:=A:QD.M PIP B:=A:OPTQ.S PIP B:=A:SYS.EQU PIP B:=A:MMETA.S PIP B:=A:ZDOS.S PIP B:=A:QSYS.S PIP B:=A:BK1.S PIP B:=A:MSUB.S PIP B:=A:QBUG.S PIP B:=A:UNSYM.S PIP B:=A:XX.S PIP B:=A:DEASM.S  IP B:=A:QSYS.S PIPBLKSZ+BOTTOM POPL RR4 ...XFADR MOVDTA_(LDL RR2,RR8[BUFADR_]; R3:+R0) ...move R1 bytes from @RR2 to @RR4; RR4 updated POP R1 until R6:+1>R1; ...until I:+1>LSTBLK RL0:=OK RDFX~ POP R12 ...requested len. if R12>R13 and BITB RL0,6 zero then#)a#0@!T# `#(a#.X !T#`#+a#4,ՠՂ{\U!] # n#(o#.o# wq] # o#.n#(EJ!3] #o#0n#)T # a#.`#(qIcߜ!u] # o#.n#(T#a#0te ... WORD FPUTBF ...loc. of attributes ... WORD 116 ...no. of bytes of attr. ... WORD 0 0 ... BYTE 0 ...CC ... THE CLOSE VECTOR FOLLOWS ...FILCLO: BYTE 4 ...unit no. ... BYTE 6 ...CLOSE ... WORD 0 0 0 0 ... BYTE 0 ...completion code CLOSFL: PUSH IX; PU  00 99ʫ) EE ee1 --5Ƀx ++<Ёx!TP!  qr9諀  詀*" * p 00 99  ~w;P!  qr{諀 MOutpzwRDaHLzWRaHL{Id{Digit{Hexd{Latchs|Outset{Copyin{Sr|Sr1)|Count INSTLISTIg~lLkupnl~LkupGen>ZpUSavrRezPpXcEff1DbugfJASMSTCOMMAN RL0:=EOFERR RET MOVDTA_: ...move R1 bytes from @RR2 to @RR4; update RR2,RR4 R0:=R1|R3|R5 if BIT R0,0 zero then begin SRL R1; LDIR @RR4,@RR2,R1 end else LDIRB @RR4,@RR2,R1 RET B_READ: ...enter with R3=block no., RL5=LU, RR10=^filetab ...ret. RR8=^b`#)f] #o#2n#*T # a#.`#(T#a#0`#)֤T#a#2`#*xa#  L(!֘ Zy!֣ k~e!֮a# YsS7{QB] # o#.n#(*]#o#6n#,ӹ]#$wT # a#.`#(SH DE; PUSH HL CloseF(R.A->R.B) POP HL; POP DE; POP IX 00; RET ...CLOSFL: R.A->B.FILCLO ...logical unit no. ... LD IY,FILCLO ...SYSTEM: ... fake entry ... DI; EX AF,AF'; EXX ...shadow regs. saved for QBUGing progs. using them ... PUSH HL; PUSH DE; PU  PX詀 vg    E++ E--P E..P *ު EEEP  E--P E++P E  00.IPn00.FP APbSE{m^P{D`7LABELCOLhINST*XINSTCBNBITOP2柧WN}NumجHNum顡XCOMMdOptmNumHNum XCOMMOptmBNBITOP2JWNS}Num<HNumMXCOMMȯOptmLkup+vGenqZpSavRePpufhdr with data (unless error); RL0=CC GETBLK() ...pass block no., LU; rets. RR8=^bufhdr if RL0=0 then begin ...if data not in buffer (& no error) SETXFCNT() SET @RR8,RDB; FILIO_() RL0:=@RR8[CCD] if BITB RL0,6 not zero then begin PUSH R0; RѴT#a#6`#,c\#$ @!oT#$T # a#.`#(O$@P]#$] #o#0n#)q @!] # o#.n#(M#" T#$M]#$(k#"$] #o#0n#)qIT#$M]#$ T# a#.`#(\k#"SH BC; PUSH AF ... EXX; EX AF,AF'; P.C_EI ... PUSH HL; PUSH DE; PUSH BC; PUSH IX ... CALL SYSTM ...@1403 ... POP IX; POP BC; POP DE; POP HL ... DI; EX AF,AF'; EXX ... POP AF; POP BC; POP DE; POP HL ... EXX; EX AF,AF' ... LD A,(IY+10) ...CC ... CP 080H .xi[{уtf{юѠ{*l{{ѣh{ѭя{ 1 (  0 !4ȅ!@ H4$уѼ{ 1 (0.HP{4|ÃXcEff1DbugJASMSTCOMMAND-LABELCOLQhINSTLTXINSTCBNןBITOP2WN"}Num HNumXCOMMOptmpace left in buffer` SBC HL,BC8L>}2?}:a >8!L>` -!?!l^M>8ߐ l ;;   // //[ ## ߡߓj8!   XXT - **K*  II o >8..check if call was successful ... ... C_EI: PROC ...do EI iff I_SW=0 PUSH AF; if B.I_SW=0 then EI; POP AF; RET FINBUF: ...if list file open, fill rem. buffer with spaces +CR at end & put out B.DIAGSW; BIT 2,A; RET Z LD BC,(FPUTRM); W.FPUTNX->R.HL re4vQ|!҄mo#  q @!Ҙ] # n#(o#.qҢ] #n#)o#0G!T#`#)a#0ҼC!] #n#*o#2T #`#)a#0dm'!j6Tbuffer would overflow, BC gets len. of remaining space R.HL->W.FPUTRM; W.FPUTNX->R.HL ...next open buffer space EX DE,HL; LDIR ...text->buffer if zero then PUTOUT() ...if buffer is exactly filled (flag set in SBC abov`else begin EX DE,HL ie if BIT @RR8,GDDTAB not zero and RH7=@RR8[LU_] and R1:=R6-@RR8[BLKNO] >=zero and R1<@RR8[NBLKS] then begin repeat RL0:=@RR8[CCD] until R1<@RR8[NBLKSDUN] or BIT @RR8,IOINPRGB zero and BITB RL0,6 not zero; if R1<@RR8[NBLKSDUN] then RL0:=OKH !>Zo>o >h>֞] - ,, ޽o >8}} ]莞        ;;   .  󡕃5  ;,<>=* !! ~~ !.TEM>8ݣݼ F GFILE NOT FOUND\n peat LD (HL),' '; INC HL; DEC BC until R.B|R.C zero; DEC HL; LD (HL),0D ...fall thru: ... PUTOUT: LD BC,RECL; LD (FPUTRM),BC; ^FPUTBF->W.FPUTNX PUTO2: PUSH IX; PUSH DE ...$$$ EX DE,HL; R.BC->R.HL WriteF(B.FILPTO->R.B) POP DE; POP IX ... LD (FPUTL),!T# `#(a#.a#    qT #`#*a#2 T#`#*a#2҇a# /{qw   $GOD ҙq8Q|!?(Qo# {Q|!N7o# { q @!UMERR ...zero error count GetN(LD DE,DATA1) ...get new chars; DE pts. to beg. of buffer end GETRCX: LD (LASTCR),DE; LD (LASTDE),DE ...LASTDE needed in case Errm before set RET ...READFL: 0A->R.A ...read binary ...RDFL2: RDFIL(^RECL) ...read into 6  JR GETBLKX end end ADDBUF(R3:=BLKSZ; RL5:=RH7) ...allocate a buffer and bufhdr for block if not zero then begin ...if no bufhdr or buffer avail. LDAR RR8,SPBUFHDR ...use special buff if BIT @RR8,ALLOCB not zero then begin FINBUF() .F GWRONG FILE TYPE\n F G%B???\nF G???\na- .. /093 00 99 AA FF aa ff  AAߴys!>^!x!Bء8 !  M>^sXsD1, BOTTOM:R0, LEN:R1, OFFSET:R0 PUSHL RR2; RH7:=RH1 ...RH7=LU LDL RR2,RR10[FPSREQ]; LDL RR4,RR10[FLEN] if CPL RR2,RR4 >=zero then begin POPL RR2; R13:=0; RL0:=EOFERR; RET end R12:=0; ADDL RR2,RR12 if CPL RR2,RR4 >zero then LDL RR2,RR10[FLEN] PUSHL Rda#  c] # n#(o#.qx] #n#)o#0C@0!ӭ] #n#*o#2T #`#)a#0X,!}ӡJQ!T#`#)a#0Ӳi!T#`#*a#2ӲT# `#(a#.Oq] #n#)o#0__!low buffer, waiting ... CALL Z,GETFIL ...if no error (such as EOF), fill high buffer, returning immediately ... CALL NZ,RDERR ...if error ... RET READFL: ...read in file, LU LOGUN, starting from fpos AHL; also set FPOS,FPOSH R.A->FPOSH; R.HL->FPOS RDF..write out buffer if necessary BITB RL0,6; JR NZ,GETBLKX ...if err end LD @RR8,#2**ALLOCB RH7:->@RR8[LU_]; 1->@RR8[NBLKS]; 0->@RR8[NBLKSDUN] end R6:->@RR8[BLKNO] RL0:=0 GETBLKX~ POPL RR6; RET FINBUF: ...release bufhdr (& buffer) @RR8, fB!>^ L>^##L>s<ҍCЯ mkU 8  0PV!>:0.X/nXޞ   uު` >>a c e` >>aec  ;; R2 ...fpos at end of request SUBL RR2,#1; SRLL RR2,#BLKSZPWR; R3->R1 ...R1=LSTBLK SLLL RR2,#BLKSZPWR; POPL RR4 ...RR2=beg last blk, RR4=end of req. SUBL RR4,RR2; R5:->R12 ...R12=LSTBLKTOP LDL RR2,RR10[FPSREQ]; SRLL RR2,#BLKSZPWR; R3->R0 ...R0=FSTB] #n#*o#2T #`#)a#0r|!m!'T#`#)a#0 __!8T#`#*a#2 a# ӜӾ n #8j !L#9] # n#(o#. [MA=!T # `#(a#. T# a#.`IL1() RDFIL2() RET RDFIL1: ...read RECL bytes @file pos. FPOS,FPOSH to @DATA1, LU LOGUN ...set RCADR1,RCAD1H; update FPOS,FPOSH FPOS->RCADR1->R.HL; FPOSH->RCAD1H->R.A READFIL(LD BC,DATA1) RET RDFIL2: ...read RECL bytes @file pos. FPOS,FPOSH to @DATirst writing out if necessary ...ret. BIT RL0,6 set if err, else RL0=OK repeat until BIT @RR8,IOINPRGB zero; RL0:=OK if BIT @RR8,ALLOCB not zero then begin ...otherwise rel'd in int. rtn. if BIT @RR8,DELWRB not zero then B_WRITE() PUSH R0; RELBU<< >>C6hL,!><1.cAe!>^!Aa ҋ!hs@5j af! >va3 5aa7̡6"0! JC']>]>a<_DCf}} $00(  LK POPL RR4 ...XFADR PUSH R13 ...requested len. R13:=0; R6:=R0 ...TOTLEN:=0; I:=FSTBLK repeat PUSH R1; PUSHL RR4; PUSH R1 ...R1=LSTBLK B_READ(R6;RL5:=RH7) ...rets. RR8=^bufhdr (buffer has data); RL0=CC if BITB RL0,6 not zero then begin .#( @!VL#91T # `#(a#.@!ԡ] #n#)o#0T # `#(a#.ԒT#a#0`#)ԈL#9 T # `#(a#.] # n#(o#.qԴ] #n#)o#0T!T#`#)a#0eG!] #n#*o#2T PIP A:=B:Q.COM PIP A:=B:QD.COM PIP A:=B:Q.M PIP A:=B:QD.M PIP A:=B:OPTQ.S PIP A:=B:SYS.EQU PIP A:=B:MMETA.S PIP A:=B:ZDOS.S PIP A:=B:QSYS.S PIP A:=B:BK1.S PIP A:=B:MSUB.S PIP A:=B:QBUG.S PIP A:=B:UNSYM.S PIP A:=B:XX.S PIP A:=B:DEASM.S  IP A:=B:QSYS.S PIPF(); POP R0 end RET SETXFCNT: ...calc XFCNT & store @RR8 (bufhdr); RR10=^LUvec LDL RR2,RR10[FLEN] R5:=@RR8[BLKNO]; R4:=0; SLLL RR4,#BLKSZPWR ...RR4=blk fpos (blk no.*BLKSZ) SUBL RR2,RR4 ...RR2=flen-blk fpos R5:=@RR8[NBLKS]; R4:=0; SLLL RR4,#BLKS % 0}} ]>ދ!5   ;; << >>    60/caqW  /iap s'Y2!B .80.8T>P>T>ߜj>a >؞}} H>!  / $$" 11 99 0K>..if err POP R3; POPL RR2; POP R3; JR RDFX end POP R1 ...LSTBLK if R6=R1 then R1:=R12 else R1:=BLKSZ ...if I=LSTBLK then TOP:=LSTBLKTOP else TOP:=BLKSZ R3:=R6; R2:=0; SLLL RR2,#BLKSZPWR LDL RR4,RR10[FPSREQ]; SUBL RR4,RR2 R0:=R5#`#)a#0e2!eG!T#`#*a#2T# `#(a#. f#9d!9f#9 q d!&`#8Ԟ{Ԣ{@!] # n#(o#.  pԾT # `#(a#.w  !Ҟ{ tes ... BYTE 0 ...completion code ... WORD FILPSP ...^supplemental ...FILPSP: BYTE 1 ...open output, overwriting ... BYTE '*' ... BYTE -1 ...name length set to -1 because ASSIGN handles name ... THE OUTPUT WRITE VECTOR FOLLOWS ...FILPUT: BYTE 4 ...unit noZPWR ...RR4=NBLKS*BLKSZ if CPL RR2,RR4 @RR8[XFCNT] RET ADDBUF: ...add buffer of size R3, LU RL5; ^bufhdr->RR8; ret. Z=1 iff succeed ...init. BUFADR,LU,NBLKS,NBLKSDUN PUSHL RR6; R6:=R3;3a5>!U HPk.hp.hp .kp.k}} ]>! > !  ! @ܞ- 90100-(00 99...800 99. !@ {p ...BOTTOM:=FPSREQ-I*BLKSZ R1:-R0; R13:+R1 ...LEN=TOP-BOTTOM; TOTLEN:+LEN LDL RR2,RR10[FPSREQ]; R5:=R1; R4:=0 ADDL RR2,RR4; LDL RR10[FPSREQ],RR2 ...FPSREQ:+LEN R3:=R6; R5:=@RR8[BLKNO]; R3:=(R3-R5)*BLKSZ; R0:+R3 ...OFFSET:=(I-BLKNO)*X !h] # n #+so#4T # `#(!Zy!Ղ] # n #*so#2@!չ] # n#(o#.T #`#*a#2@!հT# `#(a#.զ] # n#(o#.q] #n#)o#0jI!UM!T#`. ... BYTE 0EH ...write binary, wait ...FPUTAD: WORD FPUTBF ...file output buffer ...FPUTL: WORD RECL ...length ... WORD 0 0 ... BYTE 0 ...completion ... THE UPDATE VECTOR FOLLOWS ...UPDATE: BYTE 5 ...unit no. (used only when imaging) ... BYTE 02C ...upda RH7:=RL5 LDAR RR8,BUFS DIS_BRK() repeat if BIT @RR8,ALLOCB zero then begin if M_REQ(R3) zero then begin LD @RR8,#2**ALLOCB; LDL RR8[BUFADR_],RR2; RH7:->@RR8[LU_] R3:=R6; R2:=0; SRLL RR2,#BLKSZPWR; R3:->@RR8[NBLKS] R3:-R3->@7   먐    #V2!C7 }3 13 57 \  A4@!@}Ѐ~ BREAK AT TATzZ` -  GG JJ DD߷ RR SS OO!@!P9?`!@DEC_EXP DEC_EXP:-1 end while DEC_EXP<<0 do begin PUSH DEC_EXP FLOATING_DIVIDE() POP DEC_EXP DEC_EXP:+1 end RET ...END CONVERT_ASCII INSERT_DIGIT PROC ...CHAR CONTAINS DECIMAL ASCII DIGIT TO BE INSERTED ...INTO THE RIGHTMOST DIGIT OF AC. .. LDAR RR2,BUF1 end save R6..R11 LDL REG4,RR2 CONVERT_ASCII() STORE_AC() restore R6..R11 IRET Flttoasc: PROC ...enter with RR2=floating pt. number in internal form, ... RR4=^buffer to put ascii string form of number (if R4=0FFFF, use ... seg. of AC COM AC_3 ADDL AC #1 end else AC_SIGN:=PLUS AC_EXP:=159 ... AC CONTAINS BINARY INTEGER ... POINT IS TO THE RIGHT OF BIT 0 NORMALIZE_AC() ... CORRECT TO NORMAL FORM RET ...END IFLOAT IFIX PROC ... CONVERTS FLOATING POINT TO 32 BIT 2'() ...OUTPUT EXPONENT DIGITS LDB @REG4 #0 ...TERMINATOR CHARACTER RET ...END CONVERT_FLOAT BYTE_TO_DECIMAL PROC ...CONVERTS BYTE TO DECIMAL STRING : RANGE 00 - 99 ...INPUTS: RL1 DATA BYTE ...REG4 POINTER FOR OUTPUT STRING R0:=0 RH1:=0 DIV RR^aAT  SS  HH]AT}} aAP}\A0yAPA0-͑1 ,,0& . .|.s   .. |.* }bғC5X .MULTIPLY AC BY 10 TO MAKE ROOM SLLL AC, #1 ...MULTIPLY BY 2 LDL OP AC ...SAVE IN OP SLLL AC, #2 ...MULTIPLY BY 8 TOTAL ADDL AC OP ...RESULT IS 10X ...ADD DIGIT TO AC SUBL OP OP LDB OP_1L CHAR ANDB OP_1L #00F ADDL AC OP ... CHECK FOR FULL FRACTIONcaller) if R4=0FFFF then R4:=@RR14[4] PUSHL RR4 FLTTOASC() POPL RR4 repeat RL0:=@RR2'->@RR4' until RL0=0; ... R0:=13; RL0:->@RR4' ...size of floating pt. no. in ascii=13 ... LDIRB @RR4,@RR2,R0 ... CLRB @RR4 IRET FLTTOASC: PROC ...enter with RR2=floS COMPLEMENT INTEGER ... INPUT: IN AC ... OUTPUT: IN AC ...@REG4 AC_EXP:-080 ... CHECK FOR FRACTIONAL if <= then SUBL AC AC ... ALL FRACTIONAL -- RETURN ZERO else begin ... SOME INTEGER PART AC_EXP:-31 if <= then begin ...WILL FIT IN 30 #10 OUT_DEC() EX R0 R1 OUT_DEC() RET OUT_DEC: RL1:|030->@REG4' RET ...END BYTE_TO_DECIMAL OUT_DIGIT PROC ...CONVERTS MSB HIGH NIBBLE OF AC TO ASCII DIGIT ...AND OUTPUTS IT @REG4 TEMP:=AC_2 WORD 0BC6E ...INTERCHANGE NIBBLES TbA}R_}Z (}R_}Z.(0_}ZC: ::::13L8g& . .|.s   .. |.* }bғC5X  PART ... CHECK 4 MSB if AC_2>=01000 then COUNT:=0FF ...SET FULL FLAG RET ...END INSERT_DIGIT DECIMAL_INTEGER PROC ...CONVERTS DECIMAL ASCII STRING TO BINARY INTEGER ...RESULTS RETURNED IN EXP_VAL EXP_VAL:=0 ... DEFAULT = 0 COUNT:=2 ... MAX OFating pt. no. in internal form ...put ascii string in buffer (ends with 0), ret. RR2 pointing to it ... (should be moved elsewhere by outer routine) ...Note: len of string (without 0)=FLTPRSZ=13 save R6..R11 LOAD_AC() LDAR REG4,BUF1 CONVERT_FLOAT() 2 BITS SDLL AC AC_EXP ...MAKE BINARY INTEGER if AC_SIGN<>0 then begin ... NEGATIVE COM AC_2 ... NEGATE AC COM AC_3 ADDL AC #1 end end else begin ...TOO BIG -- RETURN MAX. VALUE if AC_SIGN=0 then LDL AC #07FFFFFFF ... EMPH:&00F TEMPH:|'0' ...CONVERT TO ASCII LDB @REG4 TEMPH PTR4:+1 RET ...END OUT_DIGIT READ_CHAR PROC ...READS ONE ASCII CHARACTER @ REG4 CHAR:=@REG4' RET ...END READ_CHAR ERROR: PROC ...INSERT APPROPRIATE ERROR ROUTINE HERE ...ERRORS HACTIONAL if <= then SUBL AC AC ... ALL FRACTIONAL -- RETURN ZERO else begin ... SOME INTEGER PART AC_EXP:-31 if <= then begin ...WILL FIT IN 32 BITS SDLL AC AC_EXP ...MAKE BINARY INTEGER if AC_SIGN<>0 then begin ... NEGATIVE CO TWO DIGITS while CHAR>='0' and CHAR<='9' do begin MULT EXP_VALR #10 CHAR:&00F EXP_VALL:+CHAR if COUNT:-1 zero then RET READ_CHAR() end RET ...END DECIMAL_INTEGER CONVERT_FLOAT PROC ...CONVERTS FROM INTERNAL FLOATING POINT TO ASCII STRING @RE LDAR RR2,BUF1 restore R6..R11 RET ...****** SPECIAL FUNCTIONS MODULE ****** ...sin,cos,tan,arctan,log,exp,power TEMP1 LONG 00000000 TEMP2 LONG 00000000 TEMP3 LONG 00000000 TEMP4 LONG 00000000 TEMPP LONG 00000000 INTER WORD 00000000 CNT WORD 00000000 POSITIVE else LDL AC #080000000 ... NEGATIVE end end RET ...END IFIX CONVERT_ASCII PROC ...CONVERTS ASCII STRING TO INTERNAL FLOATING POINT ...READS STRING @REG4 ...READ IN SIGN AC_SIGN:=PLUS ... SIGN DEFAULT IS POSITIVE READ_CHVE DEFAULT FIXUP CONDITIONS ...SO THAT ERROR PROCESSING MAY NOT BE NEEDED ...TEMP CONTAINS ERROR NUMBER ...%01 UNDERFLOW - SET RESULT TO ZERO ...%O2 OVERFLOW - SET RESULT TO MAX = +/-1.701412E+38 ...%04 DIVIDE BY ZERO - RETURNS DIVIDEND UREG4 ...S = -1 0FFFF AC < OP ...S = 0 00000 AC = OP ...S = +1 00001 AC > OP FLOATING_SUB() ...TAKE THE DIFFERENCE if AC_EXP=0 then begin ...CHECK IF NUMBERS ARE EQUAL SUBL AC,AC RET end if AC_SIGN=PLUS then LDLG4 DEC_EXP:=0 ...INITIALIZE DEC_EXP if AC_EXP<>0 then begin ... ZERO VALUE - SKIP RADIX DEFLATION, ... ELSE PERFORM RADIX DEFLATION ... MULTIPLY OR DIVIDE AC BY 10 TO GET IT IN THE RANGE 1 <= AC <= 10 ... KEEP TRACK OF MULTIPLICATLINTE LONG 00000000 TEMP1_SIGN BYTE 0 TEMP2_SIGN BYTE 0 TEMP3_SIGN BYTE 0 TEMP4_SIGN BYTE 0 TEMPP_SIGN BYTE 0 BYTE 0 TEMP1_EXP WORD 0 TEMP2_EXP WORD 0 TEMP3_EXP WORD 0 TEMP4_EXP WORD 0 TEMPP_EXP WORD 0 SIGN: BYAR() ... GET FIRST CHAR if CHAR ='+' then CALR READ_CHAR else if CHAR='-' then begin READ_CHAR() AC_SIGN:=MINUS end ... READ DIGITS TO THE LEFT OF THE DECIMAL POINT SUBL AC AC ... CLEAR AC CLR DEC_EXP COUNT:=0 ... CNCHANGED ...%08 SQUARE ROOT OF NEGATIVE NUMBER - TAKES ABSOLUTE VALUE FIRST ...%10 ILLEGAL CHAR IN INPUT STRING - STRING IS TERMINATED ... ?"ERROR ",TEMP RET Fadd: PROC ...RR2+RR4->RR2 save R6..R11 LOAD_AC(); LOAD_OP() FLOATING_ADD() STOR AC,#000000001 ...AC > OP else LDL AC,#0FFFFFFFF ...AC < OP RET ...END FLOATING_CMP LOAD_AC PROC ...expects accumulator in RR2; don't clobber RR4 ...LOADS AC @REG4 AND CONVERTS TO INTERNAL FORM ...LOAD 2 WORD EXTERNAL FORM! L7 IONS OR DIVISIONS IN DEC_EXP LDL OP #050000000 ...LOAD OP WITH 10 OP_EXP:=132 OP_SIGN:=PLUS while AC_EXP<129 do begin PUSH DEC_EXP OP_SIGN:=AC_SIGN OP_EXP:=AC_EXP LDL OP,AC OP_EXP:+1 AC_EXP:+3 FLOATING_ADD() POP DEC_EXP DEC_EXP:-1 TE 0 AFLAG: BYTE 0 Tan: PROC ... enters RR2, outputs tan(RR2) LOAD_AC() LDL OP,#0517CC1B7; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=4/PI=1.273239545 FLOATING_MULTIPLY() BRK() R5:-> INTER if R5:& 1 not zero then begin LDL OP,AC; OP_SIGN:=AC_SILEAR CONVERSION FULL FLAG while CHAR>='0' and CHAR<='9' do begin ... CHECK FOR FULL BINARY FRACTION PART if COUNT=0 then INSERT_DIGIT() else DEC_EXP:+1 READ_CHAR() end ...READ DIGITS TO RIGHT OF DECIMAL POINT if CHAR='.' then begin RE_AC() restore R6..R11 IRET Fsub: PROC ...RR2-RR4->RR2 save R6..R11 LOAD_AC(); LOAD_OP() FLOATING_SUB() STORE_AC() restore R6..R11 IRET Fmult: PROC ...RR2*RR4->RR2 save R6..R11 LOAD_AC(); LOAD_OP() FLOATING_MULTIPLY() STORE_AC() restore R6DL AC,RR2 AC_EXP:=AC_3 ...SEPARATE EXPONENT AC_EXPH:=0 AC_3:&0FF00 ...ZERO OLD EXP. FIELD if BIT AC_2,15 zero then AC_SIGN:=PLUS else AC_SIGN:=MINUS if AC_EXP<>0 then begin ...RESTORE HIDDEN MSB AND SHIFT RIGHT SET AC_2 #15 SRLL ACend while AC_EXP>132 do begin ...DIVIDE BY TEN PUSH DEC_EXP FLOATING_DIVIDE() POP DEC_EXP DEC_EXP:+1 end ...IF AC IS GREATER THAN OR EQUAL TO 10 THEN DIVIDE BY TEN AGAIN if AC_EXP=132 then begin if AC_2>=05000 then begin PUSH DEC_GN; OP_EXP:=AC_EXP LDL AC,#040000000; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=1.0 FLOATING_SUB() end ...TAN APPROXIMATION ...Q POLYNOMIAL LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP FLOATING_MULTIEAD_CHAR() while CHAR>='0' and CHAR<='9' do begin ...CHECK FOR FULL BINARY FRACTION PART if COUNT=0 then begin INSERT_DIGIT() DEC_EXP:-1 end READ_CHAR() end end ...READ EXPONENT PART if CHAR='E' or CHAR='e' then begin READ..R11 IRET Fdiv: PROC ...RR2/RR4->RR2 save R6..R11 LOAD_AC(); LOAD_OP() FLOATING_DIVIDE() STORE_AC() restore R6..R11 IRET Fcmp: PROC ...RR2==RR4; rets. R3={-1,0,1} if {<,=,>} save R6..R11 LOAD_AC(); LOAD_OP() FLOATING_CMP() LDL RR2,AC resto, #1 end RET ...END LOAD_AC LOAD_OP PROC ...expects operand in RR4 ...LOADS OP @REG4 AND CONVERTS TO INTERNAL FORM ...LOAD 2 WORD EXTERNAL FORM LDL OP, RR4 OP_EXP:=OP_1 ...SEPARATE EXPONENT OP_EXPH:=0 OP_1:&0FF00 ...ZERO OLD EXP. FIEXP FLOATING_DIVIDE() POP DEC_EXP DEC_EXP:+1 end end ...POSITION AC SO THAT RADIX POINT IS BETWEEN BITS 27 & 28 if AC_EXP=132 then SLLL AC, #1 else begin TEMP:=AC_EXP TEMP:-131 SDLL AC TEMP AC_EXP:-TEMP end ...ROUPLY() LDL TEMP2,AC; AC_SIGN:->TEMP2_SIGN; AC_EXP:->TEMP2_EXP LDL OP,#047989780; OP_EXP:=087; OP_SIGN:=MINUS ...OP:=-71.59606050466 FLOATING_ADD() LDL OP,TEMP2; OP_SIGN:=TEMP2_SIGN; OP_EXP:=TEMP2_EXP FLOATING_MULTIPLY() LDL OP,#0439DE700; OP_EXP:=089_CHAR() if CHAR='-' then begin READ_CHAR() DECIMAL_INTEGER() DEC_EXP:-EXP_VAL end else begin if CHAR='+' then READ_CHAR() DECIMAL_INTEGER() DEC_EXP:+EXP_VAL end end ... else if CHAR>=42 then ERROR(TEMP:re R6..R11 IRET Float: PROC ...RR2 (int)->RR2 (float) save R6..R11 LDL AC,RR2 IFLOAT() STORE_AC() restore R6..R11 IRET Fix: PROC ...RR2 (float)->RR2 (int) save R6..R11 LOAD_AC() IFIX() LDL RR2,AC restore R6..R11 IRET Sqrt: PROC ELD if BIT OP_0,15 zero then OP_SIGN:=PLUS else OP_SIGN:=MINUS if OP_EXP<>0 then begin ...RESTORE HIDDEN MSB AND SHIFT RIGHT SET OP_0 #15 SRLL OP, #1 end RET ...END LOAD_OP STORE_AC PROC ...returns answer in RR2 ...CONVERTS AC TO EXTND AC TO 7 DECIMAL DIGITS ADDL AC #086 if AC_2>=0A000 then begin ... ROUNDING OVERFLOW LDL AC #01000,0 DEC_EXP:+1 end end ...GET DECIMAL DIGITS BY DIGIT STRIPPING if AC_SIGN=PLUS then LDB @REG4 #'+' else LDB @REG4 #'-' PTR4:+1; OP_SIGN:=PLUS ...OP:=270.46722349399 FLOATING_ADD() LDL TEMP3,AC; AC_SIGN:->TEMP3_SIGN; AC_EXP:->TEMP3_EXP ...P POLYNOMIAL LDL AC,TEMP2; AC_SIGN:=TEMP2_SIGN; AC_EXP:=TEMP2_EXP LDL OP,#0646D2700; OP_EXP:=084; OP_SIGN:=MINUS ...-12.55329742424 FLOA=010) ... CHECK FOR SEPARATER, ILLEGAL CHAR ...PUT AC IN NORMAL FORM AC_EXP:=159 ... AC CONTAINS BINARY INTEGER NORMALIZE_AC() ...MULTIPLY OR DIVIDE AC BY POWER OF TEN SPECIFIED BY DEC_EXP ...LOAD FLOATING POINT 10 INTO OP LDL OP #050000000 OP...sqrt(RR2)->RR2 save R6..R11 LOAD_AC(); SQUARE_ROOT() STORE_AC() restore R6..R11 IRET BUF1: BYTE 0[20] Asctoflt: PROC ...enter with RR2=^ascii string (either DEFT or string+'0'; ... if R2=0FFFF then use seg. of caller) of floating pt. constantERNAL FORM & STORES @REG4 if AC_EXP<>0 then begin ADDL AC #040 ... ROUND TO 24 BITS NORMALIZE_AC() end SLLL AC, #1 ...SHIFT TO HIDE MSB if AC_SIGN=0 then RES AC_2,15...ELSE -- WAS ALREADY SET BY SHIFT! ...SAVE PARTIALLY CONVERTED RESULT AND INSER OUT_DIGIT() ... GET LEFTMOST DIGIT LDB @REG4 #'.' PTR4:+1 COUNT:=6 ...OUTPUT SIX DIGITS TO RIGHT OF DECIMAL POINT repeat AC_2:&00FFF SLLL AC, #1 ...MULTIPLY BY 10 LDL OP AC SLLL AC, #2 ADDL AC OP OUT_DIGIT() until COUNT:-1 zero ...OTING_MULTIPLY() LDL OP,#06A365480; OP_EXP:=088; OP_SIGN:=PLUS ...212.42445758263 FLOATING_ADD() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXP FLOATING_MULTIPLY() if R0:=INTER&3=1 or R0=2 then begin LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP_EXP:=132 OP_SIGN:=PLUS ...IF DEC_EXP IS POSITIVE THEN MULTIPLY BY 10. ...IF DEC_EXP IS NEGATIVE THEN DIVIDE BY 10. while DEC_EXP>>0 do begin PUSH DEC_EXP OP_SIGN:=AC_SIGN OP_EXP:=AC_EXP LDL OP,AC OP_EXP:+1 AC_EXP:+3 FLOATING_ADD() POP  ...ret. RR2=floating pt. number in internal form if R2=0FFFF then R2:=@RR14[4] if RL0:=@RR2<020 then begin ...change deft 'string'->string+0: R3:+1; RH0:=0 if R0>19 then R0:=19 LDAR RR4,BUF1 if R0<>0 then LDIRB @RR4,@RR2,R0 CLRB @RR4 T EXPONENT FIELD LDL RR2,AC; RL3:=AC_EXPL RET ...END STORE_AC IFLOAT PROC ... CONVERTS 32 BIT 2'S COMPLEMENT INTEGER TO FLOATING POINT ... INPUT: IN AC ...@REG4 ... OUTPUT: IN AC if BIT AC_2,15<>zero then begin AC_SIGN:=MINUS COM AC_2 ...NEGATE UTPUT EXPONENT ... LDB @REG4 #' ' ... PTR4:+1 LDB @REG4 #'E' PTR4:+1 if DEC_EXP<<0 then begin ...NEGATIVE EXPONENT LDB @REG4 #'-' PTR4:+1 NEG DEC_EXP end else begin LDB @REG4 #'+' PTR4:+1 end R1:=DEC_EXP BYTE_TO_DECIMAL8  LDL AC,TEMP3; AC_SIGN:=TEMP3_SIGN; AC_EXP:=TEMP3_EXP end else begin LDL OP,TEMP3; OP_SIGN:=TEMP3_SIGN; OP_EXP:=TEMP3_EXP end FLOATING_DIVIDE() STORE_AC() ...GET SIGN OF RESULT if R0:=INTER&2 not zero then SET R2,15 IRET BRK: ...enter with AC_SIGN:=PLUS ...OP:=PI/4=.7853981634 FLOATING_ADD() end else if BITB AFLAG,1 not zero then begin LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP LDL AC,#06487ED80; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=PI/2=1.570796327 FLOATING_SUB() end  FLOATING_MULTIPLY() end until CNT:-1 end until CNT:-1<<=0 STORE_AC() RET ...************ ROM: ADDR $  STO() LDL RR4,LINTE; SLAL RR4; LDL LINTE,RR4 if carry then begin LDL OP,TEMP1; OP_EXP:=TEMP1_EXP; OP_SIGN:=TEMP1_SIGN #072A47C00; OP_EXP:=07F;OP_SIGN:=PLUS ...OP:=.447822343969 FLOATING_MULTIPLY() LDL OP,#06DA9FC00; OP_EXP:=084;OP_SIGN:=MINUS ...OP:=-13.70800004765 FLOATING_ADD() LDL OP,TEMP2; OP_SIGN:=TEMP2_SIGN; OP_EXP:=TEMP2_EXP_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN FLOATING_MULTIPLY() LDL OP,#063F7DF9C; OP_EXP:=085; OP_SIGN:=PLUS ...OP:=24.9920639458976 FLOATING_ADD() LDL TEMP1C, etc ...ret. ACC,etc=fraction (above lower int); RR4=lower int LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN ...save IFIX() ...fix(AC)->AC if OP_SIGN=MINUS then begin if OP_EXP<=080 or begin LDL RR4,OP; TEMP:=OP_EXP-080 SDLL RR4,TEMP; RE AC_SIGN:=SIGN STORE_AC IRET Log: PROC LOAD_AC() Log_() STORE_AC() IRET Log_: PROC ...check for valid arguments AC_SIGN:=PLUS LDL OP,#040000000; OP_EXP:=081; OP_SIGN:=PLUS...OP:=1.0 LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP FLOATIDIVIDE() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXP FLOATING_MULTIPLY() if BITB AFLAG,0 not zero then begin LDL OP,#06487ED80; OP_EXP:=080; OP_SIGN:=PLUS ...OP:=PI/4=.7853981634 FLOATING_ADD() end else if BITB AFLAG,1 not zero the FLOATING_MULTIPLY() LDL OP,#05F5FE500; OP_EXP:=086; OP_SIGN:=PLUS ...47.68729218663 FLOATING_ADD() LDL OP,TEMP3; OP_SIGN:=TEMP3_SIGN; OP_EXP:=TEMP3_EXP FLOATING_DIVIDE() end ...GET SIGN OF RESULT if R0,AC; AC_EXP:->TEMP1_EXP; AC_SIGN:->TEMP1_SIGN LDL OP,TEMP2; OP_EXP:=TEMP2_EXP; OP_SIGN:=TEMP2_SIGN FLOATING_SUB() LDL TEMP3,AC; AC_EXP:->TEMP3_EXP; AC_SIGN:->TEMP3_SIGN LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN LDL OP,TEMP2; OP_EXP:=TEMP2_ES R4,15 TESTL RR4 end not zero then SUBL AC,#1 end PUSHL AC IFLOAT() EX OP_0,AC_2; EX OP_1,AC_3; EX OP_EXP,AC_EXP; EXB OP_SIGN,AC_SIGN FLOATING_SUB() POPL RR4 RET Cos: PROC LOAD_AC() LDL OP,#0517CC1B7; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=4NG_CMP() if CPL AC,#0=zero then begin LDL AC,#0;AC_SIGN:=PLUS;AC_EXP:=0; STORE_AC() RET end LDL AC,TEMP1; AC_SIGN:=TEMP1_SIGN; AC_EXP:=TEMP1_EXP if AC_EXP=0 then begin AC_SIGN:=MINUS LDL AC,#0EFFFFFFF; AC_EXP:=0FF; AC_SIGN:=MINUS...AC:=MINUS n begin LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP LDL AC,#06487ED80; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=PI/2=1.570796327 FLOATING_SUB() end AC_SIGN:=SIGN STORE_AC IRET Log: PROC LOAD_AC() Log_() STORE_AC() IRET Log_: PROC ...chec:=INTER&4 not zero then AC_SIGN:=MINUS STORE_AC() RET Arctan: PROC LOAD_AC SIGN:=AC_SIGN AC_SIGN:=PLUS LDL OP,#06A09E680; OP_EXP:=07F; OP_SIGN:=PLUS ...TAN(PI/8)=.4142135624 AFLAG:=0 LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP FLOAXP; OP_SIGN:=TEMP2_SIGN FLOATING_ADD() LDL OP,TEMP3; OP_EXP:=TEMP3_EXP; OP_SIGN:=TEMP3_SIGN FLOATING_DIVIDE() ...ADD IN FRACTIONAL AND INTEGER POWERS OF 2 case INTER&3 of 1: begin LDL OP,#04C1BF828; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=2^1//PI=1.273239545 FLOATING_MULTIPLY() BRK() R5:+2->INTER SIN_APPROX() IRET Sin: PROC LOAD_AC() LDL OP,#0517CC1B7; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=4/PI=1.273239545 FLOATING_MULTIPLY() BRK() R5:-> INTER SIN_APPROX() IRET SIN_APPINF. STORE_AC() RET end AC_3:=AC_EXP-080 EXTS AC IFLOAT() LDL OP,#058B90C00; OP_EXP:=080; OP_SIGN:=PLUS ...OP:=LOG BASE E OF 2=.6931471806 FLOATING_MULTIPLY() LDL TEMP4,AC; TEMP4_SIGN:=AC_SIGN; TEMP4_EXP:=AC_EXP LDL AC,TEMP1; AC_SIGN:=TEMPk for valid arguments AC_SIGN:=PLUS LDL OP,#040000000; OP_EXP:=081; OP_SIGN:=PLUS...OP:=1.0 LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP FLOATING_CMP() if CPL AC,#0=zero then begin LDL AC,#0;AC_SIGN:=PLUS;AC_EXP:=0; STORE_AC() RET endTING_CMP() if CPL AC,#0>>=zero then begin LDL OP,#04D413D00; OP_EXP:=082; OP_SIGN:=PLUS ...OP=TAN(3*PI/8)=2.414213562 LDL AC,TEMP1;AC_SIGN:=TEMP1_SIGN;AC_EXP:=TEMP1_EXP FLOATING_CMP() if CPL AC,#0>>=zero then begin LDL OP,TEMP1; OP_EXP:=TE4=1.189207115 FLOATING_MULTIPLY() end 2: begin LDL OP,#05A827999; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=2^1/2=1.414213562 FLOATING_MULTIPLY() end 3: begin LDL OP,#06BA27E65; OP_EXP:=081; OP_SIGN:=PLUS ...OP:=2^3/4=1.681792831 ROX: PROC if R5:& 1 not zero then begin LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP LDL AC,#040000000; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=1.0 FLOATING_SUB() end if R0:=INTER&3=0 or R0=3 then begin ...sine approximation ...Q POLYNOMIA1_SIGN; ...scale to 1/sqrt(2)<=xTEMP1_EXP; AC_SIGN:->TEMP1_SIGNL LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP FLOATING_MULTIPLY() LDL TEMP2,AC; AC_SIGN:->TEMP2_SIGN; AC_EXP:->TEMP2_EXP LDL OP,#043403000; OP_EXP:=0878 =1.0 FLOATING_ADD() LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP LDL AC,TEMP3; AC_SIGN:=TEMP3_SIGN; AC_EXP:=TEMP3_EXP LDL OP,#040000000; OP_EXP:=081; OP_SIGN:=PLUS...OP:=1.0 FLOATING_SUB() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXOP_SIGN:=PLUS ...OP:=LOG BASE E OF 2=.6931471806 FLOATING_MULTIPLY() LDL TEMP4,AC; TEMP4_SIGN:=AC_SIGN; TEMP4_EXP:=AC_EXP LDL AC,TEMP1; AC_SIGN:=TEMP1_SIGN; ...scale to 1/sqrt(2)<=xTEMP2_SIGN; AC_EXP:->TEMP2_EXP LDL AC,TEMP1;AC_SIGN:=TEMP1_SIGN;AC_EXP:=TEMP1_EXP FLOATING_SUB() LDL OP,TEMP2; OP_EXP:=TEMP2_EXP; OP_SIGN:=TEMP2_SIGN FLOATING_DIVIDE() AFLAG:=1 end end else begin LDL AC,OP; AC_EXP:=OP_EXP; AC_SIGN:=OP_SIGN LDL TEMPP,OP; OP_EXP:->TEMPP_EXP; OP_SIGN:->TEMPP_SIGN BRK() LDL LINTE,RR4 ...for y a noninteger, take exp(y*log(x)) if AC_EXP<>0 then begin LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN Log_() ;OP_SIGN:=PLUS ...OP:=67.250731777791 FLOATING_ADD() LDL TEMP3,AC; AC_SIGN:->TEMP3_SIGN; AC_EXP:->TEMP3_EXP ...P POLYNOMIAL LDL AC,TEMP2; AC_SIGN:=TEMP2_SIGN; AC_EXP:=TEMP2_EXP LDL OP,#058D62C80; OP_EXP:=0P FLOATING_DIVIDE() LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP FLOATING_MULTIPLY() LDL TEMP2,AC; AC_SIGN:->TEMP2_SIGN; AC_EXP:->TEMP2_EXP ...p polynomial LDL OP,#06A491100; OP_EXP:=07F; OP_SIGNh!vzqv~qV2.07. tdd disassemblerWrrdi {i Ói pj j j j" 7k 6 w * KDDDS $OeKKG]G;D DSKD(*** l:KK CLL3HfW""+L $O"  K LDL AC,TEMP1; AC_SIGN:=TEMP1_SIGN; AC_EXP:=TEMP1_EXP end ...Q POLYNOMIAL LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP FLOATING_MULTIPLY() LDL TEMP2,AC; AC_SIGN:->TEMP2_SIGN; AC_EXP:->TEMP2_EXP LDL OP,TEMPP; OP_EXP:=TEMPP_EXP; OP_SIGN:=TEMPP_SIGN FLOATING_MULTIPLY() Exp_() STORE_AC() RET end ...for y an integer, multiply if TESTL LINTE zero then begin LDL AC,#040000000; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=1.0 STORE_AC() RET end7D;OP_SIGN:=PLUS ...OP:=.0867545069521 FLOATING_MULTIPLY() LDL OP,#04A511A80; OP_EXP:=083;OP_SIGN:=MINUS ...OP:=-4.644800481954 FLOATING_ADD() LDL OP,TEMP2; OP_SIGN:=TEMP2_SIGN; OP_EXP:=TEMP2_EXP FLOATING_:=PLUS...OP:=.41517739 FLOATING_MULTIPLY() LDL OP,#0554DE880; OP_EXP:=080; OP_SIGN:=PLUS...OP:=.6664400777 FLOATING_ADD() LDL OP,TEMP2; OP_SIGN:=TEMP2_SIGN; OP_EXP:=TEMP2_EXP FLOATING_MULTIPLY() LDL OP,#040000200; OP_EXP:=082; OP_SIGN:=PLUS...OP:=2.01(* O9* 9(  9Gwk~kBinfFN~h #x ^VBi~kBi~kfnͦiѷbk# w>2@i#~: +~@##+x8( ~9j #x 2jx8(> >2@i~. LDL OP,#054B68000; OP_EXP:=084; OP_SIGN:=PLUS ...OP:=10.5891113168 FLOATING_ADD() LDL OP,TEMP2; OP_SIGN:=TEMP2_SIGN; OP_EXP:=TEMP2_EXP FLOATING_MULTIPLY() LDL OP,#06547A700; OP_EXP:=084; OP_SIGN:=PLUS ...OP:=12.65998646243 FLOATING_ADD() LDL TEMP3 LDL RR4,LINTE LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN if BIT R4,15 not zero then begin COM R4; COM R5; ADDL RR4,#1; LDL LINTE,RR4 LDL TEMP2,AC; AC_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN LDMULTIPLY() LDL OP,#069A31F80; OP_EXP:=086; OP_SIGN:=PLUS ...52.81860134812 FLOATING_ADD() LDL OP,TEMP3; OP_SIGN:=TEMP3_SIGN; OP_EXP:=TEMP3_EXP FLOATING_DIVIDE() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXP 000008368 FLOATING_ADD() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXP FLOATING_MULTIPLY() LDL OP,#058B90C00; OP_EXP:=07F; OP_SIGN:=PLUS ...OP:=LOG BASE E OF SQR(2)=.3465735903 FLOATING_SUB() LDL OP,TEMP4; OP_SIGN:=TEMP4_SIGN; OP_EXP:=TEM(2j#x8( ~9j #xh> 2@i:@iGj( k#v@@@@@kkkjkj!+h$=(x͆jkj0x͆jj >jx͆jj kj>jOkj0#kj!!jw#w#w(>~W#~O#~,AC; AC_SIGN:->TEMP3_SIGN; AC_EXP:->TEMP3_EXP ...P POLYNOMIAL LDL AC,TEMP2; AC_SIGN:=TEMP2_SIGN; AC_EXP:=TEMP2_EXP LDL OP,#065E83280; OP_EXP:=083; OP_SIGN:=PLUS ...OP:=6.3691887127 FLOATING_MULTIPLY() LDL OP,#06547A700; OP_EXP:=084; OP_SIGN:=PLUS ...L AC,#040000000; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=1.0 FLOATING_DIVIDE() LDL TEMP1,AC; AC_EXP:->TEMP1_EXP; AC_SIGN:->TEMP1_SIGN end CNT:=32 repeat LDL RR4,LINTE; SLAL RR4; LDL LINTE,RR4 if carry and CNT:-1 not zero then begin repeat  FLOATING_MULTIPLY() end else begin ...cosine approximation ...Q POLYNOMIAL LDL OP,AC; OP_SIGN:=AC_SIGN; OP_EXP:=AC_EXP FLOATING_MULTIPLY() LDL TEMP2,AC; AC_SIGN:->TEMP2_SIGN; AC_EXP:->TEMP2_EXP LDL OP,#P4_EXP FLOATING_ADD() RET Exp: PROC LOAD_AC() Exp_() STORE_AC() IRET Exp_: PROC LDL OP,#05C551D94; OP_EXP:=083; OP_SIGN:=PLUS ...OP:=4*LOG BASE 2 OF E=5.770780164 FLOATING_MULTIPLY() LDL TEMP1,AC; AC_SIGN:->TEMP1_SIGN; AC_EXP:->TEMP1_EXP bk##w#~: +~@##+>Jk~. #>Jk>\k >Gx( ~hk #x (@8Z80(.`8}8&($/898(!8 ͊:_͊!J$=(xͬ͊0xͬ! >xͬ! ͊>O͊0#͊!!OP:=12.65998609915 FLOATING_ADD() LDL OP,TEMP3; OP_SIGN:=TEMP3_SIGN; OP_EXP:=TEMP3_EXP FLOATING_DIVIDE() LDL OP,TEMP1; OP_SIGN:=TEMP1_SIGN; OP_EXP:=TEMP1_EXP FLOATING_MULTIPLY() if BITB AFLAG,0 not zero then begin LDL OP,#06487ED80; OP_EXP:=080; OP LDL TEMP2,AC; AC_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN FLOATING_MULTIPLY() LDL RR4,LINTE; SLAL RR4; LDL LINTE,RR4 if carry then begin LDL OP,TEMP1; OP_EXP:=TEMP1_EXP; OP_SIGN:=TEMP1_SIGN 05F5FE480; OP_EXP:=086;OP_SIGN:=PLUS ...OP:=47.68729082658 FLOATING_ADD() LDL TEMP3,AC; AC_SIGN:->TEMP3_SIGN; AC_EXP:->TEMP3_EXP ...P POLYNOMIAL LDL AC,TEMP2; AC_SIGN:=TEMP2_SIGN; AC_EXP:=TEMP2_EXP LDL OP,BRK() R5:-> INTER if AC_EXP<>0 then AC_EXP:-2 ...EVALUATE RATIONAL APPROXIMATION TO 2^X LDL TEMP1,AC; AC_EXP:->TEMP1_EXP; AC_SIGN:->TEMP1_SIGN LDL OP,#0454AED91; OP_EXP:=084; OP_SIGN:=PLUS ...OP:=8.6615859416262 FLOATING_MULTIPLY() LDL TEMP2,AC; AC9 w#w#w(>V#N#~$#~+: ~@##>c~. #>c>u >Gx( ~́ #x (@8Z80(.`8}8&($/898(!8)8(+( -(\(^ xͬ((#͊!!OW_}T]Oů)lau!t"w#CLR @RR8 EN_BRK(); RET FILIO_: ...enter bufhdr @RR8; send to Z80 ...set up for SYSIO: PUSH R13 if BIT @RR8,RDB not zero then begin RL1:=RD if BIT @RR8,RDAB not zero then RL1:=RDAHD|080 end else begin RL1:=WRT if BIT @RR8,ASYNCB not zero te write in prog. ... SNDBUK(); RET ...WRCON3: ...enter & ret. same as WRCON2, may put in buffer instead of bucket ... DI_() ... if WRCONFLG=0 or R0:=R5+PUTBUFCNT>PUTBUFSZ then begin ... EI_() ... repeat until WRCONFLG=0; ... WRCON2() ... end else be->TEMP1_EXP; AC_SIGN:->TEMP1_SIGN end CNT:=32 repeat LDL RR4,LINTE; SLAL RR4; LDL LINTE,RR4 if carry and CNT:-1 not zero then begin repeat LDL TEMP2,AC; AC_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AR4 LDL RR10[FPSREQ],RR2 ...FPSREQ:+LEN LDL RR4,RR10[FLEN] if CPL RR2,RR4 >zero then LDL RR10[FLEN],RR2 ...poss. update flen R13:+R1 ...TOTLEN:+LEN POPL RR2 ...XFADR MOVDTA_(LDL RR4,RR8[BUFADR_];R5:+R0) ...move R1 bytes from @RR2 4x( >!O  ̀4x( >"O  ̀SH)lgxͬ!!G͊H͊ 4 # (  >>KHB~0 #~/ >:w>A+w͐( >Ƿ ͐(>>;Ϳ~I #~ ( ͜~# (Xhen SETB RL1,7 end RH1:=@RR8[LU_]; LDL RR2,RR8[BUFADR_]; R13:=@RR8[XFCNT] R5:=@RR8[BLKNO]; R4:=0; SLLL RR4,#BLKSZPWR ...RR4=fpsreq REQBUKW() ...wait for prev. i-o to finish, then get bucket SET @RR8,IOINPRGB; N_IOINPRG:+1 if BIT @RR8,RDB not zero tgin ...if last write not done & fits, add to PUTBUF ... PUSHL RR6 ... LDAR RR6,PUTBUF; R7:+PUTBUFCNT ... R0:->PUTBUFCNT ... repeat ... if RL0:=@RR2'<>0A then begin ... RL0:->@RR6'; R5:-1 ... if RL0=0D then begin RH0:=0A->@RR6'; R5:`;J!: 8J8(0n;ս`;!: 8*0`n;ΞL;`8J:)LVqa4 G`9B:nYELY jYj8`. L9!\r$4h:L:a4Kpыo4L9L>ӯ` >n :L:j:$L;L:to @RR4; RR2 updated PUSHL RR2 SET @RR8,GDDTAB if BIT @RR8,RDAB zero then @RR8[NBLKS]->@RR8[NBLKSDUN] ...mark good data in buffer if R12>BLKSZ then begin ...if did big buffer R3:=R12; R2:=0; SRLL RR2,#BLKSZPWR R6:+R3-1 ...adjus(>3>3!>Z##y:(+:!` ͍  Q B  ͩ :(& :1   $  `͓͞J ɯ!w#4#(!4#(͓ ͜ !͓ G͜ x+| !@ (+| >G͜ xZ8000 SYS NOT READY 2222!hen SET @RR8,GDDTAB ...want these set only when guaranteed i-o req. will be started ...since after REQBUK, this is so since can be no NMI PUSH R1; RESB RL1,7 SNDFIO2() ...i-o req. sent to Z80 POP R1 if BITB RL1,7 zero then repeat until BIT @RR8,hNaR@LNooP!bq0hNaP LNKP/!: 8J.(0 DqoT`N q22 jNՄUaP q oR!N*0*0aRoRaP aRױFa4so4a6ssso6X+L;`8n:3` ;DJ `:J8h:n ;F`;L:j:`n;YLNapKLL;j>I!0R!7n2!w#͟ ͦ(͓ >ͩ ͤ  !!6`͓ 2O: ͨ y ͺ ((   (>>2 ?P 2222`h"`h"22`h"`h"͟ ɷ <8>G>(?2~IOINPRGB zero; POP R13; RET WRITEF: ...enter R1=orig R0=LU,cmd, R13=orig R1=xflen, RR2=xfadr, R4-R12 free ...do `write', update fpsreq, ret. RL0=CC, R13=no. bytes written R13==0; RL0:=OK; RET Z FNDLU_() ...RR10=^LUvec if CKERRCD() not zero then begi!ֽ֜LN _םשoDo6aR1KPKRLNړ KPaPoPaRoRaDoDaD1pL;aRLNЋaP< y 11 44 11aPasass5 x EELN{կ_lo6a6ֈ Jߠ ֗  LLSTBLK RL0:=OK WRFX~ RET B_WRITE: ...write out block with bufhdr @RR8, waiting for  #= (͟ > >2CAN'T DO CMD !=(!" (k :G: ͥͶ2Sy2  ` *:G'? >&8~O# w!H [ "2O:G(2J !" `i:G;2(+> * *" *| >( ` n R13:=0; RET end ...if prev. err, Z=0, code->RL0 PUSHL RR2; RH7:=RH1 LDL RR2,RR10[FPSREQ]; R12:=0; ADDL RR2,RR12 PUSHL RR2 ...fpos at end of request SUBL RR2,#1; SRLL RR2,#BLKSZPWR; R3->R1 ...R1=LSTBLK SLLL RR2,#BLKSZPWR; POPL RR4 ...RR2=beg laL;` 9n :_ B x EEpLN x TT\О^H`:n:n9L;w 1p 4s_ LNև|_иaRqCPٗa4KPa6KRo6aPso6aRs o4a6o6aPo4a6s 40 8  s01p x xp   x` ;!0 8  LR0 ...R0=LSTBLKTOP LDL RR2,RR10[FPSREQ]; SRLL RR2,#BLKSZPWR ...R3=FSTBLK R6:=R3; R13:=0 ...I=FSTBLK; TOTLEN:=0 POPL RR2 ...XFADR WRTLUP~ ...repeat PUSHL RR0; PUSHL RR2 R12:=BLKSZ if R6=R1 then R12o6o6^_ Ğֶa43 q0Vޗu_ _ Ğ 4 1!7_ __2!__ _ _ߒ_ Ğ x AAa43 0`.n:L; o4_ )a430֚_ _ L!<`}`.=7 h9!p t ɀȀW[  Lp x  `xw`>  x 11D 226 33'anaL;n x OO)Ӭa6cn ;ә`. !: 8J. comp. (GDDTAB set) SET @RR8,ASYNCB RES @RR8,RDB; RES @RR8,DELWRB; SETXFCNT() FILIO_() RL0:=OK; RET B_DWRITE: ...mark block with bufhdr @RR8 as needing writing, but don't write ... out yet SET @RR8,DELWRB RL0:=OK; RET INVALID: RL0:=INVLDERR; RET *B 0DM[!!oR !!w"qp*:utw*ut:w!~(6ɯ2m >::*|}:: :*|} :*|}ͤ [ G: m >::[QYAaiͤ [:O "2ɹR* ":=R0 ...if I=LSTBLK then TOP:=LSTBLKTOP else TOP:=BLKSZ R3:=R6; R2:=0; SLLL RR2,#BLKSZPWR LDL RR4,RR10[FPSREQ]; SUBL RR4,RR2 ...BOTTOM:=FPSREQ-I*BLKSZ ...here: R5=BOTTOM; R0=LSTBLKTOP; R12=TOP; R1=LSTBLK; R13=TOTLEN PUSH R5 if R5=0_ LXpJ q**13LW_ V0LW_ LN!E_ ,! LN!L_ $(0_ _ܠ_  dW!\poB~ x TTn @_ L@ n ?_ L? x UU_ pph-_  NNh-LN(`.__(0ՒLN qXp qp`>Jn9թݞs! 10 8 5 p!Zo6ӓRCn ;_ x OOILNԸ!,0oF3p x nnNnI ** NNp!Ԣ1nIoD!H.8NXTBUFI: LDAR RR8,BUFS-BHLEN; RET NXTBUF: ...get ^next bufhdr of device ->RR8; Z=0 if no more (incl. SPBUFHDR) repeat R9:+BHLEN R9==^BUFS+(NBUFS+1)*BHLEN-1; RET UGT until BIT @RR8,ALLOCB not zero; R0==R0; RET ROM: ADDR $  0100|08000 MBUFF: ADDR *B":O! 6:O! 6ɯO! (wA<8x m >ͩ ͙ ͤ `iB8( >ͩ ͈ ͤ   DM ͨ ͈ ͟ yx(ͩ ͙ `iB0 DM  B8 (   DMm >ͩ yx(PUTBUFCNT repeat if RL0:=@RR2'<>0A then begin RL0:->@RR6'; R5:-1 iͤ =#B !͍*w "[*R~G> >X  R ":!> X O:m yͩ xͩ ͤ ͓  ͟ @( (͟ (ͨ >ɯɯ$#~+: ~@##>t~. #>t> u >Gx( ~KSZ then R3:+1 R3:*BLKSZ; PUSH R3 ADDBUF(R3; RL5:=RH7) ...try to get buffer for all rem. whole blks POP R3; JR NZ,WRFT1 R12:=R3 ...TOP:=(LSTBLK-I(+1))*BLKSZ R6:->@RR8[BLKNO]; RL0:=OK end else begin WRFT1~ if ROK; RET end RL0:=INVLDERR; RET ...invalid INITCON: PUTBUFCNT:=0; ...WRCONFLG:=0 ...INITCON2: PRTSW:=0; ^KBUF->NXTIN->NXTOUT; RET GETLINE: ...get line of input to @RR2, R5=max len., echoing, backspacing, etc ...ret. R3=len. (to CR or EOT or max len) KjKLI** ԱaLMp0kD 11q7$LJ!"`I ** !9LM*0 9 NNLJԞ--From here: --To here^ LNԆaP@RR6'; R5:-1 end end until R5<<=0; EI_(); POPL RR6 ... end RET ...WRCON2: ...enter with R5=#bytes to send (max 0100), RR2=addr ... ...ret. updated RR2, R5=-1 if overflowed because CR last (else R5=0) ... REQBUK();  RET end ...for y an integer, multiply if TESTL LINTE zero then begin LDL AC,#040000000; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=1.0 STORE_AC() RET end LDL RR4,LINTE LDL AC,TEMP1; AC_EXP:=TEMP1_EXP; AC_SIGN:=TEMP1_SIGN if BIT R4,15 not zero then b12=BLKSZ or begin R3:=R6; R2:=0; SLLL RR2,#BLKSZPWR; R5:=R12; R4:=0; ADDL RR2,RR4 LDL RR4,RR10[FLEN]; CPL RR2,RR4 end >=zero then GETBLK(R3:=R6; RL5:=RH7) else B_READ(R3:=R6; RL5:=RH7) ...if TOP=BLKSZ or TOP>=eof then GETBLK() else B_ register COL:RL6, PRVCOL:RH6, BUFPTRL:RR8, BUFPTR:R9 register BUFBEG:R12, BUFEND:R13 ... save R6..R13 LDL BUFPTRL,RR2; BUFBEG:=R3 BUFEND:=R3+R5-1 COL:=0 GETLLP~ repeat RL3:=CONIN1() ...get char. RL3==EOTCH; JR Z,GETLX if RL3=8 then begin RR8[NBLKSDUN] ...Z=1 end JR ADDBX end until R9:+BHLEN=^BUFS+NBUFS*BHLEN; RESFLG Z ADDBX~ EN_BRK() POPL RR6; RET RELBUF: ...release buffer & bufhdr @RR8 DIS_BRK() if R9<>^SPBUFHDR then M_REL(LDL RR2,RR8[BUFADR_]) ...assumed R8=MYSeg R4:=DATA ... RL0:=CONWRCD; OUTB @R4,RL0 ... OUTB @R4,RL5 ... repeat ... if RL0:=@RR2'<>0A then begin ... OUTB @R4,RL0; R5:-1 ... if RL0=0D then begin RH0:=0A; OUTB @R4,RH0; R5:-1 end ... end ... until R5<<=0; ... SETB WRCONFLG,0 ...mark consolegin COM R4; COM R5; ADDL RR4,#1; LDL LINTE,RR4 LDL TEMP2,AC; AC_EXP:->TEMP2_EXP; AC_SIGN:->TEMP2_SIGN LDL OP,AC; OP_EXP:=AC_EXP; OP_SIGN:=AC_SIGN LDL AC,#040000000; AC_EXP:=081; AC_SIGN:=PLUS ...AC:=1.0 FLOATING_DIVIDE() LDL TEMP1,AC; AC_EXP:READ() end end else B_READ(R3:=R6; RL5:=RH7) if BITB RL0,6 not zero then begin ...if error POP R3; POPL RR2; POPL RR2; JR WRFX end POP R0 ...BOTTOM R1:=R12-R0 ...LEN:=TOP-BOTTOM LDL RR2,RR10[FPSREQ]; R5:=R1; R4:=0; ADDL RR2,R: ~ӞЉu q^^_Y^anЯ sy x ++ -- && ||pw#9 x ** //pw LթվO^$I_LPߢWߧB߬L߱Q)ߺ'#+ LP4 LP<٤Cap x00  p x00 pLP1 qRR_m _m 6 qRRL_LDR-ޞADD __ SUB __ׄSLA SLL_(SRA .SRL_9SDA ?SDL_0JBYTE_m _mҪVWORD_m6^PUSHa MgPw!S#/CCBz  @1p=.xp_[   _[..xp_[ Tw!Oߚߨ_R     _Rܗ ߹_Rܫps   '  ݄_e.H_[dŞ0O؞_X5anj'y_p$W1C09 * $W5C09 ! K0W1C01- ;W5C01#8 #՗Lմ^:ҵ<TfB3D BB^ LL^տ.xpM^te^_YDpC _YLsmf_Z p_Zjфvalue( QݎU q))pw|вR_Z$p_Zj Х Pђҥ/򂪞/aP"^c&ejoߔ q paP$oP&g_t _`8  p x LLF ﲨ HH P 蘒B RR\L QQfQ oW.W,7O_e%4>O*_e;_fHR.xp_[CLLLLWWLLLLS x OPLjVpLONG_mLxCALR{gr^ԄCALLԇy{wԑLDARԔ4Ԇ_nԃՔԅԟMULTԓYԏԩDIVLԝ[ԙԳIRETԪ{ԼDJNZ Կ_tԬնԮW_֞LDPS_W3900Ը _zW7900͞LTws_Yx_Y s xp_R$).38<!|,s ?!ssG4B(X ppSC _[ "CALL 9_[ž_Y_[_[1 !aȗ}} C X_.տb h BB^0ԁm߄W8000lol߃ԋ| Ԩߐ> BB^zߛ߫Wߏߒߕߨߨ ߥߧ߽O_eߩ߬߻d BB^߾)WٞՁ _VZfP4waPL_Zդߕ$_Qn[!]տLP0 q//E q p K H_[H_[,֍ ֑ *L֖%,#(8;...2>J081:>5:LW.cRB.iXBB LLpm`s#_n{#_n 3o_e8_rdڂڊڊڒ$ڒښڮ#"_n4_rd>_rdF_rdK_rdQ ɞ@6ɞΞDIRLDDR _eXCPIRCPDR (CPSICPSD X $OTIR+OTDR 6INIR=INDR2 .HTSET<֮8RTESTFָB\EXTSJӹePUSHL0h$ h㠉q&nb03}} Tw8_Yaw@1 &߹!߾s_Y/qs1o6З2.8!_Y*_Y !v5!0 &354 5a0B!_Y*!vh 7 BB^ٞ5 ^YJ^Z^Z^Z^Z^[^\^\^e:^eD^d^e$^Ql^ed^e^e^e^e^r BB^ LL^ߓHp 1_rdߘߡ Y|1!_rd+ BB^ LL^߽$rլJ!_rdD.n q EuabWWageaP$aP TP"B_Yb_Y*qQ boP$!^_Y*1LPA_Y*1Q_Y*1aP"O@aP OAS0at.M@.E@.K@.C L itIP/A(/@@DԞ, Pif$([_etqH_e@д_e-)0]8(;[є'@)C]-6ѻ_n|LPR|_faP _pG_f3K񠓣?_rdhTnMULTLb ^xDBJNZ {_LhrjB_֞ՇCPSIR{ՏCPSDRՃՀ՚LDCTL`ՈգSETFLG՘լRESFLGայCOMFLGժռ)ըճ_   ^eD߈LF`G`GJ83359!v!0 _[52_[y5_[<=>?z|} {{ { { 96.,(*   &$":;0123457pqrstuwTw@_Y a ֞X   d  6Մմ\!_rdV BB^@ LL^6pP՘vЋHoІ ЄВЗ МG BB^СЪйOХ_eШз#c BB =֙; <֦:͞a_ae_`ߨ e q..ECa_Y q::p_`_` _`        x [[ (((_`._`  _`_`a_a<׮_a_`G׳_a!_i|SX_o_ra _f/aP _rdn_rp_YۊALۋۂ۔<<_pۂۛ>>ۆ_f?]ۥWۍیۋۢ۬W3000Uۙۘ۫۔T LL^ BB^иۮ۰3۸њ۸"/ї W0D05۾n۾˞5 $               LFLFfGfAEL>L>L>L>L>L>L?fGfGE3MBEaBKFE fCEL`!~8!4VP {ߒ!~J!4P?? ^ g!~^4 99. P!~f4 ' PP??!~k49S!~q4GSP!~}!4VP P֨աȞֈ BB^C?ָ;Mޞ"h>ɞ:r$ֶ;_e* 0_eI:.W+׆6W2 BBS/ז1_eM9 BQW7D00;<;P^FLAGSpLN `R׽Rg100 ȋca8 x  %aL aP&a_YoS_[aL  U_[_[L_P,aP&KP$&! Q Pu u p @@ u[[p | _X_[0KP$].xpp_[7&11$.}2: oѪ W4D05уO!_efo. W0C05 ь- ҄ 2,Ҍn -W4C05*ѫ#2.В 2_ef_e_etKOC069H1LfBD7L.pLNq?L?LpL?L?L?`p`@  LpJ@CL@L@L@`pLF`pLFn!L> ЃLPd adE7Tв3 q00p_Z$qCLaw:3Vaw:gw>aw8_Y1_YXjر Y W `waw0Q ߥߩߙXٲawgw>Tw1_Ygw> 1_YٲAwQckFLAGSW`e4wNSP {OFFlsLPEыSEGv134_._oW_YѡA.ypѣњgP$_QP ODD BOUNDARY x CC ZZ SS PP VVpw_r q E_laPJ_Z_m ?}:5LPaP$` PaP$oLPaP$LPLPaoP$Հha!uƕoP$n PaP"5/]}2LP?oaPKa7]oaov}2?}:5Dya]v_\3}2?}:1^S^-t[f]5SnjΞn_e[zvڞ6z_e̞+ LL^R BB^љ܅/ܡW܋܊܍܈ܟ܈H BB^Ѳܞ3yя W4000ܪܯܮܱܬܬܽL7ȞD])҂?L>LAL@MBMHJ!JaHaFʡ4u'\!SӋC!SS߀QZ߇!0!>1P_!>!PД!!fAQ aH JQ'\!!S4` A`BJ@ bAaBߡ5(CS9!S.C!S߮E1gw>1_Y1_Y}}}$}55(}X gw>_YnSaw>Tw@]w&!0bq_Yow  ]wow^LawTwb!_Y*Tw aw Mw Tw@ &s!u X О?_B   0 0 BB LLWӞ ^ ^ ^ ^ ^R BBn ^8 ^ ^ ^ BB LLn ^ ^ ^ОJJR LԨLOE09H>3YJPL]ԹդJdEI@QS_QD_Fԑ$+ReޤRu_ԻFC PCN4ԴvwaLHߍ BB^: LL^RX_et ҇מW0001 W4001 E_et ґӇ1 ӎݤp҃0W,6W!3>W"9 BB^ӚlѮ#YW4000CBGBYBuQC!SQ9CaS`AbA>nACoFQbswE _Tw81357 }6377 1 vJ! w 1v>?# p !.}2?}:Tw@Pw^aw00 b2 8*0 8!^B2!1b_Y*bx _nD .xp.xp=_[FjDI^orVIxNVIm|W7C00fgz҈SC~_nx_e8oҕOR_ ҅ҟEX,_ҏҩINҖҰRLңҷRRҪҧLD ҮCP _Ҿ _ҾSL SRSDSUqafGߑLwiJߣߊ]w@LwiBߣB߳ߚߋvX߱QXߨJL'߰Tw03,!_Z$_[d_Z$ _[d.=0̞n N߿ 5S 5 pw,  qp ypC֞Z #! BB^0y>4kҎpҏv3ҋUK݂ҥ݇ҦݍJҾ_etݢݶZݹEQݬNZNEݷCULTNCUGE̞PL ӞM #WaHQҋuoHs1aH11poH}aH1oH!3KBdAaH0 JQ'\1!S<ЌaH JQ'\ S1RaH11 oHnonpnq`o``_e 8nr HH0_[rotns_e~_[J_e Ҷnaw>\ w^z_nDTw@_[Ԇa_[fjwh^^!`wi ^Tw@ҽTw@]aw>oTw8]\ w^v7u3u}B?1u# p !.O}JaT^o}2oaw8?K aw:  @?!@SSP"LWW__mdGRET EOPOP LDMLDA _n_֛"DIV+LDK -__J_9BIT& ?SET$ERES"_6PANDVXOR_GaINC(gD3Tw]Ӱ x   ,,Tw@ q,,p"nwh!wi]wՁTw]w_[‘ߨ!P!a_Y6]w 80_[ 80_[_[ |.xp 8   ..xp0 |.xp_[>&!A_cuC IڞOVPENOVPO GE  LTGT LE  UGT 'ULE~O! '<W4000$'*%<%ƞ>Զ  dqKwm_[J`oLrHHat_e~ 1HH0_[r`GJqE_e~$&񊘍ELqE֞'3`sȨ ȪLs..LsLs Ls Җ3 Lo VҤ?1󪀞ҹU_ x ::p qa}:a^vZLP@oP$_r q _Qn! }2oLPE`P_VLwi q//p_g$,SP$0w.9Lwi!,oP$o_gb=H@!nN!}: -DW*-*AKW8000543JTWBD00>=R>?BaOF0LEC*_)XrCLR xCOM~NEGrnӈADC4ӎSBC6_әOUTҰӆӠLDIӓӧLDD Ӛӝ_eӛӵCPIӨӼCPDӯӬRLCӹRRC (ӽTCC_6LWW_t_ a _`QM@Eqqo_[.ө8` 1p+.xp_[ Tw@_[%_[ߚө _[ߥީ _[R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10R11R12R13R14R15 N4 FC_[DwD!BUԷ mW0D09YVkT_etӖמL W4000iliniހi~ӪӠ(P+P$< BB^x LL^ ޚ_e* ޤ_e4ޮ_e(> c BB^ LL^1"޿F+W0200; == p == >> <<dAPPCaLq--Lq>>_o_f_d_ xp ]]_et q((_t߾ ۽؈W0C01_؆opw ؈_etؓ|Ȁؖ{ بW0C04_ئ؏س҅C_0_`AaaM 3M5M1ܐ x )) ,,n Cp_begin_qendif_ then_q__q _rendif while_`_)do_q_.J08+"_r<repeaepPpOfASMSTgCOMMANDfLABELCOLqXCOMM INSTYJ#TestZZ#DelZ~#IcopyZ#Copyin@Z#Copy[*#Outset\#Out\#OutNGe:#SaveD#SavBAd#Gene$#ZpQl$ݠݵ} ߭߈ߴ ߉ߺX ߐ] !! ߸_et0ƞ  ߤ-՞͞ܞ_R _e8_OC03_ȗ __W2000_'W" _et_Ξ_et_o_et_fX_rdE x ++ -- || &&.XOR.<->М x ** // %%_rL_ep_YАӣ^  Ğ_rd  T 3 aP _et_rdaP _rp6["+t_`_q.E1Kcase aҭ_qTof?YendD^until$_qL__e_t_rTY_RBW___e_taP _rZm_lp_rӍelse߬_q_r_qӛJ08ӆ_epӉӚ_r_q%ӬӯorӯJ06ӢӫӶӢ_rӻ#Err0ed#ReEe|#Xc0e#WRe0Oe#WRe4e#WRe8afa3 5aa˩!71!11ߴMrߵߦMara;]/oMMM!! P! ]4!7oo_et_et_et_et_etANߔ@֘ ϞӞ  ! !! ֊קзV,  6ֿ֥_ސW`uތ_ޘWhރ~ޕ~U_ޣWs_etފޡ_{ޥާ_޸WޜޟC]-ߚ߉Ӣߪ]-ߛߦް?<+ߪߵߠN߲ߴ45n[_`Sb_rdak^ _`q QKٓ]}نوٗW8100قٕמȀٙN!>1P!>0J0E_epӸ:ӰLӷӷ;end^ SF_fWF_qSF_WFMF_MF_aF___R_|_v else_r_q__q__ oF':-1_n"+ q;;1L-$8J$_END&pUSERCCqpR_AFpQuit{Copy;|OuthexpErrmqErrerOutmsg*|HLoutDELqGet1wPut1IrWSbgnYrWSendqrPutconzTestg|OutĐOutNvyGetrecyGetconW|OutpzwRDaHLzWRaHL]{Id{ޞޣ޶֬8ֻ Џ޹0;_:)Н_ȀMSЫ_R_rd_rd _WB200ٞ_Z_b_ש__\__f_WB10A߂_2߇_@SFjGWFw  gӂ7yӆtC ܬ߃0ߺߡܹ==b͊0+h-j 6Wޗ_et_n _f?_etek _W4C08 ` k*W4C05(ߐbЖet_ep7_r_rNor NJ_et<;_epN'_rcand,}_q_q_f_n"_n_n"ԃnotԅ_eԎcarry߹_n"ԙ<>ԟ=ԓԕ_eԭ<=ΞԳ>=؞Թ>>=̞Կ{Digit{Hexd{LatchO|Outset{Copyin{Sr{Sr1|CountINSTLIST[Ig~lLkupnl~LkupԁGenZp1SavNReVPplXcEff1fDbugBJASMSTfCOMMAND<7LABELCOLhINST*XINSTFдл ў  ֞ !!rо h_et2VA_etU׈Ξڞ_sW2000[Z[`_etu)+t_`q{`p~__rd߅_ߋ_ߑ__`aF SCQ0a a x ;;ߛO$ݩСݱ_o#ӊ,يPW6̀(_`oD WW BBԛԚԿdAfAdAoBoFeSnv߫ڮ_r-_r.,4Ȁڭ<<=Ξ>>Ϟ<<><̞_e ՞_e ޞ_e _e?' $CF\nT qaastop"printf(_Z''_[.) pP M8)"DӯdCBNBITOP2ŸWNˬ}NumHNumšXCOMM@OptmNumجHNum顡XCOMMdOptmNumHNum XCOMMOptmBNBITOP2JWNS}Num<HNumMXCOMMȯOptmLkup+vGenqZpSavRePp ,, .._r x _m F~7ppE (() [[] "" ''  p x  p x  ^YJ^Z^Z^Z^Z^[^\^\^e:^eD^d^e$^Ql^ed^e^e^e^e^r%(,3_rd$& (MF۪_rd$R ' EU.! @ CǩAQ Cݩ@P !S3[NIP!O3j 绕_2_@_D_H^YJ^Z^Z^Z@/Ԯ_dwڲ[ڷ@ڿ_< [!_d [҈_rd_eW@ڞՓb()&Lv_o_n_fۃ ^_`_rdխ(W81D0%ъ_n!;":J; P1ӭDsave=2MrestoreG<Wsetseg O}3} gresseg_-} sreturn y(_gb~)hӵՃcalx Ն_Ys~ՋALՌՇՕpatch$c՛r__qՎ0$ժ[ _Z ՗՞շ]աՔգ_ssÃXcEff1DbugJASMSTCOMMAND-LABELCOLQhINSTLTXINSTCBNןBITOP2WN"}Num HNum``ɗOptmpace left in buffer``C HL,BC ps->eݠ߽gege_iQ_gdAU_ӈ.Л_8A_R0_rdЧ_!Ыӂ^Z^[^\^\^e:^eD^d^e$^Ql_ZCTest_n&<k+>/[_Y1CLatch._n_r?])C(G)1_rN/MJ06_epJ_r_qE]CErr0Y_qk.OUT(ߪYs.SAV(_q( nȗ_[u~CSavBz ߊ08-6D_[_nDL6?6_tKH_[C>W(C\)F`- нLDaxoz 3_Y""={ xЈCSavЄБ){fЗ{PЛ}ЅУ$ТLДНАГШJ06ЛФЛФж?ПТЭ_YоCой| COutN×H_[_[11p)p"ўCOut),7_ZCIcopy_1V,_nҩҔ2@ۻ_`_rdҴ Þ=ȞDDϞKM'~ߞӓ_rd_eaCձpaaȀf qaaputchar!Egetchar!D%close!A_rd(0read!B8write!C hh!x|qxÀqV2.07E.C100 vdi {i Ói pj j j j" 7k 6 w ߅_qE}/|B_q +V;Z_p_"J`~_`ΊM_qCdP1x;~wordхbyten~яregisterntў_YњџіѥѨ:ђѩ_і߂_rT_l_``_`MnCOutset"Ԟ*CCopyin"#1"CGenn0.DO( 3_7:;?))_[ACCopy=_nM"H_Z$_[p x )) ,,K eJ0EXamL_h__q x ;; // )) ::p x< H2104FFFF_[8Jopen K H2102FFFF7F40G YKM Oad->yQk+]q-cw|i }&o܃.XOR.wt܎<-> ,܁n[_et߂܄ܜܟ*ܑ ܥ/ܗܫ%ܝܚ}xaAAќѻg_rDaP _[a_[_epJ08ΞaP$oMa_@Ma_@aAAAa۲bP1MP,MP.MP(MP*_sa_a^_ax ; o=ix`~_`_`a BB LL% p ==,ю:=ђ/ч7эў;>N6z*LASTCRLASTDECNEXTDETP"NCDSEGKP$NCODEPFTABBSEPJEXTADRdPJEXTENDPLUSERCCv՘ߓaD_rdӨ`Cܺש @ܿaBםȀɞKaaרȀԞ8.߱.C߹_etstkȓ flag!} ג! ޗW_[ stk- +ՏePFߎVfԞ~8 0߽ӐՉՌFQQ%%o@!A|azC|ߝoߠo!AzaxCzaa!]Q_`_@@C_`@ @@@CCCo!a| !o!ooQa=o 8AA_Af!A|azC|cff!]Q_`PQuitN[OuthexQPErrmSbOutmsgLSjPutconTVZGetrecOVGetconЁYId&Z DigitZ$HexdhZBNumZjHNumFZR#Latch[.Cnt[dOutpetIgaLkupaLkupnl> SFց5ߧ*LG֐ߘaFoFǞSF ֟Ֆ֦߬K×aF5ؗ SFaFLpLFdG׫݌ݛWC000݁ݘݘ!ݚX ȠݤȡݧݸWݜݡ< RET_: ...test for RET @HL=0C9; JR Z,RETT if R.A=0ED then begin @(R.HL+1)=04D; JR Z,RETT R.A=045; JR Z,RETT R.HL-1; RET end @HL&0C7=0C0; RET NZ if TSTCC() then begin RETT: @2R_SP->R.HL end else R.HL+1 CP A; RET -To here^ CkInst0: ...ret. inst. @R_PC in R.A; also set HL=R_PC CKFF(R_PC); RET NZ ...chk if brk byte (F BIT 0,B not zero or R.A=020 and BIT 2,B zero T end @HL&0C7=0C0; RET NZ if TSTCC() then begin RETT: @2R_SP->R.HL end else R.HL+1 CP A; RET -To here^ CkInst0: ...ret<  R.HL+1 CP A; RET -To here^ CkInst0: ...ret. inst. @R_PC in R.A; also set HL=R_PC CKFF(R_PC); RET NZ ...chk if brk byte (F; JR Z,RETT R.A=045; JR Z,RETT R.HL-1; RET end @HL&0C7=0C0; RET NZ if TSTCC() then begin RETT: @2R_SP->R.HL end else= = > > ? ? @ @ A A B B C @@@@@@@@@@@@@@@@@@@@@@@@@@C @@@@@@@@@@@@@@@@@@@@@@@@@@D @@@@@@@@@@@@@@@@@@@@@@@@@@D @@@@@@@@@@@@@@@@@@@@@@@@@@E @@@@@@@@@@@@@@@@@@@@@@@@@@E @@@@@@@@@@@@@@@@@@@@@@@@@@F @@@@@@@@@@@@@@@@@@@@@@@@@@F @@@@@@@@@@@@@@@@@@@@@@@@@@G @@@@@@@@@@@@@@@@@@@@@@@@@@G @@@@@@@@@@@@@@@@@@@@@@@@@@H @@@@@@@@@@@@@@@@@@@@@@@@@@H @@@@@@@@@@@@@@@@@@@@@@@@@@I @@@@@@@@@@@@@@@@@@@@@@@@@@I @@@@@@@@@@@@@@@@@@@@@@@@@@J @@@@@@@@@@@@@@@@@@@@@@@@@@J @@@@@@@@@@@@@@@@@@@@@@@@@@K @@@@@@@@@@@@@@@@@@@@@@@@@@K @@@@@@@@@@@@@@@@@@@@@@@@@@L @@@@@@@@@@@@@@@@@@@@@@@@@@L @@@@@@@@@@@@@@@@@@@@@@@@@@