I can use prodos MLI calls for OPEN file and READ file,
other commands should be easy now...
MLI call parameters are passed to MAIN ram through
the input buffer....
I just loaded a file, "TEST" (contains 01 02 03 04 05 06 07 08 09)
to $1400 (what a weird spot... not really, I put #20 instead of #$20)
in aux RAM, just by making an MLI call from AUX ram!
prior to the MLI call from AUX RAM,
*1400L
all it shows is random junk...
after the call,
jsr mli
dfb commandcode (open)
dfb parmtablelo
dfb parmtablehi
jsr mli
dfb commandcode (read)
dfb parmtablelo
dfb parmtablehi
rts
I type:
*1400L
and it shows:
01 02 03 04 05 06 07 08 09
woo hoo!
now I'd like to add:
#00
from aux ram, save file to disk.
just a few more lines of code and I'll have this
execute from main RAM:
1)"load to aux bank # XX", so I can call the mli and have it load the
file to the
appropriate RWIII bank...
2)execute from aux bank, LOAD to aux bank ##, so I can call the MLI and
load
a file to another aux bank
3)execute from aux bank, save AuxBank #XX, address WXYZ to disk, so I
can
save (from aux ram) other areas of RAM in another aux bank
4) add active bank MLI call, caught by my code before it gets to the
MLI,
initializes an aux bank for running code
5) MLI call to JSR any address within another AUX bank, or in main RAM.
basic system doesn't work... I haven't tried to get it to work yet.
basic works from the aux bank, the monitor works from the aux bank,
only 847 bytes of ram required to use OPEN and READ from aux,
as well as switching code to allow switching between "active" banks,
or banks with programs running in them..
thats 847 bytes of ram for code... the buffers require:
256 bytes of ram at $200, to pass call info between
main and aux.. doesn't count towards total, because
input buffer isn't being used during MLI call (as far as I can tell)
256 bytes of ram at $2000, for READ ***data**** buffer,
and 1024 bytes of ram at $6000, for open ***file*** buffer...
847
+1024
+ 256
---------
2127 bytes total
I can cut this down a bit by making some of the code
subroutines..
all of the buffers are definitely moveable... I need to change
some hard coded assembly addresses to labels to make it easy.
that would just allow me to change the buffers at assembly time..
perhaps I should add a few bytes of information to what is transferred
in the input buffer, so the MLI patch knows where the buffers should go
in main RAM..
the data buffer in aux ram is definable, the usual data buffer
specification
in the MLI READ call..
Rich
also, another command in the patched MLI:
command:
$FF (I'll have to figure out a suitable code)
parm list:
+00 = len, although I don't need this, since I'm grabbing
this before the mLI gets it...
+01 = src bank#, 0 = main, 1 =aux bank1, 2=aux bank2, etc
+02 = destination bank #
+03 = source lo address
+04 = source hi address
+05 = source end lo address
+06 = source end hi address
+07 = dest lo address
+08 = dest hi address
then I can make a call ,
JSR MLI ;update main ram screen
dfb $FF
dfb #>parmlist
dfb #<parmlist
rts
parm list:
dfb #05 ; +00 = len, although I don't need this, since I'm
grabbing
; this before the mLI gets it...
dfb #01 ;+01 = src bank#, 0 = main, 1 =aux bank1, 2=aux bank2, etc
dfb #00 ;+02 = destination bank #
dfb #00 ;+03 = source lo address
dfb #04 ;+04 = source hi address
dfb #FF ;+05 = source end lo address
dfb #07 ;+06 = source end hi address
dfb #00 ;+07 = dest lo address = 0400
dfb #04 ;+08 = dest hi address
and move $400-$7FF, aux bank "text screen" to the main RAM
text screen... the apple II displays
the text screen from main ram only
and it would use the switching code I already have set up in
the MLI patch..
Rich
something wrong with the return address, so there are
multiple RTS instructions at the end of the routine..
ORG $2600
;TEST TO SEE IF IT WILL LOAD FROM AUX RAM
MLI EQU $BF00
OPENFILE
JSR MLI
DFB #$C8
DFB #<OPENFILEPARM
DFB #>OPENFILEPARM
LDA $207
STA READ_REF_NUM
STA CLOSE_REF_NUM
READFILE JSR MLI
DFB #$CA ;command code = READ
DFB #<READFILEPARM
DFB #>READFILEPARM
RTS
RTS
;CLOSEFILE
; JSR MLI
; DFB #$CC
; DFB #<CLOSEFILEPARM
; DFB #>CLOSEFILEPARM
;
; RTS
NOP
NOP
NOP
CLOSEFILEPARM
DFB #01
CLOSE_REF_NUM DFB #00
READFILEPARM
DFB #04 ;NUM of parameters
READ_REF_NUM DFB #00 ; read ref number
DFB #00 ;<IO_buffer
DFB #$20 ;>IO_buffer
DFB #$90 ;lo requested length
DFB #01 ;hi
ACTUALREAD DFB #00 ;lo actual length read
DFB #00 ;hi
;read:
;+00 = 04 len
;+01 = ref number
;+02, 03 = address of data buffer
;+04, 05 = requested length
;+06, 07 = actual length
OPENFILEPARM
DFB #03
DFB #<PATHNAME
DFB #>PATHNAME
DFB #$00 ;FILE BUFFER
DFB #$60
OPEN_REF_NUM DFB #00 ;reference number of open file
;+00 = 3 len
;+01, 02 = address of pathname
;+03, 04 = address of file buffer
;+05 = reference number
PATHNAME DFB #4 ;LEN
ASC "TEST"
> this code executes properly (loads a file from disk into
> aux ram using prodos MLIfrom a program running in aux ram..
>
> something wrong with the return address, so there are
> multiple RTS instructions at the end of the routine..
This is using your homebrewed "MLI interceptor" thing, right? If so, the
"something" that's wrong with the return address is probably the fault
of your interceptor not doing things quite the same way the MLI normally
does. (Standard MLI calls diddle the return address by +3 to jump over
the command byte and the pointer to the parameter block - Are you paying
attention to that step in your interceptor?)
--
Don Bruder - dak...@sonic.net - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info
yeah..
>If so, the
> "something" that's wrong with the return address is probably the fault
> of your interceptor not doing things quite the same way the MLI normally
> does. (Standard MLI calls diddle the return address by +3 to jump over
> the command byte and the pointer to the parameter block - Are you paying
> attention to that step in your interceptor?)
yeah.. it's fixed now. Thanks for the reply..
Rich
>256 bytes of ram at $200, to pass call info between
>main and aux.. doesn't count towards total, because
>input buffer isn't being used during MLI call (as far as I can tell)
Unfortunately this isn't true. If ProDOS finds a Thunderclock
compatible clock it'll call it in about every MLI call to update its
time in the $BF page. And the Thunderclock protocol is to put the
time/date in the input buffer. It was designed that way to be easily
usable from BASIC.
You'll find several places in 'Contiki for the Apple2' where the input
buffer is saved before MLI calls and restored afterwards ;-)
Best, Oliver
OK.. I didn't know this.. how much of the input buffer is used
for the Thunderclock protocol?
> You'll find several places in 'Contiki for the Apple2' where the input
> buffer is saved before MLI calls and restored afterwards ;-)
What is the purpose of saving the input buffer before MLI call?
IE, what is in the input buffer before the MLI that you would
want to keep?
Thanks for the reply,
Rich
working on the SAVE portion...
requested length to save...
hibyte = # of 256 byte blocks
lobyte = # of left over bytes
I use a 256 byte window to transfer
data between aux and main.. this is to
keep MAIN ram usage minimal.
To save a file, with requested lengh $HILO,
I need to :
transfer $HI blocks of 256bytes,
ldx $hi
loop move aux to main 256 bytes
save (write) 256 bytes
dex
bne loop
there are $lo bytes left over, so I do:
move aux to main 256 bytes
save (write) $LO bytes
just like David Empson suggested on
Thurs, Aug 10 2006 on this newsgroup..
Rich
If ProDOS optimizes aligned (with start of file)
512-byte transfers, that would be a much more
efficient choice.
-michael
NadaNet networking for Apple II computers!
Home page: http://members.aol.com/MJMahon/
"The wastebasket is our most important design
tool--and it's seriously underused."
OK...
what the code is doing right now:
in aux... call MLI, "bload" file (read), a$abcd (data buffer), l$abcd
(req. length)
the command code and parm table are saved
the command code and parm table are moved to MAIN
LOWLEN = req. length lowbyte
HILEN = req length hibyte
auxdatabuffer = databuffer ;save the databuffer address
DataBuffer = $2000 in main RAM
req len = $00FF ;request 256 bytes ata time..
loop
call MLI ;loads 256 bytes
dfb command code
dfb parmtable LO
dfb parmtable HI
call auxmove, move those bytes to
databuffer in aux RAM... Increment data buffer
in aux RAM by 256 bytes (increment hibyte)
inc auxdatabufferHI
dec HILEN ;this is number of pages to transfer
bne loop
;now there are LOWLEN bytes left to load then move...
Once it's all running good with my 6502 code that needs
it, I'll optimize it to your suggestions...
Thanksfor the reply,
Rich
You want $100 for 256 bytes. ;-)
And if you read the file in chunks of 512 ($200) bytes,
ProDOS won't have to read the disk into its buffer and
then move data to your buffer--instead it can read data
directly to your buffer.
Since you already have to move the data once to/from
your "window" buffer, it would be good to avoid another
move by ProDOS.
> loop
> call MLI ;loads 256 bytes
> dfb command code
> dfb parmtable LO
> dfb parmtable HI
>
> call auxmove, move those bytes to
> databuffer in aux RAM... Increment data buffer
> in aux RAM by 256 bytes (increment hibyte)
>
> inc auxdatabufferHI
>
> dec HILEN ;this is number of pages to transfer
> bne loop
>
> ;now there are LOWLEN bytes left to load then move...
>
>
>
>
> Once it's all running good with my 6502 code that needs
> it, I'll optimize it to your suggestions...
Happy coding!
oops..
> And if you read the file in chunks of 512 ($200) bytes,
> ProDOS won't have to read the disk into its buffer and
> then move data to your buffer--instead it can read data
> directly to your buffer.
cool... so If I read 512bytes, the filebuffer is bypassed?
Open command requires filebuffer
read/write command require databuffer.
the filebuffer is 1kilobyte...
to open a file from aux RAM, I use 1k of MAIN RAM just
to open the file...
I am trying to keep the DATA buffer (read/write commands)
small to minimize main RAM usage..
Rich
Rich
I understand, but another page is only 20% more main RAM space,
and it could considerably speed data transfer, particularly
for fast storage devices.
OK... The requested length (to read/write) and the ammount
of data to move from main-->aux(read) or aux-->main (write)
are now POKE-able, so you can optimize for 1)minimal RAM
usage or 2)"fast storage device"
a small basic program gives you options 1 and 2 above.
Rich
>> Unfortunately this isn't true.
>> the Thunderclock protocol is to put the
>> time/date in the input buffer. It was designed that way to be easily
>> usable from BASIC.
>
>OK.. I didn't know this..
I know, therefore I told it to you ;-)
> how much of the input buffer is used
> for the Thunderclock protocol?
I didn't try to figure that out. When I knew I had to deal with it I
just copied the whole page.
>> You'll find several places in 'Contiki for the Apple2' where the input
>> buffer is saved before MLI calls and restored afterwards ;-)
>
>What is the purpose of saving the input buffer before MLI call?
>IE, what is in the input buffer before the MLI that you would
>want to keep?
The cc65 C-Library for the Apple2 allows to pass command line
parameters with this construct:
call 2048:rem param1 param2 "param 3 with blanks" param4 param5
The C-Library startup code then parses the parameters from the input
buffer and makes them accessable via:
main(int argc, char *argv[])
So I need to take care of the input buffer on MLI calls necessary
before parsing the command line parameters.
BTW: I wrote a generic ProDOS loader. This is a SYS file that loads a
BIN file into memory and jumps to it. It's generic in that it works
with all BIN files fitting into memory (and not using page 3). It
works especially well with cc65 programs as it has a special feature
for them:
My ProDOS loader supports the ProDOS startup file protocol and
"emulates" the behaviour of the command line above so that cc65
programs started with my loader can receive the startup file as the
first (and only) parameter in their main().
I used this feature in Contiki for GS/OS finder integration using a
suitable ICON file. When opening a Contiki program in the GS/OS
finder, Contiki get's started via my loader and receives that program
in its main() and autoloads that program...
Maybe you didn't want to know all those details but I was in the mood
for it ;-)
Best, Oliver
Most clock cards used the input buffer ($200) to pass their
results to BASIC. The most space that can be used depends on
the format of the time/date information returned, which is
usually selectable by the user.
In no case does it exceed $2FF, since ProDOS uses $280..$2FF
as a pathname buffer (another possible issue).
Actually, lots of that kind of detail can only encourage others
to write code for Contiki. ;-)
In the absence of a "Contiki Technical Reference Manual", every
additional bit of lore helps!
Whoops, that first $2FF was supposed to be $27F. ;-)
I try loading basic.system to 2000 and then
type 2000G...
the rom gets stuck in an infinite loop in the F100
area..
I'm trying to see if I can modify the exerciser to
not flip the 80 column switches, so I can run
it from aux ram.
Rich
woohoo! I got the Exerciser screen to come up
in aux ram (with 80columns active)
I can type in command code,
modify paramaters..
something goes wrong when I execute
the command (BRK at 00) which tells
me something isn't quite right..
but it's progress.
It isn't %100 necessary to get it
working, but it would be nice to..
then I could "exercise" the prodos
MLI commands from aux, to prove
they all work.
anyway, OPEN, READ, WRITE, and
CLOSE are working perfectly from
aux ram.. (verified by me running programs
that call the MLI from aux ram)...
programs can run, unmodified, in aux ram.
(as long as they don't flip aux/main switches)..
IE mli calls work great from aux ram.
now I need to work on my memory manager
to keep track of what I have stored, where
I think I'll do:
file1: bank, address
file2: bank, address
and:
aux1:
page0:used
page1:used
page2:used
page3:free
etc..
maybe copy Prodos method of keeping track of
free pages.
I wish text/graphics could be displayed
directly from aux banks.
Rich
I see.. my MLI call catcher gets overwritten
when exerciser relocates itself.. I need to find
out if exerciser looks at the global page Memory in use
map.. if it does, I can modify the globalpage
to reflect the fact that the RAM is in use..
Rich
I can modify CSW (character output)
to point to my own routine...
set WriteMain ram
call the regular CSW routine,
set writeaux ram
rts
the code in main ram will have to save
the text screen to disk if it's important
(or just save it to another part of RAM,
reload it on returning to main ram program)
Rich
I was thinking about the read ROM/Write wram for
the LC area.. you cannot change read/write seperately
for the lower 48k..
but... I figured out a way to do it...
change CSW to myroutine:
PATCHCSW
lda #<myroutine
sta csw
lda #>myroutine
sta csw+1
rts
myroutine:
;A contains character to send to screen?
;set normal RAM state for Prodos
sta wrmainRam; r/w main ram
sta setstdZI ;read/write main zeropage
==;this code has to be in MAIN RAM!
==jsr (CSW)
==sta wrAuxRAM ;set to aux bank RAM
RTS ; in aux ram
That'll slow down text screen access for
aux ram programs, but it should work.
Rich
>>> I didn't try to figure that out. When I knew I had to deal with it I
>>> just copied the whole page.
>> Most clock cards used the input buffer ($200) to pass their
>> results to BASIC. The most space that can be used depends on
>> the format of the time/date information returned, which is
>> usually selectable by the user.
>>
>> In no case does it exceed $2FF, since ProDOS uses $280..$2FF
>> as a pathname buffer (another possible issue).
>
>Whoops, that first $2FF was supposed to be $27F. ;-)
I was just looking at my code and say that actually didn't copy the
whole page as I stated above but only the first half for the same
reason you pointed out above ;-)
Best, Oliver