Jump to content
Sign in to follow this  
Kchula-Rrit

How to make Level-2 I/O work?

Recommended Posts

I'm trying to use the Level 2 I/O function to get file information, but cannot seem to make it work.  Using Thierry Nouspikel's information, I placed the following values in scratch-pad RAM:

0x834C = 2 (DSK2)

0x834D = 0 (Get file info)

0x834E = 0x2000 (filename = TEST;C)

0x8350 = 0x30 (0x8330 for returned info)

0x8356 = 0x2010 (start address for "command")

 

I placed the following in VDP RAM:

0x2000 = 'TEST;C    '

0x2010 = 1 ("Command" length)

0x2011 = 0x14 (Get file info)

 

Here's the code I used.  I've fiddled with it, and gotten bleary-eyed from trying to read about how to make this thing work.  I assume I'm doing something wrong, but just cannot figure out what.  The part between the ellipsis(es) are the code I'm using.

...
#asm
* Clear STATUS byte.
    CLR  R8
    MOVB R8,@>837C
 
* File is in DSK2.
    LI   R8,>200
    MOVB R8,@>834C
 
* Zero means "get file info".
    CLR  R8
    MOVB R8,@>834D
 
* Copy name to VDP RAM.
    LI   R0,2000
 
* Save file-name pointer for DSR access.
    MOV  R0,@>834E
 
    LI   R1,MYNAME * File-name.
    LI   R2,14     * Name length.
    BLWP @VMBW
 
* Copy "get file info" command to VDP.
    LI   R0,GETNFO
    LI   R1,2010
 
* Save PAB pointer for DSR access.
    MOV  R1,@>8356
 
    LI   R2,2   * "Command" name length.
    BLWP @VMBW
 
* Place results at 0x8330.
* C99 doc said this is unused by C99.
    LI   R8,>30
    MOV  R8,@8350
 
* Set return status.  0 = success.
    SETO @RESULT
 
    MOVB @GRMRA,@MYGROM
    NOP
    MOVB @GRMRA,@MYGROM+1
    DEC  @MYGROM
 
* Call DSR.
    BLWP @DSRLNK
    DATA 10
 
* If error, skip next instruction.
    JEQ  ERROR
 
* Call succeeded; set status to 0.
    INC  @RESULT
 
ERROR
* Save dsr return code.
    SRL  R0,8
    MOV  R0,@DSRERR
 
* Restore GROM address.
    MOVB @MYGROM,@GRMWA
    NOP
    MOVB @MYGROM+1,@GRMWA
...
 
* Saved GROM address.
MYGROM BSS 2
 
* Test file.
MYNAME
    BYTE 10            * Name length.
*   BYTE 6             * Name length.
*   TEXT 'DSK2.'
    TEXT 'TEST;C    '
    TEXT '      '
    BYTE 0
 
    EVEN
 
GETNFO
    BYTE 1   * "name" length.
    BYTE >14 * "Get file info" routine.
...

 

 

Any advice would be appreciated.

K-R.

Share this post


Link to post
Share on other sites
Posted (edited)
15 hours ago, Kchula-Rrit said:

I'm trying to use the Level 2 I/O function to get file information, but cannot seem to make it work.

   ...

Any advice would be appreciated.

K-R.

 

I remember working through this quite some time ago. At first glance, it looks like the only thing wrong is the filename pointer. It should be pointing at the filename, not the length byte as with Level 3 access:

* Copy name to VDP RAM.
    LI   R0,>2000       <----FORGOT '>' in front of 2000
 
* Save file-name pointer for DSR access.
    MOV  R0,@>834E
    LI   R1,MYNAME+1    * File-name.    <----POINT TO FIRST CHARACTER OF FILENAME
    LI   R2,11          * Name length.  <----COPY 10 CHARACTERS + TERMINATING 0
    BLWP @VMBW

 

Also, insure that the 11th character is a null (0):

* Test file.
MYNAME
    BYTE 10              * Name length.
    TEXT 'TEST;C    '    <----EXACTLY 10 CHARACTERS
    BYTE 0
    EVEN

 

I presume you are using the E/A cartridge’s DSRLNK. If so, I am not sure why you are saving and restoring the GROM location. I guess I should review Thierry’s information. |:)

 

...lee

Edited by Lee Stewart
code correction
  • Like 1

Share this post


Link to post
Share on other sites

Quick glance also. Double check 8350 - I think you need to move a byte to >8350, not a word.  LI R8,>3000; MOVB r8,@>8350.

 

* Place results at 0x8330.
* C99 doc said this is unused by C99.
    LI   R8,>30
    MOV  R8,@8350

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, InsaneMultitasker said:

Quick glance also. Double check 8350 - I think you need to move a byte to >8350, not a word.  LI R8,>3000; MOVB r8,@>8350.

 

* Place results at 0x8330.
* C99 doc said this is unused by C99.
    LI   R8,>30
    MOV  R8,@8350

 

Good eye! Sorry, I missed that one. Yes, indeed, that needs to be a byte because it is the low byte of the scratchpad address of the Additional Information block—in this case, >8330.

 

...lee

Share this post


Link to post
Share on other sites

First, thanks for your assistance and the "extra eyeballs".  I did the following:

 

Got rid of the length byte on the filename, then set it to ten bytes padded with spaces, with a NULL byte.

Changed MOV R8,@8350 to a MOVB.

 

Tried running it with and without saving the GROM address.  I did it because Tom Bentley did so in TCIO.C, figuring that he knew more about calling DSRs than I do.  Is it plagiarism if you admit it? 8-)

 

I still got all zeroes in my return values.

 

Then, thinking it might be a mismatch between C and assembly (I would not be surprised if it is) I plugged values into the return variables on the assembly side and they printed OK.

 

While I was prettying-up the code to possibly post it, I noticed several places where I forgot to include the ">" to make values hex instead of decimal.  One of many bonehead mistakes I seem to make a lot.

It still returns all zeroes, but now, after answering "N" to the "re-run C99" prompt, the computer locks up.  Last time that happened I "fixed" it by re-formatting the "disk" in the NanoPEB and recompiling.  I'll try that tonight.

 

I'm running this with the E/A cartridge, with v5.1 of C99 with a date of 1994.  The C part just prints the results.  I can post the whole test program, but it's 180 lines.  How would I do the scrolling blu-ish window thing that people do for code?

 

K-R.

 

  • Like 1

Share this post


Link to post
Share on other sites

In this section, R0 is typically the VDP address and R1 is CPU ram address. Are the two reversed.  The address moved to 8356 would be the VDP address now in R0.    Also, I believe your address in R1 should be >2010 not 2010, i.e., hex value vs. decimal value.  Maybe post your updated code for the group.

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

* Copy "get file info" command to VDP.
    LI   R0,GETNFO
    LI   R1,2010

 
* Save PAB pointer for DSR access.
    MOV  R1,@>8356
 
    LI   R2,2   * "Command" name length.
    BLWP @VMBW

 

Edit: similar thing here.

* Copy name to VDP RAM.
    LI   R0,2000

 

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, Kchula-Rrit said:

I'm running this with the E/A cartridge, with v5.1 of C99 with a date of 1994.  The C part just prints the results.  I can post the whole test program, but it's 180 lines.  How would I do the scrolling blu-ish window thing that people do for code?

 

If you mean what we oldies call a spoiler, I used to use the old BBCs (Bulletin Board Codes), which still seem to work, sort of. What you can do is to choose the spoiler icon (the eye) on the edit menu bar. Then, click inside the window and choose the code icon (“</>”). You can put your code into the window that pops up. That will give the code that folks see a monospaced appearance that preserves all of your proper spacing.

 

...lee

  • Like 1

Share this post


Link to post
Share on other sites

It works!  I had the VDP and CPU RAM addresses reversed on the two-byte VMBW, and a few more missing ">"s on constants.  If it works, here is the source for my test program.  The good stuff is done in the assembly part; the C part is just for pretty-printing the results.

 /* test.c  (TI-name "TEST;C") */
 
#include "dsk1.stdio;h"
 
 
 /* Definitions. */
 
#asm
    REF  VMBR,VMBW
    REF  GRMRA,GRMWA
    REF  DSRLNK
    REF  DUMPREGS
 
#endasm
 
int   dsknum; /* Disk number.            */
int   sectr1; /* Sector 1 locatin.       */
int   filtyp; /* File-type flags.        */
int   recsec; /* Records-per-sector.     */
int   eofoff; /* EOF offset.             */
int   reclen; /* Record length.          */
int   recrds; /* Record count.           */
int   result; /* EQ flag after DSR exit. */
int   dsrerr; /* DSR error code.         */
int   my8350; /* Whatever's returned in 0x8350. */
 
int  outfile; /* Output file descriptor. */
 
extern putline(); /* Send string to file. */
extern dp4();     /* Print value as decimal to file. */
extern xp2();     /* Print 2 hex digits to file. */
extern xp4();     /* Print 4 hex digits to file. */
 
 
main ()
 
{
 
    dsknum = 2;
 
    diskinfo ();
 
    /* Use C to just print results. */
    outfile = fopen ("SIO.BA=9600", "a");
 
    putline ("File name is \"DSK", -1, outfile);
    dp4 (dsknum, outfile);
    putline (".", -1, outfile);
    putline (MYNAME, -1, outfile);
 
    putline ("\".\nSector 1 location = ", -1, outfile);
    xp4 (sectr1, outfile);
 
    putline (".\nFile flags = ", -1, outfile);
    xp2 (filtyp, outfile);
 
    putline (".\nRecords-per-sector = ", -1, outfile);
    xp2 (recsec, outfile);
 
    putline (".\nEOF offset = ", -1, outfile);
    xp2 (eofoff, outfile);
 
    putline (".\nRecord length = ", -1, outfile);
    xp2 (reclen, outfile);
 
    putline (".\nRecord count = ", -1, outfile);
    xp2 (recrds, outfile);
 
    putline (".\nDSR \"eq\" bit = ", -1, outfile);
    dp4 (result, outfile);
 
    putline (".\nDSR error = ", -1, outfile);
    xp2 (dsrerr, outfile);
 
    putline (".\nDSR return code = ", -1, outfile);
    xp2 (my8350, outfile);
 
    putline (".\n", -1, outfile);
    fclose (outfile);
 
    exit (0);
 
}
 
 
diskinfo ()
 
{
 
#asm
* Save caller's registers.
    MOV  R0,@OLDR0
    MOV  R1,@OLDR1
    MOV  R2,@OLDR2
 
* Clear STATUS byte.
    CLR  R8
    MOVB R8,@>837C
 
* File is in DSK2.
    MOV  @DSKNUM,R8
    SWPB R8
    MOVB R8,@>834C
 
* Zero means "get file info".
    CLR  R8
    MOVB R8,@>834D
 
* Copy name to VDP RAM.
    LI   R0,>2000
 
* Save file-name pointer for DSR access.
    MOV  R0,@>834E
 
    LI   R1,MYNAME * File-name.
    LI   R2,11     * Name length.
    BLWP @VMBW
 
* Copy "get file info" command to VDP.
    LI   R0,>2010
    LI   R1,GETNFO * GETNFO-> 0x0114.
 
* Save PAB pointer for DSR access.
    MOV  R0,@>8356
 
    LI   R2,2   * "Command" name length.
    BLWP @VMBW
 
* Place results at 0x8330.
* C99 doc said this is unused by C99.
    LI   R8,>3000
    MOVB R8,@>8350
 
* Set return status.  0 = success.
    LI   R8,1
    MOV  R8,@RESULT
 
* Call DSR.
    BLWP @DSRLNK
    DATA 10
 
* If error, skip next instruction.
    JEQ  ERROR
 
* Call succeeded; set status to 0.
    DEC  @RESULT
 
ERROR
* Save dsr return code.
    SRL  R0,8
    MOV  R0,@DSRERR
 
* Get first-sector location.
    MOV  @>8332,@SECTR1
 
* Get file flags.
    MOVB @>8334,R8
    SRL  R8,8
    MOV  R8,@FILTYP
 
* Get records-per-sector.
    MOVB @>8335,R8
    SRL  R8,8
    MOV  R8,@RECSEC
 
* Get EOF offset.
    MOVB @>8336,R8
    SRL  R8,8
    MOV  R8,@EOFOFF
 
* Get record length.
    MOVB @>8337,R8
    SRL  R8,8
    MOV  R8,@RECLEN
 
* Get record count.
    MOVB @>8338,R8
    SRL  R8,8
    MOV  R8,@RECRDS
 
* Get whatever's returned in 0x8350
    MOVB @>8350,R8
    SRL  R8,8
    MOV  R8,@MY8350
 
* Restore caller's registers.
    MOV  @OLDR0,R0
    MOV  @OLDR1,R1
    MOV  @OLDR2,R2
 
#endasm
 
    return;
 
}
 
 
#asm
 
    EVEN
 
OLDR0 BSS 2
OLDR1 BSS 2
OLDR2 BSS 2
 
 
* Saved GROM address.
MYGROM BSS 2
 
* Disk number.
MYDISK
    DATA 2
 
MYNAME
* Test file name.
    TEXT 'TEST;S    '
    BYTE 0
 
GETNFO
* "Get file info" Level-2 command.
    BYTE 1   * "name" length.
    BYTE >14 * "Get file info" routine.
 
BFRDSR
    TEXT 'Before dsrlink...'
    BYTE 0
 
AFTDSR
    TEXT 'After dsrlink...'
    BYTE 0
 
#endasm
 

The blue-ish scrolling-window thingie works!  I made some test runs with various types of files and will put the results in my next post.

 

K-R.

 

  • Like 1

Share this post


Link to post
Share on other sites

Okay, the blue-ish thing worked, but the scrolling bit did not.  I was hoping to not make the posts so big, but do not seem to have a choice.  Anyway, here are the results:

[Display/Variable File]
File name is "DSK2.TEST;S    ".
Sector 1 location = 0023.  (Not used for file-info command)
** Values here are hex **   These are from Fred Kaal's Web site.
File flags = 80.           (Bit 0 set = Variable-length records)
   0x80  Set = Variable    Clear = Fixed
   0x08  Set = Protected   Clear = Not Protected
   0x02  Set = Binary      Clear = ASCII
   0x01  Set = Program     Clear = Data
Records-per-sector = 03.   (makes sense; int(256 / 3) = 80)
EOF offset = 93.           (I'll have to trust it.)
Record length = 50.        (Correct 0x50 = 80 bytes)
Record count = 23.         (DM2K shows 36 records; count + 1 for heaer)
DSR "eq" bit = 1.          (DSR "eq" bit set upon return; not sure why)
                           (E/A manual says that I/O sets this bit)
DSR error = 01.            (Not sure what this is)
DSR return code = 00.      (MS 3 bits = 0; means "success")


[Display/Fixed File]
File name is "DSK2.DISKDIR;C ".
Sector 1 location = 000F.
File flags = 00.
Records-per-sector = 02.
EOF offset = 00.
Record length = 80.
Record count = 1E.
DSR "eq" bit = 1.
DSR error = 02.
DSR return code = 00.


[Non-existent file.]
File name is "DSK2.TEST;Q    ".
Sector 1 location = 0000.
File flags = 00.
Records-per-sector = 00.
EOF offset = 00.
Record length = 00.
Record count = 00.
DSR "eq" bit = 1.
DSR error = 01.
DSR return code = E0.


[Write-protected file.]
File name is "DSK2.DUMPREGS;S".
Sector 1 location = 0026.
File flags = 88.
Records-per-sector = 03.
EOF offset = 25.
Record length = 50.
Record count = 26.
DSR "eq" bit = 1.
DSR error = 01.
DSR return code = 00.


[XBASIC File]
File name is "DSK3.LOAD-TELCN".
Sector 1 location = 0005.
File flags = 01.
Records-per-sector = 00.
EOF offset = 9B.
Record length = 00.
Record count = 00.
DSR "eq" bit = 1.
DSR error = 02.
DSR return code = 00.


[Program File]
File name is "DSK3.TELCN     ".
Sector 1 location = 0001.
File flags = 01.
Records-per-sector = 00.
EOF offset = DA.
Record length = 00.
Record count = 00.
DSR "eq" bit = 1.
DSR error = 01.
DSR return code = 00.


[Length-byte not equal to one]
File name is "DSK2.TEST;S    ".
Sector 1 location = 0000.
File flags = 00.
Records-per-sector = 00.
EOF offset = 00.
Record length = 00.
Record count = 00.
DSR "eq" bit = 1.
DSR error = 00.
DSR return code = 30.


[Non-existent DSR call ("command" = 0x34)]
File name is "DSK2.TEST;S    ".
Sector 1 location = 0000.
File flags = 00.
Records-per-sector = 00.
EOF offset = 00.
Record length = 00.
Record count = 00.
DSR "eq" bit = 1.
DSR error = 00.
DSR return code = 30.


[Non-existent Drive (Disk Number = 4)]
Computer locked up.

Since the computer locked up when I specified a nonexistent drive, and probably would do so with other errors, I figure I could use the Level-3 DSR call for STATUS (PAB Command 9) first to catch the "egregious" errors and not lock the computer.  If the STATUS command works I could then use the Level-2 get-file-info command (0x114) to get further file information to complement what the STATUS command returns.

 

K-R.

 

  • Like 2

Share this post


Link to post
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.

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...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...