Jump to content
IGNORED

Learning GPL and XML routine programming


speccery

Recommended Posts

I have continued to work on my StrangeCart project, which is here in a separate thread. After working quite a bit on the hardware design, firmware design, board validation and so on I'm now working on integrating the StrangeCart with TI Basic, at least a bit. In this process I have had to learn some GPL, but I am definitely a newbie with it. I decided to open a new topic on this, since my GPL adventures and related questions are probably going to be simple in terms of code, and might be of interest (?) to others as well. 

 

Even if I am working on this code on my StrangeCart hardware, the GPL code which is not communicating with the StrangeCart should be runnable using Final GROM. Having said that I am not sure if it emulates the 4K SRAM included in the Mini Memory, but that SRAM is not the point of this discussion, normal 32K RAM could be used equally well. Right now my code is not really using RAM outside scratchpad area.

 

My goal is to simply add some new commands to TI Basic, to enable it to interface with the StrangeCart from TI Basic. But before getting that far, I need to develop an understanding how one adds Basic callable routines to a cartridge. 

 

I took as the basis of my code the source of the Mini Memory module. It is very interesting for me, as it includes both GPL code and machine code and interfaces between the two. I have now implemented my first GPL routine which can be called from TI Basic, something like CALL LIST(1). My GPL code gets successfully reached and executed, and it manages to get back to Basic gracefully. It decodes one parameter passed by Basic, converts it into an integer, and then passes it over to my assembler routine using the XML GPL opcode.

 

Very conveniently the Mini Memory module implements a XML jump table, and it has one empty unused slot for XML >73. I'm now using that slot for my own machine code.

 

Since GPL debugging is pretty tough, I have resorted to writing to screen memory some characters, to show how my code is advancing.

 

Thierry's tech pages contain the source code for the Mini Memory module. The pages also explain very nicely how the XML tables work, in the GPL section of the website. I ported the source code so that I can use XDT99 (xga99.py and xas99.py) to compile the mini memory module source code with my additions.

 

For those not in the know, the XML >73 is a GPL opcode to branch to a machine code routine. Thus it enables GPL code to call TMS9900 machine code routines. The address where the code branches to is provided in a series of jump tables. The parameter >73 is a hexadecimal value which identifies the jump table to use. It means that the address where to branch to is given in the CPU address >6016. This happens to be in the cartridge ROM space, so it is ideal for my use. I just place into >6016 a pointer to TMS9900 machine code which handles the XML code.

 

The Mini Memory module contains a normal 6K GROM chip. My StrangeCart assumes that all GROMs are actually 8K. This gives me additional 2K of GROM space, where I can easily mock around with my code and add small routines without removing existing Mini Memory code.

 

I have added this GPL routine to handle CALL LIST. I modified the GROM header so that subprogram "LIST" points to the GLIST routine below. The routine decodes the parameter which is passed to it, and writes stuff to screen based on it. If the parameter is zero, it writes the word STRANGE to the screen. If it is non-zero, it writes that value in hexadecimal to the screen at a fixed location. The hexadecimal conversion and writing to screen is done in the assembler code, not in GPL.

Spoiler

 


****************************
* Our listing command "CALL LIST"
GLIST   CALL  G@G6530         Skip subprogram name in Basic statement and open parenthesis
        PARSE >B6             parse next parameter (B6 is closed parenthesis)
        CEQ   >65,@>834C      Is it a string?
        BS    G@G6DBE         yes: string number mismatch 
        XML   >12             no: convert float to integer
        CEQ   >03,@>8354      overflow occured?
        BS    G@G6DB9         yes: issue error
        ; Now @>834A has our integer. Now we can do something.
        DCEQ  >0000,@>834A    Is the integer zero?
        BS    G@DISP_MSG      Yes: display our message
        ; No, just continue.
        ST   >A1,V@>0020       Write something to the screen, we're here!
        XML   >73              Call my assembly routine to display the value in 834A
                               ; >73 returns with Cnd set.
        B     G@G6749

DISP_MSG  ; Alright let's show a message from GROM!
        MOVE >07,G@DSTR1,V*>8320
        DADD  >0007,@>8320    Advance screen positiong by 7.
        ST   >A2,V@>0020       Write something to the screen, we're here!
        BR    G@G6749          Check current token for ) and return to Basic.

DSTR1   DATA  >B3B4           'S' & 'T' + 0x60
        DATA  >B2A1           'R' & 'A'
        DATA  >AEA7           'N' & 'G'
        DATA  >A500           'E',00

 


 

The Mini Memory contains 4K of ROM memory in CPU space from >6000..>6FFF. Luckily there is a large chunk of this space which is not used, and I put the XML >73 handler in that space. The routine just writes to screen memory in hexadecimal the value passed from Basic.

Spoiler

*
*---------------------------------------
* Bytes >697E to >6F0D all contain >00
*---------------------------------------
*     BSS  >0588
*------------------------------------------
* EP: Except in my case I put code in here.
* This is where XML >73 lands.
* It appears the low registers at least are 
* safe to change.
*------------------------------------------
STRANGECODE
; Test and write the argument from GPL in 834A in hex to the screen.
; Set address
      MOV 11,@>7004           ; Save return address, probably not needed
      LI  4,>80               ; Screen address where to write to.
      LI  1,>8E00             ; '.'+96, write the period character
      BL  @A694E              ; Set VDP address, and write byte from R1
      MOV @>834A,2            ; Load value to be printed to R2
      LI  3,4                 ; 4 digits to write.
!     MOV 2,1
      BL  @HEXDIG
      SLA 2,4
      DEC 3
      JNE  -!

      B     @A6970            Jump to above, get back to GPL

HEXDIG ; Write the highest nibble of 1 in hex to VDP memory
      SRL   1,4               Shift to low nibble of byte
      CI    1,>0900           Is the value 9 or lower
      JLE   !                 Yes: branch
      AI    1,>0700           No: Add 7 to high byte of R1
!     AI    1,>9000         Add screen offset 60 and 30 to get ASCII of 0
      MOVB  1,@>8C00
      B     *11

       BSS  >054A
A6F06  BSS  >0008
*
*---------------------------------------
* Default symbol table
*---------------------------------------
A6F0E  TEXT 'UTLTAB'          utility table for loader

 

 

I have tested this stuff with a Basic program, you can see the listing and output in the pictures below.

 

I could check this, but I wonder what workspace is used to run the XML routine?

I assume it is either >8300 or the GPL workspace >83E0, but since the Mini Memory code seems to explicitly restore workspace into >83E0, it is probably at >8300.

 

The other question is, what registers are safe to use in the XML routine machine code? I know I could set up my own workspace, but I like the idea of keeping the workspace in scratchpad memory.

 

Also, what is the "right" way of returning from a XML routine back to Basic? I am currently using the code in the Mini Memory module, at address A6970:

A6970  LWPI >83E0             GPL workspace
A6974  SOCB @A660D,@>837C     set Cnd bit
       B    @>0070            to GPL interpreter

 

 

IMG_4732.jpg

IMG_4733.jpg

  • Like 3
Link to comment
Share on other sites

8 hours ago, speccery said:

I could check this, but I wonder what workspace is used to run the XML routine?

I assume it is either >8300 or the GPL workspace >83E0, but since the Mini Memory code seems to explicitly restore workspace into >83E0, it is probably at >8300.

 

The other question is, what registers are safe to use in the XML routine machine code? I know I could set up my own workspace, but I like the idea of keeping the workspace in scratchpad memory.

 

Also, what is the "right" way of returning from a XML routine back to Basic? I am currently using the code in the Mini Memory module, at address A6970:

Not entirely sure about BASIC ...but when working with GPL images, I've observed >83E0 to be the GPL interpreters workspace. While executing an XML op-code, >061A BL *R4, uses WORKSPACE >83E0, where R4 holds the jump table's vector address. Thus R11 contains RT address >061C, which in turn jumps to >05E4 B @>0070.

 

I usually try to utilize my own WORKSPACE, than restore GPL WORKSPACE, before using "B *R11" to return to GPL. Pretty sure you're not supposed to alter R13, 14, 15. But I'd bet BASIC might be even more finicky.

 

So, looks like you're doin' AOK!;-)

 

1.thumb.jpg.9dec1761753f08fa6ac814e5f7d40ca4.jpg

 

2.thumb.jpg.608365d8a251f3d3601545de31aa6dd8.jpg

 

Edited by HOME AUTOMATION
  • Like 2
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...