Jump to content
matthew180

Assembly on the 99/4A

Recommended Posts

1 hour ago, PeteE said:

To use the scratchpad for data, I use a group of EQUates to define address of variables, leaving room for the register workspace, and calculate the offsets manually by adding the size of the previous item to the current offset:

WRKSP EQU >8300    ; workspace at top of scratchpad
PLAYER EQU WRKSP+32  ; 32 is the size of WRKSP, player is 2 bytes
ENEMY EQU WRKSP+34   ; 2 bytes after PLAYER, enemy is 2 bytes
KEYLOC EQU WRKSP+36   ; 2 bytes after ENEMY, keyloc is 2 bytes
ETC

Keep in mind the scratchpad is only 256 bytes, so the offset cannot exceed 255... and you either need to avoid using scratchpad data used by the ISR, or keep  interrupts off (LIMI 0) for the duration of your program.

   Thanks @PeteE. I’m familiar with the scratchpad and EQUates. I do like the way you’re using offsets vs actual addresses, as I’m using.

 

   Your method makes it easy to maintain available scratchpad awareness without doing any Hex math. 
 

   As for the ISR, I’ve been convinced to avoid that for game programming with LIMI 0 as per previous posts on this same thread. Rolling my own routines to preserve scratchpad predictability and speed.  

  • Like 1

Share this post


Link to post
Share on other sites
50 minutes ago, Airshack said:

   Thanks @PeteE. I’m familiar with the scratchpad and EQUates. I do like the way you’re using offsets vs actual addresses, as I’m using.

 

   Your method makes it easy to maintain available scratchpad awareness without doing any Hex math. 
 

   As for the ISR, I’ve been convinced to avoid that for game programming with LIMI 0 as per previous posts on this same thread. Rolling my own routines to preserve scratchpad predictability and speed.  

Another method I've been meaning to try out is the xdt99 feature of XORG, so you could lay out your data in memory using DATA statements without having to calculate offsets manually, like this:

VARDAT XORG >8320      ; start after workspace
PLAYER DATA >0000
ENEMY  DATA >0000
KEYLOC DATA >0000
ETC

The difference between this and AORG, is that the DATA bytes are copied into your program at VARDAT, so you can initialize your variables by copying words from VARDAT to >8320 when your program starts.

  • Thanks 1

Share this post


Link to post
Share on other sites
11 hours ago, PeteE said:

In order to run on an unexpanded console, you need to put your program in cartridge ROM like this:

       AORG >6000      ; start at cartridge ROM

* cartridge header
* your program code

MAPDAT
       BYTE ....  ; your map data from Magellan
       BYTE ....  ; note this is now read-only

This is interesting. Let’s say I’d like to test what I have so far using FinalGROM. After using AORG >6000, I’ll need to know more about cartridge headers.

 

Any good sources? I have but a vague notion of what a cartridge header involves. 

Share this post


Link to post
Share on other sites
41 minutes ago, Airshack said:

This is interesting. Let’s say I’d like to test what I have so far using FinalGROM. After using AORG >6000, I’ll need to know more about cartridge headers.

 

Any good sources? I have but a vague notion of what a cartridge header involves. 

Here's an example cartridge header, with a single program in the program list:

       AORG >6000         ; Cartridge header in all banks

HEADER
       BYTE >AA     ; Standard header
       BYTE >01     ; Version number 1
       BYTE >01     ; Number of programs (optional)
       BYTE >00     ; Reserved (for FG99 this can be G,R,or X)
       DATA >0000   ; Pointer to power-up list
       DATA PRGLST  ; Pointer to program list
       DATA >0000   ; Pointer to DSR list
       DATA >0000   ; Pointer to subprogram list

PRGLST DATA >0000   ; Next program list entry
       DATA START   ; Program address
       BYTE CRTNME-CRTNM       ; Length of name
CRTNM  TEXT 'CARTRIDGE NAME'
CRTNME
       EVEN

START                         ; Your program starts here
       LWPI WRKSP             ; Load the workspace pointer to fast RAM
       LIMI 0                 ; Interrupts off
       ...

You would change the string at CRTNM to reflect what you want to appear in the TI menu "PRESS 2 FOR" ... and it must appear in all upper-case.

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
22 hours ago, Airshack said:

 One thought: If I keep track of where my key objects should be located on the scrollable game map, I can simply plot them over grass tiles, after each viewport redraw. I’m imagining this will create a blinking appearance as the map is continually redrawn, and the key is then replotted. Perhaps it will appear as a nice feature highlighting the key’s location?

If you, say, "require" the Memory Expansion (32K) for your game, you can copy the map from ROM (cartridge) to CPU RAM (and go from there as you wanted). Lots of bigger games of later years require the Memory Exp., so that's all okay, except if you're a wannabe purist. It's probably my kinda niche, though I'll keep doors open. Back in the day, millions or most TI-99/4A owners did not have the Memory Exp. These days, anyone with emulation has easy (or de-facto) access to the Memory Exp.
 
Also (with or without Memory Exp.), you can have more than one screen in VDP RAM. You can draw on one, while displaying another. Often refered to as double buffering. When you've done drawing, you switch the display to that new location. You can theoretically (and practical) have as much as 16 different screens stored in the VDP at once. If you switch right after a VDP interrupt, you'll see no screen tearing on real hardware (have to assume unexpanded console because of interrupts) (also Classic99 generally tears a lot these days, but that's another issue).

 

Edited by sometimes99er
  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites
21 hours ago, PeteE said:

Here's an example cartridge header, with a single program in the program list:

       AORG >6000         ; Cartridge header in all banks

HEADER
       BYTE >AA     ; Standard header
       BYTE >01     ; Version number 1
       BYTE >01     ; Number of programs (optional)
       BYTE >00     ; Reserved (for FG99 this can be G,R,or X)
       DATA >0000   ; Pointer to power-up list
       DATA PRGLST  ; Pointer to program list
       DATA >0000   ; Pointer to DSR list
       DATA >0000   ; Pointer to subprogram list

PRGLST DATA >0000   ; Next program list entry
       DATA START   ; Program address
       BYTE CRTNME-CRTNM       ; Length of name
CRTNM  TEXT 'CARTRIDGE NAME'
CRTNME
       EVEN

START                         ; Your program starts here
       LWPI WRKSP             ; Load the workspace pointer to fast RAM
       LIMI 0                 ; Interrupts off
       ...

You would change the string at CRTNM to reflect what you want to appear in the TI menu "PRESS 2 FOR" ... and it must appear in all upper-case.

Hmmm... with this tidy information I can see a Cartridge version of CAMEL99 Forth coming out of the cross-compiler. :) 

This makes it look very straightforward.

 

Thanks very much for this.

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
4 minutes ago, TheBF said:

Hmmm... with this tidy information I can see a Cartridge version of CAMEL99 Forth coming out of the cross-compiler. :) 

This makes it look very straightforward.

 

Thanks very much for this.

 

Same kind of info at the head of each of the four banks of fbForth 2.0 source code available on my website below.

 

...lee

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
1 minute ago, Lee Stewart said:

 

Same kind of info at the head of each of the four banks of fbForth 2.0 source code available on my website below.

 

...lee

Awesome. Thanks Lee.

I have never gone down that path but it was on my todo list. The post by PeteE made me see that it's not as tricky as I imagined.

Away on some business for the weekend but will get back to the coding next week early. 

Freeing up 8K more Expansion RAM would really make a difference for the size of project I can support.

I have been envious of you and Willsy on that front. :) 

 

 

  • Thanks 1

Share this post


Link to post
Share on other sites
43 minutes ago, TheBF said:

Hmmm... with this tidy information I can see a Cartridge version of CAMEL99 Forth coming out of the cross-compiler. :) 

This makes it look very straightforward.

 

Thanks very much for this.

 

You're welcome. I can't claim credit though, I'm sure I took it from somewhere else, but I can't remember where.  Probably here

Edited by PeteE
  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
On 1/23/2020 at 2:44 PM, Airshack said:

   Anyway, it’s working now. I have a bridge key on my game map! 

 

   MOV    @MAPDAT, R6     * pointer to beginning of map

   LI        R7,>D900          * Character D9 = bridge key

   MOVB  R7,*R6               * Place key at map origin as a test

 

   My problem last night was I was using the following first line:

 

    LI        R6, @MAPDAT        * then basically corrupting MAPDAT                                         

 

   Caused all sorts of havoc onto my game screen.

Well, none of the above is 100% correct.

 

MOV @MAPDAT,R6 will not store a pointer to MAPDAT in R6, but the content of the memory word at MAPDAT. Thus your byte >D9 will end up at the address pointed to by the data at the first word of MAPDAT, not in the first word of MAPDAT. This will defnitely not be what you expect, and will perhaps lock up your computer. That's the least myserious thing that could occur.

 

On the other hand, LI R6,@MAPDAT isn't correct either. It's not even correct syntax, since such a construct doesn't exits for the TMS 9900. What you want to do is LI R6,MAPDAT, since it's the value of MAPDAT you want to use as a pointer to the first MAPDAT word.

 

To map an area in memory, that's not in line with your code, you can use a construct even TI's original assembler provides. You can use dummy segments, where the dummy origin, DORG, allows for generating entries in the symbol list, without generating any code.

 

DORG >8300

FIRST DATA 1234

SECOND DATA >35F2

THIRD BYTE 22

FOURTH TEXT 'X'

 

Will generate symbol table entries for the labels, like if they were assembled starting at address >8300. But no data is created in a dummy segment, nor loaded into memory at load time.

Edited by apersson850
  • Like 2
  • Thanks 1

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