home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d429
/
v
/
v.a
< prev
next >
Wrap
Text File
|
1991-01-10
|
12KB
|
489 lines
;;; REMOVE DISK LOADING OF MORE
; This is an entirely new version of V, the front end for Commodore's More.
; The old version ran More as a Workbench process, even when V was run from
; CLI, so that More would always open its own window. This version always
; runs More as a CLI process, even when run from Workbench. The reason for
; the change is that this way V can open More's window, and you can specify
; which window V will use with the environment variable MOREWINDOW (the
; default is "CON:0/0/640/200/More"), and also More's "E" command, which makes
; it pass the current file to the program in the environment variable EDITOR,
; only works when More is a CLI process. (Note that it does NOT work when
; you run More (or V) with no argument, and it asks for a file and you tell
; it. There is a bug in More that makes it think the name of the file it's
; showing is the same as the command in ENV:EDITOR. Also the E command
; is not available when More is displaying from its standard input.) This
; version of V runs More as part of its own process, and does not use the
; Execute() function. This makes it more efficient at a slight cost in size.
; It is written in assembly to make it as small as possible, to minimize disk
; loading time when it is run from workbench, because the workbench can't use
; a resident copy of V (yes, it's pure). Since V can use a resident copy of
; More, the workbench doesn't have to load that. If More is not resident V
; will look for C:More or SYS:Utilities/More. Maybe I should have an
; environment variable for that too?
; V is by Paul Kienitz and is in the public domain. I assembled it with the
; Aztec 5.0 assembler, but it should be compatible with other Amiga
; assemblers. Requires no link libraries. Use Aztec's -n one pass option.
; Last update 12/24/90.
include "exec/types.i"
include "exec/memory.i"
include "exec/ports.i"
include "workbench/startup.i"
include "libraries/dosextens.i"
fdef: macro
_LVO\1 equ -\2
endm
; exec funcs:
fdef Forbid,132
fdef AllocMem,198
fdef FreeMem,210
fdef FindTask,294
fdef GetMsg,372
fdef ReplyMsg,378
fdef WaitPort,384
fdef CloseLibrary,414
fdef OpenLibrary,552
; DOS funcs:
fdef Open,30
fdef Close,36
fdef Read,42
fdef Write,48
fdef LoadSeg,150
fdef UnLoadSeg,156
fdef Delay,198
; I found a mistake in Aztec's c.lib in version 5.0d: all the dos.library
; offsets (_LVO...) are accidentally defined as positive numbers! oooooops
; ... the mistake did not exist in 3.6a ... oh well, we make our own _LVO's.
callib: macro
jsr _LVO\1(a6)
endm
callx: macro
move.l 4,a6
callib \1
endm
calld: macro
move.l dosbase,a6
callib \1
endm
; a node on the resident program list:
STRUCTURE theResidents,0
BPTR next
LONG usecount
BPTR seglist
UBYTE namelength
BYTE name ; first char of var-length array
; local vars on the main program stack frame:
STRUCTURE mainargs,0
STRUCT newa,300 ; char [300]
CPTR wbm ; workbench startup message
LONG ret ; our program return code
CPTR cli ; struct CommandLineInterface
LABEL main_sizeof
winf equr d5 ; window filehandle
mos equr d6 ; seglist of More if from disk
alen equr d7 ; length of cmd argument line
aptr equr a2 ; ptr to cmd argument line
me equr a3 ; this process
rezzy equr a4 ; struct theResidents
; rezzy is also temporarily used to point to our process's MsgPort
dosbase equr a5 ; dos.library base
; note: we follow a convention that you can trash regs d0-d4/a0/a1/a6.
; for debugging:
xdef BEGIN,Start,dosname,morename,umorename,exit
xdef ewinname,defaultwin,loaderrmsg,warnmsg
xdef winerrmsg,makeCLI,doQuotes,runit,unLoad
xdef GO_FER_IT,FindResiProg,CBsame,OpenWin,Mash
xdef cmorename,emptyarg,MeasureAptr,getMore,notWB
BEGIN: bra Start ;;; ENTRY POINT
dosname: dc.b "dos.library",0
morename: dc.b "More",0
umorename: dc.b "SYS:Utilities/More",0
cmorename: dc.b "C:More",0
ewinname: dc.b "ENV:MOREWINDOW",0
defaultwin: dc.b "CON:0/0/640/200/More",0
emptyarg: dc.b 0
loaderrmsg: dc.b "Can't find More in resident list, "
dc.b "SYS:Utilities, or C:.",10,0
loaderrlength equ 56
warnmsg: dc.b 10,"*** Remember, DO NOT use the 'E' "
dc.b "command this time!",10,0
warnlength equ 54
winerrmsg: dc.b "Couldn't open window!",10,0
winerrlength equ 22
; =================== here we go!
Start: lea -main_sizeof(sp),sp
move.l d0,alen
move.l a0,aptr
lea dosname,a1
moveq #0,d0
callx OpenLibrary
move.l d0,dosbase
clr.l ret(sp)
clr.l wbm(sp)
sub.l a1,a1
callx FindTask
move.l d0,me
add.l #pr_MsgPort,d0
move.l d0,rezzy
tst.l pr_CLI(me)
bne notWB
move.l rezzy,a0
callx WaitPort
move.l rezzy,a0
callib GetMsg
move.l d0,wbm(sp)
notWB: bsr OpenWin
move.l d0,winf
lea morename,a1
bsr FindResiProg
move.l d0,rezzy
tst.l pr_CLI(me)
beq makeCLI
move.l pr_CLI(me),d0
asl.l #2,d0
move.l d0,cli(sp)
bra doQuotes
makeCLI: tst.l winf
beq ret10
move.l #cli_SIZEOF,d0
move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
callx AllocMem
move.l d0,cli(sp)
beq ret10
move.l d0,a0
move.l #1000,cli_DefaultStack(a0)
asr.l #2,d0
move.l d0,pr_CLI(me)
move.l winf,pr_COS(me)
lea emptyarg,aptr
move.l wbm(sp),a0
cmp.l #1,sm_NumArgs(a0)
ble emptyWBarg
move.l sm_ArgList(a0),a0
addq #wa_SIZEOF,a0
move.l wa_Lock(a0),pr_CurrentDir(me)
move.l wa_Name(a0),aptr
emptyWBarg: bsr MeasureAptr
bra doQuotes
ret10: move.l #10,ret(sp)
bra doQuotes
doQuotes: lea newa(sp),a0
bsr Mash
lea newa(sp),aptr
bsr MeasureAptr
tst.l winf
beq getMore
tst.l alen
bne getMore
move.l pr_CIS(me),d0
move.l cli(sp),a0
cmp.l cli_StandardInput(a0),d0
bne getMore
move.l winf,d1
lea warnmsg,a0
move.l a0,d2
move.l #warnlength,d3
calld Write
getMore: move.l rezzy,d0 ; tst.l rezzy
bne bumpCount
lea umorename,a0 ; load More
move.l a0,d1
calld LoadSeg
move.l d0,mos
bne runit
lea cmorename,a0
move.l a0,d1
callib LoadSeg
move.l d0,mos
bne runit
tst.l pr_COS(me) ; Can't load it!
beq fail10
moveq #loaderrlength,d3
lea loaderrmsg,a0
move.l a0,d2
move.l pr_COS(me),d1
callib Write
fail10: move.l #10,ret(sp)
bra runit
bumpCount: move.l seglist(rezzy),mos
tst.l usecount(rezzy)
ble runit ; >= 1 means addable
addq.l #1,usecount(rezzy) ; bump use count
runit: tst.l winf
beq winErr
tst.l ret(sp)
bne winErr
move.l cli(sp),a0
bsr GO_FER_IT
move.l d0,ret(sp)
bra releaseIt
winErr: tst.l pr_COS(me)
beq nouh
move.l pr_COS(me),d1
lea winerrmsg,a0
move.l a0,d2
move.l #winerrlength,d3
calld Write
nouh: move.l #10,ret(sp)
releaseIt: move.l rezzy,d0 ; tst.l rezzy
beq unLoad
cmp.l #1,usecount(rezzy)
ble flee
subq.l #1,usecount(rezzy)
bra flee
unLoad: move.l mos,d1
calld UnLoadSeg
flee: tst.l wbm(sp)
beq exit
tst.l cli(sp)
beq noCLIf
move.l cli(sp),a1
move.l #cli_SIZEOF,d0
callx FreeMem
noCLIf: callx Forbid
move.l wbm(sp),a1
callib ReplyMsg
exit: move.l ret(sp),d0
lea main_sizeof(sp),sp
rts
; ====== this function actually runs More. It returns More's return code.
; a0 contains pointer to our struct CommandLineInterface.
savregs reg a2-a6/d2-d7
GO_FER_IT: move.l pr_CIS(me),-(sp)
move.l pr_COS(me),-(sp)
move.l cli_StandardInput(a0),-(sp)
move.l pr_ConsoleTask(me),-(sp)
move.l a0,-(sp)
move.l winf,pr_COS(me)
move.l winf,d0
asl.l #2,d0
move.l d0,a1
move.l fh_Type(a1),pr_ConsoleTask(me)
move.l cli_StandardInput(a0),d0
cmp.l pr_CIS(me),d0
bne piped
move.l winf,cli_StandardInput(a0)
move.l winf,pr_CIS(me)
piped: movem.l savregs,-(sp)
lea pr_ReturnAddr(me),a5
move.l (a5),-(sp) ; old pr_ReturnAddr value
move.l a5,-(sp) ; pr_ReturnAddr address
pea 3000 ; stack size for More
move.l sp,(a5) ; new pr_ReturnAddr
move.l mos,d1 ; seglist
asl.l #2,d1
move.l d1,a3
move.l alen,d0
move.l aptr,a0
jsr 4(a3) ; More's entry point!
addq #4,sp ; pop stack size
move.l (sp)+,a5 ; get pr_ReturnAddr ptr
move.l (sp)+,(a5) ; restore old value
movem.l (sp)+,savregs
move.l d0,d4 ; More's return code
beq jesfine
move.l #75,d1
calld Delay
jesfine: move.l winf,d1
calld Close
move.l (sp)+,a0
move.l (sp)+,pr_ConsoleTask(me)
move.l (sp)+,cli_StandardInput(a0)
move.l (sp)+,pr_COS(me)
move.l (sp)+,pr_CIS(me)
move.l d4,d0
rts
; ====== this procedure sets alen to be the strlen of aptr.
MeasureAptr: move.l aptr,a0
nextaptr: tst.b (a0)+
bne.s nextaptr
sub.l aptr,a0
subq.l #1,a0
move.l a0,alen
rts
; ====== this procedure re-makes the argline with quotes around it.
; a0 points to buffer space for new line.
Mash: move.l aptr,a1
add.l alen,a1
subq.l #1,a1
trim: cmp.l aptr,a1
blt trimDone
cmp.b #' ',(a1)
bhi trimDone ; unsigned char compare
subq #1,a1
bra trim
trimDone: sub.l aptr,a1
addq.l #1,a1
move.l a1,alen
beq nuthin
move.b #'"',(a0)+
move.l aptr,a1
move.l alen,d0
tram: beq nuthin
cmp.b #'*',(a0)
beq starit
cmp.b #'"',(a0)
bne nostar
starit: move.b #'*',(a0)+
nostar: move.b (a1)+,(a0)+
subq #1,d0
bra tram
nuthin: clr.b (a0)
rts
; ====== this function opens the window and returns the file handle.
bufsize equ 100
OpenWin: lea -bufsize(sp),sp
move.l pr_WindowPtr(me),d4
move.l #-1,pr_WindowPtr(me)
move.l #MODE_OLDFILE,d2
lea ewinname,a0
move.l a0,d1
calld Open
move.l d4,pr_WindowPtr(me)
tst.l d0
beq default
move.l d0,d4 ; read environment var value
move.l d4,d1
move.l sp,d2 ; result goes on stack
move.l #bufsize,d3
callib Read
move.l d0,-(sp)
move.l d4,d1
callib Close
move.l (sp)+,d0
ble default
cmp.l #bufsize,d0 ; value too long for buffer?
bge default
move.l sp,a0
clr.b 0(a0,d0) ; make it nul terminated
bra openIt
default: lea defaultwin,a0
openIt: move.l a0,d1
move.l #MODE_OLDFILE,d2
callib Open
lea bufsize(sp),sp
rts
; ====== this function tests whether a resident node has a given name.
; a0 = (struct theResidents *), a1 = (char *), returns a zero byte if the
; name of the resident node is the same as the string, ignoring case.
CBsame: move.b namelength(a0),d2
lea name(a0),a0
loupe: move.b (a1)+,d0 ; toupper(string[x])
cmp.b #'a',d0
blt notLow1
cmp.b #'z',d0
bgt notLow1
sub.b #'a'-'A',d0
notLow1: move.b (a0)+,d1 ; toupper(name[x])
cmp.b #'a',d1
blt notLow2
cmp.b #'z',d1
bgt notLow2
sub.b #'a'-'A',d1
notLow2: cmp.b d0,d1
beq continu
moveq #-1,d0 ; names are different
rts
continu: subq.b #1,d2
beq dunne
tst.b (a1)
bne loupe
dunne: move.b (a1),d0
or.b d2,d0 ; do lengths match?
rts
; ====== this function returns the resident node of More, if it exists.
; a1 points to name, return value is pointer to struct theResidents.
FindResiProg: move.l a1,d3
move.l dosbase,a0
move.l dl_Root(a0),a0
move.l rn_Info(a0),d0
asl.l #2,d0
move.l d0,a0
move.l di_NetHand(a0),d0
asl.l #2,d0
move.l d0,a0 ; the resident segment list
ooop: move.l a0,d4
bsr CBsame
move.l d4,a0
move.l d3,a1
tst.b d0
bne agin
move.l a0,d0 ; found it!
rts
agin: move.l next(a0),d0
asl.l #2,d0
move.l d0,a0
tst.l d0
bne ooop
rts ; didn't find it, return 0