473 lines
16 KiB
Plaintext
473 lines
16 KiB
Plaintext
|
|
===============================
|
|
Writing Nifty List 3.4p Modules
|
|
|
|
David A. Lyons 17-Oct-91
|
|
===============================
|
|
|
|
This is sketchy documatation for writing your own modules. Along with
|
|
the sample module, hopefully it's enough to get you started.
|
|
|
|
|
|
-------------------------------------------------------
|
|
Using Nifty List Services from Outside a Command Module
|
|
-------------------------------------------------------
|
|
Many Nifty List service calls can be made from outside of Nifty List
|
|
command modules. But if you're not a module, you need a special way to
|
|
determine the Nifty List service address. Here it is:
|
|
|
|
1. Call MessageByName with
|
|
createFlag=0
|
|
input record = $1F "DAL Systems: Nifty List service"
|
|
|
|
2. Pass the resulting Message type to MessageCenter, along
|
|
with action=2 (get message) and a new handle you've
|
|
created with NewHandle. MessageCenter sizes and fills in
|
|
your handle. The address of the Nifty List service routine
|
|
is at offset $28 in the handle (it's the only thing in
|
|
there besides the system overhead and the name string).
|
|
|
|
Starting with Nifty List 3.3, there is another way to ask Nifty List
|
|
to do things if you are running under System 6: Call SendRequest
|
|
by name to "DAL Systems~Nifty List~" with reqCode = $8000+nlXXXX,
|
|
dataIn = data value for the service, and dataOut = NIL if you don't
|
|
want a result, or a pointer to a 6-byte buffer if you do (first word
|
|
is the recvCount from SendRequest, and the other 4 bytes are the
|
|
service result).
|
|
|
|
------------------------
|
|
Command Module Structure
|
|
------------------------
|
|
A Nifty List command module has the same basic structure as an NDA, so
|
|
it should be possible to write Nifty List modules in common high-level
|
|
languages, as well as in assembly. (Be careful if your compiler is trying
|
|
to be helpful by putting special glue code around some of the entry
|
|
points.)
|
|
|
|
The module's filetype must be $BC, and the auxiliary type must be $4001.
|
|
Modules have to be in the same directory at Nifty List.
|
|
|
|
|
|
------------------
|
|
DAOpen: @infoTable
|
|
------------------
|
|
The module's DAOpen routine returns pointer to the module's info table,
|
|
which has the following format.
|
|
|
|
*
|
|
* Info Record
|
|
*
|
|
InfoRec dc.w InfoEnd-InfoRec ;size of this Info record
|
|
dc.w 0 ;format (use 0)
|
|
dc.w 0 ;patch type (use 0)
|
|
dc.l NLService ;address to patch
|
|
dc.w 12 ;bytes per cmd in cmdTbl (use 12)
|
|
dc.l cmdTbl ;pointer to command table
|
|
InfoEnd
|
|
|
|
The command table looks like this:
|
|
|
|
*
|
|
* Command Table--for each command in this module:
|
|
* +000: pointer to command name (Pascal string)
|
|
* +004: address of command entry point
|
|
* +008: address of help routine
|
|
*
|
|
* (The first entry is for the module itself.)
|
|
*
|
|
cmdTbl dc.l moduleName,0,HelpModule
|
|
dc.l nameOne,cmdOne,helpOne
|
|
dc.l nameShPurge,cmdShPurge,helpShPurge
|
|
dc.l 0
|
|
|
|
For each command there's a pointer to the Pascal-string name, a
|
|
pointer to the command's entry point (which should RTL), and a
|
|
pointer to the command's Help routine (which should display help
|
|
and then RTL).
|
|
|
|
|
|
--------
|
|
DAAction
|
|
--------
|
|
Nifty List calls the DAAction routine with A equal to one of the
|
|
following. X and Y are undefined. You should return A=0 (the
|
|
return value may eventually be used to refuse to shut down, for
|
|
example, but right now you must always return 0 in A).
|
|
|
|
A = actBirth
|
|
Called when Nifty List first loads a module
|
|
|
|
A = actDeath
|
|
Called when Nifty List is about to remove a module
|
|
|
|
A = actEnterNL
|
|
Called when the user enters the Nifty List command environment
|
|
|
|
A = actExitNL
|
|
Called when the user leaves the Nifty List command environment
|
|
|
|
|
|
-------------------------
|
|
NLService(long,code):long
|
|
-------------------------
|
|
Nifty List patches over 4 bytes at the address indicated in the
|
|
module's info record. The module should JSL *to* the patched location
|
|
to call a Nifty List service routine, with parameters on the stack.
|
|
|
|
Every service takes a four-byte input parameter (although some of the
|
|
services ignore part or all of this parameter). Some services also
|
|
return a four-byte result.
|
|
|
|
To call a service with no result space:
|
|
|
|
pha
|
|
phx
|
|
pea nlXXXXXX
|
|
jsl NLService
|
|
|
|
The service removes the long input and the service code from the
|
|
stack before returning (just like a toolbox call would).
|
|
|
|
To call a service that needs result space:
|
|
|
|
pha
|
|
pha ;make room for result
|
|
phx
|
|
phy ;push 4-byte input
|
|
pea nlXXXXXX
|
|
jsl NLService
|
|
ply
|
|
plx ;pull 4-byte result
|
|
|
|
|
|
Here is a list of all the services.
|
|
|
|
|
|
*
|
|
* Environment management
|
|
*
|
|
0000 nlRecover()
|
|
Does not return. Enters Nifty List command level but BRKs when
|
|
you leave. For debugging when you've crashed and need a special
|
|
way to go into Nifty List because you were already in a CDA.
|
|
|
|
0001 nlEnter():result
|
|
Attempts to call Nifty List command level. Returns 0 if
|
|
successful.
|
|
|
|
0002 nlRemoveNL(@WordBuff):Handle
|
|
Data = pointer to 2-byte result buffer (gets ID for UserShutDown),
|
|
Result = handle to feed to RemoveCDA (NIL if can't remove)
|
|
|
|
0003 nlGetInfo(@buffer)
|
|
Data = pointer to 256-byte buffer to receive table; first word =
|
|
length in bytes, including the length count itself.
|
|
Buffer:
|
|
+000 TableSize Word
|
|
+002 nlVersion Long
|
|
+006 nlMemID Word
|
|
+008 nlBusyFlag Word
|
|
+010 CompactFlg Word
|
|
|
|
0004 nlInstallHook(ref,@hook)
|
|
[not implemented]
|
|
This will allow modules to install routines for NL to call at
|
|
certain times.
|
|
|
|
0005 nlRemoveHook(ref,@hook)
|
|
[not implemented]
|
|
|
|
0006 nlGetDirectory():@dirname
|
|
Returns pointer to class-1 string giving name of directory
|
|
Nifty List is executing from. (Don't change the string,
|
|
just use it.)
|
|
|
|
0007 nlNewSession(@callBackProc):sessionRef
|
|
Creates a Nifty List session and returns a long value
|
|
distinguishing the new session from all other sessions.
|
|
|
|
0008 nlKillSession(sessionRef)
|
|
Destroys a Nifty List session that was created with
|
|
nlNewSession.
|
|
|
|
0009 nlSetSession(sessionRef):oldRef
|
|
Makes the specified session the current one, returning
|
|
the old session reference. When you're done doing your
|
|
stuff, call nlSetSession again to restore the old one.
|
|
|
|
CallBack(LongIn,code) (Pascal-style parameters)
|
|
|
|
Code:
|
|
0 = cbWrite = output (LongIn points to word-string)
|
|
2 = cbWriteC = output (LongIn points to a C string)
|
|
4 = cbFlush (output all the output, if you've been saving some)
|
|
6 = cbGetKey (store a key at *LongIn (word) or don't--defaults
|
|
to the "continue" key)
|
|
8 = cbChkAbort (store a $0001 at *LongIn to ask for abort)
|
|
$A = cbAbort (abort, don't return!)
|
|
$C = cbGetString (input into GS/OS result buffer at LongIn)
|
|
|
|
CallBack is called with B and D undefined (must preserve).
|
|
|
|
000A nlWelcome(0)
|
|
Outputs the Nifty List title screen.
|
|
|
|
000B nlLoadStuff(0):error
|
|
Forces the data file to get loaded, if it isn't.
|
|
Input parameter is 0. Result is error code (0 if
|
|
no problem).
|
|
|
|
000C nlGetTextState [NL 3.3]
|
|
[For internal use for now.]
|
|
|
|
000D nlSetTextState [NL 3.3]
|
|
[For internal use for now.]
|
|
|
|
*
|
|
* Information services
|
|
*
|
|
0010 nlGetFirstHandle(Kind):Handle
|
|
Kind = 0, 1, or 2
|
|
Result = first handle in one of the Memory Manager's 3 handle
|
|
chains (0=Used, 1=Purged, 2=Free)
|
|
|
|
0011 nlGetHandleInfo(@info)
|
|
info:
|
|
+000 = handle (Long)
|
|
+004 = @buffer
|
|
What's returned in buffer:
|
|
+000 = count of bytes returned
|
|
+002 = at least 20 bytes of stuff--a copy of the *current*
|
|
format of a Master Pointer record (ptr, attr, id,
|
|
size, previous, next)
|
|
|
|
0012 nlLookup(@stuff)
|
|
Data = pointer to stuff:
|
|
+000: Word Section number to look in (nlSecSysTool, etc)
|
|
+002: Long Data to look up
|
|
+006: Page @outbuffer (256 bytes)
|
|
Returns a pascal string in the output buffer (null string
|
|
means nothing found)
|
|
|
|
0013 nlIndLookup(@stuff)
|
|
Data = pointer to stuff:
|
|
+000: Word Section number to look in (nlSecSysTool, etc)
|
|
+002: Long Index (1=first item in section, etc)
|
|
+006: Page @outbuffer (256 bytes)
|
|
Returned in outbuffer:
|
|
+000: Long Value associated with the Index-th piece of data
|
|
+004: PString String associated with the Index-th piece of data
|
|
(null string if no data found)
|
|
|
|
0014 nlGetProcName(address/4):@procName [NL 3.1]
|
|
Data = address.
|
|
Result = address of Pascal string name associated with the address,
|
|
or NIL if none.
|
|
|
|
0015 nlClassifyAddr(address/4):result [NL 3.3]
|
|
Data = address.
|
|
Low word of result indicates the owner of the address:
|
|
0 = System (for example, ROM or a RAM-based system tool set)
|
|
1 = System-owned toolbox patch (within TSx)
|
|
2 = non-system-owned RAM address
|
|
3 = strange or invalid
|
|
High word of result contains a corresponding ASCII character:
|
|
0 = blank
|
|
1 = "+"
|
|
2 = "*"
|
|
3 = "?"
|
|
|
|
*
|
|
* Utility
|
|
*
|
|
0020 nlScanHandles(@parms)
|
|
parms:
|
|
+000 Word WhichList (0=used handles, 1=purged, 2=free)
|
|
+002 Ptr BankValue Any pointer to desired bank
|
|
+006 Ptr theProc Procedure to call for each handle
|
|
(gets parameter = Handle)
|
|
|
|
theProc must remove the 4-byte parameter from the stack before
|
|
returning. When theProc gets control, the Bank register is
|
|
already set to the bank specified by BankValue (byte +2).
|
|
|
|
|
|
0021 nlDisasm1(@code):@NewAddress [NL 3.2]
|
|
Disassembles one line of code at the specified address, and returns
|
|
a pointer to the byte just following the line disassembled.
|
|
|
|
0022 nlExecCmdLine(@cmdline):0
|
|
Executes a specified command line (pointer to GS/OS
|
|
string). The return value is reserved & is currently
|
|
always 0.
|
|
|
|
0023 nlGetRange(@buffer):NumParms
|
|
Returns 2 if the user typed a range before your command;
|
|
otherwise returns 1.
|
|
|
|
Fills your 16-byte buffer with the following:
|
|
+000 rangeStart
|
|
+004 rangeEnd
|
|
+008 rawStart
|
|
+012 rawEnd
|
|
|
|
This is for fetching the one or two hex numbers or addresses
|
|
the user typed *before* your command. They are already parsed
|
|
by Nifty List.
|
|
|
|
Use rangeStart and rangeEnd if you're looking for *addresses*.
|
|
The bank byte is handled appropriately for you.
|
|
|
|
Use rawStart and rawEnd if you're looking for *numbers*; no
|
|
special bank handling is done for these values, so typing
|
|
a 0 always gets you a 0, not a $xx0000.
|
|
|
|
|
|
0024 nlGetAGlobal(ref):value/4
|
|
Data = reference number, value = long result
|
|
|
|
Retrieves a value from a Nifty List global variable (the
|
|
reference number values are in the equates file).
|
|
|
|
0025 nlSetAGlobal(@(ref,value))
|
|
Data = ptr to a record:
|
|
+000 reference word
|
|
+002 long value
|
|
|
|
Stores a value into a Nifty List global variable.
|
|
ref = nlgNUM1: the number parsed before your command
|
|
|
|
0026 nlAbortToCmd(ignored)
|
|
Aborts to the Nifty List command line, if possible
|
|
[should return error if Nifty List not active--doesn't check yet]
|
|
|
|
*
|
|
* Input/Output
|
|
*
|
|
0030 nlWriteChar(char)
|
|
Outputs a character--control characters are acted on.
|
|
|
|
0031 nlShowChar(char)
|
|
Outputs a character, but nonprintable characters show up
|
|
in a harmless way (like as periods).
|
|
|
|
0032 nlWriteStr(@pascalString)
|
|
Outputs a Pascal string.
|
|
|
|
0033 nlShowStr(@pascalString)
|
|
Outputs a Pascal string, but nonprintable characters show
|
|
up in a harmless way.
|
|
|
|
0034 nlWriteCStr(@cString)
|
|
Outputs a C string.
|
|
|
|
0035 nlShowCStr(@cString)
|
|
Outputs a C string, but nonprintable characters show up in
|
|
a harmless way.
|
|
|
|
0036 nlWriteText(@record)
|
|
record+000 = length of text
|
|
record+002 = pointer to text
|
|
Writes the specified number of characters.
|
|
|
|
0037 nlShowText(@record) [see above]
|
|
Writes the specified characters, but nonprintable characters
|
|
show up in a harmess way.
|
|
|
|
0038 nlWriteByte(byte)
|
|
Outputs a byte in hex (2 characters).
|
|
|
|
0039 nlWriteWord(word)
|
|
Outputs a word in hex (4 characters).
|
|
|
|
003A nlWritePtr(long)
|
|
Outputs a pointer (xx/xxxx).
|
|
|
|
003B nlWriteLong(long)
|
|
Outputs a long in hex (8 characters).
|
|
|
|
003C nlGetLn(...)
|
|
[not implemented]
|
|
|
|
003D nlGetChar(dummy):char
|
|
result = character (waits for one to be input)
|
|
|
|
003E nlCheckKey(dummy):result
|
|
result, low word 0=no key pressed; nonzero=a key was pressed
|
|
|
|
003F nlCrout(dummy)
|
|
Outputs a carriage return (begins a new line). Does NOT
|
|
return to the caller if the user hits Apple-period, etc!
|
|
|
|
0040 nlSpout(dummy)
|
|
Outputs a blank.
|
|
|
|
0041 nlPause(dummy)
|
|
Lets the user pause the screen, do screen dumps, etc.
|
|
Normally returns right away. Does not return if the
|
|
user wants to abort.
|
|
|
|
0042 nlHandleInfo(handle)
|
|
Displays address and owner information for a handle,
|
|
in the same format as the "I" command.
|
|
|
|
0043 nlWriteNoVoice(@cString)
|
|
Displays a C String if and only if the user did not set the
|
|
"v" flag (avoids annoying decorative displays, like lines of
|
|
dashes, which may be prounced "dash, dash, dash, dash...")
|
|
|
|
0044 nlShowWString(@wString)
|
|
Displays a string that begins with a length word. Nonprintable
|
|
characters appear in a harmless way.
|
|
*
|
|
* Parsing
|
|
*
|
|
0050 nlChrGet():char
|
|
Advances to the next character on the command line and
|
|
returns is.
|
|
|
|
0051 nlChrGot():char
|
|
Returns the command line character we're already on.
|
|
|
|
0052 nlEatBlanks():char
|
|
Advances 0 or more times, until we're not sitting at a
|
|
blank. Returns like nlChrGot.
|
|
|
|
0054 nlEvalExpr(@buffer):actualSize
|
|
buffer:
|
|
+000 Word MaxExprSize maximum size of expr this buffer
|
|
can hold (must be at least 4)
|
|
+002 Word ActExprSize actual size of parsed expression
|
|
(returned)
|
|
+004 n Bytes Expr parsed expression (0 or more bytes,
|
|
returned)
|
|
|
|
The nlEvalExpr result is just a copy of the ActExprSize word
|
|
returned in buffer.
|
|
|
|
Note that calling nlEvalExpr is a simple way to let the user
|
|
type a GS/OS pathname. The expression, starting with the
|
|
length word, is already a class-one GS/OS string.
|
|
|
|
*
|
|
* Memory access
|
|
*
|
|
0060 nlGetByte(@addr):byte
|
|
Data = addr; value = byte found at that address
|
|
|
|
0061 nlGetWord(@addr):word
|
|
Data = addr; value = word found at that address
|
|
|
|
0062 nlGetLong(@addr):long
|
|
Data = addr; value = long found at that address
|
|
|
|
|
|
Reference numbers for globals:
|
|
01 = nlgNUM1 (appropriate for getting an address-type value that NL parsed
|
|
before calling your command)
|
|
02 = nlgADDR
|
|
03 = nlgInfoTable (address of the table nlGetInfo uses; need to document
|
|
which fields are ok)
|
|
|
|
[end of Writing.Modules]
|