z80:Application Variables (AppVars)

From Learn @ Cemetech
Jump to navigationJump to search

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

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.