Jump to content
TheBF

DSRLINK Code Tutorial

Recommended Posts

If you don't care about GROM DSRs or tape casette I/O, here is Paolo Bagnaresi’s DSRLNK extracted from @Willsy’s 1-06-Blocks.html:

 

 

;
; dsr link routine - Written by Paolo Bagnaresi
;
dsrlnk  data dsrlws                 ; dsrlnk workspace
        data dlentr                 ; entry point

dlentr  li r0,>aa00
        movb r0,@haa                ; load haa
        mov *r14+,r5                ; get pgm type for link
        mov r5,@sav8a               ; save data following blwp @dsrlnk (8 or >a)
        szcb @h20,r15               ; reset equal bit
        mov @>8356,r0               ; get ptr to pab
        mov r0,r9                   ; save ptr
        mov r0,@flgptr              ; save again pointer to pab+1 for dsrlnk 
                                    ; data 8
        ai r9,>fff8                 ; adjust to flag
        bl @_vsbr                   ; read device name length
        movb r1,r3                  ; copy it
        srl r3,8                    ; make it lo byter
        seto r4                     ; init counter
        li r2,namsto                ; point to 8-byte buffer
lnkslp  inc r0                      ; point to next char of name
        inc r4                      ; incr char counter
        ci r4,>0007                 ; see if length more than 7 chars
        jgt lnkerr                  ; yes, error
        c r4,r3                     ; end of name?
        jeq lnksln                  ; yes
        bl @_vsbr                   ; read curr char
        movb r1,*r2+                ; move into buffer
        cb r1,@decmal               ; is it a period?
        jne lnkslp                  ; no
lnksln  mov r4,r4                   ; see if 0 length
        jeq lnkerr                  ; yes, error
        clr @>83d0
        mov r4,@>8354               ; save name length for search
        mov r4,@savlen              ; save it here too
        inc r4                      ; adjust for period
        a r4,@>8356                 ; point to position after name
        mov @>8356,@savpab          ; save pointer to position after name
srom    lwpi >83e0                  ; use gplws
        clr r1                      ; version found of dsr
        li r12,>0f00                ; init cru addr
norom   mov r12,r12                 ; anything to turn off?
        jeq nooff                   ; no
        sbz 0                       ; yes, turn off
nooff   ai r12,>0100                ; next rom to turn on
        clr @>83d0                  ; clear in case we are done
        ci r12,>2000                ; see if done
        jeq nodsr                   ; yes, no dsr match
        mov r12,@>83d0              ; save addr of next cru
        sbo 0                       ; turn on rom
        li r2,>4000                 ; start at beginning of rom
        cb *r2,@haa                 ; check for a valid rom
        jne norom                   ; no rom here
; 
; dstype is the address of R5 of the DSRLNK workspace (dsrlws--see bottom of page),
; which is where 8 for a DSR or 10 (>A) for a subprogram is stored before the DSR
; ROM is searched.
; 
        a @dstype,r2                ; go to first pointer (byte 8 or 10)
        jmp sgo2
sgo     mov @>83d2,r2               ; continue where we left off
        sbo 0                       ; turn rom back on
sgo2    mov *r2,r2                  ; is addr a zero (end of link)
        jeq norom                   ; yes, no programs to check
        mov r2,@>83d2               ; remember where to go next
        inct r2                     ; go to entry point
        mov *r2+,r9                 ; get entry addr just in case
        movb @>8355,r5              ; get length as counter
        jeq namtwo                  ; if zero, do not check
        cb r5,*r2+                  ; see if length matches
        jne sgo                     ; no, try next
        srl r5,8                    ; yes, move to lo byte as counter
        li r6,namsto                ; point to 8-byte buffer
namone  cb *r6+,*r2+                ; compare buffer with rom
        jne sgo                     ; try next if no match
        dec r5                      ; loop til full length checked
        jne namone
namtwo  inc r1                      ; next version found
        mov r1,@savver              ; save version
        mov r9,@savent              ; save entry addr
        mov r12,@savcru             ; save cru
        bl *r9                      ; go run routine
        jmp sgo                     ; error return
        sbz 0                       ; turn off rom if good return
        lwpi dsrlws                 ; restore workspace
        mov r9,r0                   ; point to flag in pab
frmdsr  mov @sav8a,r1               ; get back data following blwp @dsrlnk
                                    ; (8 or >a)
        ci r1,8                     ; was it 8?
        jeq dsrdt8                  ; yes, jump: normal dsrlnk
        movb @>8350,r1              ; no, we have a data >a. get error byte from
                                    ; >8350
        jmp dsrdta                  ; go and return error byte to the caller
dsrdt8  bl @_vsbr                   ; read flag
dsrdta  srl r1,13                   ; just keep error bits
        jne ioerr                   ; handle error
        rtwp
nodsr   lwpi dsrlws                 ; no dsr, restore workspace
lnkerr  clr r1                      ; clear flag for error 0 = bad device name
ioerr   swpb r1                     ; put error in hi byte
        movb r1,*r13                ; store error flags in callers r0
        socb @h20,r15               ; set equal bit to indicate error
        rtwp

data8   data >8                     ; just to compare. 8 is the data that
                                    ; usually follows a blwp @dsrlnk
decmal  text '.'                    ; for finding end of device name
        even
h20     data >2000

dsrlws  bss 10      ; data 0,0,0,0,0    ; dsrlnk workspace
dstype  bss 22      ; data 0,0,0,0,0,0,0,0,0,0,0  

 

 

...lee

  • Like 2

Share this post


Link to post
Share on other sites

R13,R14,R15, in GPLWS ... copies FAC off to VDP ... That nop ... Do you mean sbz on your second to last line?

 

Those are some good points, but the entire routine is running in User WS, with only the jump using GPL WS. You can see that I only modify R9 and R12.

 

I didn't know about FAC restauration, but this does not cause my endless loop.

 

The NOP is only temporary, but you're right about the sbo that should be a sbz.

 

Unfortunately, all this doesn't really explain why my DSRLNK doesn't work. Does the peripheral need more data in the FAC area besides >8354 and >8356?

Share this post


Link to post
Share on other sites

You could try a debug session in MAME to watch the register contents. Or send me your test program so I can check it.

Share this post


Link to post
Share on other sites

You could try a debug session in MAME to watch the register contents. Or send me your test program so I can check it.

 

Ugh, I tried that, but lost patience. It starts alright for the first three or so loop iterations within the TIFC, but it's just one bad breakpoint and BOOM!

 

I would never foist this on you. ;)

Share this post


Link to post
Share on other sites

Stuart, thanks for the Bagnaresi code, but there are some undefined symbols:

.

HAA  FLGPTR  NAMSTO  SAVLEN  SAVPAB  SAVVER   SAVENT  SAVCRU  SAV8A

.

HAA I can guess, but where should the others be? Inside the upper workspace, or just somewhere?

Share this post


Link to post
Share on other sites

Stuart, thanks for the Bagnaresi code, but there are some undefined symbols:

.

HAA  FLGPTR  NAMSTO  SAVLEN  SAVPAB  SAVVER   SAVENT  SAVCRU  SAV8A

.

HAA I can guess, but where should the others be? Inside the upper workspace, or just somewhere?

 

They are nothing special. Each one is just a word (2 bytes) in RAM except for NAMSTO, which is the name buffer and 8 bytes long. @Willsy put them in high expansion RAM, I think.

 

...lee

Share this post


Link to post
Share on other sites

They are nothing special. Each one is just a word (2 bytes) in RAM except for NAMSTO, which is the name buffer and 8 bytes long.

 

OK, now it's working ... I used just a word for NAMSTO, so it got overwritten by the other variables and the device/file would not be found.

 

Finally! A working DSRLNK. :)

  • Like 2

Share this post


Link to post
Share on other sites

but it's just one bad breakpoint and BOOM!

Anyone injured?

 

I would never foist this on you. ;)

I believe I've gained some experience with the MAME debugger.

 

<shrug> Well, I can't do more than offer to help. :)

Share this post


Link to post
Share on other sites

Thanks for the offer again, I'd pick it up, but I made some progress by finding the bug in the test program. Do you notice something about this code? :P

.

start:
       limi 0
       limi >8300

test1:
       li   r0, >3000
       li   r1, pab_open
       li   r2, pab_open_end - pab_open
       bl   @vmbw
       mov  @c_3009, @>8356
       bl   @dsrlnk
       data 8
;      ...

.

After I fixed my test program, my DSRLNK is suddenly working. I shouldn't code for that long ...

Share this post


Link to post
Share on other sites

  • Did you rewrite DSRLNK and VMBW to work without context switch?

How does the linker find the lowercase symbols for both?

Share this post


Link to post
Share on other sites
  • Did you rewrite DSRLNK and VMBW to work without context switch?
  • How does the linker find the lowercase symbols for both?

 

Yes, my versions work with BL instead of BLWP, and symbols are case insensitive. The missing symbols like PAB_OPEN are just somewhere, so this is not the bug ...

Share this post


Link to post
Share on other sites

Hmmm ... you certainly know that your interrupt mask constant is equivalent to 0, since only the last four bits are considered...

 

(you might as well try another instruction with it which sounds similar ... ;) )

  • Like 2

Share this post


Link to post
Share on other sites

Well—your statement “li r2, pab_open_end - pab_open” is not going to work as it appears you intend with those 3 spaces in the operand field, is it? Should it not be “li r2,pab_open_end-pab_open”?

 

...lee

Share this post


Link to post
Share on other sites

Yes, I wrote LIMI >8300 instead of LWPI >8300, but this sequence of LIMI 0 LWPI ws is so common I rarely look at it. :) The missing LWPI caused the test program and thus the DSRLNK to run at >83e0, which caused havoc with the actual >83e0 part. I took me several hours to find the bug.

 

The spaces are fine, as xas99 is more tolerant than E/A.

 

EDIT: clarification

Edited by ralphb

Share this post


Link to post
Share on other sites

The spaces are fine, as xas99 is more tolerant than E/A.

 

I suppose line end comments require something like a leading "*"?

Share this post


Link to post
Share on other sites

So I am working DSRLINK the hard way... of course I am.

Trying to write as much In Forth as I can. You know, for the fun of it.

 

 

And I found this table:

Bytes Content

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

>x000 >AA indicates a standard header

>x001 Version number

>0xx2 Number of programs (optional)

>x003 Not used

>x004 Pointer to power-up list (>0000 if none)

>x006 Pointer to program list (>0000 if none)

>x008 Pointer the DSR list (>0000 if none)

>x00A Pointer to subprogram list (>0000 if none)

 

I am reading the code by Signore Paolo Bagnaresi (Riposare in pace Senore)

So am I to understand that the only reason that "BLWP @DSRLNK" is followed by a literal number '8' is because that is the offset into the ROM table????

If so I am stunned.

 

It reminds of that famous saying:

 

" Eschew Obfuscation.

Be perspicuous!"

 

B :grin:

Edited by TheBF

Share this post


Link to post
Share on other sites

So I am working DSRLINK the hard way... of course I am.

Trying to write as much In Forth as I can. You know, for the fun of it.

 

 

And I found this table:

Bytes Content

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

>x000 >AA indicates a standard header

>x001 Version number

>0xx2 Number of programs (optional)

>x003 Not used

>x004 Pointer to power-up list (>0000 if none)

>x006 Pointer to program list (>0000 if none)

>x008 Pointer the DSR list (>0000 if none)

>x00A Pointer to subprogram list (>0000 if none)

 

I am reading the code by Signore Paolo Bagnaresi (Riposare in pace Senore)

 

So am I to understand that the only reason that "BLWP @DSRLNK" is followed by a literal number '8' is because that is the offset into the ROM table????

If so I am stunned.

 

It reminds of that famous saying:

 

" Eschew Obfuscation.

Be perspicuous!"

 

B :grin:

 

Yes!

 

...lee

Share this post


Link to post
Share on other sites

So am I to understand that the only reason that "BLWP @DSRLNK" is followed by a literal number '8' is because that is the offset into the ROM table????

If so I am stunned.

 

This is not so uncommon. There are two typical ways of parameter passing: using registers, or using a memory location behind the call. You find lots of examples in assembly code where you have a BL @SOMEWHERE with one or more DATA items afterwards; the subprogram can retrieve the values using *R11+. The same is true for BLWP and XOP, where *R14+ must be used.

Share this post


Link to post
Share on other sites

 

This is not so uncommon. There are two typical ways of parameter passing: using registers, or using a memory location behind the call. You find lots of examples in assembly code where you have a BL @SOMEWHERE with one or more DATA items afterwards; the subprogram can retrieve the values using *R11+. The same is true for BLWP and XOP, where *R14+ must be used.

 

I guess my surprise is around the fact that I believe all the ROMS mapped to >4000. It seems a needless complication to supply only the offset.

I suppose it is the ultimate in optimism.

 

<dream_sequence_music>

 

"We might have a 32bit TI-99 one day...

 

</dream_sequence_music>

 

:-)

Edited by TheBF

Share this post


Link to post
Share on other sites

 

I guess my surprise is around the fact that I believe all the ROMS mapped to >4000. It seems a needless complication to supply only the offset.

I suppose it is the ultimate in optimism.

 

<dream_sequence_music>

 

"We might have a 32bit TI-99 one day...

 

</dream_sequence_music>

 

:-)

 

Well, for one thing, the TI-99/4A spec does not require DSRs to all start at >4000 ROM. They are allowed to start in GROM space, as well.

 

EDIT: I should add that Bagnaresi’s and the E/A’s DSRLNK routines do not check for GROM DSRs, but the console's GPL DSRLNK does. It is the GPL DSRLNK that fbForth 2.0 uses via the MG (Millers Graphics) DSRLNK. This allows tape cassette usage as well as any GROM DSR one (not I) might invent.

 

...lee

Share this post


Link to post
Share on other sites

 

Well, for one thing, the TI-99/4A spec does not require DSRs to all start at >4000 ROM. They are allowed to start in GROM space, as well.

 

EDIT: I should add that Bagnaresi’s and the E/A’s DSRLNK routines do not check for GROM DSRs, but the console's GPL DSRLNK does. It is the GPL DSRLNK that fbForth 2.0 uses via the MG (Millers Graphics) DSRLNK. This allows tape cassette usage as well as any GROM DSR one (not I) might invent.

 

...lee

 

Ah yes the GROMs. Ok I will relent.

 

On another matter. I have created Forth words to turn on the disk card and I can read the header, and search for DSR names.

But from what I see in CLASSIC99 the address for DSK1 is >4800. However when I dump the ROM at address 4800 I see only zeros?

What am I missing here?

 

The screen shows my partially completed DSRLNK word operating... partially.

post-50750-0-08067600-1520905951.jpg

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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...