Omnimaga

Calculator Community => TI Calculators => Axe => Topic started by: JustCause on April 04, 2011, 12:04:25 pm

Title: Quick question about archived programs' VAT entries
Post by: JustCause on April 04, 2011, 12:04:25 pm
OK, if anyone's been following Cubes, I'm making an editor. By necessity, that also includes a level browser, and I'm using the VAT routines in the Routines thread to make one: however, while that approach works fine with unarchived programs (I believe the start of the var is at {P-4}rr? I've got it written down somewhere.), with archived programs I don't see an easy way of accessing the data. The best I can come up with is on-the-fly assembling a name string to pass to GetCalc(), which seems like a huge kludge to me. Is there any easier way?

Thanks.
Title: Re: Quick question about archived programs' VAT entries
Post by: Xeda112358 on April 04, 2011, 12:11:43 pm
So do you need a way to read the archived data and obtain information about it?
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 04, 2011, 12:13:12 pm
Obtaining information, not so much (that's all in the entry, right?). But I would like a way to read from it.
Title: Re: Quick question about archived programs' VAT entries
Post by: Xeda112358 on April 04, 2011, 12:19:47 pm
Okay, well if the program is going to be an app, then it will be a little more complicated (not too complicated, though). How do you want to read it? Is there a specific number of bytes you plan to read? Or will it be variable?
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 04, 2011, 12:25:30 pm
The program isn't an app, and I'll need to read the entire thing (which will be of variable length).
Title: Re: Quick question about archived programs' VAT entries
Post by: Xeda112358 on April 04, 2011, 12:27:04 pm
Okay! Also, I just realised that it won't actually be any more difficult for an App XD. So that helps... where do you want to copy the data to?
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 04, 2011, 12:28:34 pm
Free RAM. L1 ideally, though it can be any free location.
Title: Re: Quick question about archived programs' VAT entries
Post by: Xeda112358 on April 04, 2011, 12:30:06 pm
Okay, so will the var be guaranteed to be small enough to fit there? And do you by any chance know the address of L1? (I can find it if you don't). I almost have the code ready :D
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 04, 2011, 12:33:29 pm
I think it's just saveSscreen, and...damn, you're right, it'll need to be copied in bits...these levelsets, even with RLE, are liable to be effing huge...graar. Okay, maybe it'd be simpler to just assemble the name string. It'll need to copy from a variable point within the data until a sentinel value...yea, this might be more trouble than it's worth. :) Am I wrong?
Title: Re: Quick question about archived programs' VAT entries
Post by: Xeda112358 on April 04, 2011, 12:41:25 pm
I understood almost none of that XD Is there a maximum size that it will need to be? If so, you could create an appvar as a temporary memory buffer.
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 04, 2011, 01:50:22 pm
Err...okay, I'll put a better explanation up soon. Basically, the levelset data is stored in one location as raw data separated by 254s, and each level needs to be loaded separately into a writable location.
Title: Re: Quick question about archived programs' VAT entries
Post by: squidgetx on April 04, 2011, 03:19:00 pm
This shouldn't be that difficult. A link to The Psyche is in my sig: I made a levelpack editor as well and I have a very nice routine that assembles the name string and everything. XXEdit's search function also does something similar. Anyway, basically the name string is pretty easy to build, just prefix your data with a 5 for reg. program, 6 for prot. prog, and 21 for appvar. So the name string data for an appvar called LOL is [15]"LOL"[00]... and if that data is stored in L1 you can just use L1 as your GetCalc argument with no issues.

Also you may want to only allow reading levels from archive, since I don't think many people would actually prefer having them in RAM anyway.
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 08, 2011, 02:21:53 pm
Also you may want to only allow reading levels from archive, since I don't think many people would actually prefer having them in RAM anyway.
True, true...Thanks. I totally forgot about The Psyche. Strange, considering it's been on my calc for about two months now. Thanks a lot.
Title: Re: Quick question about archived programs' VAT entries
Post by: DrDnar on April 08, 2011, 02:37:24 pm
If you need to read data from the archive and don't care about speed, the OS provides several helpful routines for reading data from the archive: FlashToRam, copies an arbitrary block of data from the archive to RAM; PagedGet, used with SetupPagedPtr, lets you read and process data a byte at a time; LoadCIndPaged, reads a byte from any ROM page; and LoadDEIndPaged, reads a word from any ROM page. All of these automatically deal with wrapping, too.
Title: Re: Quick question about archived programs' VAT entries
Post by: aeTIos on April 08, 2011, 02:39:14 pm
If you need to read data from the archive and don't care about speed, the OS provides several helpful routines for reading data from the archive: FlashToRam, copies an arbitrary block of data from the archive to RAM; PagedGet, used with SetupPagedPtr, lets you read and process data a byte at a time; LoadCIndPaged, reads a byte from any ROM page; and LoadDEIndPaged, reads a word from any ROM page. All of these automatically deal with wrapping, too.
DrDnar: you maybe didnt see that this was in the Axe Language section. Nice explaination, though ;)
Title: Re: Quick question about archived programs' VAT entries
Post by: DrDnar on April 08, 2011, 02:55:13 pm
Is there not a B_CALL axiom? Those routines are pretty much entirely stand-alone. If there isn't a general-purpose B_CALL axiom, I could probably throw together an axiom for these pretty quickly.
Title: Re: Quick question about archived programs' VAT entries
Post by: aeTIos on April 08, 2011, 03:17:17 pm
Wowowow a b_call axiom would be freakin' cool!
EDIT: but very hard to create, I think...
EDIT2IN10SECONDS: But 1000 times easier to use than "Asm(hex)"
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 08, 2011, 03:21:00 pm
Hmm. Thanks for the heads-up. I'll look into that. Legitimate assembly is not my strong point, though ;)
Title: Re: Quick question about archived programs' VAT entries
Post by: DrDnar on April 08, 2011, 03:59:28 pm
I'm writing the axiom now. Axe Parser should really add native B_CALL support. Perhaps you could use a bitmap for telling the parser what registers to use as input and output.

By the way, what exactly does the size field measure? The following is an example of what I have. Is the size field specified correctly here?
Code: [Select]
; No .org is required because this contains no absolute pointers.
wrapChkFindSym:
; ChkFindSym(PointerToDestination, PointerToName)
; Inputs:
;  - PointerToDestination: Location to write information struct to
;    This struct has the form
;        variableStruct {byte type; byte page; word location; word VATLocation};
;  - PointerToName: Pointer to name.  The type must be the byte before the name,
;    and the name must be terminated with a 0 if less than eight characters.
; Output:
;  - Data written on success, unchanged on failure
;  - Returns 1 on failure, 0 on success
.dw wrapChkFindSymEnd-wrapChkFindSym ; Size
.db 1Fh ; Compatible with everything
.db what, ever ; Token
.db 1 ; Type (subroutine, regular)
.db 2 ; Arguments
pop bc
pop de
push bc
push de
rst 20h ; Mov9ToOP1
rst 28h
.dw _ChkFindSym
pop ix
jr c, +_
ld hl, 1
ret
_: and 1Fh
ld (ix+0), a ; I'm too lazy to deal with all the register
ld (ix+1), b ; swapping
ld (ix+2), e
ld (ix+3), d
ld (ix+4), l
ld (ix+5), h
ld hl, 0
ret
wrapChkFindSym:
Title: Re: Quick question about archived programs' VAT entries
Post by: calc84maniac on April 08, 2011, 04:06:20 pm
Uhh, getCalc() is a built-in wrapper for chkfindsym.
Title: Re: Quick question about archived programs' VAT entries
Post by: DrDnar on April 08, 2011, 06:06:29 pm
Quote
getCalc(PTR): Finds the object who's name is pointed to and returns a pointer to the start of its data, or zero if it was archived or not found.
According to this documentation, it doesn't return the variable's address if it is archived, and doesn't return the page, ever. So it would be useless if you want to read data from the archive.

I won't be here tomorrow, and probably not tonight, so here's what I have. You should be able to save this as a file and assemble it Spasm. You just need to provide tokens for it to use.
Code: [Select]
.nolist
#include "ti83plus.inc"
.list
.org 0h

.dw 0C0DEh

wrapFlashToRam:
; FlashToRam(Page, Address, Destination, Length)
; Block copies Length data from Page:Address to Destination.  Automatically
; wraps to the next page as-needed.
; Inputs:
;  - Page, Address: Source
;  - Destination: Pointer to location to copy the data
;  - Length: Amount of data to copy
.dw wrapFlashToRamEnd-wrapFlashToRam ; Size
.db 1Fh ; Compatible with everything
.db what, ever ; Token
.db 1 ; Type (subroutine, regular)
.db 4 ; Arguments
ld c, l
ld b, h
pop ix
pop de
pop hl
pop af
push ix
rst 28h
.dw _FlashToRam
ret
wrapFlashToRamEnd:


; No .org is required because this contains no absolute pointers.
wrapChkFindSym:
; ChkFindSym(PointerToDestination, PointerToName)
; Returns information about a variable.
; Inputs:
;  - PointerToDestination: Location to write information struct to
;    This struct has the form
;        variableStruct {byte type; byte page; word location; word VATLocation};
;  - PointerToName: Pointer to name.  The type must be the byte before the name,
;    and the name must be terminated with a 0 if less than eight characters.
; Output:
;  - Data written on success, unchanged on failure
;  - Returns 1 on failure, 0 on success
.dw wrapChkFindSymEnd-wrapChkFindSym ; Size
.db 1Fh ; Compatible with everything
.db what, ever ; Token
.db 1 ; Type (subroutine, regular)
.db 2 ; Arguments
; Swap return address with destination pointer
pop bc
pop de
push bc
push de
; Call
rst 20h ; Mov9ToOP1
rst 28h
.dw _ChkFindSym
; Check for failure
pop ix
jr c, +_
ld hl, 1
ret
_: ; Success!
and 1Fh
ld (ix+0), a ; I'm too lazy to deal with all the register
ld (ix+1), b ; swapping
ld (ix+2), e
ld (ix+3), d
ld (ix+4), l
ld (ix+5), h
ld hl, 0
ret
wrapChkFindSym:


wrapLoadCIndPaged:
; LoadCIndPaged(Page, Address)
; Reads a single byte from Page:Address.
; Inputs:
;  - Page: Page to read from
;  - Address: Offset to read from
; Output:
;  - Data byte
.dw wrapLoadCIndPagedEnd-wrapLoadCIndPaged ; Size
.db 1Fh ; Compatible with everything
.db ; Token
.db 1 ; Type (subroutine, regular)
.db 2 ; Arguments
pop bc
pop de
push bc
ld b, e
rst 28h
.dw _LoadCIndPaged
ld h, 0
ld l, c
ret
wrapLoadCIndPaged:


; LoadDEIndPaged(Page, Address)
; Reads a word from Page:Address.
; Inputs:
;  - Page: Page to read from
;  - Address: Offset to read from
; Output:
;  - Data word
.dw wrapLoadDEIndPagedEnd-wrapLoadDEIndPaged ; Size
.db 1Fh ; Compatible with everything
.db ; Token
.db 1 ; Type (subroutine, regular)
.db 2 ; Arguments
pop bc
pop de
push bc
ld b, e
rst 28h
.dw _LoadCIndPaged
ex de, hl
ret
wrapLoadDEIndPaged:
.dw 0
Title: Re: Quick question about archived programs' VAT entries
Post by: calc84maniac on April 08, 2011, 06:34:46 pm
GetCalc(PTR,FILE): Attempts to create a file of the OS variable who's name is pointed to so it can be read from archive. Returns 0 if the variable was not found or unarchived, and non-zero otherwise.
Title: Re: Quick question about archived programs' VAT entries
Post by: DrDnar on April 09, 2011, 02:39:23 am
I'm not sure what he needs, then, as Axe's file thing seems to allow reading data from the archive as-needed.

On another note, here's an untested B_CALL Axiom:
Code: [Select]
; B_CALL Axiom
; expr(RegisterBlock, BCallAddress)
; Calls the B_CALL. The data at RegisterBlock is loaded into the registers, and
; the register values returned by the B_CALL are written to RegisterBlock
; RegisterBlock should have the variables in the following order:
;  - If treating all as 16-bit values: AF BC DE HL
;  - If working with individual bytes: FA CB ED LH
; IMPORTANT: REGISTERBLOCK MUST POINT TO THE END OF THE REGISTER BLOCK, NOT THE
; START
; This uses self-modifing code, so cannot be used from an application.
.dw wrapBCALLEnd-wrapBCALL
.db 0Fh
.db t2ByteTok, tExpr
.db 1 ; A subroutine, because B_CALLs aren't fast and might as
.db 2 ; well save space
; I haven't done any calculations on whether this is remotely optimal.
wrapBCALL:
; Write B_CALL address
.db 7Fh ; Escape load operation
ld de, wrapSysCall
ld a, l
ld (de), a
inc de
ld a, h
ld (de), a
; Move stack stuff
pop de
pop hl
push de
; Now HL has the address of the data block
ld a, i ; Save interrupt state
push af
di ; Use SP to load values
ld (0FE70h), sp ; Replace with 9311h or any other obsecure memory area if desired
ld sp, hl
pop af
pop bc
pop de
pop hl
ld (0FE6Eh), sp
ld sp, (0FE70h)
; Perform actual B_CALL
rst 28h
wrapSysCall:
.dw 0
di ; Some B_CALLs DO mess with interrupts
; Save values using SP
ld sp, (0FE6Eh)
push hl
push de
push bc
push af
ld sp, (0FE70h)
pop af
ret po
ei
ret
wrapBCALLEnd:
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 11, 2011, 03:29:10 pm
Solved. Assembling the name string from the VAT entry turned out to be much easier than I thought.

Now I've got a new issue: I know that the standard fix for the executable code limit is "put all your data at the end of the program," but if I do that I can't get to it: that is to say, I have something like this:

Code: [Select]
:[HEXDATA]->Pic1
:[MOREHEXDATA
:[EVENMOREHEXDATA

at the start of my program, and if I move it to the bottom Axe throws errors and won't let me compile (presumably because the pointer never gets initialized). What should I be doing instead?
Title: Re: Quick question about archived programs' VAT entries
Post by: squidgetx on April 11, 2011, 03:31:46 pm
When Axe compiles, it automatically sorts out the data to the end of the program; the location of the data in the source code doesn't matter as long as you create your pointers before you reference them. Unfortunately, it also likes to mix in routines with that data. So basically, if you're over 8811, there's no way to guarantee a bug-free executable unless you use an app :( Your best bet is to try and optimize more, use appvars to hold data, or to jsut make it an app.
Title: Re: Quick question about archived programs' VAT entries
Post by: JustCause on April 12, 2011, 08:52:16 am
Baaaaaaawwwwwwwww. Okay then, thanks for your help. Time to go burn out my archive chip!  :P
Title: Re: Quick question about archived programs' VAT entries
Post by: Deep Toaster on April 12, 2011, 06:27:59 pm
If you need to read data from the archive and don't care about speed, the OS provides several helpful routines for reading data from the archive: FlashToRam, copies an arbitrary block of data from the archive to RAM; PagedGet, used with SetupPagedPtr, lets you read and process data a byte at a time; LoadCIndPaged, reads a byte from any ROM page; and LoadDEIndPaged, reads a word from any ROM page. All of these automatically deal with wrapping, too.
DrDnar: you maybe didnt see that this was in the Axe Language section. Nice explaination, though ;)

Any Axe program that goes low-level enough has to use ASM. It just doesn't have enough commands for everything (not that that's a bad thing; I actually like how simple and consistent Axe is).

Wowowow a b_call axiom would be freakin' cool!
EDIT: but very hard to create, I think...
EDIT2IN10SECONDS: But 1000 times easier to use than "Asm(hex)"


What would a bcall Axiom do? If you mean making a command for each bcall, that would make the Axiom itself a couple megabytes large and compile in a few hours O.O
Title: Re: Quick question about archived programs' VAT entries
Post by: DrDnar on April 15, 2011, 11:49:00 pm
No, I meant an Axiom that executes any B_CALL, loading and saving the registers for you, too. Axe itself might implement something like
B_CALL(var8->reg, var16r->reg16, Routine address, reg8->var8, reg16->var16r) ; calls the Routine, loading variables to registers before and copying registers to variables after.