Jump to content

Photo

Assembly: Problem calling GPLLNK without 32 KB memory expansion


30 replies to this topic

#1 BJGuillot OFFLINE  

BJGuillot

    Star Raider

  • 55 posts

Posted Mon May 2, 2016 11:55 AM

I'm a bit stuck with a problem.  I want my QR Code Generator to be able to run on a non-expanded TI.  It had been working until I added support for the "small character set" needed for 40-column mode.  I traced the problem into the GPLLNK call that I found from TurboForth that was used to obtain the small character set.

 

For some reason, the BLWP call to GPLLNK works fine in js99er.net if the 32 KB memory expansion option is enabled, but if I turn that option off, the program causes the emulated TI to reset back to the title screen when it encounters the "bl *r4" line.  When the program runs correctly, it will simply display "HELLO WORLD" and freeze.

 

I'm not sure if it's my fault in the way I've got things setup, something in the GPLLNK routine itself, something in the emulator, or if there is some fundamental reason that doesn't allow GPLLNK to work on a non-expanded TI.

 

I have attached a small sample program that demonstrates the problem.  (I assemble it using "xas 99 -R -c gpltest.a99" to get an RPK that I can load with js99er.net.

 

Any assistance would be appreciated.  And if there's a way to load the small character set without using GPLLNK, I'm open to using an alternate technique.  This was just the only technique I'd been able to find so far.

Attached Files



#2 mizapf OFFLINE  

mizapf

    River Patroller

  • 3,607 posts
  • Location:Germany

Posted Mon May 2, 2016 12:03 PM

Bummer ... I wanted to do a quick test, but I cannot assemble this code with Editor/Assembler because you are using lowercase commands and other non-TI formatting.

 

I know this looks nice for external assemblers like xas, but it blocks any way to assemble this inside the emulation or on real iron.



#3 InsaneMultitasker OFFLINE  

InsaneMultitasker

    River Patroller

  • 2,427 posts

Posted Mon May 2, 2016 1:00 PM

The routine uses some of the lower 8K  (>2000). When you disable the 32K, the routine has no where to store the data it is moving or looking for when it gets to the "bl *r4".



#4 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Mon May 2, 2016 3:06 PM

The problem with calling GPLLNK is that you need a way back to ALC.  The only option I'm aware of is via the GPL XML command (>0F).  If you are not writing and executing your own GPL program, you must find in an existing GROM the >0F byte followed immediately by a byte that gets you to an ALC location that contains the address of an ALC routine.  The only areas over which the programmer has any control for this purpose in the present case are low RAM and cartridge ROM.  The GPLLNK routine you are using (from Millers Graphics, originally) uses the only viable byte combination in GROM 0, viz., >0F27, at >176C, which translates to “XML 27”, which branches to >200E in low RAM.  That is why the 32KiB expansion must be present.

 

In order to branch to cartridge space, you would need to find a GROM byte combination of >0F70 – >0F7F, which would allow branches to ROM addresses >6010 – >602E.  There is no such byte combination in GROM 0.  I don't know about GROM 1 or GROM 2 because I don't have a dump of those GROMs.

 

Another option would be to copy the character patterns from GROM to VRAM yourself.  The small capital character set (64 patterns) starts at >06B0 in GROM 0 and the lower case character set (31 patterns) starts at >0870 in GROM 0.  One fly in the ointment is that each pattern is only 7 bytes of the 8 bytes required for each character!  Between the two character sets, it saved 95 bytes.  You would need to zero the first byte and copy the next 7.  If you are interested, I could probably cobble together a routine to do either or both sets.

 

...lee


  • RXB likes this

#5 BJGuillot OFFLINE  

BJGuillot

    Star Raider

  • Topic Starter
  • 55 posts

Posted Mon May 2, 2016 3:45 PM

Thanks for the help guys.  It seems a lot more complicated than I expected.

 

When InsaneMultitasker pointed out I was hitting low expanded RAM at >2000, I had one of those Doh! moments, and thought it'd be a simple matter to just change that to a location in scratch RAM, but for all the reasons Lee pointed out, it seems like that was a dead end.

 

I did find a thread, http://atariage.com/...or-the-gpl-gate, where retroclouds was trying to do something similar, but I am not following it closely enough to try to replicate it.

 

I think trying to copy the character set from GROM to VRAM will be the better approach.  Thanks for the offer to cobble up a routine, but I'd like to try it first myself.  I hate asking for help on things unless I get totally stuck or need to discuss options.

 

I did encounter some discussions about the danger of bypassing GPL and copying the character set from GROM is that different GROM versions may have the character set starting at different addresses.  Is there any truth to that?



#6 BJGuillot OFFLINE  

BJGuillot

    Star Raider

  • Topic Starter
  • 55 posts

Posted Mon May 2, 2016 5:44 PM

OK, I went ahead and gave up on trying to use GPL to load the small character set.

 

I'm attaching a file that uses the method suggested (to read the character set out of GROM).

 

A few differences noted from what was suggested:

 

I had to use address >06B4 (instead of >06B0).

 

Also, I noticed that I could read all 95 patterns sequentially from GROM (instead of the first 64 patterns at >06B4, and then looking for the other 31 patterns at the other location).  I'm not sure if this is something being caused by the js99er.net emulator or if it might be something else.  (I have not tried this on a real console yet.)

Attached Files



#7 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Mon May 2, 2016 6:54 PM

Also, I noticed that I could read all 95 patterns sequentially from GROM (instead of the first 64 patterns at >06B4, and then looking for the other 31 patterns at the other location).  I'm not sure if this is something being caused by the js99er.net emulator or if it might be something else.  (I have not tried this on a real console yet.)

 

Yes...The two sets are contiguous.

 

...lee



#8 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Mon May 2, 2016 7:59 PM

I had to use address >06B4 (instead of >06B0).

 

 

Classic99's GROM 0 is, in fact, 3 bytes off in one place from Heiner Martin's dump of GROM 0.  The Classic99 GROM 0 does use >06B4 for the start of the small cap char set patterns.  There is an >FC byte just before the start of the table that might be useful for registration.

 

...lee


  • RXB likes this

#9 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Mon May 2, 2016 10:38 PM

BJ...

 

I noticed in grom.a99 that you set VDPSC to >08FF, which is one byte before the pattern for 'space' (ASCII 32)—not capital 'A' as you indicate.  That has the effect of shifting the characters one pixel higher than starting at >0900.  It's not a problem because the zero byte of the next character pads the bottom of the current character.  I just wondered whether that was your intent.

 

...lee



#10 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,638 posts
  • HarmlessLion
  • Location:BUR

Posted Mon May 2, 2016 11:13 PM

Since there are a couple of GROM0's out there, I actually released code a while back that copies the lower case character set by parsing the GROM jump vector to find the code... let me see if I can find that for you. :)

#11 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,487 posts
  • Location:Lansing, NY, USA

Posted Tue May 3, 2016 8:18 AM

GPLLNK can be used without the memory expansion.  I need to know a little more about your memory usage before I can help you.  It looks like your workspace is at >8300.  Do you use other parts of the scratchpad?  Will your assembly code be in a ROM cartridge?  Let me know and I will be able to look at this tonight and come up with a solution that will work. 

 

(edit) Forgot to ask if you only want to load the lower case characters or if you need the full GPLLNK for other purposes.


Edited by senior_falcon, Tue May 3, 2016 9:05 AM.


#12 acadiel OFFLINE  

acadiel

    Stargunner

  • 1,506 posts
  • www.hexbus.com
  • Location:USA

Posted Tue May 3, 2016 9:20 AM

Since there are a couple of GROM0's out there, I actually released code a while back that copies the lower case character set by parsing the GROM jump vector to find the code... let me see if I can find that for you. :)

 

 

I think I have that.  We put it as part of the 32K cart that we used with Fred's disk utility multicart, I believe.

* BANK 0-4 ROM HEADER FOR 32K BANKED
* SWITCHED CART
       DEF SFIRST,SLAST,SLOAD
       UNL
* ROM HEADER
       AORG >6000
SFIRST EQU $
SLOAD  EQU $
GRMHDR BYTE >AA,1,1,0,0,0
       DATA PROG
       BYTE 0,0,0,0,0,0,0,0
PROG   DATA 0
       DATA GOGO
       BYTE 8
       TEXT 'DM2K 2.3'
       EVEN
MINIT  EQU $
       LWPI >8300
 
* Entry point here - ideally put this code first in your ROM
* load R3 with 6 for 99/4, or 7 for 99/4A
GOGO
 CLR R0
 BL @GPLSET
 BL @GETGPL   * read GROM >0000
 LI R3,7
 CI R0,>AA01  * 99/4 is AA01, all versions of 99/4A seem to be AA02 (even 2.2!)
 JNE IS4A     * note we also assume unknown is 99/4A just to be safe
 DEC R3
 
* make a copy of the capitals for the 99/4 to 'support' lowercase
* this will be partially overwritten by the main set, but it works!
 LI R0,>0018  * GPL vector address
 LI R1,>4A00  * dest in VDP - must OR with >4000 for write
 LI R2,>0040  * how many chars
 BL @GPLVDP   * this function goes somewhere later in your ROM
 JMP MNSET
 
IS4A
* 'lowercase' letters
 LI R0,>004A  * GPL vector address (not available for 99/4)
 LI R1,>4B00  * dest in VDP - must OR with >4000 for write
 LI R2,>001F  * how many chars
 BL @GPLVDP   * this function goes somewhere later in your ROM
 
* main set
MNSET
 LI R0,>0018  * GPL vector address
 LI R1,>4900  * dest in VDP - must OR with >4000 for write
 LI R2,>0040  * how many chars
 BL @GPLVDP   * this function goes somewhere later in your ROM
 
* THIS IS THE ROUTINE THAT WILL
* SWAP BANKS TO HIGH BANK
MAIN   MOV R0,@>6000
       LI R4,>0714  * BYTES DIV 4
       LI R9,>63B0  * ADDRESS TO COPY FROM
       LI R10,>A000 * ADDRESS TO COPY TO
LP1
       MOV *R9+,*R10+
       MOV *R9+,*R10+
       DEC R4
       JNE LP1
 
* THIS IS THE ROUTINE THAT WILL
* SWAP BANKS TO NEXT BANK
MAIN2  MOV R0,@>6002
       LI R4,>0714
       LI R9,>63B0
       LI R10,>BC50
LP2
       MOV *R9+,*R10+
       MOV *R9+,*R10+
       DEC R4
       JNE LP2
 
* THIS IS THE ROUTINE THAT WILL
* SWAP BANKS TO NEXT BANK
MAIN3  MOV R0,@>6004
       LI R4,>0714
       LI R9,>63B0
       LI R10,>D8A0
LP3
       MOV *R9+,*R10+
       MOV *R9+,*R10+
       DEC R4
       JNE LP3
 
* THIS IS THE ROUTINE THAT WILL
* SWAP BANKS TO THE LOW BANK
MAIN4  MOV R0,@>6006
       LI R4,>023F
       LI R9,>7704
       LI R10,>2000
LP4
       MOV *R9+,*R10+
       MOV *R9+,*R10+
       DEC R4
       JNE LP4
 
* ALRIGHT, WE'RE DONE.  LET'S GO!
 
       B @>A000
 
* Set GROM address
GPLSET
 MOVB R0,@>9C02
 SWPB R0
 MOVB R0,@>9C02
 B *R11
 
* Get a word from GPL
GETGPL
 MOVB @>9800,R0
 SWPB R0
 MOVB @>9800,R0
 SWPB R0
 B *R11
 
* Copy R2 characters from a GPL copy function vectored at
* R0 to VDP R1. GPL vector must be a B or BR and
* the first actual instruction must be a DEST with an
* immediate operand. Set R3 to 6 for 99/4 (6 byte characters)
* or 7 for a 99/4A (7 byte characters)
GPLVDP
 MOV R11,R10    * save return address
 BL @GPLSET     * set GROM address
 BL @GETGPL     * Get branch instruction (not verified!)
 ANDI R0,>1FFF  * mask out instruction part
 AI R0,3        * skip instruction and destination
 BL @GPLSET     * set new GROM address
 BL @GETGPL     * get actual address of the table
 BL @GPLSET     * and set that GROM address - GROM is now ready!
 
 SWPB R1        * assume VDP is already prepared for write to save space
 MOVB R1,@>8C02
 SWPB R1
 MOVB R1,@>8C02 * VDP is now ready!
 
 CLR R0
 
LP8
 MOVB R0,@>8C00 * pad the top of the char with a space
 MOV R3,R0      * then copy 7 (or 6) bytes
 CI R3,6        * check for 99/4
 JNE LP9
 MOVB R0,@>8C00 * extra blank line for 99/4
 
LP9
 MOVB @>9800,@>8C00  * copy a byte (both sides autoincrement)
 DEC R0
 JNE LP9
 
 DEC R2         * next character
 JNE LP8
 
 B *R10
 
FINISH EQU $
SLAST  END
 
 


#13 BJGuillot OFFLINE  

BJGuillot

    Star Raider

  • Topic Starter
  • 55 posts

Posted Tue May 3, 2016 10:46 AM

I noticed in grom.a99 that you set VDPSC to >08FF, which is one byte before the pattern for 'space' (ASCII 32)—not capital 'A' as you indicate.  That has the effect of shifting the characters one pixel higher than starting at >0900.  It's not a problem because the zero byte of the next character pads the bottom of the current character.  I just wondered whether that was your intent.

 

Hmm...  I think I probably grabbed the >08FF address from something I saw during one of my Google searches and just stuck with it.  I'll need to go fix it.  Still getting the hang of the memory map and other oddities of the TI.  And still have a hard time thinking in hexadecimal.  :-)  Thanks for the help.



#14 BJGuillot OFFLINE  

BJGuillot

    Star Raider

  • Topic Starter
  • 55 posts

Posted Tue May 3, 2016 10:52 AM

GPLLNK can be used without the memory expansion.  I need to know a little more about your memory usage before I can help you.  It looks like your workspace is at >8300.  Do you use other parts of the scratchpad?  Will your assembly code be in a ROM cartridge?  Let me know and I will be able to look at this tonight and come up with a solution that will work. 

 

(edit) Forgot to ask if you only want to load the lower case characters or if you need the full GPLLNK for other purposes.

 

The primary purpose was just to get the character set to use for the 40- (and 80-) column modes.  It looks like reading them directly from GROM may be a suitable workaround, though.  For play and learning purposes, it might be fun to try calling some of the other GPL routines (like the beep/honk sounds), but I assume those can probably be done without GPL as well.

 

I'd like to be able to run my code from a ROM cartridge at some point (for non-expanded TI's), but also provide the flexibility to run it from disk using EA (for people with a PEB or NanoPEB).



#15 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,487 posts
  • Location:Lansing, NY, USA

Posted Tue May 3, 2016 11:33 AM

 

The primary purpose was just to get the character set to use for the 40- (and 80-) column modes.  It looks like reading them directly from GROM may be a suitable workaround, though.  For play and learning purposes, it might be fun to try calling some of the other GPL routines (like the beep/honk sounds), but I assume those can probably be done without GPL as well.

 

I'd like to be able to run my code from a ROM cartridge at some point (for non-expanded TI's), but also provide the flexibility to run it from disk using EA (for people with a PEB or NanoPEB).

Will have it tonight for you. 



#16 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Tue May 3, 2016 2:03 PM

The problem with calling GPLLNK is that you need a way back to ALC.  The only option I'm aware of is via the GPL XML command (>0F).  If you are not writing and executing your own GPL program, you must find in an existing GROM the >0F byte followed immediately by a byte that gets you to an ALC location that contains the address of an ALC routine.  The only areas over which the programmer has any control for this purpose in the present case are low RAM and cartridge ROM.

 

This last statement is wrong.  The E/A manual has an incomplete list of XML table references!  Thierry's site has the complete list and there are two XML table references to scratchpad RAM:  >A0 – >AF and >F0 – >FF, both of which refer to >8300 – >831E.  There are seven locations in GROM 0 that can be used to get you to a routine whose address is in >8300, >8306, >8316, >831C and >831E.  The locations and their references are listed below:

 

GROM 0 Address  XML Cmd  Vector Address
--------------  -------  --------------
    >00E8       XML >FF      >831E
    >034C       XML >FF      >831E
    >0379       XML >F0      >8300
    >0DBB       XML >F3      >8306
    >0EDE       XML >FB      >8316
    >1264       XML >F0      >8300
    >1675       XML >FE      >831C
 

...lee



#17 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,487 posts
  • Location:Lansing, NY, USA

Posted Tue May 3, 2016 2:41 PM

You're on the right path now.  You might find that a BL @GPLLNK will work as well as BLWP @GPLLNK.   Unless someone beats me to it I will post a BL @GPLLNK routine tonight.


  • RXB likes this

#18 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,638 posts
  • HarmlessLion
  • Location:BUR

Posted Tue May 3, 2016 3:08 PM

I think I have that.  We put it as part of the 32K cart that we used with Fred's disk utility multicart, I believe.


That's it, thanks. GPLVDP is the function in question in there, and it's called twice (once for uppercase, once for lowercase).

#19 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Tue May 3, 2016 5:31 PM

Hoo-boy!  :-o  In revisiting my last post with an eye to comparing the two GROM 0's I now know about, they only agree on the last address!!  At least, there appears to be one invariant—unless there's a third one out there that could scramble this.  Here's the result for the GROM 0 used by Classis99 compared to the one dumped by Heiner Martin:

 

   GROM 0 Address             XML Cmd          Vector Address
(Classic99) (Martin)  (Classic99) (Martin)  (Classic99) (Martin)
--------------------  --------------------  --------------------
   >00E8     >00E5      XML >FF   XML >FF      >831E     >831E 
   >034C     >0349      XML >FF   XML >FF      >831E     >831E
   >0379     >0376      XML >F0   XML >F0      >8300     >8300
   >0DBB     >0DB7      XML >F3   XML >EF      >8306     >D01E
   >0EDE     >0EDA      XML >FB   XML >F7      >8316     >830E
   >1264     >1260      XML >F0   XML >F0      >8300     >8300
   >1675     >1675      XML >FE   XML >FE      >831C     >831C
 

...lee



#20 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,487 posts
  • Location:Lansing, NY, USA

Posted Tue May 3, 2016 9:40 PM

I haven't tested it, but this should do the trick:  (edited per Lee's suggestion below)

********************************************************************************
*GPLLNK AND DSRLINK FROM THE SMART PROGRAMMER
*adapted to use scratchpad RAM only
*Uses >8320 as a workspace
********************************************************************************
 
GPLWS  EQU >83E0
GLNKWS EQU >8320
GR4    EQU GPLWS+8
GR6    EQU GPLWS+12
LDGADD EQU >60
XTABFE EQU >831C
GETSTK EQU >166C

 
GPLLNK DATA GLNKWS
       DATA GLINK1
 
GXMLAD DATA >1675
        
GLINK1	MOV @>0050,@GR4
       MOV *R14+,@GR6
       MOV @XTABFE,R12
	LI R9,XMLRTN
       MOV R9,@XTABFE
       LWPI GPLWS
       BL *R4
       MOV @GXMLAD,@>8302(R4)
       INCT @>8373
       B @LDGADD
 
XMLRTN MOV @GETSTK,R4
       BL *R4
       LWPI GLNKWS
       MOV R12,@XTABFE
       RTWP

Edited by senior_falcon, Wed May 4, 2016 5:36 AM.


#21 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Tue May 3, 2016 11:41 PM

Looks good, Harry!

 

I think I would change the 'XTAB27' label to 'XTABFE' to avoid confusion, however.

 

...lee



#22 senior_falcon OFFLINE  

senior_falcon

    Stargunner

  • 1,487 posts
  • Location:Lansing, NY, USA

Posted Wed May 4, 2016 6:47 PM

I just tested the modified GPLLNK in post #20 and it works fine for loading the 3 possible character sets (Large, regular and lower case)  Main program workspace was at >8300 and the BLWP workspace was at >8320.



#23 ralphb OFFLINE  

ralphb

    Dragonstomper

  • 654 posts
  • Location:Germany

Posted Wed Mar 20, 2019 10:20 AM

Heh, I arrived almost at the same code, but what's the relation of XTABFE and GXMLAD?  AFAIK the original routine uses >200E and >176C, but both >1675 and >176C don't make any sense address-wise.

 

How are those values used?  I might want to move XTABFE somewhere else.



#24 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,966 posts
  • Location:Silver Run, Maryland

Posted Wed Mar 20, 2019 12:38 PM

Heh, I arrived almost at the same code, but what's the relation of XTABFE and GXMLAD?  AFAIK the original routine uses >200E and >176C, but both >1675 and >176C don't make any sense address-wise.

 

How are those values used?  I might want to move XTABFE somewhere else.

 

The following probably contains a lot of what you already know, but, hopefully, it answers your questions and may help the casual reader with other details:
 
XTABFE contains the address of the 15th vector (16 possible) in the 16th XML vector table (16 possible) referenced by the GPL code: “XML >FE”.  The two-byte, hex code for this is >0FFE.  The XML table:element refrence is >FE, with >Fx referencing the table starting at >8300 and >xE referencing element >1C—hence >831C as the value of XTABFE.
 
GXMLAD contains the address of the GPL XML instruction (>0FFE) we wish the GPL interpreter to execute, which is located at GROM0 address >1675.
 
Regarding the GROM0 addresses >1675 and >176C, GPL instructions are on byte boundaries, not word boundaries as with ALC.  The GPL XML instruction opcode (>0F) appears at both locations.  The XML table:vector byte that follows it in the first reference (>1675) is >FE, which is explained above.  In the Heiner Martin GROM0 dump, the byte following >0F at >176C is >27, which points to the 8th vector (>200E) in the 3rd XML vector table, starting at >2000 in low RAM.  Because the GPL interpreter is byte oriented, it does not matter that the GPL “instructions” at >1675 and >176C are data and never normally executed.  It is sufficient that they happen, fortuitously, to be the actual instructions we need to serve our ends.
 
...lee


#25 ralphb OFFLINE  

ralphb

    Dragonstomper

  • 654 posts
  • Location:Germany

Posted Wed Mar 20, 2019 1:29 PM

Oooh, I see now!  :idea: 

 

I thought that these might be GROM addresses, but then in TI Intern I saw that these are within text strings?!  Oh, how clever!

 

Thanks for enlightening me, I'll be looking for other, more convenient >0F's!   :)






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users