Introduction
In the last tutorial we pointed out that you can not create permanent self modifying code. So, how do you save important data? The answer is in AppVars. They are a special kind of variable that can only be edited in assembly, and serve as a "permanent" saving point for app data (note that they can be deleted from the memory menu).
Creating AppVars
To create AppVars, we will use the _CreateAppVar ROM call. It's inputs are appvar name in op1 and size in HL. Note that when created it will be in RAM.
;omit header
ld hl,AppVarName
rst rMOV9TOOP1
ld hl,32
bcall(_CreateAppVar)
AppVarName:
.db AppVarObj,"AVDATA",0
Data Structure
The data in AppVars goes like this: the first two bytes are for size, and then everything else is defined by the program accessing the AppVar.
AppVar Identifier
Generally, it is a very good idea to create an identifier for your AppVar. It can be anything you want and any length you want, so long as your program can identify it later. It is good practice to put it right after the size bytes, but you don't have to if you don't want to.
Creation
Creating an identifier is as simple as ldir-ing into the AppVar.
;load our identifier
inc de ;get over size bytes
inc de
ld hl,identifier
ld bc,9
ldir
identifier:
.db "Identify",0
Detection
First it must be located. See External Levels and Files for more info.
Detection is as simple as checking for any variants between the identifier and the data in the AppVar.
;check for valid AppVar
;assuming de is pointing to start of AppVar Data
inc de ;get over size bytes
inc de
ld hl,identifier
ex de, hl
iloop:
ld a,(de)
cp (hl)
jr nz,invalid
or a
jr z,valid
inc de
inc hl
jr iloop
invalid:
;... in case identifiers don't match
vald:
;... everything matches!
identifier:
.db "identify",0
Changing AppVar Size
It's usually a good idea to create AppVars of the correct size to begin with. However, sometimes this isn't possible. So, to do so we just need to insert memory into the appvar and update the size bytes.
;assuming that DE points to size byte and that we have enough memory
push de
push de ;copy de into hl
pop hl
ld a,(de) ;ld de,(de)
ld b,a
inc de
ld a,(de)
ld d,a
ld e,b
add hl,de
ex de,hl ;end of program now in de
ld hl,20 ;insert 20 bytes to the end
bcall(_insertMem)
pop de
add hl,de ;update size
ld a,l
ld (de),a
inc de
ld a,h
ld (de),a
Note that this process is the exact same process you go through to insert memory into program variables, too.
Conclusion
AppVars are really useful tools for saving data between application uses. It is interesting to note that regular assembly programs can also access AppVars, and use them in the exact same way that flash applications use them.