Firstly, know that this is a full revamp of what this post originally said, since I realized the question was rather stupid. My current question is simple: How do I use safe RAM? Can someone supply a simple example in ASM or show how it can be used? Thanks!

Also, is it possible to somehow access the memory that is used for the A, B, C... variables available in TI-BASIC? Those have to be safe.
You'd use safeRAM like you would use any other variable, except that it is not part of your program (and thus, saves space for the more interesting parts of your program). These safeRAM locations are defined in ti83plus.inc, and you use them as though you use variables that are internal to your program. You just have to keep in mind that this memory area is not initialized and can contain anything, so it is your responsibility to set them to a known value prior to using them.

Common safeRAM areas include "appbackupscreen" and 767 bytes after that, "savesscreen" and 767 bytes after that (safe as long as your program can't APD), "plotsscreen" and 767 bytes after that (graph screen buffer). There are others that are available. Don't feel like looking them up at the moment.

You use them by reading or writing to them. It's helpful to define equates to various places in this memory so you don't have to manually keep track of each location as you're using them up.


Code:

temp1  equ appbackupscreen  ;example variable.
temp2  equ appbackupscreen+2 ;another example.

 ld hl,$0000
 ld (temp1),hl
 ld hl,$8000
 ld (temp2),hl
 ld de,(temp1)

That code doesn't actually do anything except shows you stuff you can do and the form it may take.

Accessing BASIC variables such as "A" or "B" is done by a system call in the form of bcall(nameOfRomCall) or B_CALL nameOfRomCall, depending on what assembly setup you use.

The particular system call requires the appropriate name for the variable in a safeRAM area that is the 11 bytes at Op1 (only the first 9 bytes is used).


Code:

 ld hl,RealVariableA
 bcall(_Mov9toOp1)  ;moves 9 bytes from RealVariableA to Op1
 bcall(_RclVarSym)   ;if variable exists, copies contents to Op1
 ret

RealVariableA:
.db RealObj,"A",0,0

Of course, the variable is in TI's floating point format. If you want your ASM program to actually use the value in it, you will need to add the following code after bcall(_RclVarSym):

Code:

 bcall(_ConvOp1)  ;Converts contents of OP1 to a value in DE


You cannot damage the contents of the BASIC variables this way. The only way you can damage them is if your program crashes (thus causing a RAM reset), or you use a system call to overwrite its contents (such as _StoOther)

If you didn't understand all of that, that's okay. You might want to read up on how user variables are stored in memory as to why it's necessary to use these romcalls. For a full reference to the system routines list I used to make this post, look here: http://education.ti.com/guidebooks/sdk/83p/83psysroutines.pdf
For the guide that contains that information and more, look on TI's website for their guide found with or near their SDK.
Hmm... You just game me an interesting idea. Would it be possible to create a label in the ASM code and use a .db to create a chunk of empty (unused) space in the code data? If so, would it be possible to use that chunk of data as modifiable memory?
Yes, and with most shells this data will be written back to the program after it runs so you can use it to store data between program runs. It does, however, make your program larger than it might otherwise need to be.
Would this be done by doing for example:


Code:
DummySpace:
   .db "00000000"


Then do this:


Code:
ld (DummySpace+2),3


To change the third byte? Would that work?

Quote:
It does, however, make your program larger than it might otherwise need to be.


I'm only storing a few bits/bytes of game data like health and items collected.
Quargzon wrote:
Hmm... You just game me an interesting idea. Would it be possible to create a label in the ASM code and use a .db to create a chunk of empty (unused) space in the code data? If so, would it be possible to use that chunk of data as modifiable memory?


I was under the impression that you were already doing this. Yes, you can do that. If you're running this program from the homescreen, the changes that you make in that area do not remain with the program as the copy you're writing to is not a persistent copy. If you run your program from a shell (for example, DCS) and it write-back is enabled, the changes you make inside your own program will, in fact, stick. This is how many games store their high scores.

I'd stay away from that unless you're storing persistent data or some other really good reason.

EDIT: Posted late. Whoops.

EDIT2: Responding to the post that actually comes before this one:

Quargzon wrote:
Would this be done by doing for example:


Code:
DummySpace:
   .db "00000000"


Then do this:


Code:
ld (DummySpace+2),3


To change the third byte? Would that work?

Quote:
It does, however, make your program larger than it might otherwise need to be.


1. That creates a stream of zero characters. You're in effect doing the following:

Code:
DummySpace:
.db $30,$30,$30,$30,$30,$30,$30,$30


2. You cannot do that. Every load must involve a register. Fixable by doing this:

Code:
 ld a,3
 ld (DummySpace+2),a
One more thing, is this technique fast enough for realtime use? As in, will using it freeze the game for a few seconds or something?
Quargzon wrote:
One more thing, is this technique fast enough for realtime use? As in, will using it freeze the game for a few seconds or something?


The short answer is "no".

All instructions have a certain amount of time they take to execute. You might want to look at this instruction set summary for timings. The processor on a TI-83 Plus runs at 6MHz. Romcalls take quite a bit of time but most of them are fast enough to be used "real-time". Although they're still plenty fast, I wouldn't put them in a time-critical loop.
The main thing I'm trying to figure out here is where to store temporary in-game information such as the x/y coordinates of an object or the player's health; something that will be changing constantly, but needs to persist to the next iteration of the game loop. Should these be done with registers in a stack, or somehow with the RAM?
Quargzon wrote:
The main thing I'm trying to figure out here is where to store temporary in-game information such as the x/y coordinates of an object or the player's health; something that will be changing constantly, but needs to persist to the next iteration of the game loop. Should these be done with registers in a stack, or somehow with the RAM?
That should be in the safeRAM areas, assuming it's dozens or hundreds of bytes of data at most.
There's no difference speedwise between using safeRAM areas or extra space appended to the end of your code, but users will appreciate you not taking up the extra space. Another option that is very common is using SMC. Basically, in your player drawing routine, instead of:
Code:
ld a,(playerY)
;calculate player's Y position on screen
ld a,(playerX)
;calculate player's X position on screen

...there is another smaller and slightly more efficient method:

Code:
playerY = $+1 ;you could also just define it as playerT, i'll explain below
ld a,0
;calculate playerY
playerX = $+1
ld a,0
;calculate playerX

First off, you need to know what $ means. It just means the current address in your program. So typing "playerY:" and "playerY = $" are exactly the same. playerY = $+1 means that when you use playerY, you're actually using the byte after. Let's look at ld a,0. The hex for ld a,$XX is $3E,$XX (the second byte contains the value to load into a). So ld a,0 looks like this: .db $3E,$00. playerY skips the first byte (+1) and points to the second byte of the instruction, the value we load into a. So here, we use SMC to directly load a value into a (you can use any register you want!) instead of loading from an address in memory. It's a byte smaller and 6 t-states faster (7 compared to 13 for ld a,(playerY)).

This $ character can be used in lots of situations, i use it all the time for short loops or to skip short sections of code rather than create a label (i just think it makes my code look cleaner). Using it a lot will also help you learn the size of the instructions. Just keep in mind that it is calculated from the start of the instruction, so if you do "jr $" you'll cause an infinite loop, since it will jump to the start of the instruction. "jr $+2" will simply jump to the next instruction. If you want to skip the next instruction if a = 10, you can do something like this:

Code:
cp 10
 jr z,$+4
      ld a,100
;rest of program

I usually indent the instructions i'm jumping over to improve readability. Just don't forget to add the 2 bytes from the jr instruction! Just to make things clear, though, this only applies to jumping forward. Jumping backwards you don't need to worry about the 2 bytes, since the address is calculated from the start of the instruction.

I dunno if i just confused you more or what, but if you have any questions, ask and i (or someone else) will try to explain it better.

EDIT: And the two most common uses for appending variables to your program:
-high scores
-save files, though now a lot of people like to create external files for these, i really don't understand why maybe they think it's cool? If you have a lot of data to save you really need to, but if you've only got ten to twenty bytes to save then your code to create and save the variable will probably be larger than just saving it in your program.

And one last thing, it IS possible to save high scores into your program with nostub programs, but you'll have to handle the writeback yourself. When you run a nostub program, the OS just copies it to $9D95 and deletes it when the program exits. If you want to save some data, you'll need to find your program in memory and update the bytes you want to save. It's probably easier just to use a shell if you want program writeback.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement