| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548 |
- (* Copyright (C) 1987 Jensen & Partners International *)
- (*Global equates *)
- (*
- The "ROM" string denotes those sections requiring modification when
- creating ROMmable code.
- *)
- (*ROM
- A number of these routines make use of the Int 8 timer tick - they are
- marked with an "(*INT8*)" string. If the target machine does not provide
- a user timer tick via Int 8, then 1) don't use any of the facilities that
- need it; or 2) implement an Int 8.
- *)
- True=1
- False=0
- Timer=40H (* 8253-5 Programmable Interval Timer *)
- PPIport=60H (* 8255A-5 Programmable Peripheral Interface *)
- KBCtrl=61H
- module AsmLib
- segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$HashString : ssize= 12; segm=10; offs=8; modulus=6;
- push bp; mov bp,sp
- push ds; push es; push si; push di;
- sub dx,dx
- sub ax,ax
- mov cx,[bp][ssize]
- jcxz $Exit
- mov ds,[bp][segm]
- mov si,[bp][offs]
- sub bx,bx
- mov di,[bp][ssize]
- $loop:
- lodsb
- or al,al
- jz $EndLoop
- xor dl,al
- rol dx,1
- rol dx,1
- rol dx,1
- add dx,di
- sub dx,cx
- loop $loop
- $EndLoop:
- mov ax,dx
- sub dx,dx
- div word [bp][modulus]
- $Exit:
- mov ax,dx
- pop di; pop si; pop es; pop ds
- pop bp; ret far 8
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Move : s_seg=14; s_ofs=12; d_seg=10; d_ofs=8; len=6
- push bp; mov bp,sp
- push ds; push es; push si; push di
- mov si,[bp][s_ofs]
- mov di,[bp][d_ofs]
- mov ax,[bp][s_seg]
- mov bx,[bp][d_seg]
- mov cx,si
- mov dx,di
- shr cx,1
- shr cx,1
- shr cx,1
- shr cx,1
- shr dx,1
- shr dx,1
- shr dx,1
- shr dx,1
- add ax,cx
- add bx,dx
- mov cx,[bp][len]
- and si,000FH;
- and di,000FH;
- cld
- mov ds,ax
- mov es,bx
- cmp ax,bx
- ja $Forwards (* (at least a paragraph apart) *)
- jb $Backwards
- cmp si,di
- ja $Forwards
- je $Exit
- cmp si,di
- jae $Forwards
- $Backwards:
- add si,cx
- add di,cx
- dec si
- dec di
- std
- $Forwards:
- rep
- movsb
- cld
- $Exit:
- pop di; pop si; pop es; pop ds
- pop bp; ret far 10
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$WordMove : s_seg=14; s_ofs=12; d_seg=10; d_ofs=8; len=6;
- push bp; mov bp,sp
- push ds; push es; push si; push di
- mov si,[bp][s_ofs]
- mov di,[bp][d_ofs]
- mov ax,[bp][s_seg]
- mov bx,[bp][d_seg]
- mov cx,si
- mov dx,di
- shr cx,1
- shr cx,1
- shr cx,1
- shr cx,1
- shr dx,1
- shr dx,1
- shr dx,1
- shr dx,1
- add ax,cx
- add bx,dx
- mov cx,[bp][len]
- and si,000FH
- and di,000FH
- cld
- mov ds,ax
- mov es,bx
- cmp ax,bx
- ja $Forwards (* (at least a paragraph apart) *)
- jb $Backwards
- cmp si,di
- ja $Forwards
- je $Exit
- cmp si,di
- jae $Forwards
- $Backwards:
- mov ax,cx
- dec ax
- shl ax,1
- add si,ax
- add di,ax
- std
- $Forwards:
- rep
- movsw
- cld
- $Exit:
- pop di; pop si; pop es; pop ds;
- pop bp; ret far 10
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Fill : d_seg=12; d_ofs=10; len=8; val=6
- push bp; mov bp,sp
- push es; push di
- mov cx,[bp][len]
- les di,[bp][d_ofs]
- mov ax,[bp][val]
- mov ah,al
- shr cx,1
- rep
- stosw
- jnc $Exit
- stosb
- $Exit:
- pop di; pop es
- pop bp; ret far 8
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$WordFill : d_seg=12; d_ofs=10; len=8; val=6
- push bp; mov bp,sp
- push es; push di
- mov cx,[bp][len]
- les di,[bp][d_ofs]
- mov ax,[bp][val]
- rep
- stosw
- pop di; pop es
- pop bp; ret far 8
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public @NormPtr :
- mov cx,ax
- and ax,000FH
- shr cx,1
- shr cx,1
- shr cx,1
- shr cx,1
- add dx,cx
- ret near 0
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @NormPtr
- public AsmLib$AddAddr : a_H=10; a_L=8; c_val=6
- push bp; mov bp,sp
- mov ax,[bp][a_L]
- mov dx,[bp][a_H]
- add ax,[bp][c_val]
- jnc $NoOverflow
- add dx,1000H
- $NoOverflow:
- call near @NormPtr
- pop bp; ret far 6
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @NormPtr
- public AsmLib$SubAddr : a_H=10; a_L=8; c_val=6
- push bp; mov bp,sp
- mov ax,[bp][a_L]
- mov dx,[bp][a_H]
- sub ax,[bp][c_val]
- jnc $NoOverflow
- sub dx,1000H
- $NoOverflow:
- call near @NormPtr
- pop bp; ret far 6
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @NormPtr
- public AsmLib$IncAddr : a_ptrH=10; a_ptrL=8; incr=6
- push bp; mov bp,sp
- push ds
- lds bx,[bp][a_ptrL]
- mov ax,[bx]
- mov dx,[bx][2]
- add ax,[bp][incr]
- jnc $NoOverflow
- add dx,1000H
- $NoOverflow:
- call near @NormPtr
- mov [bx],ax
- mov [bx][2],dx
- pop ds
- pop bp; ret far 6
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @NormPtr
- public AsmLib$DecAddr : a_ptrH=10; a_ptrL=8; decr=6
- push bp; mov bp,sp
- push ds
- lds bx,[bp][a_ptrL]
- mov ax,[bx]
- mov dx,[bx][2]
- sub ax,[bp][decr]
- jnc $NoOverflow
- sub dx,1000H
- $NoOverflow:
- call near @NormPtr
- mov [bx],ax
- mov [bx][2],dx
- pop ds
- pop bp; ret far 6
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @UserBreak
- public AsmLib$UserBreak :
- mov bp,sp
- jmp @UserBreak
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @Abort
- public AsmLib$FatalError:
- (* three parameters len,a_ptrH,a_ptrL *)
- pop ax
- (*public AsmLib@FatalError:*)
- pop ax
- pop si
- pop ds
- pop cx
- sub sp,cx
- sub sp,2
- mov di,sp
- push ss
- pop es
- jcxz $abort
- $Loop:
- lodsb
- or al,al
- jz $EndLoop
- stosb
- loop $Loop
- $EndLoop:
- mov al,36 (* '$' *)
- stosb
- push es
- pop ds
- mov dx,sp
- mov ah,9
- int 21H
- $abort:
- jmp @Abort
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @D_DATA
- extrn @ErrorCode
- public AsmLib$SetReturnCode : retcode=6
- push bp ; mov bp, sp; push ds
- mov ax,[bp][retcode]
- mov ds, cs:[@D_DATA]
- mov [@ErrorCode],al
- pop ds; pop bp; ret far 2
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @SetBreakInterrupt
- public AsmLib$EnableBreakCheck :
- call @SetBreakInterrupt
- ret far 0
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @ResetBreakInterrupt
- public AsmLib$DisableBreakCheck :
- push ds
- call @ResetBreakInterrupt
- sub ax,ax
- mov ds,ax
- pushf
- cli
- mov word ds:[23H*4], DummyBreak
- mov word ds:[23H*4][2],cs
- popf
- pop ds
- ret far 0
- DummyBreak :
- iret
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$SetJmp :
- push bp
- mov bp,sp
- les di,[bp][6] (* buffer *)
- push ss
- pop ds
- mov si,sp
- movsw
- movsw
- movsw
- mov ax,sp
- stosw
- sub ax,ax
- JmpReturn:
- pop bp
- ret far 4
- public AsmLib$LongJmp :
- add sp,4 (* remove return *)
- pop ax (* return value *)
- pop si (* buffer *)
- pop ds
- mov sp,[si][6]
- push ss
- pop es
- mov di,sp
- movsw
- movsw
- movsw
- jmp JmpReturn
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$ScanR : d_seg=12; d_ofs=10; len=8; val=6
- push bp; mov bp,sp
- push es; push di
- mov cx,[bp][len]
- jcxz ExitScan
- les di,[bp][d_ofs]
- mov ax,[bp][val]
- repne
- scasb
- jne ExitScan
- inc cx
- ExitScan:
- mov ax,[bp][len]
- sub ax,cx
- pop di; pop es
- pop bp; ret far 8
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$ScanL : d_seg=12; d_ofs=10; len=8; val=6
- push bp; mov bp,sp
- push es; push di;
- mov cx,[bp][len]
- jcxz ExitScan
- les di,[bp][d_ofs]
- mov ax,[bp][val]
- std
- repne
- scasb
- cld
- jne ExitScan
- inc cx
- ExitScan:
- mov ax,[bp][len]
- sub ax,cx
- pop di; pop es
- pop bp; ret far 8
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$ScanNeR : d_seg=12; d_ofs=10; len=8; val=6
- push bp; mov bp,sp
- push es; push di
- mov cx,[bp][len]
- jcxz ExitScan
- les di,[bp][d_ofs]
- mov ax,[bp][val]
- repe
- scasb
- je ExitScan
- inc cx
- ExitScan:
- mov ax,[bp][len]
- sub ax,cx
- pop di; pop es
- pop bp; ret far 8
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$ScanNeL : d_seg=12; d_ofs=10; len=8; val=6
- push bp; mov bp,sp
- push es; push di
- mov cx,[bp][len]
- jcxz ExitScan
- les di,[bp][d_ofs]
- mov ax,[bp][val]
- std
- repe
- scasb
- cld
- je ExitScan
- inc cx
- ExitScan:
- mov ax,[bp][len]
- sub ax,cx
- pop di; pop es
- pop bp; ret far 8
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Compare : s_seg=14; s_ofs=12; d_seg=10; d_ofs=8; len=6
- push bp; mov bp,sp
- push ds; push es; push si; push di
- mov cx,[bp][len]
- jcxz ExitScan
- lds si,[bp][s_ofs]
- les di,[bp][d_ofs]
- repe
- cmpsb
- je ExitScan
- inc cx
- ExitScan:
- mov ax,[bp][len]
- sub ax,cx
- pop di; pop si; pop es; pop ds;
- pop bp; ret far 10
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Sound : FreqHz=6
- (*ROM
- Generate sounds via the speaker. The machine may not have a speaker, or it
- may be accessed in a different way.
- *)
- push bp; mov bp,sp
- mov bx,[bp][FreqHz]
- mov ax,34DDH (* 1.193181 MHz *)
- mov dx,0012H
- cmp dx,bx
- jnb SOU9
- div bx
- mov bx,ax
- in al,PPIport+1
- test al,03H
- jnz SOU1
- or al,03H
- out PPIport+1,al
- (* 10 11 011 0 *)
- mov al,0B6H (* Select timer 2, LSB,MSB, mode 3, bin *)
- out Timer+3,al
- SOU1:
- mov al,bl
- out Timer+2,al
- mov al,bh
- out Timer+2,al
- SOU9:
- pop bp; ret far 2
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$NoSound :
- (*ROM
- Stop producing sound via the speaker. See the above comments.
- *)
- in al,PPIport+1
- and al,0FCH
- out PPIport+1,al
- ret far 0
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Speaker : TotalTime=10; OnTime=8; OffTime=6
- (*ROM
- Generate sounds via the speaker. See the above comments.
- *)
- push bp; mov bp,sp
- in al,KBCtrl
- push ax
- mov bx,TotalTime
- $MainLoop:
- and al,0FCH
- jmp $Next
- $Next:
- out KBCtrl,al
- mov cx,OffTime
- $OffLoop:
- loop $OffLoop
- or al,2
- out KBCtrl,al
- mov cx,OnTime
- $OnLoop:
- loop $OnLoop
- dec bx
- jnz $MainLoop
- pop ax
- out KBCtrl,al
- ret far 6
- section;
- segment D_DATA(M_DATA,28H)
- segment INITCODE(CODE,28H)
- segment C_CODE(CODE,28H)
- group G_CODE(INITCODE,C_CODE)
- select D_DATA
- @DelayFactor : org 2
- Iter : org 2
- Count : org 2
- Semaphor : org 2
- select C_CODE
- extrn @D_DATA
- public AsmLib$Delay : p_time=6
- push bp; mov bp,sp; push ds
- mov ax, [bp][p_time]
- mov ds, cs:[@D_DATA]
- mov ds:[Iter], ax
- MoreDelay:
- cmp word ds:[Iter],0
- jz DelayEnd
- mov ax,ds:[@DelayFactor]
- mov ds:[Count],ax
- Here:
- mov ax, ds:[Count]
- or ax,ax
- jz Here2
- dec word ds:[Count]
- jmp Here
- Here2:
- dec word ds:[Iter]
- jmp MoreDelay
- DelayEnd:
- pop ds; pop bp; ret far 2
- (* the Int 1C ISR, installed below *)
- TimeTrap:
- push ds
- mov ds, cs:[@D_DATA]
- inc word ds:[Semaphor] (* used when establishing delay factor *)
- pop ds
- iret
- select INITCODE
- (* calibrate timer *)
- (*ROM
- (*INT8*)
- This routine uses the INT 1C hardware tick, instead of the INT 8 user timer
- tick. It relies on the hardware tick happening at the rate defined for
- PC's.
- *)
- xor ax,ax
- mov es,ax
- push es:[70H]
- push es:[72H]
- mov ds, cs:[@D_DATA]
- mov word ds:[Semaphor],0
- mov word ds:[@DelayFactor],55
- mov word ds:[Iter],0
- mov word ds:[Count],0
- cli
- mov word es:[70H],TimeTrap
- mov es:[72H],cs
- sti
- Estab1:
- cmp word ds:[Semaphor],2
- jne Estab1
- Estab2:
- cmp word ds:[Semaphor],3
- jz Estab5
- mov ax,ds:[@DelayFactor]
- mov ds:[Count],ax
- Estab3:
- mov ax,ds:[Count]
- or ax,ax
- jz Estab4
- dec word ds:[Count]
- jmp Estab3
- Estab4:
- inc word ds:[Iter]
- jmp Estab2
- Estab5:
- cli
- pop es:[72H]
- pop es:[70H]
- sti
- mov ax,ds:[Iter]
- mov ds:[@DelayFactor],ax
- in al,PPIport+1
- and al,0FCH
- out PPIport+1,al
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- axr=0; bxr=2; cxr=4; dxr=6; bpr=8;
- sir=10; dir=12; dsr=14; esr=16; flags=18
- public @LoadRegisters :
- (* loads register in register pack pointed to by DS:SI *)
- push [si][dsr]
- push [si][sir]
- mov ax,[si][axr]
- mov bx,[si][bxr]
- mov cx,[si][cxr]
- mov dx,[si][dxr]
- mov di,[si][dir]
- mov bp,[si][bpr]
- mov es,[si][esr]
- pop si
- pop ds
- ret near 0
- public @SaveRegisters :
- (* saves register in register pack pointed to by pointer on stack *)
- push ds
- push si
- mov si,sp
- lds si,ss:[si][6]
- pushf
- pop [si][flags]
- pop [si][sir]
- pop [si][dsr]
- mov [si][axr],ax
- mov [si][bxr],bx
- mov [si][cxr],cx
- mov [si][dxr],dx
- mov [si][dir],di
- mov [si][bpr],bp
- mov [si][esr],es
- ret near 4
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @D_DATA
- extrn @LoadRegisters
- extrn @SaveRegisters
- extrn @InProgramFlag
- extrn @StopProgramFlag
- extrn AsmLib$FatalError
- msg1 : db 'Fatal error: Dos reentered',0
- public AsmLib$Dos : p_seg=8; p_off=6
- (*ROM
- Perform a DOS call. Since you're in ROM, DOS probably doesn't exist. All
- references to this procedure should be removed.
- *)
- push bp; mov bp,sp
- push ds; push es; push si; push di
- pushf
- mov ds, cs:[@D_DATA]
- cmp byte [@InProgramFlag], 1
- je ok
- cld
- mov ax,100
- push ax
- push cs
- mov ax, msg1
- push ax
- push cs
- call near AsmLib$FatalError
- ok:
- cmp byte [@StopProgramFlag], 1
- je Stop (* wait for timer to stop us *)
- mov byte [@InProgramFlag], 0
- lds si,[bp][p_off]
- push ds (* save register pointer *)
- push si
- call @LoadRegisters
- int 21H
- call @SaveRegisters
- mov ds, cs:[@D_DATA]
- mov byte [@InProgramFlag], 1
- popf
- pop di; pop si; pop es; pop ds
- pop bp; ret far 4
- Stop:
- sti
- jmp Stop
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @LoadRegisters
- extrn @SaveRegisters
- public AsmLib$Intr : p_seg=10; p_off=8; p_num=6
- (*ROM
- Perform a software interrupt. This procedure uses self-modifying code to
- generate an arbitrary interrupt.
- *)
- push bp; mov bp,sp
- push ds; push es; push si; push di
- pushf
- lds si,[bp][p_off]
- push ds (* save register pointer *)
- push si
- mov al,[bp][p_num]
- cli
- mov cs:[InterruptNo],al
- call @LoadRegisters
- db 0CDH (* INT *)
- InterruptNo :
- db 0
- call @SaveRegisters
- popf
- pop di; pop si; pop es; pop ds
- pop bp; ret far 6
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @D_DATA
- extrn @PSP
- public AsmLib$Environment : p_n=6
- (*ROM
- Get an environment string. The environment is set up by DOS, which
- probably doesn't exist.
- *)
- push bp; mov bp,sp
- push ds; push es; push si; push di
- mov ds, cs:[@D_DATA]
- mov ds, [@PSP]
- mov es, ds:[2CH]
- mov di,0
- mov cx,[bp][p_n]
- xor ax,ax
- jcxz EnFound
- cmp byte es:[di],0
- je EnFound
- mov bx,cx
- EnSeMo:
- mov cx,8000H
- repne
- scasb
- cmp es:[di],al
- je EnFound
- dec bx
- jnz EnSeMo
- EnFound:
- mov dx,es
- mov ax,di
- pop di; pop si; pop es; pop ds
- pop bp; ret far 2
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn AsmLib@CommandLine
- comma=44
- space=32
- public AsmLib$ParamStr : p_sl=12; p_sh=10; p_s=8; p_n=6
- (*ROM
- Get an argument from the command line. Since DOS probably doesn't exist,
- there won't be a command line.
- *)
- push bp; mov bp,sp
- push ds; push es; push si; push di
- les di,[bp][p_s]
- mov ax, seg AsmLib@CommandLine
- mov ds,ax
- lds si,ds:[AsmLib@CommandLine]
- mov cx,[bp][p_n]
- jcxz $Finished
- jmp $Loop1
- $Loop:
- lodsb
- cmp al,0
- je $Finished
- cmp al,comma
- je $Loop1
- cmp al,space
- ja $Loop
- (* remove leading separators *)
- $Loop1:
- lodsb
- cmp al,0
- je $Finished
- cmp al,comma
- je $Loop1
- cmp al,space
- jbe $Loop1
- loop $Loop
- mov cx,[bp][p_sl]
- add cx,di
- $Loop2:
- stosb
- cmp di,cx
- je $Exit
- lodsb
- cmp al,0
- je $Finished
- cmp al,comma
- je $Finished
- cmp al,space
- ja $Loop2
- $Finished:
- sub al,al
- stosb
- $Exit:
- pop di; pop si; pop es; pop ds
- pop bp; ret far 8
- public AsmLib$ParamCount :
- (*ROM
- Return the number of arguments on the command line. See the above comment.
- *)
- push di; push si
- push bx
- mov si,sp
- sub di,di
- $Loop3:
- inc di
- mov ax,1
- push ax
- push ss
- push si
- push di
- call far AsmLib$ParamStr
- cmp byte ss:[si],0
- jne $Loop3
- dec di
- mov ax,di
- pop bx
- pop si; pop di
- ret far 0
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Caps : Slen=10; Sseg=8; Sofs=6
- push bp; mov bp,sp
- push ds; push si
- lds si,[bp][Sofs]
- mov cx,[bp][Slen]
- $loop:
- lodsb
- cmp al,97 (* 'a' *)
- jb $notSmall
- cmp al,122 (* 'z' *)
- ja $notSmall
- sub al,32
- mov [si][-1],al
- $notSmall:
- or al,al
- loopnz $loop
- pop si; pop ds
- pop bp; ret far 6
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Length : Slen=10; Sseg=8; Sofs=6
- push bp; mov bp,sp
- push es; push di
- les di,[bp][Sofs]
- mov cx,[bp][Slen]
- sub al,al
- repne
- scasb
- jne ExitLength
- inc cx
- ExitLength:
- mov ax,[bp][Slen]
- sub ax,cx
- pop di; pop es
- pop bp; ret far 6
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$CompareStr : S1len=16; S1seg=14; S1ofs=12; S2len=10; S2seg=8; S2ofs=6
- push bp; mov bp,sp
- push ds; push si; push es; push di
- lds si,[bp][S1ofs]
- les di,[bp][S2ofs]
- mov bx,[bp][S1len]
- mov dx,[bp][S2len]
- mov cx,bx
- cmp cx,dx
- jb CompareLoop
- mov cx,dx
- CompareLoop:
- lodsb
- scasb
- jne NotEqual
- or al,al
- loopne CompareLoop
- je Equal
- cmp bx,dx
- je Equal
- ja CheckSi
- cmp byte es:[di],0
- je Equal
- Less:
- mov ax,-1
- jmp Return
- CheckSi:
- cmp byte [si],0
- je Equal
- Greater:
- mov ax,1
- jmp Return
- NotEqual:
- cmp al,es:[di][-1]
- jb Less
- jmp Greater
- Equal:
- sub ax,ax
- Return:
- pop di; pop es; pop si; pop ds
- pop bp; ret far 12
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Concat : NSlen=22; NSseg=20; NSofs=18; S1len=16; S1seg=14; S1ofs=12; S2len=10; S2seg=8; S2ofs=6
- push bp; mov bp,sp
- push ds; push si; push es; push di
- mov cx,[bp][S2len]
- sub sp,cx
- lds si,[bp][S2ofs]
- push ss
- pop es
- mov di,sp
- rep
- movsb
- mov bx,[bp][NSlen]
- lds si,[bp][S1ofs]
- les di,[bp][NSofs]
- mov cx,[bp][S1len]
- CopyLoop1:
- lodsb
- or al,al
- jz Finished1
- stosb
- dec bx
- loopnz CopyLoop1
- jz Exit
- Finished1:
- push ss
- pop ds
- mov si,sp
- mov cx,[bp][S2len]
- CopyLoop2:
- lodsb
- stosb
- or al,al
- jz Exit
- dec bx
- loopnz CopyLoop2
- jz Exit
- sub al,al
- stosb
- Exit:
- add sp,[bp][S2len]
- pop di; pop es; pop si; pop ds
- pop bp; ret far NSlen-4
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Append : NSlen=16; NSseg=14; NSofs=12; Slen=10; Sseg=8; Sofs=6
- push bp; mov bp,sp
- push ds; push si; push es; push di
- les di,[bp][NSofs]
- mov cx,[bp][NSlen]
- sub al,al
- repne
- scasb
- jne Exit
- dec di
- mov bx,cx
- inc bx
- lds si,[bp][Sofs]
- mov cx,[bp][Slen]
- CopyLoop:
- lodsb
- stosb
- or al,al
- jz Exit
- dec bx
- loopnz CopyLoop
- jz Exit
- sub al,al
- stosb
- Exit:
- pop di; pop es; pop si; pop ds
- pop bp; ret far NSlen-4
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Copy : NSlen=16; NSseg=14; NSofs=12; Slen=10; Sseg=8; Sofs=6
- push bp; mov bp,sp
- push ds; push si; push es; push di
- les di,[bp][Sofs]
- mov cx,[bp][Slen]
- sub al,al
- repne
- scasb
- jne LengthCalc
- inc cx
- LengthCalc:
- mov ax,[bp][Slen]
- sub ax,cx
- mov cx,[bp][NSlen]
- cmp ax,cx
- ja SourceBigger
- mov cx,ax
- SourceBigger:
- lds si,[bp][ Sofs]
- les di,[bp][NSofs]
- rep
- movsb
- jae Exit
- sub al,al
- stosb
- Exit:
- pop di; pop es; pop si; pop ds
- pop bp; ret far NSlen-4
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Slice : NSlen=20; NSseg=18; NSofs=16; Slen=14; Sseg=12; Sofs=10; P=8; L=6
- push bp; mov bp,sp
- push ds; push si; push es; push di
- les di,[bp][Sofs]
- mov cx,[bp][Slen]
- sub al,al
- repne
- scasb
- jne LengthCalc
- inc cx
- LengthCalc:
- mov ax,[bp][Slen]
- sub ax,cx
- mov bx,[bp][P]
- sub ax,bx
- ja NotBeyondEnd
- sub ax,ax
- NotBeyondEnd:
- cmp ax,[bp][L]
- jb OffEnd
- mov ax,[bp][L]
- OffEnd:
- lds si,[bp][Sofs]
- add si,[bp][P]
- mov cx,[bp][NSlen]
- cmp ax,cx
- ja SourceBigger
- mov cx,ax
- SourceBigger:
- les di,[bp][NSofs]
- rep
- movsb
- jae Exit
- sub al,al
- stosb
- Exit:
- pop di; pop es; pop si; pop ds
- pop bp; ret far NSlen-4
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- public AsmLib$Pos : Slen=16; Sseg=14; Sofs=12; Plen=10; Pseg=8; Pofs=6
- push bp; mov bp,sp
- push ds; push si; push es; push di
- les di,[bp][Sofs]
- mov cx,[bp][Slen]
- mov bx,cx
- sub al,al
- repne
- scasb
- jne LengthCalc1
- inc cx
- LengthCalc1:
- sub bx,cx
- les di,[bp][Pofs]
- mov cx,[bp][Plen]
- mov dx,cx
- sub al,al
- repne
- scasb
- jne LengthCalc2
- inc cx
- LengthCalc2:
- sub dx,cx
- sub bx,dx
- jb NotFound
- mov ds,[bp][Sseg]
- sub ax,ax
- SearchLoop:
- mov si,[bp][Sofs]
- add si,ax
- mov di,[bp][Pofs]
- mov cx,dx
- repe
- cmpsb
- je Found
- inc ax
- cmp ax,bx
- jbe SearchLoop
- NotFound:
- mov ax,0FFFFH
- Found:
- Exit:
- pop di; pop es; pop si; pop ds
- pop bp; ret far Slen-4
- section ;
- segment D_DATA(M_DATA,28H); segment C_CODE(CODE,28H); group G_CODE(C_CODE);
- (*ROM
- These values are for direct-memory access to the screen memory.
- *)
- ColorStatusReg =03DAH (* port value for color status register *)
- ColorRetrace =1 (* mask in color status for horiz. retrace *)
- ColorVertRetrace =8 (* mask in color status for vert. retrace *)
- extrn @D_DATA
- select D_DATA
- public AsmLib@ActivePage : org 1
- public AsmLib@IsColor : org 1
- public AsmLib@IsSnow : org 1
- select C_CODE
- public AsmLib@BWSeg : dw 0B000H
- public AsmLib@ColorSeg : dw 0B800H
- public AsmLib$BufferWrite : BuffH=16; BuffL=14; StrH=12; StrL=10; Len=8; Attr=6
- push bp; mov bp,sp
- push ds; push es; push si; push di
- mov cx,[bp][Len]
- jcxz $Exit
- mov bx,[bp][Attr]
- lds si,[bp][StrL]
- les di,[bp][BuffL]
- LDoWrite:
- cld
- mov ah,bl
- LWriteLoop:
- lodsb
- stosw
- loop LWriteLoop
- $Exit:
- pop di; pop si; pop es; pop ds
- pop bp; ret far BuffH-4
- public AsmLib$PalXlat : ToH=18; ToL=16; FromH=14; FromL=12; Len=10; PalH=8; PalL=6
- push bp; mov bp,sp
- push ds; push es; push si; push di
- mov cx,[bp][Len]
- jcxz PXExit
- sub sp,10
- mov di,sp
- (* copy pallette onto stack *)
- lds si,[bp][PalL]
- push ss
- pop es
- mov cx,5
- rep
- movsw
- mov bx,sp
- lds si,[bp][FromL]
- les di,[bp][ToL]
- mov cx,[bp][Len]
- PXloop:
- lodsw
- xchg al,ah
- db 36H (* ss override for xlat *)
- xlat
- xchg al,ah
- stosw
- loop PXloop
- add sp,10
- PXExit:
- pop di; pop si; pop es; pop ds
- pop bp; ret far ToH-4
- public AsmLib$BufferToScreen : X=14; Y=12; SourceH=10; SourceL=8; Len=6
- push bp; mov bp,sp
- push ds; push es; push si; push di
- lds si,[bp][SourceL]
- mov ax,[bp][Y]
- mov di,[bp][X]
- mov cl,4
- shl ax,cl (* 16Y *)
- add di,ax
- shl ax,1
- shl ax,1
- add di,ax (* +64Y=80Y *)
- shl di,1
- mov cx,[bp][Len]
- mov es,cs:[AsmLib@BWSeg]
- push ds
- mov ds, cs:[@D_DATA]
- cmp byte [AsmLib@IsColor],True
- jne BtsIsBW
- cmp byte [AsmLib@IsSnow],True
- mov es,cs:[AsmLib@ColorSeg]
- jne BtsNoSnowMove
- pop ds
- pushf
- mov dx,ColorStatusReg
- mov bl,1
- cld
- sti
- push bp
- BtsLoop:
- lodsw
- mov bp,ax
- BtsWaitNotHoriz:
- in al,dx
- rcr al,1
- jc BtsWaitNotHoriz
- cli
- BtsWait:
- in al,dx
- rcr al,1
- jnc BtsWait
- xchg ax,bp
- stosw
- sti
- loop BtsLoop
- pop bp
- popf
- jmp BtsRet
- BtsNoSnowMove:
- BtsIsBW:
- pop ds
- cld
- rep
- movsw
- BtsRet:
- pop di; pop si; pop es; pop ds
- pop bp; ret far X-4
- public AsmLib$ScreenToBuffer : X=14; Y=12; DestH=10; DestL=8; Len=6
- push bp; mov bp,sp
- push ds; push es; push si; push di
- les di,[bp][DestL]
- mov ax,[bp][Y]
- mov si,[bp][X]
- mov cl,4
- shl ax,cl (* 16Y *)
- add si,ax
- shl ax,1
- shl ax,1
- add si,ax (* +64Y=80Y *)
- shl si,1
- mov cx,[bp][Len]
- mov ds, cs:[@D_DATA]
- cmp byte [AsmLib@IsColor],True
- mov ds, cs:[AsmLib@BWSeg]
- jne StbIsBW
- mov ds, cs:[@D_DATA]
- cmp byte [AsmLib@IsSnow],True
- mov ds, cs:[AsmLib@ColorSeg]
- jne StbNoSnowMove
- pushf
- mov dx,ColorStatusReg
- add cx,cx (* bytes *)
- mov bl,1
- cld
- StbLoop:
- StbWaitNotHoriz:
- in al,dx
- rcr al,1
- jc StbWaitNotHoriz
- cli
- StbWait:
- in al,dx
- rcr al,1
- jnc StbWait
- movsb
- sti
- loop StbLoop
- popf
- jmp StbRet
- StbNoSnowMove:
- StbIsBW:
- cld
- rep
- movsw
- StbRet:
- pop di; pop si; pop es; pop ds
- pop bp; ret far X-4
- public AsmLib$SetVideoPage : NewPage=6
- push bp; mov bp,sp; push ds
- mov ax,[bp][NewPage]
- mov ds, cs:[@D_DATA]
- mov [AsmLib@ActivePage],al
- mov ah,5
- push bp
- int 10H
- pop bp
- mov ax,[bp][NewPage]
- mov bx,100H
- mul bx
- add ax,0B800H
- mov cs:[AsmLib@ColorSeg],ax
- pop ds; pop bp; ret far NewPage-4
- public AsmLib$ActivePage :
- push ds
- mov ds, cs:[@D_DATA]
- mov al, [AsmLib@ActivePage]
- cbw
- pop ds; ret far 0
- (* initialize screen type *)
- public AsmLib$InitScreenType : IsSnow=6
- push bp; mov bp,sp
- push ds; push es; push si; push di
- mov ds, cs:[@D_DATA]
- mov byte [AsmLib@IsColor],True
- mov byte [AsmLib@ActivePage],0
- mov ah,15
- push bp
- int 10H
- pop bp
- cmp al,7
- jne LIsColor
- mov byte [AsmLib@IsColor],False
- LIsColor:
- mov ax,[bp][IsSnow]
- mov [AsmLib@IsSnow],al
- pop di; pop si; pop es; pop ds
- pop bp; ret far 2
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- SaveSS : dw 0
- SaveSP : dw 0
- public AsmLib$DosExec : NameLen=14; NameSeg=12; NameOfs=10; ParamSeg=8; ParamOfs=6
- (*ROM
- Execute a DOS program. Even if, for some very strange reason, a ROMmed
- program could call this, it wouldn't work - this procedure needs to alter
- certain values in the code segment (which is presumably ROM).
- *)
- push bp; mov bp,sp
- push ds; push es; push si; push di
- pushf
- mov ax,4B00H
- mov ds,[bp][NameSeg]
- mov dx,[bp][NameOfs]
- mov es,[bp][ParamSeg]
- mov bx,[bp][ParamOfs]
- push bp
- push ss:[2EH] (* where DOS doth tread *)
- push ss:[30H]
- push cs:[SaveSS] (* to restore code seg *)
- push cs:[SaveSP]
- mov cs:[SaveSS],ss
- mov cs:[SaveSP],sp
- int 21H
- mov ss,cs:[SaveSS]
- mov sp,cs:[SaveSP]
- pop cs:[SaveSP]
- pop cs:[SaveSS]
- pop ss:[30H]
- pop ss:[2EH]
- pop bp
- jc ExitExec
- sub ax,ax
- ExitExec:
- popf
- pop di; pop si; pop es; pop ds
- pop bp; ret far NameLen-4
- section ; segment C_CODE(CODE,28H); group G_CODE(C_CODE); select C_CODE
- extrn @D_DATA
- extrn @InProgramFlag
- public AsmLib$SetInProgramFlag : on=6
- push bp; mov bp,sp; push ds
- mov al, [bp][on]
- mov ds, cs:[@D_DATA]
- mov [@InProgramFlag], al
- pop ds; pop bp; ret far 2
- public AsmLib$GetInProgramFlag :
- push ds
- sub ah,ah
- mov ds, cs:[@D_DATA]
- mov al, [@InProgramFlag]
- pop ds
- ret far 0
- section
- extrn @D_DATA
- extrn @PSP
- segment INITCODE(CODE,28H); group G_CODE(INITCODE)
- segment D_DATA(M_DATA,28H);
- select D_DATA
- public AsmLib@CommandLine : org 4
- public AsmLib@PSP : org 2
- select INITCODE
- (*ROM
- All of this initialization deals with the PSP and command line. It should
- be safe to just comment it out.
- *)
- (* set up PSP and command line *)
- mov ds, cs:[@D_DATA]
- mov ds, [@PSP]
- mov ax, D_DATA
- mov es, ax
- mov es:[AsmLib@PSP],ds
- mov es:[AsmLib@CommandLine][2],ds
- mov word es:[AsmLib@CommandLine],81H
- (* make command line into asciiz string *)
- mov byte bl,ds:[80H] (* make it a asciiz string *)
- xor bh,bh
- add bx,81H
- mov byte [bx],0
- mov bx,81H
- again:
- cmp byte [bx],0
- je EndFound
- cmp byte [bx],32 (* skip blanks *)
- jne StartFound
- inc bx
- jmp again
- EndFound:
- StartFound:
- mov es:[AsmLib@CommandLine],bx
- end
|