Jump to content
IGNORED

Assembly on the 99/4A


matthew180

Recommended Posts

Just now, JasonACT said:

One by one, it turns them on first, scans, then turns them off, but if a card with a higher address is already on by some non-standard user logic - you will get a conflict.  On the 2nd pass, they will all be off, because that's how the scan works.

There's no trick, it starts at >1000.

I actually edited my question for clarity just before you responded. Sorry :) Any thoughts on that?

Link to comment
Share on other sites

14 minutes ago, Vorticon said:

Now since my TIPI is at >1000, if it gets switched off on the first scanning pass, how come it remains active subsequently?

To answer that, you would need to describe why you think it remains active or what you think active means in this case.  It's just a matter of if the ROM is enabled at >4000 - and it won't be and shouldn't be once the DSR routine is done.

Link to comment
Share on other sites

So my TIPI emulates DSK1 which is actually a folder on the TIPI. Come to think of it however, it's still the same process, with the TIPI visible as a disk controller as far as the DSR scanning is concerned.

OK all clear now. Thanks for your patience is explaining things. It's important for me to understand that process since I frequently play with hardware interfacing and it's a minor miracle I haven't destroyed my system yet...

  • Like 3
Link to comment
Share on other sites

Yes, the key to understanding DSRLNK is to know the process. Here in pseudo-code.

executed = false
base_address = 1000H
repeat
  enable cru(base_address)
  if read_memory(4000H)=AAH then ' Valid DSR header
    scan for the desired device name ' Here only one card should be enabled
    if found then
      execute DSR function
      executed = true
  disable_cru(base_address)
  base_address = base_address+100H
until executed or base_address > 1F00H
 

The first scan will fail since a card with a higher address is enabled already before the scan starts. Thus the first scan will eventually finish with all cards disabled and no DSR found. Then the second scan will work properly, as no card is enabled prior to that scan.

This is very flexible but slow. A trick to speed it up is to use a stub of a DSRLNK procedure to first scan for the DSR programs you want to use (if you know them beforehand) and store their entry address and CRU base once found. But you don't execute them at that time.

Then the next time, when you really need them, you just use the pre-stored CRU address and DSR entry address directly, without scanning through all DSR addresses lower than the one you need all over again.

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

Another issue with the same program. While now I am able to save to disk, the pattern file is corrupted. Looking at the debugger in Classic 99, I see that there is VDP disk buffer corruption but I can't seem to figure out where the problem is. I have attached the executable and the listing. I have modified to program to bypass the image capture part (that part works fine and I get a proper image on screen) and have it just initialize the PDT and CT at >0 and >2000 respectively, setting the disk buffer at >1802. So when you run it as an Option #3 with the EA module, all you will see is a black screen, then 2 files will be created on DSK1, CAPTURE_P and CAPTURE_C for the pattern and color data respectively, and each should be 6144 bytes long. The pattern file is corrupted, but the color file appears OK. In the listing, the PAB info is around the beginning of the file, and the save section is toward the end, both clearly labeled. I spent several hours last night trying to figure this out to no avail. I've tried different disk buffer locations in VDP with no change. Any help from a brave soul here would be greatly appreciated...

 

TIVISIONHT TIVISHT_S

Link to comment
Share on other sites

4 hours ago, Vorticon said:

Another issue with the same program. While now I am able to save to disk, the pattern file is corrupted. Looking at the debugger in Classic 99, I see that there is VDP disk buffer corruption but I can't seem to figure out where the problem is. I have attached the executable and the listing. I have modified to program to bypass the image capture part (that part works fine and I get a proper image on screen) and have it just initialize the PDT and CT at >0 and >2000 respectively, setting the disk buffer at >1802. So when you run it as an Option #3 with the EA module, all you will see is a black screen, then 2 files will be created on DSK1, CAPTURE_P and CAPTURE_C for the pattern and color data respectively, and each should be 6144 bytes long. The pattern file is corrupted, but the color file appears OK. In the listing, the PAB info is around the beginning of the file, and the save section is toward the end, both clearly labeled. I spent several hours last night trying to figure this out to no avail. I've tried different disk buffer locations in VDP with no change. Any help from a brave soul here would be greatly appreciated...

 

You need to change the number of open files from the default 3 to 2. With 3, the PDT overlaps the bottom 40 bytes of the file buffer area. The following code should do the trick:

 

VDPWD  EQU  >8C00          ; VDP Write Data address
*
* Set maximum number of open files to 2
*
       LI   R0,>1802       ; PAB address
* "PAB" for FILES subroutine is namelength = 1..name = >16
       LI   R1,>0116       ; namelength & subroutine "name" (number)
       BLWP @VSBW          ; write the byte to the PAB
       SWPB R1             ; sub# to MSB
       MOVB R1,@VDPWD      ; write subroutine "name" to next byte of PAB
       LI   R1,>0200       ; max number of open files to MSB
       MOVB R1,@>834C      ; copy number of files to FAC+2
* R0 still pointing to PAB VRAM address
       MOV  R0,@>8356      ; copy namelength address to where DSR expects it
       BLWP @DSRLNK        ; do the subroutine
       DATA >0A   

 

...lee

  • Like 5
  • Thanks 1
Link to comment
Share on other sites

11 hours ago, Lee Stewart said:

 

You need to change the number of open files from the default 3 to 2. With 3, the PDT overlaps the bottom 40 bytes of the file buffer area. The following code should do the trick:

 

VDPWD  EQU  >8C00          ; VDP Write Data address
*
* Set maximum number of open files to 2
*
       LI   R0,>1802       ; PAB address
* "PAB" for FILES subroutine is namelength = 1..name = >16
       LI   R1,>0116       ; namelength & subroutine "name" (number)
       BLWP @VSBW          ; write the byte to the PAB
       SWPB R1             ; sub# to MSB
       MOVB R1,@VDPWD      ; write subroutine "name" to next byte of PAB
       LI   R1,>0200       ; max number of open files to MSB
       MOVB R1,@>834C      ; copy number of files to FAC+2
* R0 still pointing to PAB VRAM address
       MOV  R0,@>8356      ; copy namelength address to where DSR expects it
       BLWP @DSRLNK        ; do the subroutine
       DATA >0A   

 

...lee

Hi Lee. I actually only need one file open at any time. I honestly can't claim to understand what you just did here and I'd like to understand it better instead of just entering the code blindly. Where is the FILE routine documented?

  • Like 1
Link to comment
Share on other sites

2 hours ago, Vorticon said:

Hi Lee. I actually only need one file open at any time. I honestly can't claim to understand what you just did here and I'd like to understand it better instead of just entering the code blindly. Where is the FILE routine documented?

 

It is “Section 3.4 Buffer Allocation Routine—Subprogram 016” of GPL Interface Specification for the 99/4 Disk Peripheral. I have included it below:

GPL Interface Specification for the 99_4 Disk Peripheral V2.0 03-28-1983.pdf

 

The PAB in VRAM consists only of the counted “string” of the subprogram “name” (>0116) and you pass the length byte in >8356, which, for subprograms in the DSR is PAB+0 (not PAB+9 as with level 3 file I/O). Level 1 and 2 subprograms use what is called a transfer block that starts at FAC (>834A) or FAC+2 (>834C). Some of them require an additional information block in scratchpad RAM pointed to by the byte at >8350 (only the LSB of the scratchpad address you decide on). The byte at >8350 also receives the error code returned by these subprograms.

 

For Subprogram 016 (>16), the only item passed by your program in the transfer block at >834C is a byte representing the maximum number of files you want to allow open at the same time.

 

...lee

  • Like 3
Link to comment
Share on other sites

9 hours ago, Lee Stewart said:

 

It is “Section 3.4 Buffer Allocation Routine—Subprogram 016” of GPL Interface Specification for the 99/4 Disk Peripheral. I have included it below:

GPL Interface Specification for the 99_4 Disk Peripheral V2.0 03-28-1983.pdf 448.97 kB · 5 downloads

 

The PAB in VRAM consists only of the counted “string” of the subprogram “name” (>0116) and you pass the length byte in >8356, which, for subprograms in the DSR is PAB+0 (not PAB+9 as with level 3 file I/O). Level 1 and 2 subprograms use what is called a transfer block that starts at FAC (>834A) or FAC+2 (>834C). Some of them require an additional information block in scratchpad RAM pointed to by the byte at >8350 (only the LSB of the scratchpad address you decide on). The byte at >8350 also receives the error code returned by these subprograms.

 

For Subprogram 016 (>16), the only item passed by your program in the transfer block at >834C is a byte representing the maximum number of files you want to allow open at the same time.

 

...lee

Sounds like good bedtime reading as I am entirely unfamiliar with the topic of I/O levels. I've only dealt with the high-level DSRLNK for file access in the past. I'm sure I'll have many questions forthcoming, so you have been warned! :lol: Thanks!

  • Like 2
Link to comment
Share on other sites

I read the document and now have a clear idea of what that mysterious I/O levels business is all about. Thank you!

I do have a question: in your code snippet, you used VSBW for the first byte and VDPWD for the second byte after swapping. Couldn't you have just used VDPWD twice instead since it is self-incrementing?

Also you stated that the PDT was overlapping the bottom 40 bytes of the buffer are with 3 files. Why is that? Where does buffer allocation start and does it grow towards the top of memory?

Link to comment
Share on other sites

18 minutes ago, Vorticon said:

I do have a question: in your code snippet, you used VSBW for the first byte and VDPWD for the second byte after swapping. Couldn't you have just used VDPWD twice instead since it is self-incrementing?

VSBW is also setting up the write address in addition to writing a byte.

  • Like 1
Link to comment
Share on other sites

51 minutes ago, Asmusr said:

VSBW is also setting up the write address in addition to writing a byte.

Ah yes I see. I checked the documentation for VDPWD and the address needs to be set by VDPWA first, so using VSBW obviates that step and is more efficient. Learning something every day... Thanks.

  • Like 1
Link to comment
Share on other sites

4 hours ago, Vorticon said:

I read the document and now have a clear idea of what that mysterious I/O levels business is all about. Thank you!

I do have a question: in your code snippet, you used VSBW for the first byte and VDPWD for the second byte after swapping. Couldn't you have just used VDPWD twice instead since it is self-incrementing?

 

What @Asmusr said. I was going to give you code (coming soon!) you could call for setting up the VRAM read and write addresses, but did not want the point of my post to get lost.

 

4 hours ago, Vorticon said:

Also you stated that the PDT was overlapping the bottom 40 bytes of the buffer are with 3 files. Why is that? Where does buffer allocation start and does it grow towards the top of memory?

 

The file buffers grow down from the top of VRAM. The DSR reserves and sets up space, starting from the address it finds at >8370, for the volume information block of the current disk; data and file control block buffers (518 bytes) for each file allowed to be open simultaneously; and other space it needs such as a small stack for the DSR. When it is done, it updates >8370 with the new highest-available-VRAM address. You should always check that your program never passes the address in >8370.

 

...lee

  • Like 1
Link to comment
Share on other sites

In my Browser program I have a routine to ...

 

*Set number of disk files supported to 1 ("CALL FILES(1)") to move the disk controller reserved area in VDP RAM
*from >37D7 (where it overlaps with the colour table and sprite generator table) to >3BE3 (where it only overlaps
*with a part of the sprite generator table that we don't use anyway).

  • Like 2
Link to comment
Share on other sites

2 hours ago, Lee Stewart said:

 

What @Asmusr said. I was going to give you code (coming soon!) you could call for setting up the VRAM read and write addresses, but did not want the point of my post to get lost.

 

 

The file buffers grow down from the top of VRAM. The DSR reserves and sets up space, starting from the address it finds at >8370, for the volume information block of the current disk; data and file control block buffers (518 bytes) for each file allowed to be open simultaneously; and other space it needs such as a small stack for the DSR. When it is done, it updates >8370 with the new highest-available-VRAM address. You should always check that your program never passes the address in >8370.

 

...lee

So do I set >8370 manually or are there default locations set up depending on the number of files open simultaneously? Where is this documented by the way?

Link to comment
Share on other sites

5 hours ago, Vorticon said:

So do I set >8370 manually or are there default locations set up depending on the number of files open simultaneously? Where is this documented by the way?

 

You do not mess with >8370. You look at it to see what is the highest VRAM address you can use. DSRs that use the upper VRAM set the value for >8370 to inform other software what not to touch. Even they check >8370 for where they can start.

 

Thierry's site is a good place to start.

 

...lee

  • Like 4
Link to comment
Share on other sites

OK so I added the code for a FILES = 1, but no dice. The pattern file is only 4198 bytes instead of the expected 6144, and I can see that all but the last 128 bytes are properly initialized. Looking at the Classic 99 debugger, I'm seeing an "invalid file buffer header at >37D7" which the address of the top of VRAM  and that the file is attempting to save from VDP address >A946 instead of >0. 

Now since the color table is at >2000, it should extend to >3800, and so it is likely overwriting to top of VRAM which I suspect is probably the issue (?)

I tried setting >8370 to >3BE3 manually (i know Lee told me not to, but I was desperate), but it reverted back to >37D7.

Help?

 

Link to comment
Share on other sites

When you call the FILES=1 code, can you see the value at >8370 change from >37D7 to >3BE3? To verify that that bit of code is working correctly?

 

The code I use is as below - a few differences to the way that Lee does it but they should both achieve the same thing.

 

          ************************************
          *Set number of disk files supported.
          ************************************
          
          *Set number of disk files supported to 1 ("CALL FILES(1)") to move the disk controller reserved area in VDP RAM
          *from >37D7 (where it overlaps with the colour table and sprite generator table) to >3BE3 (where it only overlaps
          *with a part of the sprite generator table that we don't use anyway).
          
29B6 0200 ENDCONF LI   R0,PABADR      Copy PAB for sub-program to VDP RAM.
29B8 1D00  
29BA 0201         LI   R1,PABSP
29BC A65A  
29BE 0202         LI   R2,PBSPL
29C0 0002  
29C2 0420         BLWP @VMBW
29C4 28A2  
          
29C6 C800         MOV  R0,@>8356      Set up pointer to sub-program name length byte in VDP RAM.
29C8 8356  
          
29CA 0200         LI   R0,>0100       Set number of disk files in the byte required by the sub-program.
29CC 0100  
29CE D800         MOVB R0,@>834C
29D0 834C  
           
29D2 0420         BLWP @DSRLNK        Call the sub-program.
29D4 28CC  
29D6 000A         DATA 10
...
...
...
A65A 0116 PABSP   BYTE >01,>16        Program name length and program name for sub-program in Disk Controller DSR that
          *                           sets the number of file buffers.
0000 0002 PBSPL   EQU  $-PABSP        Length of this PAB.

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

I checked address >8370 and it is indeed showing >3BE3 at the end of the program with FILES = 1. So that's not it.

Looking at the debugger output, on the first SAVE operation for the CAPTURE_P file, it is attempting to save from VDP address >A946 instead of >0 which is likely why that file is truncated and corrupted, but on the second SAVE, it saves correctly from address >2000 for the CAPTURE_C file. This is really odd because only byte 2 and 3 of the PAB (the buffer address) are being affected, and only for the first SAVE operation. Completely stumped.

I have reverted back to using address >1F02 for the PAB in VDP at the location of the SAL which I invalidate by placing a >D0 at >1F00. This should be a safe location.

I have attached the source file with the FILES code incorporated right after the START label, as well as the assembled file which can be run with EA Opt #3 so you can check the debugger output in Classic 99. When you run it, you will get a black screen, which is when you should start the debugger. 

I'm running out of hair to pull...

TIVISIONHT TIVISHT_S

Link to comment
Share on other sites

8 minutes ago, Asmusr said:

The word at >a840 contains the value >a946 when the PAB is copied to VDP RAM. You can add a breakpoint in Classic99 when >a840 is written to, to see why it's changed.

>A840 is  the location of bytes 2 and 3 of the PAB for the CAPTURE_P file, and this is exactly where the problem is occurring. Something is changing that location somewhere in the program before the PAB is transferred to the VDP.... I need to see what it is.

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...