Jump to content
IGNORED

DSRLINK Code Tutorial


TheBF

Recommended Posts

I replicated your video to double check if it was the repository code's problem.

It failed just like your video on the new Classic99 but ran on the older version.

 

I recompiled the same code and commented out 1 line that compiles the "start" file. Sent it over to TI-99 and voila!.

It cleared the screen, put up the title and yes it Beeps on startup

 

You may be more rigorous with something on Classic99 now than the original hardware.

Something that my home made cross-compiler doesn't respect. (?)

 

I know Speccery loaded and ran an early version on his FPGA version as well. Don't know the particulars there.

Edited by TheBF
Link to comment
Share on other sites

Still no luck -- maybe you are squeaking by on your older version of Classic99, or maybe I'm doing something wrong, but I can't even get it to start, it doesn't make it to the first disk access. Have a look here and tell me what to try differently:

 

https://youtu.be/6osTkOynCEg

 

 

Hi Tursi, I found one piece of the puzzle.

 

So the reason that my Forth won't run on the new CLASSIC99 is because of the following code.

It puts the timer in continuous running mode with TMR! which seems to run fine.

BUT I grab a number with TMR@ and then grab another number later to test the run time of short Assembler and machine code routines.

 

I also use it to create JIFF delay used for MS delays and that is the word that doesn't work.

\ this code works fine
CODE: TMR!   (  -- )         \ load TMS9901 timer to max value 3FFF
             W 3FFF LI,      \ load scratch register W with MAXIMUM timer value
             R12 CLR,        \ CRU addr of TMS9901 = 0
             0 LIMI,
             0   SBO,        \ SET bit 0 to 1, Enter timer mode
             R12 INCT,       \ CRU Address of bit 1 = 2 , I'm not kidding
             W 0E LDCR,      \ Load 14 BITs from R1 into timer
             R12  DECT,      \ go back to address 0
             0    SBZ,       \ reset bit 0, Exits clock mode, starts decrementer
             2 LIMI,
             NEXT,           \ 16 bytes
             END-CODE

\ this code does not work on new CLassic99, but works on real hardware.
CODE: TMR@   ( -- n)         \ read the TMS9901 timer
             TOS PUSH,
             R12 CLR,
             0 LIMI,
             0 SBO,          \ SET bit 0 TO 1, ie: Enter timer mode
             TOS 0F STCR,    \ READ TIMER (14 bits plus mode bit) into W
             TOS  1 SRL,     \ Get rid of mode bit
             0 SBZ,          \ SET bit 1 to zero
             2 LIMI,
             NEXT,
             END-CODE
CODE: |-| ( x y -- x n ) \ : |-| OVER - ABS ;

*SP TOS SUB,

TOS ABS, \ get ABS of subtraction

NEXT,

END-CODE

\ JIFFS give finest resolution for delays

: JIFFS ( n -- )

0 ?DO

TMR@

BEGIN

PAUSE TMR@ |-| 650 >

UNTIL

DROP

LOOP ;

\ MS resolution limited to 1/60 second and minimum is 1/60 sec.

: MS ( n -- ) 4 RSHIFT PAUSE JIFFS ; \ MS/16 = JIFFS

Edited by TheBF
Link to comment
Share on other sites

Can you detail what "does not work" means? I mean, SOMETHING happens. To fix a problem it needs to be clear what the code is doing that is incorrect, and what it should do. I don't see any reason in the function you called out that the code would /hang/.

Link to comment
Share on other sites

Got it.. thanks for the description. The problem was upon exiting 9901 timer mode, I would reset the timer. But your code was polling the timer, continuously entering and exitting timer mode, so it never counted down. I added the 9901 timer to the debug window and it was immediately clear. Fixed that, and it came up.

 

Going to spend a few minutes on your disk issue now... no promises. Either way I'll do a new release shortly to address this bus.

  • Like 3
Link to comment
Share on other sites

Sorry, Just saw this.

The symptom was as you described when you first tried it.

 

On boot, the Beep started , the MS delay word calls the TMR@ code word and it never ended.

 

I am pretty frustrated with the disk problem. I tried cutting my own path, but clearly there is something I am missing as the DSR in ROM does some pretty strange things once it is entered, writing to VDP registers and such and never exits.

 

I am looking at a wholesale re-write using other peoples Assembler code. :?

Link to comment
Share on other sites

By symptoms, I meant you said "this code does not work" and showed me code to read the 9901 timer. My question was "how does it not work?" (I do not need the answer any longer - that function DOES work, just the timer was not counting down).

 

I'll note though, that I was not successful with writing my own DSRLNK either, and my own code just uses a ported version of the E/A one. ;)

 

I did get some progress, but I did not get all the way there. I found two absolute things and one maybe - fixing the two absolute things in the debugger let the 'open' call succeed, at least.

 

-interrupts must be off
Classic99's DSR does not suffer from this issue because Classic99's DSR takes zero time from the 9900's point of view - imagine the 9900 is halted while the DSR executes. Thus, an interrupt can't interrupt it.
-CRU Of the disk controller must be stored at >83F8 (ie: >1100)
There is no "not found" handling in the disk DSR - if the CRU can't be matched, it just searches VDP until it's happy. Since R12 was 0, it was not too hard to find a match and then make all kinds of bad assumptions about the memory space it found.
-DSR is not turned off after the call
... I think. It seems to jump back into the interpreter which is a bit hard to trace with just the disassembly. This can cause problems with the next DSRLNK which will try to enable cards without turning the previous one off.
-Code ends up jumping to >8300 where it hits invalid instructions - comes from >B8B2 (BL *R9, R9 is >8300)
So I was not sure what was going on at this point...
Link to comment
Share on other sites

 

By symptoms, I meant you said "this code does not work" and showed me code to read the 9901 timer. My question was "how does it not work?" (I do not need the answer any longer - that function DOES work, just the timer was not counting down).

 

I'll note though, that I was not successful with writing my own DSRLNK either, and my own code just uses a ported version of the E/A one. ;)

 

I did get some progress, but I did not get all the way there. I found two absolute things and one maybe - fixing the two absolute things in the debugger let the 'open' call succeed, at least.

 

-interrupts must be off
Classic99's DSR does not suffer from this issue because Classic99's DSR takes zero time from the 9900's point of view - imagine the 9900 is halted while the DSR executes. Thus, an interrupt can't interrupt it.
-CRU Of the disk controller must be stored at >83F8 (ie: >1100)
There is no "not found" handling in the disk DSR - if the CRU can't be matched, it just searches VDP until it's happy. Since R12 was 0, it was not too hard to find a match and then make all kinds of bad assumptions about the memory space it found.
-DSR is not turned off after the call
... I think. It seems to jump back into the interpreter which is a bit hard to trace with just the disassembly. This can cause problems with the next DSRLNK which will try to enable cards without turning the previous one off.
-Code ends up jumping to >8300 where it hits invalid instructions - comes from >B8B2 (BL *R9, R9 is >8300)
So I was not sure what was going on at this point...

 

 

Cool! That's great sleuthing. I will implement those changes and try and feel my way along from there.

 

This has got to be the most convoluted Disk "API" ever invented. :-)

 

Thanks!!!

Link to comment
Share on other sites

I'm not a fan of the TI Disk DSR, but people keep insisting we use it as a standard. There's no error checking, it makes assumptions about how it was called and expects random variables in scattered RAM locations. It's a pure classic case of "everything is perfect" programming. The only assumption it SHOULD make is that the PAB has a pointer to it. ;)

 

I'm thankful that we aren't expected to be similarly compatible with the RS232 or PIO DSRs... people got lazy and went straight to hardware there.

Link to comment
Share on other sites

 

Cool! That's great sleuthing. I will implement those changes and try and feel my way along from there.

 

This has got to be the most convoluted Disk "API" ever invented. :-)

 

Thanks!!!

 

I think it works! :-D I have a type 3 file, disk image with my boot files on it and it compiled them all on start up!

 

 

I spoke too soon of course. I have the new Classic99 version INI file set to type 3. :-)

But I have a direction now so it's all much better.

 

Your ideas were the same as Lee suggested with the exception that I was turning the card on in the Forth workspace, so I never set GPL R12 to the disk card address.

And I didn't turn the card off inside the GPL workspace either so it kept running.

 

So my method removes all the messy stuff of creating and manipulating the PAB data to Forth. I also scan the link list of devices in Forth and record the relevant data.

I don't search the entire list of devices because I know I only want disk card access at this time.

 

Here is what the code looks like now with your changes in CROSS-COMPILED Forth Assembler

There is a stub for and PANIC error handler but I will make that something meaningful.

 

Now I need to change it so I use the DSRWKSP to hold the parameters that I find in forth and then the GPL workspace can grab them from there.

\               workspace    compile program address
\               ---------    -----------------------
CREATE: DSKLNK  DSRWKSP T,  [cc] THERE TCELL + T, [tc]
             0 LIMI,
             837C @@ CLR,     \ clr GPL status flag
             83E0 LWPI,       \ change to GPL workspace
             R12 DSKCARD LI,  \ card address -> GPL R12
             RCODE @@ R9 MOV, \ RCODE has the ROM entry address
             0 SBO,           \ turn on the card
            *R9 BL,           \ branch to ROM code
             @@1 JMP,         \ on error DSR returns here

             0 SBZ,           \ on success turn off card
             DSRWKSP LWPI,    \ return to DSRWKSP
             2 LIMI,
             RTWP,            \ Return to Forth Workspace
             NEXT,            \ run the Forth interpreter

@@1:         0 SBZ,           \ TROUBLE! turn off card
             DSRWKSP LWPI,    \ to DSRWKSPACE
             BEGIN,
                 R0 INC,      \ shows in the debugger
             AGAIN,   \ loop forever halts program

Edited by TheBF
  • Like 1
Link to comment
Share on other sites

I was not making much progress with my own DSRLNK on a type 3 drive so I took some time to Code the same version that Vorticon is using in my RPN Forth Assembler.

That seems to be working somewhat in preliminary testing.

 

Got it to open a file but then it reports that the file is corrupt, but I know it's not because the Editor opens it just fine.

 

Here is what Classic99 is reporting on this one:

DSR opcode >0 on PAB >36C7, filename DSK1.START                                                      
Releasing file buffer 60                                                                            
Recycling unclosed file buffer 60
Opening DSK1.START on drive type FIAD                                                              
PAB requested file type is DV80                                                                    
Allocating file buffer 0                                                                           
Detected C:\Users\Public\Dev\Forth\HSF2000\cc9900\classic99\DSK1\START as a V9T9 file              
Warning: Number Records doesn't match sector length on variable file.                              
Corrupt file - truncating read.
C:\Users\Public\Dev\Forth\HSF2000\cc9900\classic99\DSK1\START read 13 records                        
Restore set record number to 0         

Does anybody want to take a guess as to where I should look for this kind of error.

Have I initialized the PAB wrong?

Link to comment
Share on other sites

The thing you need to remember when you are reading the debug is that there are two sides to the disk emulation.

 

First, the PC side needs to read and parse the file that you have on your PC.

Then, the TI side needs to read and parse the interpreted version of the file that the PC has parsed.

 

What this means is you need to pay attention to the errors. If it says "Corrupt file - truncating read.", it's the /PC/ side that thinks the file is corrupt, not the TI side. The TI side won't see the corruption because the parser simply truncated the corrupt part of the file ("truncating reads") and did not present it to the TI side (so, of course the Editor reads it without error). It's /also/ warning you that the header is invalid - the number of records and the sector length on a variable length file is expected to match, and your file doesn't. It's still doing its best to do something useful with the file, but you can't just say "it's not corrupt". It is. (if you post it, we can tell you why it's corrupt and even repair it). (I should also note that using V9T9 format files on Classic99 is deprecated, and you should switch to TIFILES headers for active development.)

 

However, all this happens on the PC side, which means that it doesn't have anything to do with your DSRLNK implementation. That happens entirely on the TI side.

  • Like 1
Link to comment
Share on other sites

I will take all that under advisement. It great to have more background on how Classic99 operates.

I did convert the file to TIFILES format on a lark but that didn't help.

 

It's important to note that I had to re-type most of the original DRSLNK file to translate it to my assembler so it's still very probable that I have done something wrong there, but I am still grokking how it does some of the magic to see what is wrong :-)

 

( i might want to visit a shrink to understand why I have insisted on doing this with homemade tools) :-)

 

I will double check the data file corruption, because I am using a copy of the data file in a different directory, however I am pretty certain I can read this file with other TI programs without that error showing in Classic99. It was created with the E/A editor.

 

All that to say, I suspect ME more than my PC, but your expertise affects my path to the future.

 

Thanks for weighing in and I can't really thank you enough for making Classic99. Outstanding hack.

Link to comment
Share on other sites

But like I said, V9T9 is deprecated - this means I literally never test it, and I only ever intended it for reading. Even if Classic99 created the file, it's not hard for a bug to have crept in. Recommending TIFILES format keeps you on the tested side of things. ;)

 

It's probably helpful to cover what a DSRLNK does too..

 

A DSRLNK starts with a pointer to a PAB, which is a structure in VDP RAM that tells the DSR what the operation is (OPEN, READ, etc), what type of file is expected (DISPLAY, VARIABLE, FIXED, etc), what part of the file we're interested in (where applicable), and what the filename is. DSRLNK only cares about that filename part.

 

Now the filename is more properly a fully-qualified path, containing the device name, options, and the filename. Since options and the filename are DSR-specific, DSRLNK again only cares about the device name part. So it first identifies the name of the device you're after.

 

Next, it turns on all the DSR ROM cards, one at a time, and looks for a match for that name. (The better DSRLNKs also check GROMs). When a match is found, DSRLNK simply branches to the address specified for that name. (The DSR then again parses the PAB from scratch to work out what to do). One at a time is important because it is possible in the hardware to turn on two cards at the same time, but if you then try to read DSR space both cards will attempt to respond. Depending on how the cards are made, that can be bad. Crossing the streams. ;)

 

Unfortunately, the way that the disk DSR was written, it assumes that the DSRLNK has done things in a particular way, and therefore that certain data is in specific memory locations, that a specific workspace is loaded, etc. So the DSRLNK has to have done all that -- but in the end its only job is to hand off to the correct DSR ROM routine.

 

In Classic99's DSR, the branch to the DSR ROM is what triggers the disk emulation to take place, so when you see in the debug that Classic99 has begun to handle a disk request, this means that your DSRLNK is done (except for turning the card back off when it returns). I can't think of anything you can put into a DSRLNK that would corrupt a file in that scenario... the structures that Classic99 are complaining about are at the sector level, rather than the record level.

 

It's also worth noting that a lot of that changes when you use the type 3 hack. Classic99 NO LONGER reads the file, it's only responsible for sector access to the disk image (nothing higher level). Most of the setup checks still take place, but when it reports "Handling %s via TICC DSR", all that means is its finished its internal housekeeping and handed off to the TI DSR, the rest of the access happens there. But this means you won't see the 'corrupt file' messages and the like, because Classic99 has no idea what that DSR is trying to do. ;)

  • Like 1
Link to comment
Share on other sites

Excellent information.

 

So I am thinking that I transferred V9t9 files into my disk image and that was the cause of the "corrupt" message.

I am starting with a clean slate and using the new emulator exclusively and things are moving forward... I think.

 

Thanks again

 

Edit: Yes, re-making the disk image with just TIFILES has stopped the corrupt file message.

 

1 step closer.

Edited by TheBF
Link to comment
Share on other sites

So CAMEL99 Forth is now loading files with a DSRLINK that is written in Assembler, using TYPE 3 disk image on Classic99.

 

And using all that assembler code it is now … 30% SLOWER than the one I had before (which didn't work on real hardware)

 

It disturbs me that the DSR scans the file name every time to find the period character it is called

All that effort for a VDP address that is known after you do it once and could be recorded in a variable in the, oh I don't know, the PAB maybe. ;)

 

Things that make me say hmm...

 

Big up as they say in Jamaica, to Tursi and Lee for all their patience.

 

B

post-50750-0-96437600-1539914776.jpg

  • Like 5
Link to comment
Share on other sites

It disturbs me that the DSR scans the file name every time to find the period character it is called

All that effort for a VDP address that is known after you do it once and could be recorded in a variable in the, oh I don't know, the PAB maybe. ;)

 

There really is no reason I can see not to limit the search. After all, all of the pointers and values have already been saved by existing DSRLNKs—and, to what end, if not to anticipate that very process! If I were not using the console’s GPL DSRLNK (which I obviously cannot manipulate), I think that is exactly what I would do in fbForth 2.0!

 

...lee

Link to comment
Share on other sites

 

There really is no reason I can see not to limit the search. After all, all of the pointers and values have already been saved by existing DSRLNKs—and, to what end, if not to anticipate that very process! If I were not using the console’s GPL DSRLNK (which I obviously cannot manipulate), I think that is exactly what I would do in fbForth 2.0!

 

...lee

 

 

Thank you for supporting my insanity. :-)

 

So my idea is to pre-compute and store the mission critical values for a given file when the PAB is created (i.e.: file OPEN) and when needed blit the values into the appropriate DSR workspace registers and only then BLWP to the GPL workspace "business end of the code". That was what I was trying to do before, but I could not figure out all the magic ins and outs of the DSRLINK "API" . LOL

 

Now with running code I can sleuth around and get a good snapshot of the mission critical values to save.

 

So that way when you do a file operation like read or write, you are running about 1/3 of the ALC that is running on each call in the existing code.

 

I will publish the current state of the ugly monster when I get downstairs to my addiction machine.

Link to comment
Share on other sites

So that way when you do a file operation like read or write, you are running about 1/3 of the ALC that is running on each call in the existing code.

 

I do not know whether you plan to support the level-3 opcodes, SAVE and LOAD, but, if you do, DSRLNK will need to treat them the same as OPEN because neither of them is required by the DSR to operate on an already “OPEN” file.

 

...lee

Link to comment
Share on other sites

Yes I want to support those so thanks for that info.

 

For those who are curious here is InsaneMultitaker's code translated to my cross-assembler. (Big thank you for this clear code)

 

A long time ago I added features like the TI Assembler has so I could more easily translate existing ALC from all the talented people in the TI world.

This decision paid off here. There are a few warts in my system still. The predefined labels are crude and so forward labels from multiple jumps need to use 2 labels.

It needs re-write but since I don't use un-structured assembler much anymore it will not get fixed soon. :-)

 

(For the non-Forther, Forth is a single pass compiler so it only knows what is already defined. Pre-defined labels for JMP etc, is quick and dirty solution. [taken from Win32Forth])

 

Brief Description Other Quirks

 

[CC] means CROSS-COMPILING and lets you use the host computer to do math and control the compiler.

[TC] means TARGET-COMPILING and directs code generation to the TI-99 memory image in the PC.

 

@@ means indirect addressing mode for the previous label.

 

I added a macro instruction to make me feel better about all the duplicate code for setting the VDP address. :-)

An interesting note about Forth Assember is that the Forth Compiler can be used to make macros.

Since the registers and arguments for instructions are place on the data stack you can DUP the arguments or do whatever you need to do with them before they are picked up by the instruction for assembly into the code.

 

I also replaced some of the jumps with structured BEGIN UNTIL and IF/ENDIF after I got it working. This will be a work in progress.

 

EDIT: Replaced with cleaned up version that has more comments for my understanding and removes SAVE1...SAVE5 and associated instructions.

 

 

 

\ DSRLNK in XFC99 cross-compiler 9900 Assembler

\ Source: 
\ http://atariage.com/forums/topic/283914-specialized-file-access-from-xb/page-2
\ by InsaneMultitasker


CROSS-ASSEMBLING  XASSEMBLER DEFINITIONS

\ we need more labels than I normally use for Forth style CODE Words
 A refer: @@A    A binder: @@A: 
 C refer: @@C    C binder: @@C:
11 refer: @@11  11 binder: @@11:

CROSS-COMPILING XASSEMBLER DEFINITIONS
\ MACRO to simplify the VDP code
: VDPWA, ( reg -- )
       DUP           SWPB,   \ setup VDP address
       DUP VDPWA @@  MOVB,
       DUP           SWPB,
           VDPWA @@  MOVB,
                     NOP,  ;

TARGET-COMPILING

[cc] HEX [tc]

8C02 EQU VDPWA
8C00 EQU VDWWD
8800 EQU VDPRD
837C EQU STATUS

l: HEX20  20 BYTE,
l: HEXAA  AA BYTE,
l: PERIOD 2E BYTE,  \ '.'
         .EVEN

CREATE: NAMBUF   6 TALLOT   \ 'since we know were using "dskN."

\
l: H2000  2000 DATA,
l: CYC1   0000 DATA,
l: H1300  1300 DATA,

\ take some space in Forth DATA stack for a workspace
[CC] SP0 100 - [TC] VALUE: DREGS

[CC] 5 2* DREGS + [TC] EQU DREG(5)

CLR-JMPTABLE

CREATE: DSR1
      *R14+     R5   MOV,    \ CALLER'S address->R5, auto inc for return
       HEX20 @@ R15  SZCB,   \ clear DSR wksp
       8356 @@  R0   MOV,    \ [PAB FNAME] to R0
       R0       R9   MOV,    \ dup R0 to R9
       R9       FFF8 ADDI,   \ R9-8 = [PAB FLG]
       R0           VDPWA,       
       VDPRD @@ R1   MOVB,   \ R1= length of FNAME
       R1       R3   MOVB,   \ DUP length byte to R3
       R3       08   SRL,    \ swap the byte to other side
       R4            SETO,   \ R4 = -1
       R2   NAMBUF   LI,     \ R2 is ^namebuf

  BEGIN, \ DLOOP1  ( copy VDP FNAME ->namebuf upto '.' character  )
       R0            INC,    \ point to next fname VDP address
       R4            INC,    \ counter starts at 0
       R4       R3   CMP,    \ is counter = fnamelength
       @@1           JEQ,    \ if true goto @@1:
       R0          VDPWA,    \ set VDP address
       VDPRD @@ R1  MOVB,    \ read next VDP char from fname
       R1      *R2+ MOVB,    \ copy to namebuf & inc pointer
       R1 PERIOD @@ CMPB,    \ is it a '.'
  EQ UNTIL,                  \ DLOOP1  ( until '.' found )

@@1:   R4        R4  MOV,    \ test R4=0
       @@6           JEQ,    \ if so, goto @@6
       R4        07  CMPI,   \ is dev name length>7
       @@8           JGT,    \ if so, goto @@8 (same as @@6)
       83D0 @@       CLR,    \ erase magic CRU addr. holder
       R4   8354 @@  MOV,    \ put length in magic address
       R4            INC,    \ +1 points to '.' character
       R4   8356 @@  ADD,    \ add offset to PAB address (real pab)

\ ==== GPL WORKSPACE ====
       83E0         LWPI,    \ SROM (search ROM device list)
       R1           CLR,     \ MAGIC GPL REGISTER=0
       H2000 @@ CYC1 @@ MOV, \ init the CYC1 variable ??
       R12     1000 LI,      \ init CRU base to 1000
       @@A          JMP, \ DLOOP2

@@11:  R12   0F00   LI,    \ SROM1
       H1300 @@ CYC1 @@ MOV,

@@A:  \ DLOOP2:  scan for device cards
    BEGIN,
       R12   R12   MOV,
       NE IF,              \ card address<>0
           00 SBZ,         \ turn off card
       ENDIF,
       R12    0100  ADDI,  \ advance CRU to next card
       83D0 @@      CLR,   \ erase magic addres
       R12    2000  CMPI,  \
       @@11         JEQ,   \  SROM1
       R12  CYC1 @@ CMP,
       @@5          JEQ,   \ DJUMP5 :ERROR
       R12  83D0 @@ MOV,   \ save card CRU in magic address
       00           SBO,   \ turn on the card
       R2   4000    LI,    \ ROM start addr -> R2
      *R2  HEXAA @@ CMPB,  \ test for card present
    EQ UNTIL,              \ loop until card is found
       DREG(5) @@ R2 ADD,
       @@C          JMP,   \ DJUMP3


@@3: \ DLOOP3
    BEGIN,
       83D2 @@   R2 MOV,   \ ROM device list -> R2
       00           SBO,   \ turn card on
@@C:  *R2       R2  MOV,   \ DJUMP3  Fetch next link
       @@A          JEQ,   \ DLOOP2  if link=0 goto @@A
       R2  83D2 @@  MOV,   \ save link address in magic address
       R2           INCT,  \ R2 = code pointer
      *R2+      R9  MOV,   \ FETCH code address ->R9
       8355 @@  R5  MOVB,  \ dev length->R5
       @@4          JEQ,   \ DJUMP4
       R5      *R2+ CMPB,
    EQ UNTIL,              \ JNE DLOOP3
       R5       08  SRL,
       R6  NAMBUF   LI,

\ DLOOP4
    BEGIN,
       *R6+   *R2+  CMPB,
        @@3          JNE, \ DLOOP3
        R5           DEC,
    EQ UNTIL,             \ JNE, DLOOP4

@@4: \ DJUMP4
       R1            INC,
      *R9            BL,  \ call the DSR code
       @@3           JMP, \ DLOOP3
       00            SBZ,

\ ==== DSR Workspace ====  \  going home!
       DREGS         LWPI,
       R9    R0      MOV,  \ put [PAB FLG] addr ->R0
       R0           VDPWA, \ set vdp address
       VDPRD @@  R1  MOVB, \ read error value to DREGS R1
       R1 0D         SRL,  \ shift error to correct range
       @@7           JNE,  \ DJUMP7 if error<>0 goto @@7
                    RTWP,  \ else back to Forth workspace

\ error condition handlers
@@5:       DREGS     LWPI, \ DJUMP5
@@6: @@8:  R1        CLR,  \ DJUMP6 bad device name
@@7:    R1           SWPB, \ DJUMP7
        R1      *R13 MOVB,
        HEX20 @@ R15 SOCB,
                     RTWP,

\ the vector for BLWP
l: DLNK   DREGS T, DSR1 T,

CODE: DSRLNK
        0 LIMI,
        DLNK @@      BLWP,
        8            DATA,
        2 LIMI,
        NEXT,
        END-CODE

 

 

 

Edited by TheBF
  • Like 4
Link to comment
Share on other sites

After an intense late night I think I have my head around this thing.

Part of the reason that the ALC version was slower than my original work was because I did not understand the error handling of the DSRLINK code.

Thanks to Lee showing the Thierry version I got to see some more comments. http://atariage.com/forums/topic/283914-specialized-file-access-from-xb/?p=4137731

 

Previously I was reading the status field in the PAB after every file read. Once I started using the DSRLINK error code compile times are almost the same as before. (~5% slower)

 

The big change is I now pass the DSR error code back to the Forth stack directly. This only took 2 small changes.

 

1. Prepare space on the Forth stack before calling the DSRLINK

CODE: DSRLNK  ( -- ior)
        TOS PUSH,          \ space for error code on Forth stack
        TOS CLR,           \ clear error code
        0 LIMI,
        DLNK @@      BLWP,
        8            DATA,
        2 LIMI,
        NEXT,
        END-CODE

2. Pass the DSR error code in DSR workspace R1 directly to R4 in the Forth workspace. (R4 is the top of stack cache register)

(* excuse the need for 2 labels on the R1 CLR line. My assembler's crude)

\ error condition handlers
@@5:    DREGS        LWPI,
@@6: @@8:  R1        CLR,  \ error code 0
@@7:    R1   8 (R13) MOV,  \ put error code in Forth TOS (r4)
        HEX20 @@ R15 SOCB, \ set EQ flag = 1
                     RTWP, \ return to Forth

In terms of nesting file access, I use a PAB/BUFFER stack. Each new PAB moves lower in memory and the buffer is just 256 of VDP RAM immediately after each PAB.

Once files are open, all I had to do was push the contents of >8356 onto the Forth return stack,

open the new file, and then restore >8356 when I come back from the new file.

Stacks are handy!

 

 

 

 

 

post-50750-0-41076700-1540047789.jpg

  • Like 2
Link to comment
Share on other sites

Once upon a time, when transistor radios were made by Sony in Japan...

 

I was told by a guy from Sony Broadcast Division that a legend at Sony was that after Engineering had designed a new radio Mr. Sony would give it to some nice ladies in the factory.

 

Their job was to remove parts one at a time.

If the radio still worked, then leave that part on the table

otherwise put it back in the radio and try the same process on the next part,

until all parts had been tried.

 

Then send it back to Engineering. :-D

-----------------------------------------------------------------------------------

I have been trying that with the DSRLINK routine. :) Konichiwa!

 

I removed all the SAVE variables because I don't use them That saved (5*4) + (5*2)= 30 bytes

 

There was also some confusing code in setting up the CRU address in R12 so I reduced that to what seemed necessary but still scanning the cards.

This is saving about 6 bytes or so.

 

 

I also noticed the when entering the GPL workspace R1 was cleared before the ROM scan and then set to 1 before calling the DSR code. Anyone know why?

I commented those lines out and everything seems to worked ok. (I call the DSR Link with interrupts off. Maybe that's why?)

So that saved another 4 bytes

So using Mr. Sony's idea I saved 30 bytes and a little execution time.

Then I realized I didn't need access to the inner names of things in the DSRLINK so using the cross-compiler's labels instead of Forth words means I save space as well.

So all together, implementing the DSR in assembler, if these changes are valid and some changes to the Forth code, has taken the CAMEL99 kernel size from 8104 to 7776 bytes. 328 Byte saving!

Edited by TheBF
  • Like 4
Link to comment
Share on other sites

I might have found a bug in CLASSIC99 when using TYPE 3 disks or I still don't understand things.

 

I was working over my DSRLNK and it worked perfectly when reading the file status field in the PAB while using TYPE 1 and TYPE 2 disks.

But with a type three disk I never got a change in status when I hit the EOF.

 

I spent a long time cursing my inability to find the problem in the Asm code. :)

 

In desperation I wanted to see what I was missing so I ran the equivalent program in BASIC and... it doesn't seem to find the EOF bits in the status flag either.

 

Here is the BASIC program:

100 REM   CATALOG DISK PROGRAM    
110 PRINT "Input DSKx. :";
120 INPUT DSK$
130 OPEN #1:DSK$,INPUT ,INTERNAL,RELATIVE
140 INPUT #1:N$,X,Y,Z
150 PRINT N$,X;Y;Z
160 GOTO 140
170 CLOSE #1
180 END

Run it and INPUT a type 1 or 2 disk and it will error out on 140.

But on a type 3 disk it runs forever, just like my Forth programs.

 

Is my analysis correct?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...