z80:External Levels/Files
It is sometimes the case where you want your program to support external files for saving data. Some examples include Rush Hour Greyscale which has external level support and Sketchy's animation files.
Contents
Requirements
Though the actual data being stored will vary, all external files follow a simple formula: they need a storage location, they should have an identifier string, and they should contain the necessary data.
Storage Location
First of There are several ways to create these external levels, but almost all of the time it boils down to one of two choices: another assembly program, or appvars. In theory both methods are fairly equivalent, but in practice assembly programs are somewhate easier to use because of the idetect (from the Ion library). Note that since idetect's source has been released, it is not much of a problem to modify the code to look for appvars instead of programs.
Identifiers
It is always a good idea to put an identifier string as one of the first lines of data in your program/appvar. This will help you to make sure that the file being searches is indeed a valid file to your program. The identifier is usually a string of at least 4 characters long. The longer the string is, the greater the guarantee that the file is usable by your programmer, but in almost all cases except for a few odd-balls, 4-6 characters long is sufficient.
Data
Here is where your data goes. The way it is ordered does not matter, so long as you write your main program to decipher the data correctly.
Assembly Program Example
Here is an example of a level from Rush Hour Greyscale that uses external assembly programs to store levels. The next section will use the same level, but display it for a appvar. For assembly programs, one thing that I like to do is include the asmprgm token and the ret with the identifier string, as it makes programming the detector easier. In this example, you can copy this entire block of code and compile it. There is no need for any header (include ti83plus.inc, define bcall, etc.)
; No header at all .db $BB,$6D ; Identifer string starts here ret .db "RHLvl" ; Everything below is data cursetname: .db 0,0,0,0,0,0,0,0,0,0,0 newmapnum: .db 1 ;start with two new map difficulty: .db 0,0,0,0,0,0,0,0 flag: .db 0 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00
Why do we need the first two lines of code? Remember, assembly programs only differ from TI-basic programs by an asmPrgm token, and it's important for that to be included. the ret is there only to prevent someone from trying access to this level as an assembly program.
Appvars
And again, here is the same level for an appvar. Again, no header is needed. Note that the only change is the omission of the first two lines of code.
; No header at all .db "RHLvl" ; Everything below is data cursetname: .db 0,0,0,0,0,0,0,0,0,0,0 newmapnum: .db 1 ;start with two new map difficulty: .db 0,0,0,0,0,0,0,0 flag: .db 0 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00 .db $00,$00,$00,$00,$00,$00
Detecting External Files
To detect an external file, use B_CALL(ChkFindSym).
LD HL,ProgABC rst rMov9ToOP1 ; same as B_CALL (Mov9ToOP1): move 9 bytes at HL to OP1 ; B_CALL(ChkFindSym) ; look up program JR C, NotFound ; jump if it is not created ; LD A,B ; A set if archived OR A ; is it archived? JR Z,NotArchived ; jump if not ; B_CALL (Arc_Unarc) ; unarchive the var NotArchived: ;Code goes here ProgABC: DB ProgObj, ‘ABC’, 0
This works for a program as external storage. For more info on different storage types, go to the SDK guide. It can be found here.
Archived complications
If the file is archived, it needs to be unarchived to use ChkFindSym. However, this may wear down your flash ROM. This is why you should not archive the variable at the end of the program. If it is meant to be read-only, it does not have to be unarchived.
Conclusion