Omnimaga
Calculator Community => TI Calculators => Axe => Topic started by: Matrefeytontias on December 11, 2012, 01:58:02 pm
-
PageSwap (http://ourl.ca/17182) is an Axiom made by myself which allows you to use Axe subroutines you defined in another program and compiled separately as an app directly in your classic Axe program.
What's the benefit for it ? Well, imagine that your Axe program is so large that it can't fit in the RAM, even if it's all free (this means that your program is greater than 24K). You can write 16K of code in an app as subroutines, make a 8k program and use PageSwap to access this last app and use the functions you defined in it. The result is 24K of executable code which take only 8k of RAM. You can even use CrabCake by Hot_Dog (http://ourl.ca/11085) or FullRene by thepenguin77 (http://ourl.ca/13513) to overpass the 8K limit, to have still moar executable code ! And more of that, you can also use PageSwap with several apps, which is 16K of executable code per app !
So, how to use this axiom ? It can be pretty complicated due to all the things you have to beware when you use that.
First, we need an API. It's an Axe program you'll compile into an app and which will contain all of your subroutines. Let's call it AppTest (app names can contain lowercase). Then we need a program to use these subroutines, let's call it APPTEST in uppercase (yeah, I'm lacking names). That's all what we need.
So, our app needs to have a specific format. Since it's a lib, it must contains functions. And in order to know where are located all of these functions, we do a jump table.
:.AppTest
:
:Goto Func1
:Goto Func2
:Goto Func3
:.and so on
:
:Lbl Func1
:. code here
:Return
:
:Lbl Func2
:.same
:Return
:
:Lbl Func3
:.same again
:Return
:
:.and so on
So when in your code you need to call one of these funcs, you'll just have to call the corresponding Goto (which has a fixed address the axiom knows).
But wait, we must not run this app ! So let's write a Start function that exits the app when the user launches it :
:.AppTest
:
:.Execution will start here
:Goto Start
:Goto Func1
:Goto Func2
:Goto Func3
:.and so on
:
:Lbl Start
:ClrHome
:Text(0,,"This app is an Axe lib
:Text(0,8,"It's not meant to be ran
:Text(0,16,"Press any key to quit
:getKeyr
:Return
:
:Lbl Func1
:. code here
:Return
:
:Lbl Func2
:.same
:Return
:
:Lbl Func3
:.same again
:Return
:
:.and so on
Okay, now we have a pattern for our API !
You can write your subroutines the same way you write ones in a classic Axe source. So you can use r1 to r6, static pointers (GDB, Pic ...) and so on.
When, let's fill these routines with something so we'll can use them.
:.AppTest
:
:Goto Start
:Goto Func1
:Goto Func2
:Goto Func3
:
:Lbl Start
:ClrHome
:Text(0,,"This app is an Axe lib
:Text(0,8,"It's not meant to be ran
:Text(0,16,"Press any key to quit
:getKeyr
:Return
:
:Lbl Func1
:Pt-On(r1,r2,r3
:Return
:
:Lbl Func2
:Text(r1,r2,r3
:Return
:
:Lbl Func3
:DispGraph
:Return
Now, let's write our prgmAPPTEST program. First, let's include PageSwap.
:.APPTEST
:
:#Axiom(PAGESWAP)
Now, you can start working with PageSwap.
Using PageSwap is a bit complicated since it works with really low level things : app pages. When you launch a regular program (I mean not an app), it's usually from the page 0, which is the RAM. Now, you want to access your lib which is an app, but apps aren't stored in page 0. So, you'll need to go to the page of your app, use the routines inside, and when you're done with it go back to the page 0 before exit your program.
You'll say "hey, but what if I launch my program from flash using a shell ?" In fact that remains the same : the program must exit in the same page as the one which he started. So at the start of APPTEST, just save your current page by using PageSwap's getCurPage (all the PageSwap commands are the Angle menu [2nd] [apps]).
:.APPTEST
:#Axiom(PAGESWAP)
:
:getCurPage?P
:
:.code here
Then, to change the current app page, use the well-named setCurPage() :P
But which page must we go in ? You know that we want to access AppTest to be able to use the subroutines in it. So search for your app by using getAppPage("APP"), and then set the current page to it.
:.APPTEST
:#Axiom(PAGESWAP)
:
:getCurPage?P
:setCurPage(getAppPage("AppTest"))
:
:.Don't forget to restore the initial page before quitting !
:setCurPage(P)
Now that you're in the page of your app, you can use its functions ! Well, in fact you don't know the addresses of your functions ... but PageSwap does ! Just retrieve the address of the Nth function of your app by using appFunc(N), then call it with Axe's (ADDR)(ARGS). Beware, the 0th function is the Start function !
:.APPTEST
:#Axiom(PAGESWAP)
:
:getCurPage?P
:setCurPage(getAppPage("AppTest"))
:
:.You have to remember which function does what
:(appFunc(1))(0,8,[3C4281818181423C])
:(appFunc(3))()
:(appFunc(2))(0,0,"Over 9000!")
:getKeyr
:
:setCurPage(P)
Now compile AppTest into an app, APPTEST into Noshell, try to run AppTest, run APPTEST, and see !
And that's all, now you know how to use PageSwap !
Now, go make a 40KB-large program ! :P
-
Now, go make a 40KB-large program ! :P
Yessir!
Awesome axiom, nice work!
-
Hmm can I call Goto within the functions in the lib?
E.g.
Lbl Func1
If ...
Goto Func2
End
Return
-
Very cool, Matrefeytontias :D This will make it much easier for people to use Apps :D I am curious, though, do Axe apps not start at 4080h? (I think when I tested it, it was 408Ch or something .__.)
@V1mes: I am pretty sure you can :) It won't cause any problems :D
-
@Xeda... thank you!
-
@Xeda Lbl Start is at $408B as far as I remember.
@V1mes yeah, you can :)
-
Ah, thanks much Matrefeytontias :D I wonder why there are 11 extra bytes? o_O It's probably to identify it as an Axe App.
-
wow, this is pretty epic, i'll soooooooooooooooooo use it! :D
-
Interesting, although for a massive game, if there are multiple apps showing up in the Axe menu, that might be a bit confusing for the player, since he might run apps he shouldn't. :P (unless it's possible through your axiom to hide/unhide specific apps from the menu?)
-
After you are happy with your tutorial, you should cross post it
(http://img.removedfromgame.com/imgs/da_here.png)
I'm not sure how many people actually go to those sections, but it's better than getting buried in all the threads.
-
@DJ_O that's true, but you can specify in your Start func the name of the prgm to launch. And no, I can't hide/unhide apps.
@thepenguin77 yeah I'd love to, but idk how to do :P
-
Another trivial question:
Say I have
Goto Start
Goto Func1
Goto Func2
Goto Func4
Lbl Start
...
Return
Lbl Func1
...
Return
Lbl Func2
...
sub(Func3)
...
Return
Lbl Func3
...
Return
Lbl Func4
...
Return
in my lib app.
will appFunc(3)(r1,r2,...) execute Func4 or Func3?
-
No, the Func3 is a routine on itself, so even running it within another routine... You can still run it alone...
-
I'm sorry I don't understand your answer :-\
-
Well, you've got 4 routines... Func1,2,3,4
And Func3 is just used in Func2 as well... But that doesn't make the Func3 dissapear... So the appFunc3 = Func3
Ooh or i missunderstood you're question, you mean like: is appFunc0 = Func1
And appFunc1 = Func2
Hmm that idk, you'dd have to find it out.. Just test with a little program and you'll know..
-
Ok i made a small mistake thanks for pointing it out. I edited my question :angel:
-
@thepenguin77 yeah I'd love to, but idk how to do :P
Click the link he pointed to, then navigate to the tutorials section you want (eg Axe), then at the bottom of the page, click "Add article". Just make sure to include a link to this topic at the end of your tutorial. You just have to copy the content of your post there.
-
Remember that appFunc(0) is the Start function. So in your code (appFunc(3))() will call Func3, and (appFunc(4))() will call Func4 (and btw (appFunc(0))() will call Start).
-
Does it not matter then that i have not included func3 in the jump table?