ClrHome
0->K
While K=/=15
Getkey->K
If K=/=0
ClrHome
Disp K
End:End
Axe ParserThanks for warning us, I'll try it once I backup my calc files or finish Crystal Defenders.
Alpha 0.0.1
WARNING:
This is still an alpha version. It is not stable and you should not run this on any calculator that has anything intellectually valuable in the RAM. Just for liability reasons, I will also add that there is a non-zero possibility your archive might not be safe either.
Apps? How do you make large Apps if the source file can only be 1.25ish pages large, due to lack of RAM?When its finished, it will allow the source programs to be in archive. You will also be able to include subprograms in your programs like the "include" feature in C. If it compiles to an app, it will have to be a one page app since it will be too complicated to switch pages with anything that resembles basic. But that's still 16k, which is large enough for most applications.
How do you use the predefined A - Z and Theta? And what about Theta?They are stored in the saveSScreen ram location. I have not included theta yet because I am still considering using it for some other purpose.
Can you have comment blocks?You can do single line comments, but I feel that inline comments will just make the code very unreadable.
Can you include the ++ and -- operators from C++?I might. A++ can save 2 bytes when assembled instead of doing A+1.
Does the Ans Variable work the same way as in basic?No, I no longer use it, its pointless. If you have no argument, it automatically assumes the last expression. But it must immediately follow or it will just be garbage.
If you Pause, and the run indicator is off, does it stay off?Yes
How does Disp work when you get to the end of a line?Disp is not fully functional right now. I only included it so I have some type of output to test everything. Nothing will display at the end of the line. It will work like it does in BASIC when its finished.
Can getKey ever go back to the getKey of basic, or is it always GetScanCodes?Probably not, but I will have a directkey command in the future (for multiple key presses)
While is still PreTest, and Repeat is still PostTest, right?Its pretest right now... was it post test in basic? I've never used it before, but that would be very easy to change and also save 3 bytes.
Can you check if sub( has a comma in it, and if so use it like it is in TiBasic? (If it dosn't have a comma, it's subroutien.)Nope. You will be able to do substrings like this: Str(5) gets 5th character in string.
__=Var means what equals Var? And is the underscore a space? Is it Ans?Yes, basically any expression, variable, number, or Ans before it.
Okay, that's like a million questions, but I will attempt to answer them all:Thanks! ;D
That sounds great! Does this mean you could hold down 2nd, Enter, and Down at the same time and getKey would equal 1, 9, and 54 at the same time?QuoteCan getKey ever go back to the getKey of basic, or is it always GetScanCodes?Probably not, but I will have a directkey command in the future (for multiple key presses)
Yes, it is post test in basic. :)QuoteWhile is still PreTest, and Repeat is still PostTest, right?Its pretest right now... was it post test in basic? I've never used it before, but that would be very easy to change and also save 3 bytes.
How do you access multiple characters like:QuoteCan you check if sub( has a comma in it, and if so use it like it is in TiBasic? (If it dosn't have a comma, it's subroutien.)Nope. You will be able to do substrings like this: Str(5) gets 5th character in string.
Can you include the ++ and -- operators from C++?
I might. A++ can save 2 bytes when assembled instead of doing A+1.I'm not very familiar with C++, but if I understand properly the ++ and -- commands do Variable +/-1 ==Variable? IE A++ would increment A by 1 and store the new value to A? If this is correct you could use the IS>( for ++ and DS<( for --. They are commands that aren't really used in BASIC and act somewhat similarly anyway. I should also take a moment to mention that this looks like a very promising undertaking. Can't wait to see how it develops!
Another thing I love about this project is how the produced programs are not dependent on the application. I mean, when running a FastRPL game you need the FastRPL app installed on the calc, same with BBC Basic. Since these apps are huge, this limits the amount of games or programs you can have on your calc at once. Not to mention many people like to be able to run their programs either from the PRGM menu using Asm( or from a popular shell like Ion/MirageOsBut so many people have 84+'s these days, where the 48KB doesn't really matter.
Hmmm, it seems the - character is not supported correctly in Strings? It becomes a q on my 84SEThanks for pointing that out! Unfortunately, TI decided that the single character tokens are not the same as their corresponding ascii values. I've already re-routed the question mark, exclamation mark, and space. I haven't done + or - yet, I'll get to those next time.
Does anyone know a fast routine for dividing two unsigned 16-bit registers?Hehe, I offered on the previous page ;D
div_hl_de:
; BC = HL/DE, HL = remainder
ld a,h
ld b,l
ld hl,0
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
ld c,a
ld a,b
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
scf \ rla \ adc hl,hl \ sbc hl,de \ jr nc,$+4 \ add hl,de \ dec a
ld b,a
ret
Note: Code is untested, so tell me if there are problems
_DE_Times_L:
xor a
ld h,a
ld a,l
ld l,h
_Loop:
rra
jr nc,_Skip
add hl,de
_Skip:
sla e
rl d
or a
jr nz,_Loop
ret
div_hl_de:
; BC = HL/DE, HL = remainder
xor a
sub e
ld e,a
sbc a,a
sub d
ld d,a
ld a,h
ld b,l
ld hl,0
ld c,8
div_loop_1:
rla
adc hl,hl
add hl,de
jr c,$+4
sbc hl,de
dec c
jr nz,div_loop_1
rla
ld c,a
ld a,b
ld b,8
div_loop_2:
rla
adc hl,hl
add hl,de
jr c,$+4
sbc hl,de
djnz div_loop_2
rla
ld b,a
ret
HL_div_DE:
ld a,h
ld c,l
ld hl,0
ld b,16
__DivLoop:
sll c
rla
adc hl,hl
sbc hl,de
jr nc,__DivSkip
add hl,de
dec c
__DivSkip:
djnz __DivLoop
ld h,a
ld l,c
ret
Thanks for that division routine, but I found this one and its a lot smaller.You are correct. You can replace it with "scf \ rl c" thoughCode: [Select]HL_div_DE:
ld a,h
ld c,l
ld hl,0
ld b,16
__DivLoop:
sll c
rla
adc hl,hl
sbc hl,de
jr nc,__DivSkip
add hl,de
dec c
__DivSkip:
djnz __DivLoop
ld h,a
ld l,c
ret
I'm just a little bit worried about the use of the sll command, will that sacrifice compatibility with the Nspire?
ld hl,(var_a)
ld d,h
ld e,l
add hl,hl
add hl,hl
add hl,hl
add hl,de
Thanks for that division routine, but I found this one and its a lot smaller.I definitely want this to work on the NSpire, so could you use another method instead?Code: [Select]HL_div_DE:
ld a,h
ld c,l
ld hl,0
ld b,16
__DivLoop:
sll c
rla
adc hl,hl
sbc hl,de
jr nc,__DivSkip
add hl,de
dec c
__DivSkip:
djnz __DivLoop
ld h,a
ld l,c
ret
I'm just a little bit worried about the use of the sll command, will that sacrifice compatibility with the Nspire?
Also, if you haven't done this already, I'd like to suggest that you auto-generate multiplication algorithms when multiplying by constants.I probably will for powers of 2, but I don't think there will really need to be such high speed math operations, I mean, I don't think anyone will be making a first person shooter or anything. But I guess if a few microseconds are important enough to account for the program size increase, you can always add some Hex code to do the faster multiplication.
I am confused by what this means. Does it means it would be only possible to mutiply by 2, 4 and the like? It might become an issue for example if I did a small RPG where your max HP and attack power was like 101 x character LVHe's just saying that it would be slower to multiply by anything else because it would call a general routine instead of adding manually
I think (but i'm not sure) is that when multiplying by any arbitrary number, it uses the general multiplication routine, but when multiplying by 2, you use the dedicated x2 routine?
I think the only way to speed up anything related to text display is to have a custom font routine, though. I am not sure how easy it would be to implement such thing for Axe parser, especially for home screen stuff, where it might be impossible.I think the problem here is that the output ASM program has to work on its own, so all the font data and routines would be unnecessary overhead
"" Creates a non-terminating string in memory.What makes one terminating, and the other non terminating?
""→NAME Creates a terminating string in memory and names it.
I noticed this hasn't been fixed, and I was wondering if you'd forgotten about it. :DQuoteYes, it is post test in basic. :)QuoteWhile is still PreTest, and Repeat is still PostTest, right?Its pretest right now... was it post test in basic? I've never used it before, but that would be very easy to change and also save 3 bytes.
WOW awesome, glad to see new updates :)/me glares at Spencer...
That said, could this be the first time a TI programmer respects a deadline in history? :O
You both did? :ONah, I was glaring because of procrastination
I myself never did actually x.x, generally the programs got released either later or... earlier :P
It's about 1.5x the speed of straight asm, and you won't have to worry about scrapping it, all new versions do is add new commands, so at most you will have to modify it a bit or update a command if there is a change in syntax, which hasn't happened yet.
Buzzkill, Builder. Buzzkill. D:It's not Basic. It's a whole new language that takes some of the Basic syntax.
I am slightly saddened by this fact.
But, any speed boost in BASIC is an upgrade.
That much is true.
Btw I don,t remember if I asked this or if someone asked this, but does Axe programs run at the same speed on both 15 MHz calcs and the 6 MHz 83+, like other ion/mirage games?I think Axe runs faster in 15Mhz because it makes use of the faster speed available.
Nah, Axe programs run in 6MHz. I tried running in 15MHz and the Fastcopy routine failed. :( Quigibo, you should use a Safecopy routine so people won't need to use ALCDFIX with Axe programs. Also, running the Axe parser in 15MHz mode could really speed up compiling times.Btw I don,t remember if I asked this or if someone asked this, but does Axe programs run at the same speed on both 15 MHz calcs and the 6 MHz 83+, like other ion/mirage games?I think Axe runs faster in 15Mhz because it makes use of the faster speed available.
But wouldn't safe copy make the routine really slow? And if that's the case, why not just use GrBufCpy since isn't that what it does already?The only difference with safe copy as opposed to fast copy is that it uses a loop to poll the LCD port and wait until it's ready for data. DoorsCS uses this as its fast copy routine. GrBufCpy, on the other hand, is simply a slow TI routine no matter how you look at it.
Hmm... is it possible to sort the symbol table alphabetically before stepping through it? That way everything would already be in order and it wouldn't have to be sorted as its going through the list. Is there a bcall for that? If not, is it as simple as swapping the entries, or are there other dependent pointers I have to change?There is an assembly program for that already and the source code is available.
How about just making Axe programs with headers?I myself like this solution best...
The way I would personally like it is simple one-line headers (something akin to MirageOS headers in Basic, but not exactly the same) and then options in the App to control other options and program output. And i have seen games (such as factory theta for example) that do end in theta, so thats not an entirely foolproof method.I think the same as Builderboy...
I think a heading like
:"AXE
would be sufficient and there would be other options in the App as well.
I think a heading like
:"AXE
would be sufficient and there would be other options in the App as well.
Well any MirageOS program called Axe would show up then :P
Maybe just 'Axe? Since ' is the symbol for comments anyway?
Genius!I think a heading like
:"AXE
would be sufficient and there would be other options in the App as well.
Well any MirageOS program called Axe would show up then :P
Maybe just 'Axe? Since ' is the symbol for comments anyway?
This ^^^
Actually, I was thinking of changing the single quote to be an ascii character constant like 'A'. Not sure what will replace it yet, maybe the decimal point since I haven't used it yet and its a single key press instead of [2nd][angle][down][enter]I like that idea, but does it rule out floating point numbers?
Floats would be prefixed with "Float" so it wouldn't matter, but I don't plan on adding floats until near the end. Its really an advanced feature.Actually, I was thinking of changing the single quote to be an ascii character constant like 'A'. Not sure what will replace it yet, maybe the decimal point since I haven't used it yet and its a single key press instead of [2nd][angle][down][enter]I like that idea, but does it rule out floating point numbers?
Well what about if you had specific code for 84+'s and some for 83+'s and you wanted the compiler to smartly compile it, like a clock function that calls the clock on one, and for the 83+ it just uses cycles or something.I like this idea and I think it would be a nice feature. :)
It would help for the more advanced users.
Well what about if you had specific code for 84+'s and some for 83+'s and you wanted the compiler to smartly compile it, like a clock function that calls the clock on one, and for the 83+ it just uses cycles or something.
It would help for the more advanced users.
Well I would be ok with compiling smartly. We could just give out the source and people could compile it themselves. Unless we send it to ticalc then we would just make different versions. Running smartly would make it run slower.How often are you going to have to check calc type though? It's not that slow anyway.
So if it is on a 15MHZ calc it will compile certain code and on 6MHZ it will compile something else. That makes it easier to compile for timing and such.Once there is timing support, it will probably be independent of clock speed anyway (using interrupts)
This is a very good point! Can there be support for both options? :DWell what about if you had specific code for 84+'s and some for 83+'s and you wanted the compiler to smartly compile it, like a clock function that calls the clock on one, and for the 83+ it just uses cycles or something.Well do we want it to compile smartly or run smartly? Most likely Axe programs will be released as just regular asm programs, and the user wont even ever need to touch the Axe compiler, so having a smart compiler wouldn't make much sense. What would be better is if the clock function worked different ways on different calculators.
It would help for the more advanced users.
I kind of have to disagree with you a bit DJ, I think graphics is pretty important (although he really doesn't need to add too much, it's already amazing), but, at least from my point of view, Axe is a program that will let the most basic BASIC programmers make games at assembly level with equal graphics and speed, and I think that being able to do most of the graphic capabilities of actual ASM programs is important. But that's just my opinion, and I do agree that other things should also be focused on.He's talking about graphical user interface for compiling programs
Ah fair enough. I take back what i said.. heh.I kind of have to disagree with you a bit DJ, I think graphics is pretty important (although he really doesn't need to add too much, it's already amazing), but, at least from my point of view, Axe is a program that will let the most basic BASIC programmers make games at assembly level with equal graphics and speed, and I think that being able to do most of the graphic capabilities of actual ASM programs is important. But that's just my opinion, and I do agree that other things should also be focused on.He's talking about graphical user interface for compiling programs
Yeah that's what I meant, I really was talking about fancy GUIs. If he decided to make the Axe APP so it has a grayscale program list with 3D animations with rotating program name texts, it would take unnecessary space IMHO. In games, I like to have a lot of graphical abilities. Of course, personally if someone releases an ASCII game I'll still play it, though. Unlike some other people, I don't only play games just for graphics.Yeah, I completely agree with that. I just misunderstood what you had posted before :) Plus I really do like ASCII games, although I don't think I would program an ASCII only game with Axe, but that's just me.
Yeah that's what I meant, I really was talking about fancy GUIs. If he decided to make the Axe APP so it has a grayscale program list with 3D animations with rotating program name texts, it would take unnecessary space.lol
Don't do an ASCII-only game with Axe. I don't recommend it, because due to TI's slow text routines, such game will run considerably slower than a game using sprites. Notice how every text-based demos seems to run much slower than the graphical stuff so farYeah that's what I meant, I really was talking about fancy GUIs. If he decided to make the Axe APP so it has a grayscale program list with 3D animations with rotating program name texts, it would take unnecessary space IMHO. In games, I like to have a lot of graphical abilities. Of course, personally if someone releases an ASCII game I'll still play it, though. Unlike some other people, I don't only play games just for graphics.Yeah, I completely agree with that. I just misunderstood what you had posted before :) Plus I really do like ASCII games, although I don't think I would program an ASCII only game with Axe, but that's just me.
I believe I made a topic for it already.Where does Axe fit into all of this? And Axe does not install any OS hooks or anything like that.
But, I'm entering a competition for a scholarship using xLib and BASIC.
Lemonade Tycoon is my game.
Now, here's where it comes together.
I'm using a Presentation Link and a TI ViewScreen.
I ran my program that uses xLib. It shows up fine on the calc...
but it's got the wavy screen on the screen.
AND IT'S JUST THAT PROGRAM.
Everything up to that point (the PRGM menu, the Home Screen, the Graph Screen) displayed fine.
Can Axe screw up xLib programs?
:15->{A+1}
:Disp {A+1}>Dec
OH! Also, one thing:Yeah, it's too bad that Mirage relies on so much. :(
When Axe will support Mirage and Ion (and DCS since MOS/Ion progs shows in it), it will be important to be careful to not use RAM areas in your games that are used in MirageOs. I remember Zelda: Dark Link Quest used an ASM utility that did and when exiting Mirage (back when it was in beta, the game showed in Mirage) it crashed. I heard xLIB sometimes had issues, too, with this.
It should be Asm(C930) The assembly header is automatically added by the parser.Right, I forgot about that. :)
Just testing out the commands.Are you sure its a random error? Or does it have something to do with your source?
Axe 0.1 still throws out random errors when parsing.
Is this still supposed to happen?
Wow, this language looks powerful! And also very different from the Basic that I remember. I see that it's still pretty early in development though, so how much is the syntax going to change over the coming months? Should I start learning how to use it now, or should I wait for it to stabilize a little more (or is it already fairly stable)?From what I've seen, it's pretty stable. I don't know if you've seen some of the games made already by Axe, but you can do a lot already in the early stages of this program.
Either way I can't wait to get my hands on this :D
-1->A
5+A->B
If(A>30000)
-(-A*5)->A
Else
A*5->A
End
A<10
A<10 OR (A>65326)
Ah, after reading that I finally understand your code now! ;DCode: [Select]If(A>30000)
-(-A*5)->A
Else
A*5->A
End
int(EXP) Returns a sign extention for the expression. Converts a signed byte in the range -128 to 127 into a 16 bit number in the same range.And it was really cryptic. I totally couldn,t understand what you meant by that. "Returns a sign" to me sounds like it returns 1 if the sign is negative and 0 if it isn't, and stuff like that.
Fill(PTR1,SIZE) Whatever byte is already at the location Ptr1 is copied to Size more consecutive bytes. Zero is not a valid Size.
conj(PTR1,PTR2,SIZE) Size bytes starting from the location Ptr1 are copied to the location at Ptr2. Zero is not a valid Size.
expr(PTR1,PTR2,SIZE) Size bytes starting from the location Ptr1 are exchanged with the bytes starting at the location Ptr2. Zero is not a valid Size.
Fill(PTR1,SIZE) Whatever byte is already at the location Ptr1 is copied to Size more consecutive bytes. Zero is not a valid Size.
conj(PTR1,PTR2,SIZE) Size bytes starting from the location Ptr1 are copied to the location at Ptr2. Zero is not a valid Size.
expr(PTR1,PTR2,SIZE) Size bytes starting from the location Ptr1 are exchanged with the bytes starting at the location Ptr2. Zero is not a valid Size.
:For(X,0,5
:0->{L1+X
:End
You can do this:0->{L1}
Fill(L1,6
:For(X,0,9
:{L1+X}->{L2+X
:End
And here is the new way::conj(L1,L2,10
Mhmm ok, because the way it is explained in the doc seems like something totally different. I think it may be best to clarify in the doc that fill does the same thing as the BASIC command, but for pointers instead of lists. Also if I read Builderboy way, I still doN,t get it. To me it seems like he's saying Fill just copy one list element to the next one, not fill the entire list with an element.For that example, you would want conj(L1+9,L2+9,4
About Conj, what if we want to do For(X,9,12:{L1+X}->{L2+X:End?
Also are lists defined the same way as other stuff? Like at the beginning of a program I just do {2,34,5,23,0->L1?
:[0222051700->Pic1
:conj(Pic1,L1,5
'CHAR' The expression becomes the ASCII value of the single character between the apostrophes. It can even be another apostrophe.
Disp EXP▶Dec The value of the expression is displayed at the current cursor position in base 10. The cursor is then advanced 5 spaces.
Disp EXP▶Frac The ASCII character the expression represents is displayed at the current cursor position. The cursor is advanced. A new line is added if it hits the edge.
This?Yep, that would be it. Like, if you read a byte, B, from a string you can check to see if it is "A" by doing:Quote'CHAR' The expression becomes the ASCII value of the single character between the apostrophes. It can even be another apostrophe.
If B='A'
instead of the more crypticIf B=65
-2->{L1}
-1->{L1+1}
0->{L1+2}
1->{L1+3}
2->{L1+4}
For(A,0,4)
Disp int({L1+A})+2>Dec
End
For({Pic99+3},0,{Pic99+2}
This line compiles fine, but if I add an "End" later then the compiler gives me a "Block" error. I was able to use Pic99 before this part, and it is 4 bytes long
Can anyone help please?I think the first argument is required to be a variable, not a memory location.
I have this line of code:Code: [Select]For({Pic99+3},0,{Pic99+2}
This line compiles fine, but if I add an "End" later then the compiler gives me a "Block" error. I was able to use Pic99 before this part, and it is 4 bytes long
[20:32:26] <@calc84> DJ_Omni: I think the larger executable sizes is fine because it's still less than a 16KB app that has to be packaged with it :)
[20:33:13] * Tribal ([email protected]) has joined #omnimaga
[20:33:14] * Netbot45 sets mode: +o Tribal
[20:33:14] <@Netbot45> [Tribal] If you are near to the dark, I will tell you 'bout the sun...
[20:34:56] * Jarvis_ ([email protected]) has joined #omnimaga
[20:34:56] * Tribal sets mode: +v Jarvis_
[20:35:44] <@Tribal> !uptime
[20:35:44] <+Jarvis_> I have been awake for 1min 1sec
[20:35:49] <@Tribal> rrawr
[20:35:55] <@DJ_Omni> calc84 what are you replying to?
[20:36:11] <@DJ_Omni> !uptime
[20:36:11] <+Jarvis_> I have been awake for 1min 27secs
[20:36:16] <@DJ_Omni> oh
[20:36:47] <@calc84> just general discussion
[20:36:55] * @HAL ([email protected]) Quit (Ping timeout: 360 seconds)
[20:36:57] <@calc84> since we have talked about this before
[20:37:02] <@DJ_Omni> but idk what you are talking about calc84 x.x
[20:37:05] <@calc84> Axe
[20:37:09] <@DJ_Omni> could you give me the context?
[20:37:19] * HAL ([email protected]) has joined #omnimaga
[20:37:20] * Tribal sets mode: +v HAL
[20:37:27] <@DJ_Omni> the post in particular, preferably
[20:37:28] * Netbot45 sets mode: +o HAL
[20:37:41] <@calc84> like, you were talking about how big the compiled programs were compared to the source
[20:37:59] <@DJ_Omni> oh ok
[20:37:59] <@DJ_Omni> but
[20:38:09] <@DJ_Omni> what if a prog is larger than 24389 bytes
[20:38:19] <@DJ_Omni> how will ion/mirage unarchive it to run it
[20:38:35] <@DJ_Omni> axe cannot compile into flash app atm
[20:39:06] * @Jarvis ([email protected]) Quit (Ping timeout: 493 seconds)
[20:39:11] <@Netham45> The calc can't run anything bigger than 16384 bytes, iirc.
[20:39:15] <+Iambian> You mean, what happens if the executable portion is over number a little over 8000?
[20:39:29] <+Iambian> The execution boundary is at $C000
[20:39:36] <@calc84> hmm, true, Iambian
[20:39:40] <+Iambian> You start at $9D95
[20:39:46] <@DJ_Omni> i was talking about the program size
[20:39:48] <@DJ_Omni> i mean
[20:39:50] <@DJ_Omni> in ram
[20:39:52] <@DJ_Omni> before running
[20:39:59] <@calc84> so most of the program would be data if you have 24K size
[20:40:04] <@DJ_Omni> if you have a 8xp file that is 65536 bytes
[20:40:08] <@DJ_Omni> er
[20:40:10] <@DJ_Omni> 65535
[20:40:23] <+Iambian> The linker wouldn't accept it.
[20:40:23] <@Netham45> oh
[20:40:23] <@DJ_Omni> how do you run such program in ion?
[20:40:30] <@DJ_Omni> ion will not even be able to unarchive it
[20:40:31] <@Netham45> knowing the OS, it'd just do a RAM reset.
[20:40:43] <@DJ_Omni> ion must unarchive stuff before running it
[20:40:49] <@DJ_Omni> it wont run programs directly from archive
[20:40:53] <@calc84> and at some point, external appvars will be supported
[20:40:54] <+Iambian> I *have* sent a 65500 byte program before. The OS *will* accept it into FlashROM
[20:41:07] <@calc84> asm programs have this size problem too
[20:41:08] <@Netham45> Iambian, what happened when you unarchived it?
[20:41:16] <+Iambian> The OS *will* give the memory error.
[20:41:21] <+Iambian> If you try to unarchive it.
[20:41:22] <@DJ_Omni> maybe in the future, if axe produces a much larger than allowed program, it could simply split the data in another file?
[20:41:23] <@calc84> but it doesn't really happen for most games/programs
[20:41:32] <+Iambian> Still.
[20:41:49] <@DJ_Omni> also about the 8000 byte limit
[20:41:52] <+Iambian> Doesn't Axe refuse to generate programs that are above known limits? Isn't that something that every ASM programmer should know?
[20:41:58] <@DJ_Omni> does it means if my axe program compiled code ends up larger
[20:42:05] <@DJ_Omni> that my program will not run properly?
[20:42:11] <@DJ_Omni> i mean just the code, not the data
[20:42:16] <@calc84> if the code section is larger, correct
[20:42:20] <+Iambian> DJ_Omni: That truly depends on how Axe assembles that program.
[20:42:22] <@DJ_Omni> ouch x.x
[20:42:27] <@DJ_Omni> that might pose a problem
[20:42:35] <@Netham45> we could all just get 73's and use the hacked 83 OS on them
[20:42:37] <@DJ_Omni> maybe an asm expert should ask quigibo if he thought about that
[20:42:41] <+Iambian> If data is attached at the end of the program, then it'll be fine as long as the executable portion is below address $C000
whenever you store something to a pic/str/gdb does it work in order, ie if you had "[00]-->Pic1 \ [11]-->Str1" would the end of the program be "0011" or "1100"?it would be 0011
no, you have to fill each app that takes up less than that with just zeros so that it equals 16384 bytesPlayer is right. :) Even if you only have 20 bytes of code in the App, it would still be 16384 bytes. ;D
.MUSICAL
[0000000038444438 //These are all the different sprites. They are actually on one line, i just
040404043C444438 //spread them out so you can see them
040404043C7C7C38
040605043C7C7C38
040605063D7C7C38
0000000000000000]→Pic1
4→{L1} //Initializes stuff not really important to this part of the program.
2→{L1+1} //Well, it was. Then i deleted the part that used it in frustration
5→{L1+2}
2→{L1+3}
50→{L1+4}
DiagnosticOff //This is the happy little intro screen that works perfectly fine
Repeat getKey //It just displays random notes with a title. I like it :)
For(X,0,11
For(Y,0,7
Pt-Off(X*8,Y*88*(rand/13107)+Pic1
End
End
DispGraph
Output(2,0,"Unreal Music"
Output(4,1,"Notator"
End
Lbl MN
ClrDraw
Pt-Off(0,0,Pic1 //This is a remanant I left for example. No matter what i put, it will not draw any of the sprites
DispGraph //(I have tried all the ones I defined above) Nor will any of the other sprite routines work.
Output(0,1,"O" //This is just to show, this still works. So does the horizontal line drawing routine which used to be here...
While 1
0→K
Repeat K //Yes, i know this is a lot of pointless code. Remember that deleting i mentioned above? this is what remains
getKey→K
ReturnIf K=15
End
End
.....(There's more, but the rest doesnt matter)
:.MUSICAL
:[0000000038444438040404043C444438040404043C7C7C38040605043C7C7C38040605063D7C7C380000000000000000]→Pic1
:
:
:DiagnosticOff
:ClrHome
:Repeat getKey
:For(X,0,11
:For(Y,0,7
:Pt-Off(X*8,Y*8,8*(rand/13107)+Pic1
:End
:End
:DispGraph
:Output(2,0,"Unreal Music
:Output(4,1,"Notator
:End
:
:
:Lbl MN
:ClrDraw
:Pt-Off(0,0,Pic1 if this is here, it crashes/doesnt work. otherwise life is good.
:DispGraph
:While 1
:
:ReturnIf getKey(15)
:End
:
:
:Lbl PS
:0→X
:While {L1+X}≠50
:For(A,0,{L1+X+1}
:{L1+X}→B
:SinRegB2/4+(B*14)+269,10000
:End
:X+2→X
:ReturnIf getKey(15)
:End
there ya go
if you use the appvars for saving, it might be best to encrypt them somehow, as I have heard its quite easy to hack into mario 2.0's appvar to give you extra stuff or something like that. especcially if you are doing something where one byte (or two) are the items/level/whateverErrm, I didn't think Mario 2.0 had an appvar...
Just beware the new commands are kind of vulnerable to change since I'm not sure exactly how I'll generalize them to other variables in the future.Aaah, I'm noting this. Will the change be very drastic? Again, in my case, I doubt it would be much hassle to change, because generally, I only use such type of commands in two place in my program (I never really have auto-saving features in my games)
eh, It was some game like mario that used an appvar and people could easily hack itif you use the appvars for saving, it might be best to encrypt them somehow, as I have heard its quite easy to hack into mario 2.0's appvar to give you extra stuff or something like that. especcially if you are doing something where one byte (or two) are the items/level/whateverErrm, I didn't think Mario 2.0 had an appvar...
Say again?he was testing cooliojazz music program, which previously crashed on his calc or emu, and now it works fine
Explain.
I know, I haven't actually made a real tutorial for it yet. I don't think I will either until its finished. I might make a mini one when the beta comes out, but other than that, these threads are the only resource for those types of general information.Lol yeah, I noticed a suddent increase in activity there. However the entire Omnimaga forum has been going this way for over a month now. We have hit records in March. I think the IRC post notifier bot helps a lot now, though, because IRC chat users now frequent the board more often.
Speaking of which, whats with all the sudden influx of posts? Just a few days ago there were only a handful of posts per day in this subforum, and now entire threads get filled up in a matter of hours. There's got to have been over 100 new posts here just from today alone...
Another new thing that might need explanation is the new grayscale command. I haven't added any grayscale drawing commands yet, but I think it can still be useful. Basically, whatever is drawn on the back buffer will appear gray wherever the front buffer is white. So it effectively gives you a background layer. Keep in mind you have to update the display an odd number of times each frame (3 is fine spread out around the code) and you have to make sure sprites update their positions an even number of of draw cycles apart (every other cycle is perfect). Otherwise they leave a checkered blur.What do you mean exactly by "draw cycles"?
Eh.
Noobish mistake.
:P
It happens.
The sad part though is that in some cases, when you download something, there's no doc provided or the doc is separate from the binaries x.xEh.
Noobish mistake.
:P
It happens.
He's right. You will learn eventually never to download anything without documentation.
:"RAWR
:"prgmA"->Str1
:Disp {Str1}>Frac
Code: (prgmA) [Select]:"RAWR
Code: (prgmB) [Select]:"prgmA"->Str1
Why is this not working?
:Disp {Str1}>Frac
QUESTION: What can you do with the accessing of programs in Axe?/me pokes calc84maniac to re-make OTBP Assembler with Axe
If this is true, how would you read and write data from programs in Axe?
PROGRAM:A
"RAWR
PROGRAM:B
"prgma"→Str1
Disp Str1
Output:
►A__________Done
PROGRAM:C
"prgmA"→Str1 //"prgm" is typed out.
Disp Str1
Output:
prgmA_______Done
Prgm A:
:RAWR <--No quotes here, we're reading raw data.
PrgmAXE:
:"prgmA"->Str1
:GetCalc(Str1)->P
:For(A,0,3)
:Disp {P+A}>Frac
:End
@Quigibo
I was looking at prgmCOUNTER and was trying to retype it in by hand (for practice and such) and wasn't able to make it work because the "v" you store in Str1 at the beginning of the string was a different one. Where is that token found or is it something else that is going wrong?
Anyone can answer this, just wasn't sure what was going on and it's his example.
That 'v' is the prefix for appvars and is not the lowercase 'v', its the one on the [2nd][8] button.
While you can run executable code from another program, its way too dangerous, so I'm not going to support it right now. But you can with assembly commands. Anyway, the main usage is for reading and writing to programs. Like if you made a new program with HELLO as the first line, you can read that just like you read an appvar, and also write over and modify it. The advantage is that appvars are not easily editable. So if you want to make an external level pack come with your game, you might want to consider using a program instead so levels can easily be edited.Oh, personally I am not certain if I would want to do this, especially if I can use internal sub-routines. What I thought about is reading external data like tilemaps and the like. See for example Metroid II: Evolution. The BASIC code is about 15 KB large, there's xLIB, that is 16 KB large, but tilemap data, stored into a list of sub-programs named prgmM40 through M60 or something like that, are a whooping total of 85 KB.
Where did you say that? And thanks, I completely forgot about that key. :)In reply to Quigibo post?
I'd say no to manditory headers. Maybe use the header system shells use to identify which BASIC progs to run.I don't understand... wouldn't this make all Mirage basic programs show up in the list?
the ::"String
Thanks again Builderboy for the Logo. I didn't end up using the whole thing, just the picture of the Axe, but it looks great.
an Ion app exists.Really? URL to it?
.OMNOM
[00FFFF77FFFF8BFFFF91000000DFFFABF81F8B00C36E0000->Pic1
Pic1->{L6}
DispGraph
Mhmm I've been messing around with L6 a bit. I wanted to figure out how to store data directly to the graph buffer instead of going through the other commands. However I can't really figure out what I am doing wrong that cause nothing to be changed. Here's my code:Oh, you're going to need to use the copy command. Since you have 24 bytes there, you should do conj(Pic1,L6,24)Code: [Select].OMNOM
[00FFFF77FFFF8BFFFF91000000DFFFABF81F8B00C36E0000->Pic1
Pic1->{L6}
DispGraph
.OMNOM
[00FFFF77FFFF8BFFFF91000000DFFFABF81F8B00C36E0000->Pic1
Conj(Pic1,L6,24)
DispGraph
Even two 83+ calcs could have different quality between each others.Is it because of difference in hardware? Did TI change the hardware during the production of TI83+ just like what they did with the extra ram page in TI84+SE? Anyways, good luck on fixing the greyscale, Quigibo!
There is only one thing that could make the menus better: make them in 3D and 8 level grayscale. Oh, and add some lobsters as well! ;DLol, nah, 16 level grayscale and sound
Seriously, those menus are epic!!!
Yes, Axe needs to have a theme song to play on the main menu xDThere is only one thing that could make the menus better: make them in 3D and 8 level grayscale. Oh, and add some lobsters as well! ;DLol, nah, 16 level grayscale and sound
Seriously, those menus are epic!!!
jk. Lobsters seems like a good idea, though :P
In my case, in Opera/Firefox with Quigibo version I had Times New Roman as doc font but in IE it was something like Arial for some reasons. I did not have issues viewing the text, though.
What is the difference between bytes and bits? I've never really understood that.
Actually, there is a little trick you can use extract them. Try this:
:X->B
:For(A,1,N)
:B/2->B
:End
:B^2
Can you archive the source file before compiling it?
:[FF]→GDB01
:"GDB01"→Str01
:Disp GetCalc(Str01)►Dec
For the GDB# thing. I don't think there is a GDB10, only GDB0 to GDB9. Could be wrong though, please correct me if I'm wrong.
Another thing is that Axe allows you to name everything with up to 2 numbers/letters instead of just a single number. The following are all valid names:
Str1
Pic0
GDB4Str1A
Pic9Z
GDB45Str66
Pic8C
GDB3X
There is another way to get the Nth arbitrary pointer (not consecutive not the same size) but its a little more complicated and involves pointers to pointers.
Yeah I'm used to forums where double-posting is just fine, so sometimes I don't think to check here. But once I look down at my post(s) and see two in a row I instantly realize :-[
But anyways...For the GDB# thing. I don't think there is a GDB10, only GDB0 to GDB9. Could be wrong though, please correct me if I'm wrong.
From the documentation:QuoteAnother thing is that Axe allows you to name everything with up to 2 numbers/letters instead of just a single number. The following are all valid names:
Str1
Pic0
GDB4Str1A
Pic9Z
GDB45Str66
Pic8C
GDB3X
I was wondering Quigibo because I plan on making a project in which tiles will appear in groups of 16 at a time, with each tile being either white or black.
its 6 bytes per program, not six bytes per call correct? Or else that would be very significant :P yayyyy line routine! This is one i have been waiting for a while, glad its finally in :) and signed division yaayyyyy! Haha now to go through and re-optimise some of the code i have ;DYes, for the entire program. Glad you like the update :)
I finally finished rewriting the entire math engine. The code was getting way too messy and especially with the addition of signed and unsigned versions of math operations. It was making it way too complicated to optimize the code. The parser code is now a lot more organized, smaller, faster, and uses fewer variables. In addition, nearly all of my example programs became a few bytes smaller from my increased auto-opt list. In my game of life example, it actually shrunk by 9 bytes (1.3% reduction) without changing any code, simply by compiling with the newer version! Everyone will most likely see small drops in the executable sizes. These aren't the big optimizations though. Those will eventually come when I get to look-ahead parsing.cool! Glad to hear!
I'm going to focus on some new commands now. I might have it ready by late tonight, but I'm not sure. Don't expect too many new things, I spent most of my time swatting bugs and cleaning the code so that future versions will be easier to write.
I'm going to focus on some new commands now.
I,m confused at what you mean, could you clarify ???I'm going to focus on some new commands now.
Bit getting/setting? ;D
hmm... but its the same size to do:It does make a difference if you do
ld a,(var)
and
ld a,(ix+var)
So I don't think it makes a difference. Don't forget, the byte commands need to use the "a" register, not "hl".
By the way, I don't think my original plan to use flags for the conditionals is going to work, but at least the "and" "or" and "xor" commands are half of what they were.
How about having a variable that tells the program what type of delay to do? I mean that for example the default state is 0 so that each time a grayscale is run, it uses the 6MHz delay. However, if you put 1 into it, then the grayscale commands will be using 15MHz delays. And maybe have it so that 2 different programs are compiled when the variable is modified.This is the best option possible. I think it would be like this:
Dunno if I made myself clear.
I prefer to keep my 15 MHz games cross-compatible, even if it means they run twice slower on older models.What you can do is this:
One thing about the new update:
Can someone please tell me how the new commands would be used?
More specifically, conj()r and the bitwise "and", "or", and "xor".
Hmm...
What are the applications of such?
I only see redundancy as of right now.
Ah ok thanks, that migth work.QuoteI prefer to keep my 15 MHz games cross-compatible, even if it means they run twice slower on older models.What you can do is this:
prgm15MHZ
:Full
<some code>
:Normal
:DispGraphr
:Full
<more code>
That way it will do all the game calculations in 15MHz mode but still update the graph in 6MHz mode. The 6MHz and 15MHz DispGraph routines take the same amount of time since they are limited by the same LCD delay in both cases.One thing about the new update:
Can someone please tell me how the new commands would be used?
More specifically, conj()r and the bitwise "and", "or", and "xor".
This is a good explanation for the bitwise features:
http://en.wikipedia.org/wiki/Bitwise_operation
As for conjr, these are the same:
conj(L1,L6,100)
conj(L1+99,L6+99,100)r
It copies the 99th byte first then the 98th, the 97th, ... to the 0th byte instead of the other way around.
I actually switch to 6MHz before grayscale display in Chip's Challenge. It's not an uncommon method.Alright, that reinforces my thoughts. If you want 15MHz grayscale, you will have to switch to 6MHz manually to display it. Even if some new programmer accidentally tries it in the 15MHz mode, it doesn't crash the calc or anything, it just displays funky garbage on the screen, so its not a big deal.
I actually switch to 6MHz before grayscale display in Chip's Challenge. It's not an uncommon method.That makes it sound a lot better. I now think this is the best method. :D
I could have it do that for you, but I'd rather the programmer do it themselves since those making 6MHz games won't want to have the extra size increase for a feature they're not using.Ah, very good point! :)
[Pic1]->GDB1
I believe that you store that data into another variable.You just used exactly what you're asking about in that example. [Pic1] is the "DATA" and GDB1 is the "NAME".
Then, use that variable normally.Code: [Select][Pic1]->GDB1
EDIT: Also, does anyone know what DATA→NAME does? Use? Practical application?
:[Pic1]->Pic1 ;Store the picture in memory call it Pic1
:det(12) ;Add 12 zeros (96 pixels) to the bottom
:conj(Pic1,L6,768) ;Copy all 768 bytes to the graph buffer
:DispGraph ;Draw the buffer onto the screen
:[Pic1]->Pic1 ;Store the picture in memory call it Pic1
:det(12) ;Add 12 zeros (96 pixels) to the bottom
:Pic1->DispGraph ;Draw the picture directly onto the screen
Amazing work, Quigibo. That was a impressive optimization. ;)
Is there any main optimizations like that left? ;D
Raytracing or Raycasting? Raytracing is much more complex, and I do not know of any raytracing ever done on a calculator.
Lol so which one is it? Either way you might want to talk to bwang, he has written both the raycaster, and the raytracer for the nSpire :) And both are quite amazing :O
I estimate it will take me about 20 hours to finish at the current rate I'm finishing problems (its only 4 problems by the way). Despite being my hardest class, its still the most fun and I'm actually doing pretty well in it. Wish me luck!20 hours? Good Gravy man! I wish you the best of luck with it!
Do you mean you could just convert a PRGM to APPVAR, lock programs, hide them and even convert a string to a picture?I think so, yes (though renaming to a different name length would be somewhat difficult in Axe)
EDIT: or even rename them?
Nice idea Quigibo. Personally, once the project is nearly done, I would add those lower level commands, but warn the user that those commands are not necessary to make great Axe programs and they are just for people who got ASM knowledge or wants to go lower level. The main doc part needs to remain for higher level language programmers and as user-friendly as possible.Yes.
We also need to keep in mind about people who might accidentally mess things up very bad
.S S
"S"→Str1
GetCalc(Str1)→P
!If P
GetCalc(Str1,9)→P
End
"vS"->Str1
You need the prefix "v" in the Str1.
That means it should show this:Code: [Select]"vS"->Str1
The v is question is [2nd]+[8].
I don't have the Full command anywhere in my code, but now that I actually think about it, my Archive space is nearly full would that maybe have something to do with it? Because I sent it to another 83+ and it ran faster on her calc.Strange, this shouldn't be happening. What is the person's OS? If it's a TI-Nspire, then this is why, though (because the Nspire won't emulate 84+ ASM programs at the right speed)
Pointers (page 9)
Actually, there's no such thing as "the zeroth item"; the correct way to say this would be "the first byte has address zero, the second byte has address one". Not exactly intuitive, I know. If you don't want to change this I can understand.
It might be easier to understand to write "GDB1+A" (assuming that Axe understands this; I didn't check, but assume it does). I understand the current notation is not so much wrong, but it could be unclear for beginning programmers.To answer your first question, sometimes. If you are adding an arbitrary number like A+492 or some pointer it won't generally make a difference. But, certain numbers get automatically optimized (smaller size, faster speed) like A+1 or A-256, there is a big list of these "auto-ops" in the zip file. My intention is to get the programmer in this habit so they don't have to think about it when optimizing their code. Maybe I'll mention the reason somewhere there, I do mention it at the end in the optimization section.
Since you are very consistent about this notation, I assume there's a reason for it... performance? Can Axe optimize "A+GDB1" better than it optimizes "GDB1+A"? If so, maybe you should explicitely state both are valid, but "A+GDB1" is slightly faster.
"We use the curly brackets to indicate that we want the byte that's at the address of the pointer, not the the value of the pointer itself."
From reading your code samples:
Disp Str1 Displays the contents of the (probably zero-terminated) string starting at the address in Str1.
Disp {A+GDB1} Displays the value of the single byte at base address GDB1 incremented with offset A.
That's quite a difference from what you're saying in the documentation...
Data & Arrays (page 11)
The comments for one of the pieces of sample code say "BAISC", oops...
An Example Program (page 14)
You're already using the "optimized dual-store":
0->S-1->D
This hasn't been explained yet and is hardly standard notation. Putting a note "see page 17 for details" would be helpful.
Optimization tricks (page 17)
"Evaluate all constant expressions before compiling."
It would be very awesome if you could teach Axe to recognize expressions working on two constants and automatically decide to pre-compute them...
"If the last line of your program is Return, then remove it. Even if it was part of a subroutine, the return is automatically added at the end for you so there's no need to have 2 returns at the end. Saves 1 byte."
Uhm, that saves 1 byte in the source, not in the executable, right?
And about commands.htm:
Fix CODE: Changes how text is drawn. Code must be a constant.
Wouldn't it make more sense to make CODE consist of flags? That way you can set multiple values at once. Especially useful if you want to reset everything at the end of your code.
ReturnIf EXP
Is there a special reason to include this? It seems to be equivalent to If EXP Return End.
Actually, I was thinking about binary flags. There's two possible ways to do this though...And about commands.htm:That's actually a really cool suggestion! Are you suggesting that saying Fix 135 would behave the same as Fix 1:Fix 3:Fix 5 ? That could work, I like the idea!
Fix CODE: Changes how text is drawn. Code must be a constant.
Wouldn't it make more sense to make CODE consist of flags? That way you can set multiple values at once. Especially useful if you want to reset everything at the end of your code.
Like I said, it's a minor nit-pick; it's more of a linguistics thing than a technical one. I'm a computer science student myself, the standard example I know is "you have five fingers, with indices 0, 1, 2, 3 and 4. The first has index zero, the second has index one, ..., the fifth (and last) has index four." Essentially, ordinal numbers start at "first" (both in computer science and in general) while cardinal numbers start at zero (at least in computer science). With "ordinal numbers" and "cardinal numbers" I mean the linguistic terms.Pointers (page 9)Actually, in computer science, you really DO start counting at zero so you can have a 0th element as part of a list.
Actually, there's no such thing as "the zeroth item"; the correct way to say this would be "the first byte has address zero, the second byte has address one". Not exactly intuitive, I know. If you don't want to change this I can understand.
I wonder... if BASIC Builder could be used to package an Axe program into an app?? That could be an interesting work-around.That would be interesting. Someone needs to check.
I r confus.
Explain your spasm, sir.
Repeat K=15
getKey→K
If K=49
sub(D)
Disp 65502>Dec
Pause 5000
End
End
Lbl D
sub(SO)→{L}r
conj(P-2,L+2,sub(SL)+2)
If sub(NS)-{V}≠0
sub(SS)→T
{V}→A+1→{V}
conj(T,sub(SS),sub(AL)-(sub(DS))-(sub(SO)))
{V}-1→{V}
Else
{V}-1→A
End
conj({V}*2+V+2→T+2,T,sub(AL)-T-2)
sub(AL)-(sub(SL)+4→T)→J→{V+2}r
sub(NS)-1→{V+1}
A^256→{V}
conj(V,T+L→T,J)
GetCalc(Str0,J)→V
conj(T,V,J)
sub(L)
Disp 65501>Dec
Pause 5000
Return
Why yes it does :) It takes advantage of the fact that when you do 5->{L1+5}, the value returned in Ans is not 5, but L1+5aaah ok awesome ^^
@Runer
Axe doesn't have restrictions on this other than the 150 individual label names. Its more of a hardware limitation. I think the stack size is like 400 bytes or something although I have no idea really I'm basically making up this number. Anyone actually know?
It sounds more like you have a memory leak on the programming side than on the parser side. Double check that all the subroutines end in Return and that you aren't using goto between subroutines or trapping recursive subroutines, I don't know if you're using those.
well maybe you can post your code so we can actualy see what is going on. Its possible there might be something you are missing, or hardware thats going wrong
.SPREDIT Sprite Editor
.PIXEL SPRITES
.5x5
[F8F8F8F8F8000000]→Pic1
.3x3
[E0E0E00000000000]
.2x2
[C0C0000000000000]
.BLANK SPRITE
[0000000000000000000000000000000000000000000000000000000000000000]→Pic0
.HEX KEYS
∆List(33,34,26,18,35,27,19,36,28,20,47,39,31,46,38,30)→GDB1
.HEX TEXT
"0123456789ABCDEF"→Str1
.APPVAR NAME
"vSPREDIT"→Str0
.HELP TEXT
"2ND: INVERT PIXEL"→Str00
"ARROW KEYS: MOVE CURSOR"→Str01
"0-F: HEX INPUT"→Str02
"DEL/STAT: HEX NAVIGATION"→Str03
"F2: NEW 8X8 SPRITE"→Str04
"F3: NEW 16X16 SPRITE"→Str05
"+/-: CHANGE OPEN SPRITE"→Str06
"CLEAR: EXIT"→Str07
sub(I)
.Disp {V}>Dec
.Disp {V+1}>Dec
.Disp {V+2}>Dec
.Disp i
.Disp {V+3}>Dec
.Disp {V+4}>Dec
.Disp {V+5}>Dec
.Disp i
.Disp {V+6}>Dec
.Disp {V+7}>Dec
.Disp {V+8}>Dec
.Disp i
.Disp {V+9}>Dec
.Disp {V+10}>Dec
.Disp {V+11}>Dec
.Disp i
.Disp {V+12}>Dec
.Disp {V+13}>Dec
.Disp {V+14}>Dec
.Disp i
.Disp {V+15}>Dec
.Disp {V+16}>Dec
.Disp {V+17}>Dec
.Pause 10000
.<MAIN LOOP>
Repeat K=15
getKey→K
.KEYPAD CHECK
sub(K)
.HELP CHECK
If K=53
ClrDraw
Fix 0
Str00→{L₁}ʳ
Str01→{L₁+2}ʳ
Str02→{L₁+4}ʳ
Str03→{L₁+6}ʳ
Str04→{L₁+8}ʳ
Str05→{L₁+10}ʳ
Str06→{L₁+12}ʳ
Str07→{L₁+14}ʳ
For(A,0,7)
Text(0,A*8,{A*2+L₁}ʳ)
End
DispGraph
Repeat getKey≠0
End
sub(L)
End
.CHANGE SPRITE
If K=10 and (sub(NS)≠{V})
{V}+1→{V}
sub(L)
End
If K=11 and ({V)≠1)
{V}-1→{V}
sub(L)
End
.NEW 8X8 SPRITE
If K=52
8sub(N)
End
.NEW 16X16 SPRITE
If K=51
16sub(N)
End
.DELETE SPRITE
If K=49 and (sub(NS)≠1)
sub(D)
Disp 65502>Dec
Pause 5000
sub(L)
End
.CHANGE PIXEL CHECK
If K=54
sub(IP)
End
0→H
.HEX MOVE FORWARD CHECK
If K=32
0→D
3→K
3-X^4→W
For(A,0,W)
If sub(K)=0
65533→Z
sub(MC)
End
End
1→D
sub(DG)
End
.HEX BACK UP CHECK
If K=56
0→D
2→K
X-1^4→W
For(A,0,W)
sub(K)
End
1→D
sub(DG)
End
16→H
.HEX ENTRY CHECK
For(A,0,15)
If K={GDB1+A}
A→H
End
End
.HEX ENTRY EXECUTION
If H≠16
0→D
3→K
H→N
0-(X^4)→Z
sub(MC)
For(A,0,3)
A+4sub(GB)sub(SP)
If sub(K)=0
65533→Z
sub(MC)
End
End
1→D
sub(DG)
16→H
End
End
.<EXIT CLEANUP>
ClrDraw
DispGraph
Fix 0
Fix 4
Fix 6
Archive Str0
.<SUBROUTINES>
.CHECK IF CAN MOVE CURSOR
Lbl K
If K=3 and (X+Y≠14 or (S=16 and (Q≠3)))-(K=2 and (X+Y≠0 or (S=16 and (Q≠0))))→Z or (K=1 and (Y≠7 or (S=16 and (Q≤1)))-(K=4 and (Y≠0 or (S=16 and (Q≥2))))→θ)→M
sub(MC)
End
M
Return
.CHECK IF DISPGRAPH NEEDED
Lbl DG
If D≠0
sub(UH)
If S=8
0→E
56→F
Else
65→E
16→F
End
sub(PH)
Output(0,0)
DispGraph
End
Return
.UPDATE HEX
Lbl UH
If S=8
For(A,0,7)
conj(A+22*12+10+L†,A+P,1)
End
Else
For(J,0,1)
For(T,0,1)
For(A,0,7)
conj(J*8+A*12+T+9+L†,J*2+T*8+A+P,1)
End
End
End
End
Return
.PRINT HEX
Lbl PH
For(A,0,sub(SL)-1)
If Q*8+Y=A
X≥4+254→I
End
{A+P}sub(BH)
If Q*8+Y=A
A*2+(X≥4)→I
End
End
If S=8
I*6→E
56→F
For(J,0,95)
Pxl-Off(J,55)
End
Else
I^8*4+65→E
I/8*6+16→F
Line(64,0,64,63)
For(J,0,3)
J*12+16→T
Line(64,T,95,T)
End
End
If E≠0
Line(E-1,F,E-1,sub(CS)+F+5)
End
For(J,0,sub(CS)+4)
If E+J>0 and (E+J≤96)
Pxl-On(E+J-1,S=16*7+F-1)
End
End
Return
.BYTE TO PRINTED HEX
Lbl BH
→B
B/16+Str1sub(PC)
If I≥254
I-1→I
End
B^16+Str1sub(PC)
Return
.PRINT CHARACTER
Lbl PC
→U
If I=254
Fix 3
End
If S=16*3+90≠E
Text(E,F,{U}>Frac)
Else
If S=8
For(J,0,sub(CS)+5)
pxl-Test(91-(sub(CS)),F+J)→{J+L₁}
End
Text(91-(sub(CS)),F,{U}>Frac)
For(J,0,sub(CS)+5)
For(T,0,sub(CS)+3)
If pxl-Test(94-T,F+J) xor pxl-Test(95-T,F+J)
Pxl-Change(95-T,F+J)
End
End
If {J+L₁} xor pxl-Test(91-(sub(CS)),F+J)
Pxl-Change(91-(sub(CS)),F+J)
End
End
Else
Text(66,1,{U}>Frac)
For(J,0,5)
For(T,0,3)
If pxl-Test(69-T,J+1) xor pxl-Test(96-T,F+J) and (T≠0)
Pxl-Change(96-T,F+J)
End
Pxl-Off(69-T,J+1)
End
End
End
End
If I=254
Fix 2
End
S=8*2+E+4→E
If 93-(sub(CS))<E
S=16*65→E
sub(CS)+F+6→F
End
Return
.MOVE CURSOR
Lbl MC
sub(DC)
If S=8
If X+Z→X=8
0→X
Y+1→Y
End
If X=65535
7→X
Y-1→Y
End
Else
If X+Z→X=8
0→X
If H=16
Q+1→Q
If sub(QX)=0
If Y+1→Y=8
0→Y
Else
Q-2→Q
End
End
Else
If Y+1→Y=8
0→Y
Q+1→Q
End
End
End
If X=65535
7→X
If H=16
Q-1→Q
If sub(QX)≠0
If Y-1→Y=65535
7→Y
Else
Q+2→Q
End
End
Else
If Y-1→Y=65535
7→Y
Q-1→Q
End
End
End
End
If Y+θ→Y=8
0→Y
Q+2→Q
End
If Y=65535
7→Y
Q-2→Q
End
sub(DC)
sub(DG)
Return
.DRAW CURSOR
Lbl DC
If S=8
Pxl-Change(X*6+4,Y*6+4)
Else
Pxl-Change(sub(QX)+X*4+1,sub(QY)+Y*4+1)
End
Return
.INVERT PIXEL
Lbl IP
If S=8
Pt-Change(X*6+2,Y*6+2,Pic1)
Pt-Change(X*2+57,Y*2+18,Pic1+16)
Pxl-Change(X+80,Y+22)
Else
Pt-Change(sub(QX)+X*4,sub(QY)+Y*4,Pic1+8)
Pxl-Change(sub(QX)+X+72,sub(QY)+Y)
End
sub(DG)
Return
.SET PIXEL
Lbl SP
If =1 xor (sub(PT))
sub(IP)
End
Return
.PIXEL TEST
Lbl PT
If S=8
pxl-Test(X+80,Y+22)
Else
pxl-Test(sub(QX)+X+72,sub(QY)+Y)
End
Return
.GET BIT
Lbl GB
→B
N→O
For(C,1,7-B)
O/2→O
End
O^2
Return
.SET BIT
.Lbl SB
.Return
.CONVERT QUADRANT TO X
Lbl QX
Q=1 or (Q=3)*8
Return
.CONVERT QUADRANT TO Y
Lbl QY
Q≥2*8
Return
.CHARACTER SIZE MODIFIER
Lbl CS
S=8*2
Return
.LOAD SPRITE
Lbl L
ClrDraw
0→D
sub(DS)+(sub(SO))+V+2→P
Fix 0
Fix 3
Text({V}<10*4+81→A,0,{V}>Dec)
Fix 2
If A≠81 or ({P-2}=8)
Line(A-1,0,A-1,6)
End
Line(A,6,87,6)
For(J,0,6)
conj(J*12+10+L†→A,A+1,1)
conj(Pic0,A,1)
End
If {P-2}=8
sub(8)
0→J
Else
sub(16)
3→J
End
For(Q,0,J)
For(Y,0,7)
sub(LR)
For(X,0,7)
If sub(PT)
sub(IP)
End
End
sub(LR)
End
End
1→D
sub(IV)
sub(DC)
sub(DG)
Return
.LOAD SPRITE ROW
Lbl LR
conj(Q*8+Y+P,S=8*22+(sub(QY))+Y*12+(sub(QX)≠0)+(S=8)+9+L†,1)
Return
.NEW SPRITE
Lbl N
→S
sub(DS)→J
sub(NS)+1→{V+1}
sub(NS)→{V}
conj(V,L₁,sub(AL))
J+L₁→O
If sub(AL)-J→C≠0
conj(O+C-1,O+C+1,C)ʳ
End
C→{O}ʳ
S→{sub(AL)+L₁+2→C}
2→{C+1}
conj(Pic0,C+2,sub(SL))
GetCalc(Str0,sub(AL)+(sub(SL))+4→T)→V
T→{L₁+2}ʳ
conj(L₁,V,T)
sub(L)
Return
.DELETE SPRITE
Lbl D
sub(SO)→{L₁}ʳ
conj(P-2,L₁+2,sub(SL)+2)
If sub(NS)-{V}≠0
sub(SS)→T
{V}→A+1→{V}
conj(T,sub(SS),sub(AL)-(sub(DS))-(sub(SO)))
{V}-1→{V}
Else
{V}-1→A
End
conj({V}*2+V+2→T+2,T,sub(AL)-T-2)
sub(AL)-(sub(SL)+4→T)→J→{V+2}ʳ
sub(NS)-1→{V+1}
A^256→{V}
conj(V,T+L₁→T,J)
.Disp {T}>Dec
.Disp {T+1}>Dec
.Disp {T+2}>Dec
.Disp i
.Disp {T+3}>Dec
.Disp {T+4}>Dec
.Disp {T+5}>Dec
.Disp i
.Disp {T+6}>Dec
.Disp {T+7}>Dec
.Disp {T+8}>Dec
.Disp i
.Disp {T+9}>Dec
.Disp {T+10}>Dec
.Disp {T+11}>Dec
.Disp i
.Disp {T+12}>Dec
.Disp {T+13}>Dec
.Disp {T+14}>Dec
.Disp i
.Disp {T+15}>Dec
.Disp {T+16}>Dec
.Disp {T+17}>Dec
.Disp i
.Disp J>Dec
.Pause 10000
GetCalc(Str0,J)→V
conj(T,V,J)
.ClrDraw
.ClrHome
.Output(0,0)
.Disp {V}>Dec
.Disp {V+1}>Dec
.Disp {V+2}>Dec
.Disp i
.Disp {V+3}>Dec
.Disp {V+4}>Dec
.Disp {V+5}>Dec
.Disp i
.Disp {V+6}>Dec
.Disp {V+7}>Dec
.Disp {V+8}>Dec
.Disp i
.Disp {V+9}>Dec
.Disp {V+10}>Dec
.Disp {V+11}>Dec
.Disp i
.Disp {V+12}>Dec
.Disp {V+13}>Dec
.Disp {V+14}>Dec
.Disp i
.Disp {V+15}>Dec
.Disp {V+16}>Dec
.Disp {V+17}>Dec
.Disp i
.Disp J>Dec
.Pause 10000
Disp 65501>Dec
Pause 5000
Return
.NUMBER OF SPRITES
Lbl NS
{V+1}
Return
.APPVAR LENGTH
Lbl AL
{V+2}ʳ
Return
.SPRITE LENGTH
Lbl SL
If S=8
8
Else
32
End
Return
.SPRITE OFFSET
Lbl SO
{{V}*2+V+2}ʳ
Return
.SPRITE START
Lbl SS
sub(DS)+(sub(SO))+V
Return
.ALL SPRITE DATA START
Lbl DS
sub(NS)*2+4
Return
.INITIALIZE 8X8 SPRITE EDITING
Lbl 8
Fix 1
sub(IV)
8→S
Line(0,0,50,0)
Line(50,0,50,50)
Line(50,50,0,50)
Line(0,50,0,0)
Line(55,16,74,16)
Line(74,16,74,35)
Line(74,35,55,35)
Line(55,35,55,16)
Line(78,20,89,20)
Line(89,20,89,31)
Line(89,31,78,31)
Line(78,31,78,20)
Return
.INITIALIZE 16X16 SPRITE EDITING
Lbl 16
Fix 0
sub(IV)
16→S
Line(70,0,70,15)
Line(89,{V}≥10*7,89,15)
Return
.INITIALIZE POSITION VARIABLES
Lbl IV
0→Q→X→Y
Return
.PRIMARY INITIALIZATION
Lbl I
DiagnosticOff
Full
Fix 5
Fix 7
UnArchive Str0
!If GetCalc(Str0)→V
GetCalc(Str0,4)→V
∆List(0,0,4r)→GDB0
conj(GDB0,V,4)
8sub(N)
Else
sub(L)
End
0→K
Return
.<VARIABLES>
.A=temp
.B=bit number (bit subroutine use)
.C=temp
.D=DispGraph needed
.E=text x position
.F=text y position
.H=hex entry
.I=invert character marker
.J=temp
.K=getKey
.M=can move
.N=number input to bit subroutines
.O=bit subroutine temp
.P=pointer to working sprite
.Q=quadrant
.R=sprite number overlay timer
.S=sprite size
.T=temp
.U=text
.V=pointer to appvar
.W=temp x position
.X=x position
.Y=y position
.Z=change in x position
.θ=change in y position
.DELETE SPRITE
If K=49 and (sub(NS)≠1)
sub(D)
Disp 65502>Dec
Pause 5000
sub(L)
End
Quigibo, it would be nice to maybe describe what involves pushing/poping and the stack when it comes to Axe code, because it is ASM stuff that isn't referenced in the Axe manual, so it might be confusing to Axe programmers that doesn't know ASM.As I said before, Axe doesn't allow you do use the stack unless you use your own assembly code, that's why I never mention it.
Runer, are the numbers off by 2 or by a lot? Try putting it in your other subroutines and see if you narrow down the one that changes it.
there was probably a "push without a pop" somewhere in the code so that by the time it get to the return, it has changed the stack order becasue something else was pushed, hopefully a label and not a number since Axe doesn't allow you to use the stack directly, and so it is actually returning not to the place from where it was called but some other place instead, or a random location if a number got pushed.I got confused there, considering Axe doesn't use the stack, yet you mention his code might be doing stuff to it. Or is push/pop something that has nothing to do with the stack?
Hah, wow if that isnt spaghetti code i dont know what it ;D I was jumping around with the find button to see if any of the Lbls called eachother in a loop or something. Sometimes i was jumping around for 8 or more Lbls before i got to an end :P
Whenever you call a subroutine, you "push" the place its supposed to return to into the stack so it knows where to go back to in the code when it reaches the Return, which then "pops" the stack. Also, I wasn't sure at the time of writing if he did use any assembly code which is why I was explaining it at a lower level.
Glad you found the error :)
Whenever you call a subroutine, you "push" the place its supposed to return to into the stack so it knows where to go back to in the code when it reaches the Return, which then "pops" the stack. Also, I wasn't sure at the time of writing if he did use any assembly code which is why I was explaining it at a lower level.aaah ok, thanks for explaining. Makes more sense now ^^
Glad you found the error :)
When I'm finished with it I'll make sure to post my project. It's a really nice (albeit BIG) sprite editor that can store multiple sprites of either 8x8 or 16x16, and has support for hex entry and live hex displayI,m glad you fixed it. Can't wait to see it in action :)
→
L₁
L₂
L₃
L₄
L₅
L₆
θ
∆List
≠
≤
≥
·
﹢
□
√
²
ʳ
▸Frac
▸Dec
Oh yeah that one, I never tried it personally so I can,t tell. In my early calc programming days, we used TI-Graph LinkI do the exact same thing. :D
Personally I prefer programmign on the calc, though. I type faster on it when programming in BASIC or Axe :P
That's what I thought. So yes, you can use that optimization. So you can do things like 2->{1->{L6}+1} but the code can get pretty crazy looking really fast.
I don't know exactly what is the reason for it, but my program that started within a second with version 0.2.5, now takes 2 seconds to startup. is this perhaps because of the interrupts? of could it be so because of I start my program with a pretty complex for-loop? Has that become slower?
Has anyone mentioned a Memcheck utility yet?Do you mean something to display the free RAM and archive on the screen, for example, or check to make sure there are enough RAM?
I remember Quigibo mentioning a while ago that statements like "If A" may not work in some situations any more. Why was this again?
For(A,0,65333)
Output(1,1,A->Dec)
{A}->B
{A+1}->C
{A+2}->D
If B=17 and C=17 and D=17
Disp 4999->Dec
End
End
EXP1·EXP2
EXP1+EXP2
EXP1☐EXP2
Returns respectively the bitwise "and", "or", and "xor" of the two expressions. These are the plot style tokens.
can someone explain to me how these work?
.APFIND
ClrHome
{є9830}→H
Disp H►Dec
Repeat getKey:End
ClrHome
Lbl ML
7→C
Lbl FL
ReturnIf getKey(15)
{є982E}→D
If H(>/<)D:Goto D:End
(More code which doesnt matter cause it always executes that line ^^)
Lbl D
Disp H►Dec
Disp D►Dec
Now the problem is, that first part always is showing H as 61. But, that goto statement ALWAYS executes regardless if I put < or >. I put <, and the second time it shows H, it'll show 61. (D is 102) If I put > though, It'll show up as 65389. Any help to why this is happening...
Could anyone explain a scenario in which that stuff might be useful in a game? I know what it does but I am just curious how useful it can be?I think they're most useful when dealing with binary numbers or sprites. :)
Programs are people, too.
can a program archive itself at the beginning of execution?A basic program cannot archive itself when it's running, but an Asm program could possibly pull it off, just make sure it wouldn't write back over the original location. It would probably be unstable, though, so I'd try to stay away from it. :)
Yes, I am extremely busy with finals.Good luck with finals. :)
"XXXXX ZZZZZZ YYYYYYY "->Str1
"XXXXX "->Str2
While 1
getkey->K
A+(K=3)-(K=2)->A
conj(A*10+Str1,Str2,10
Text(30,30, Str2
End
This displays the proper string, but with random garbage characters afterwards, ie, "XXXXX eoppp"Quick question on text displaying:You didn't initialize A...Code: [Select]"XXXXX ZZZZZZ YYYYYYY "->Str1
This displays the proper string, but with random garbage characters afterwards, ie, "XXXXX eoppp"
"XXXXX "->Str2
While 1
getkey->K
A+(K=3)-(K=2)->A
conj(A*10+Str1,Str2,10
Text(30,30, Str2
End
I tried putting in Fill(Str2+9, 32) after the conj( line to overwrite possible garbage in Str2 with spaces, but with no success. Any thoughts?
Are you sure Str2 is exactly 10 characters? Maybe you mistyped it.there we go...I missed it by one and I guess it messed things up
wow didn't even know that and I used Mirage for almost a decade x.xAre you sure Str2 is exactly 10 characters? Maybe you mistyped it.OnMode
As long as you have interrupts enabled, and don't write data over the L2 free ram, then its safe to use. But it doesn't save you from buffer overflows or corrupting ram of course.Yeah, that sounds right. By the way, if you want, you can add some simple code to preserve interrupt state. Having interrupts enabled for even one microsecond can cause disasters.
What I'm curious about is the opposite. If you disable interrupts, can you use L2 ram area in mirage? (All the DispGraph routines re-enable interrupts so immediately disable them after those).
ret poThanks. ;D
conj <-> Copy
Expr <-> Exch
SinReg <-> Freq
det <-> Zeros
int <-> sign
>Frac <-> >Char
deltalist <-> Data
Repeat <-> Until
Tangent <-> Bitmap
Ooh, base 2 logarithm/exponent can be useful for a simple floating-point implementation.
Come to think of it, to improve the usefulness of fixed-point values (see: sin/cos), you should make an alternate multiplication routine, "**", to multiply two numbers but return the top 16 bits of the 32-bit result. Currently, there is no easy way to do that.
The Tangent() command uses an OS bcall which is much slower than the 8x8 sprite drawing routines, but its still fast enough for most things and more convenient than drawing a bunch of 8x8s and it takes up hardly any memory in the program. Because its an OS routine, they decide how the flags affect it so I really can't do anything about that other than tell you to change the flags with the Fix commands.mhmm I see. Thanks for the info. Would it be slower to use a Tangent() with 16x16 sprites than a for() loop with 4 8x8 Pt-Off() sprites?
Also, I know it clips the sprites, but the documentation for that command (_DisplayImage) says that you cannot draw the image totally off the screen for some reason. I don't know if that means it will corrupt ram or something so use with caution if you draw completely off screen.
Oh another thing, I should mention. It uses Pt-Off() logic to draw the sprite. That is, it erases behind it as it draws.
It probably would be slower -- this is TI-OS we're talking about.The Tangent() command uses an OS bcall which is much slower than the 8x8 sprite drawing routines, but its still fast enough for most things and more convenient than drawing a bunch of 8x8s and it takes up hardly any memory in the program. Because its an OS routine, they decide how the flags affect it so I really can't do anything about that other than tell you to change the flags with the Fix commands.mhmm I see. Thanks for the info. Would it be slower to use a Tangent() with 16x16 sprites than a for() loop with 4 8x8 Pt-Off() sprites?
Also, I know it clips the sprites, but the documentation for that command (_DisplayImage) says that you cannot draw the image totally off the screen for some reason. I don't know if that means it will corrupt ram or something so use with caution if you draw completely off screen.
Oh another thing, I should mention. It uses Pt-Off() logic to draw the sprite. That is, it erases behind it as it draws.
Also, I know it clips the sprites, but the documentation for that command (_DisplayImage) says that you cannot draw the image totally off the screen for some reason. I don't know if that means it will corrupt ram or something so use with caution if you draw completely off screen.
If getkey(1)
[0000000000000000->Pic1
end
If getkey(2)
[FFFFFFFFFFFFFFFF->Pic1
[FFFFFFFFFFFFFFFF
0000000000000000]→Pic1
If getKey(1)
0→A
End
If getKey(2)
8→A
End
Pt-On(0,0,Pic1+A
0→A
[0000000000000000→Pic1
[FFFFFFFFFFFFFFFF
Pt-On(0,0,getKey(2)*8→A+Pic1
was it like 2-2.5x faster or even faster?Eh, it seems that Quigibo is unarchiving the AxeData appvar and rearchiving it every time you run the app. Quigibo, does it really need to be archived? It just holds a couple of options...
On my 83+ there are things that won't necessarly go just 2.5x slower. For example, when exiting Axe parser, there is a 2 seconds pause.
woops I didn't see that. X.x. IMHO it might be best if it was left unarchived. I sure don't mind re-enabling lowercase manually and setting up the shell again when going back in the APP next time.was it like 2-2.5x faster or even faster?Eh, it seems that Quigibo is unarchiving the AxeData appvar and rearchiving it every time you run the app. Quigibo, does it really need to be archived? It just holds a couple of options...
On my 83+ there are things that won't necessarly go just 2.5x slower. For example, when exiting Axe parser, there is a 2 seconds pause.
optimized:Code: [Select]0→A
[0000000000000000→Pic1
[FFFFFFFFFFFFFFFF
Pt-On(0,0,getKey(2)*8→A+Pic1
was it like 2-2.5x faster or even faster?Eh, it seems that Quigibo is unarchiving the AxeData appvar and rearchiving it every time you run the app. Quigibo, does it really need to be archived? It just holds a couple of options...
On my 83+ there are things that won't necessarly go just 2.5x slower. For example, when exiting Axe parser, there is a 2 seconds pause.
meishe91: i'm not sure it'll work all the time under every circumstance, but my snippet of code works. (of course if you add in a dispgraph)
mhmm that would mean Pause 1000 is approximately 3350000 clock cycles?was it like 2-2.5x faster or even faster?Eh, it seems that Quigibo is unarchiving the AxeData appvar and rearchiving it every time you run the app. Quigibo, does it really need to be archived? It just holds a couple of options...
On my 83+ there are things that won't necessarly go just 2.5x slower. For example, when exiting Axe parser, there is a 2 seconds pause.
This is true I forgot about that. I think I will only unarchive/archive at the end from now on if you actually changed any options.
EDIT: And pauses are directly proportional to clock cycles. However each number on the pause is around 3350 clock cycles I believe.
I've noticed that there are problems with Pause on Full, did you factor that into the Pause command?Perhaps that should be left to the user. getKey won't detect keys pressed during a Pause if interrupts are disabled.
Maybe it would be more accurate to DI beforehand.
I've noticed that there are problems with Pause on Full, did you factor that into the Pause command?
Maybe it would be more accurate to DI beforehand.
Well, think about it this way: What does 6MHz stand for? That's 6,000,000 cycles per second so 3,350,000 clock cycles in a command that should take around a second seems very reasonable.So Pause 6000 would take a second on 83+ and 0.4 on SE?
X/2+2X is pretty close.:)X*25/10 is exact :)
X/2+2X is pretty close.:)X*25/10 is exact :)
SetupEditor is no longer needed or supported.
Well, I'm assuming that the interrupts are taking up the extra time then.
EDIT: actually, I just used a stopwatch, half a second per 1000 on the pause seems a lot closer.
We could probably do that once he adds support for custom interrupt routines. Until then, we can use the Stop command to do an interrupt-based delay and save power, too :DWell, I'm assuming that the interrupts are taking up the extra time then.
EDIT: actually, I just used a stopwatch, half a second per 1000 on the pause seems a lot closer.
What would happen if you used interrupts themselves for timing? For instances, have a little counter in the interrupt section, and everytime you have an interrupt, increase the counter, and then when the counter reaches a certain number, that's a second?
Before using for data storage, ensure that the calculator will not APD™ by disabling it with B_CALL DisableApd.
Question about L1/SaveSScreen:Nope. What happens is that when it APDs, the current data on the LCD is put into savesscreen, and then when it powers up, savesscreen is copied back into the LCD. A side effect of this is that any of your own data that was in savesscreen will be overwritten.
If the data in this is modified, will the calc mess up on the next Auto Power Down/APD?
I am wondering because I just saw this: http://wikiti.brandonw.net/index.php?title=83Plus:RAM:86ECQuoteBefore using for data storage, ensure that the calculator will not APD™ by disabling it with B_CALL DisableApd.
I think you mean the latter is 16 bit and the former is 8.oh right yeah, my mistake x.x. As for the double-post, there were 6 hours between both posts, so I am within the rules :P
And do I see a double-post by DJ :) Or did someone delete a post?
I can't answer that question (sorry), but I have a related question that someone could answer along with his: Is there any way to get 16-bit signed numbers, like int(L1)r (which doesn't work, by the way)?
No, its ever so slightly slower since it has to convert the 8 bit number into a 16 bit number (since C is a 16 bit number) in order to do the addition and then convert it back again to an 8 bit number. The fact that its 3 bytes larger I think? is the greater concern than the speed though. Its actually an optimization if you can store all your variables with constant addresses as 16-bit variables if you have enough ram. Variable addresses however ARE more optimized as 8 bit than as 16 bit.Oh right I forgot about the fact variables remain 2 bytes and have to be converted when using inside addresses x.x. MY bad. I guess I'll need to be careful to what I choose depending of if speed is really a huge concern or not.
There is a size optimization I can do when I get to doing byte mode which allows me to reference the variables from a relative location using the IY register instead of an absolute location. This is becasue IY is located slightly after the free ram area in L1 for normal OS uses. I'm still not 100% sure I will have time for that in Axe 1.0.0 because it might end up being a 2.0.0 thing if I don't have time to finish it. Its an ambitious feature requiring the addition of many new routines.Actually, maybe you could make a way in the parser to reference variable locations so it will never break things. Perhaps the lowercase versions?
EDIT: Ninja'd Maybe I'll move them now as a precaution so that people can use the L1 hack to reference them more reliably.
No, I mean that 40h and forward are lowercase characters outside of TI Basic, in the normal ASCII set. The TIOS TI Basic editor is not regular ASCII, but tokenized. The equivalent of 40h in ASCII is "a", but gibberish in TI Basic. TI Basic lowercase tokens take up two bytes. 60h and forward are uppercase characters, so one byte lowercase characters are possible, assuming Axe makes up for it.I don't really see much point in this. First of all, they won't be used very much in the source and secondly, there won't be any size change in the executable. Also, "A" is 41h in ASCII and so is the TI-Basic token. "a" is 61h in ASCII.
This will, however, make it near impossible to modify Axe Basic code that uses lowercase letters without the token hook installed.
No, I mean that 40h and forward are lowercase characters outside of TI Basic, in the normal ASCII set. The TIOS TI Basic editor is not regular ASCII, but tokenized. The equivalent of 40h in ASCII is "a", but gibberish in TI Basic. TI Basic lowercase tokens take up two bytes. 60h and forward are uppercase characters, so one byte lowercase characters are possible, assuming Axe makes up for it.
This will, however, make it near impossible to modify Axe Basic code that uses lowercase letters without the token hook installed.
I'm pretty sure the OS is in some of the hidden portion of the 32KB (I think) of RAM that all 83s and 84s should have. 24KB of this is User RAM, but the rest of it isn't normally accessible by the user. ASM programs can access it though. The 32KB isn't part of the 48-128KB extra RAM(I know 84s have this much, but I'm positive the 83s have less).That part of the RAM is used by the OS, but it is not the OS itself (which is in Archive/FlashROM)
Could an assembly programmer possibly clarify this?
For(A,1,8
0→{L3-A}
End
will bad things happen if i do the following code:Code: [Select]For(A,1,8
0→{L3-A}
End
27 bytes of empty space
9866: 00 FF 3E 8D
986A: 03 13 22 70
986E: 00 00 00 00
9872: 6A 98 00 00
all the rest of L3
appErr1 equ 984Dh
appErr2 equ 985Ah
flashByte1 equ 9867h
flashByte2 equ 9868h
freeArcBlock equ 9869h
arcPage equ 986Bh
arcPtr equ 986Ch
appRawKeyHandle equ 9870h
appBackUpScreen equ 9872h
If {Q}sub(2T)
Disp {Q}*256+{Q+1}▸DMS
Q+2→Q
Else
Disp {Q}▸DMS
Q+1→Q
End
And to read programs, you first read the size field of the program and then you'll know when you've reached the end.
"prgmUNWISE"→Str1
GetCalc(Str1,8)
→Ans
This is a bit off topic, but:
Program editor? Did you make an on-calc IDE? Can I have a link? :D
The signed multiplication is performed using the high byte as the integer part and the low byte as the decimal part returning a number in the same format.
You can't really think of it as "first" and "second" because they're stored in registers one way and in memory the opposite way. I don't know a better way of describing it, but the high byte is 2329 and the low byte is 2329 where this is a hexadecimal representation of your favorite number.QuoteThe signed multiplication is performed using the high byte as the integer part and the low byte as the decimal part returning a number in the same format.
I don't do too much lower level programming, so from what I know this sounds like decimal-multiplication. Which would be extremely useful. My question is, which byte is the high byte? The first one?
Loading pics...
How do you do that?
I know you do [Pic1] or whatever pic it is but then what?
[Pic1]→Pic1
[ ... ]→Pic1
"HELLOL"->Str1
ClrHome
Disp Str1+3
pause 5000
That routine displays LOL, and then pauses for about 5 seconds.From now on, I'm going to greet people with "Hellol" :PI think that's a good idea. Maybe "appv" would work, too. I get confused a lot too and always end up almost hitting 2nd+ALPHA+ALPHA+6 by mistake x.x
I'm changing a token name. You know how programs have the "prgm" token in front of them? Well, I'm doing the same thing with appvars. The problem is that its impossible to distinguish between the lowercase "v" and the recursive "v" because they share an identical ascii character. It has led to confusion in the past, and I think it will do so in the future so I've decided to change it to "apvr" to mimic the way "prgm" is formatted so that it is both distinguishable and recognizable as to how to use it since its interchangeable with prgm. Thoughts?
Update:Nice features!
I have reading and writing to ALL external variables working right now, I just need to find a clever way to create and delete them. I might be getting rid of the delvar command used in labels and make that the delete os var useage like how it works in BASIC.
Also I got direct link port I/O working and I was experimenting with the possibility of a "WaveToAxe" converter. Right now, at 6MHz, I can just barely make out the "It's a-me Maaario!" clip that came with realsound which is what I'm using as a reference goal. I will update on my progress later and possibly release it if I can get some decent quality, and it seems very possible. This is NOT an assembly routine, this is in pure Axe code with the direct port commands in 0.4.0. Unlike realsound however, the clip is much more compressed. The realsound clip generates a 2 page app whereas the appvar created with my converter is less than 2KB. Hopefully I can keep it that low as I start finding ways to increase the quality.
Hopefully I will get one more major optimization before the next release because I had a revelation yesterday. I got to thinking, what's the difference between data and subroutines? There isn't any! So I can mix in all the subroutines with the data as if it was data without having to make a 3rd pass which can save a lot of bytes in the executable. The only side effect to this is that if you are defining 2 blocks of data that are split by a command that uses a subroutine, then the 2 pieces of data are no longer consecutive in memory. I doubt anyone will have a problem with this though because its always good practice to define consecutive data together without interruptions and I've never seen anyone do it wrong in their code.Great work Quigibo.
Features major optimizations that will reduce the size of just about ALL programs.
Sorry, I didn't have time for the update today. I left in the afternoon for something I thought would take a couple hours, but I didn't get back until almost midnight. But I should have it tomorrow for sure.
.A
"prgmZIMG"→Str1
Disp GetCalc(Str1)→θ▸Dec
Pause 2500
For(A,0,63)
Disp i
Disp A▸Dec
Disp {A+θ}▸Dec
Pause 500
End
.A
"prgmZIMG"→Str1
Disp GetCalc(Str1,Y₁)▸Dec
Pause 2500
For(A,0,63)
Disp i
Disp A▸Dec
Disp {A+Y₁}▸Dec
Pause 500
End
"Str1"->Str1
"0123456789ABCDEF"->Str2
GetCalc(Str1,16)->A .the OS var Str1 is created and A is now a pointer to the beginning of the data
Copy(Str2,A,16)
Value→{Pointer}
Fill(Pointer,X-1)
How exactly do you use the new PORT commands to send data?
There isn't automatic linking yet, so no multilayer games until next version, but you can manipulate the link port directly for applications like sound, interaction with micro controllers, shake detectors, etc. The codes are as follows: 0-both tip,ring high, 1-tip low, ring high, 2-tip high, ring low, 3-both tip,ring low. I might have ring and tip mixed up.
EDIT: Oh yeah, the main purpose for the big-endian was for reading 2 byte tokens from programs since they're stored in reverse order.
Let me explain the new masked sprite routine because its really cool. The first layer is the sprite and the second layer is the mask. The way it works is that anything drawn on the first layer is going to be black or gray and any bit that is neither in the sprite layer nor the mask layer becomes transparent. So the codes are 11 for black, 10 for gray, 01 for white, and 00 for transparent. Think of it like a controlled Pt-Off() that also draws gray since you can control which pixels to see through when drawing. The routine is slower than the normal sprite drawing but much faster than trying to draw to both layers individually. Also, due to the choice of color codes, you can use this for monochrome masking as well with the first layer being the sprite you want to draw and the second layer is black in the areas you want to draw over. However keep in mind that the routine still draws to both buffers so make sure you aren't storing anything there first. Here is an exampleWow nice, that will come handy for sure for grayscale games. Nice update. I will try to test app compiling when the app exist at one point, although I cannot promise yet.
Layer1:
████████
██ ██
██ ██
██ ████ ██
██ ████ ██
██ ██
██ ██
████████
Layer2:
████████
████████████
████████████████
██████ ██████
██████ ██████
████████████████
████████████
████████
Result:
░░░░████████░░░░
░░██ ██░░
██ ██
██ ████ ██
██ ████ ██
██ ██
░░██ ██░░
░░░░████████░░░░
The crosshatched color means those pixels don't change when drawing the sprite (transparent).
Also, please let me know if you are still getting errors that you were getting before. I tried to fix as much as I could but since I still can't figure out the problem, that means I'm just guessing so I need your help to see if anything actually got fixed.
"0123456789ABCDEFG"->Str1
[00000000000000000]->Pic1
For(A,0,7
A*2+Str1->E
{E}-48->C
A*2+Pic1->G
C-((C>9)*7)->H
{E+1}-48->C
C-((C>9)*7)->M
H*16+M->{G}
I'm trying to convert the character values of the letters in Str1 into the numbers they represent.
That many? Is that just the nature of BCalls or just TI stupidness?
Nice!He said that they don't have to be automatic, so I'm guessing there is an option for it.
Can you disable this feature, though?
In case anyone is wondering what's been going on recently with the lack of the promised Axe update last week, the main reason is the time I've been spending to get the automatic backups working. I spent about 5 days writing a ton of extra code since the OS did not support the archiving of invisible programs. After all that testing I finally had it all ready to be uploaded and I sent it to my calculator to do some last minute testing. That's when it gave me an ERR: Undefined when trying to create a backup. It turns out the trick I was using was no longer possible on OS 2.4x and so that really set me back. The only way I saw I could get it done now was writing directly to the flash. So I wrote routines for that. Then I realized that not only do I have to write my own routine for that, I have to write my own symbol table searching, vat entry updater, and program creator routines since I can't use the OS's routines given that they no longer support the format. It just got too crazy and I finally gave up. So I now have to throw away about a weeks worth of code and start fresh.I'm gonna love this backup feature. Glad you figured out the problem. Sometimes those TI changes are annoying x.x. I still remember the whole TI-Boy SE saga. I can't wait for the update ^^
The main reason I had to make the files invisible was to be 100% sure that important appvars do not get overwritten accidentally. But I've though of a simpler way to do that now by checking if a non-backup file of the same name exists first and then refuse to backup the file until you manually delete it, that way you won't accidentally erase it. But unfortunately, now backups will crowd the memory management list which I really didn't want, but I guess on the plus side you can erase the backups without having to go into the Axe app.
Anyway, the update should be ready now in less than 24 hours I hope. The backup feature, when it was working on the older OS, is like a night-and-day difference in how you program. I feel like I would never program without it now because its such a huge convenience. Its definitely a reason to upgrade if you have an older version. I fixed a lot of other little bugs too to make it more stable.
bit bit#,A
:.<name of program here>
Disp {P}/16->T>=10*7+T+48>Char,{P}^16->T>=10*7+T+48>Char
The condition is to add the right amount to make $30+$10 $41 (which is A)
.eulers 'e'
{Y*12+(X/8)+L6} e X^8
minor question.
which is faster, pxl-Test(X,Y) or this:Code: [Select].eulers 'e'
{Y*12+(X/8)+L6} e X^8
If you already had the location of the buffer's byte, I would say yes (like from scanning a horizontal line of the screen). But if you have to find it given just an X and a Y, the extra math to find the particular byte and bit from the buffer is going be less optimized than if you just used the pxl-test command since it does all that math for you but in optimized assembly.
Nice to see ElseIf and Else!If; that should help reduce some excess End's in programs.
Keep up the good work! :D
Wow...75 pages.
I was wondering: is there a good way to easily get less flickery gray? it bugs me that I can't just type in Pt-On( and Pt-On()r and see some smooth gray! I wouldn't mind typing more, but I don't know what to type :P
The only way to get less flickery gray is to update the screen more often. If you're doing things like drawing sprites, a good way to help maximize the update frequency is to make sure you're only drawing things on the screen that moved or weren't there before and actually need to be redrawn. Also, optimize your program for speed as much as you can. Use as little processing power as you can between screen updates, and try to make sure the time between updates is somewhat constant and doesn't have large spikes of processing time used up between two screen updates.
If you wondering why there's no automated process to display grayscale without having to call DispGraphr/DispGraphrr, it's because that would require interrupts to update the screen automatically, but the display routines don't work with interrupts. You wouldn't want that anyways, because it would display the buffer contents a potentially inopportune moments, which could cause tearing (the screen updating while the buffers are being updated, resulting in displaying part of the new image and part of the old).
I cant seem to find the elseif token x.xYou just type the Else and If tokens together.
the more dispgraphs the faster it goes.If you mean the grayscale refresh, yes. If you mean the program execution, no. In Super Sonic Ball, if I add grayscale then run a for loop executing dispgraphr 100 times, there will be a considerable drop in speed
the more dispgraphs the faster it goes.If you mean the grayscale refresh, yes. If you mean the program execution, no. In Super Sonic Ball, if I add grayscale then run a for loop executing dispgraphr 100 times, there will be a considerable drop in speed
^
||
I thought custom interrupts didn't work with 4lvl grayscale
"[A]->GDB1
getcalc(GDB1)->A
Disp A(1,1)
"[A]"→GDB1
GetCalc(GDB1)→P
.Number of columns
{P-2}→C
Disp float{A-1*C+(B-1)*9+P}▸Dec
There is no built-in support for reading specific entries from OS matrices or lists. However, the most recent version of Axe (0.4.4) includes the new float{PTR} function, which is the fPart() function. This converts a 9-byte real number from the OS to a 2-byte integer Axe can understand. This would not accurately convert decimal data or numbers that exceed the 2-byte integer limitation (0-65,535), but it should work otherwise.
Anyways, how to apply this to a matrix. The first two bytes of an OS matrix (the 2 bytes before the pointer a GetCalc() would return) are the number of columns and rows. To access the entry in row A and column B, for example, you'd have to do something like the following:Code: [Select]"[A]"→GDB1
GetCalc(GDB1)→P
.Number of columns
{P-2}→C
Disp float{A-1*C+(B-1)*9+P}▸DecI haven't tried this code myself, so I can't guarantee it will work. But it should (unless I have where the OS stores the rows and columns reversed).
EDIT: I have tried this code, and it works.
Yes, that's easy. Put a Fix 7 towards the beginning of your program. Remember to put a Fix 6 towards the end! :)
(Fix 0 - 9 are found next to Float in the Mode menu.) ;D
the axe "variables" are stored in the allocated portion just before L1, are they not quigibo(im just guessing here). if i wanted to set them all to the same value with one command instead of [num]->A->B etc could i just use for(A,0,number of vars:0->{L1-[whatever the offset is]+L:end? also, i too am unsure as to how reading from the arch works(probably because i havent read the command lists in a while, but because someone else already brought it up i dont feel guilty about asking XD)the easiest way is (imo):
5->A
Fill(L1-56,56
o no! please don't! I'm using this pretty much u know!
{GDB1+B}^r->A
A/256->C
A^256->D
.optimizes into..
{GDB1+B}^r->A
{L1-55}->C
{L1-54}->D
{GDB1+X}->A
A/16->B
A^16->C
.or
{GDB1+X}->A
{L1-54}/16->B
{L1-54}^16->B
I was just asking Iambian how he gets grayscale to work in his project Escheron: Shadow over Ragnoth because I was wondering why it seems that every ASM game does grayscale in interrupts. Why exactly do the grayscale routines for Axe have problems with interrupts?
While 1
If A
blah
end
end
quick question: do conditionals speed up executionThis is true.
exampleCode: [Select]While 1
If A
blah
end
end
!if A, then will the code run almost at the same speed as if the 'blah' wasn't there? in other words, does the program 'skip' the code if the conditional is false, and is that significantly faster than actually executing it?
Nested blocks hmmm? Oh well, i can program it in when i need it ^^ I just thought that assembly naturally did things lice short circuit because it used label jumps to do logic. So i guess you do logic in a different way?The logic is actually 8-bit bitwise logic. (This is why things like If A and B might not work as expected and you would need to use If A!=0 and (B!=0) instead)
If you are using this area for data storage, avoid archiving any variables or using routines such as Regraph.
[Pic1]->Pic1->DispGraph if I'm not mistaken.
if the batteries are low, will that effect the speed of the calculator? i know this isn't completely axe-related, but it's because i have this grayscale screen with some animated objects, and it's flickering quite a bit. my batteries are low though, and i was still planning on adding more objects on the screen. so if i put in new batteries, should the grayscale get less flickery? or would it not even be noticeable?I think that only happens on very very old calcs or certain newer ones (83+). I never had that issue on mine, but tr1p1ea reported it I think. I think it was because he was using interrupt-based grayscale, though, and interrupts are slightly slower with low batteries.
"varA"->Str1
GetCalc(Str1)->A
Output(0,0,float{A}>Dec
Wow. I wonder if there's going to be some F-Zero clone in the next few years or something.I sure hope there will be. :P
Oh, I finally found it! It uses what's on the screen before you run it as the background. Arrows move, + and - change incline, no rotation. Best wabbit setting for grayscale is 6.Thanks!
FinaleTI, try float{A-2}. The getcalc() function automatically skips the "size" bytes of a variable, but floats don't have them since they're always the same size (9 bytes) so you need to compensate for that.
MatrixI hope that helped! :)
One byte with the number of columns, one byte with the number of rows. Followed by r × c × 9 bytes, each of which is a real FP-number. Matrices are organized in row-major order.
$03 $02
$00 $81 $14 $95 $72 $75 $75 $00 $00
$80 $82 $83 $67 $57 $54 $74 $00 $00
$80 $81 $33 $57 $61 $43 $96 $00 $00
$00 $80 $48 $48 $78 $16 $76 $24 $00
$80 $81 $85 $56 $56 $72 $78 $00 $00
$00 $80 $86 $56 $01 $97 $47 $00 $00
[ [14.95727575, -836.7575474, -33.57614396]
[4.878167624, -85.56567278, 8.656019747 ] ]
GetCalc("[A]",81)→A
3→{A-2}
3→{A-1}
That causes the 3x3 matrix and fills it with zeros. It doesn't screw up if the matrix previously existed, either.
That would be {L1+3}/16. Note that there will be built in nibble support in later version so this wont be needed.
Oh dear, recursive subroutines is going to destroy Portal D: I use r1-r6 as temp variables inside of my object code, so im going to have to make sure that i don't use those across subroutinesWell, my idea was to use sub()r for that. I'm not sure exactly how it's really going to work though.
As for all of the other features though, that sounds awesome :D
EDIT: Another question, where are R1-R6 stored anyway? And how much can you recurse before bad things happen?
Builderboy, no need to panic, nothing is changing with the existing sub() command I am only adding a new command sub()r :)
It only backs up the variables its using so if you call sub(SUB,A,B)r it will only save r1 and r2. In recursive subroutines, they are saved to the stack. The actual addresses of r1-r6 are in a really small free-ram area not part of L1-L6. You can get the actual location now with or1 if you want to pass them by reference or something.
I think I will give a warning message from now on when the size passes 8812 bytes.Could you simply display the code size after compiling even when it is under 8812? It might act as a guide for people who are trying to stay under the limit.
PRAISE THE ALL-MIGHTY LORD OF CALCULATORS, AXE 0.4.5!
Yea!PRAISE THE ALL-MIGHTY LORD OF CALCULATORS, AXE 0.4.5!
:)
Recursive subprograms!
Recursive subroutines FTWAgreed. This will help Blox like nothing else. ;D
I am still unsure what are recursive sub-routines for, but I would need someone who is more visual to explain it to me, otherwise it won't work just with code x.x. I will probably stay away from those personally.
:Lbl FCT
:!If r1
:1
:Return
:End
:sub(FCTr,r1-1)*r1
:Return
:.Add 2 vectors
:.Vector 1 pointer in r1
:.Vector 2 pointer in r2
:.Resultant vector pointer in r3
:Lbl ADD
:{r1}r+{r2}r->{r3}r
:{r1+2}r+{r2+2}r->{r3+2}r
:Return
:.Initialize vector A with (10,20)
:10->A
:20->B
:
:.Initialize vector C with (5,-10)
:5->C
:-10->D
:
:.Add the vectors and store the result into vector E
:sub(ADD,°A,°C,°E)
I think I will give a warning message from now on when the size passes 8812 bytes.
I would suggest you only say that when code passes that mark, but then I remembered that you decided to mix subroutines and code ;D
I think he meant mixing subroutines and data.
Question: Axe can copy data from archived appvars?
If GetCalc("appvDATA",Y₁)
Copy(Y₁,L₁,256)
Else
.Appvar not found in archive
End
Repeat getKey(15)
For(A,0,383)
.That ﹢ symbol is the 16-bit OR operator
{A*2+L₆}ʳ﹢{A*2+L₃}ʳ→{A*2+L₆}ʳ
End
C+1→C
End
.# represents the 16-bit or operation
L₆→A
While -768-L₆
{A}ʳ#{A+L₃-L₆}ʳ→{A}ʳ+1→A
End
That's pretty much the way to do it. You'd be surprised just how fast one massive For() loop that OR's the contents of both buffers is, though. I calculated that the following loop runs about 40 times per second at 6MHz:Code: [Select]Repeat getKey(15)
For(A,0,383)
.That ﹢ symbol is the 16-bit OR operator
{A*2+L₆}ʳ﹢{A*2+L₃}ʳ→{A*2+L₆}ʳ
End
C+1→C
End
"ʳ" There is a symbol for it. Just copy/paste.That's pretty much the way to do it. You'd be surprised just how fast one massive For() loop that OR's the contents of both buffers is, though. I calculated that the following loop runs about 40 times per second at 6MHz:Code: [Select]Repeat getKey(15)
For(A,0,383)
.That ﹢ symbol is the 16-bit OR operator
{A*2+L₆}ʳ﹢{A*2+L₃}ʳ→{A*2+L₆}ʳ
End
C+1→C
End
Whoa, how'd you get the small r to work in a code tag?
min→{L1+A}
While {L1+A}<max
{L1+A}+1→{L1+A}
<code>
End
For(Var, min, max)
<code>
End
Quick question: Is this:Code: (1 byte variable For() loop) [Select]min→{L1+A}
While {L1+A}<max
{L1+A}+1→{L1+A}
<code>
End
faster than:Code: (Standard For() loop) [Select]For(Var, min, max)
<code>
End
?
For(A,0,5)
<code>
End
0->A
While -5
<Code>
A+1->A
End
:Lbl LP
//code
:Goto LP
would be more efficient than:While 1
//code
:End
right? If so, a quick feature request: automatically making While 1 and Repeat 0 infinite loops.
True. And just wondering: Does anyone have an example of where DS<( would be useful?
While we're on the topic of optimizations... Would something like A-128≥≥0 be more optimized than A≥≥128? And if so, why is the ≥≥CONST entry in Auto Opts.txt listed as taking a whole 11 bytes more than ≥≥0?A-128≥≥0 will fail for 128 values close to -32768. That's because after you subtract 128, they become positive and then the comparison will think it is greater. The ≥≥CONST routine takes this into account.
"appvWHGLVL1"→Str01
"appvWHGLVL2"→Str02
"appvWHGLVL3"→Str03
...And so on
"appvWHGLVL9"→Str09
.A is the level number
.↓Reference like this
Str01+(A*9)
"appvWHGLVL0"→Str0V
.A is the level number
A→{Str0V+7}
Ideally, this would change the number in the Str0V and so reference a different appvar.A+30→{Str0V+8}
instead ofA→{Str0V+7}
.It's because "0" and 0 are different. The character "0" actually has value E30. Plus, appv is really two bytes, so what you'd need to do isCode: (Axe) [Select]A+30→{Str0V+8}
instead ofCode: (Axe) [Select]A→{Str0V+7}
.
EDIT: Haven't tested it myself; can you tell me if it works?
So I have to do the little F or something?Use the little E. Press [2nd] then [,] to get it. :)
Got it.So I have to do the little F or something?Use the little E. Press [2nd] then [,] to get it. :)
.TEST
30->A
55->B
ClrHome
Disp A->DEC,B->DEC,i
Exch(A,B,2)
Disp A->DEC,B->DEC,i
Pause 5000
:Exch(°A,°B,2)
instead.the 30 should either be replaced with E30 or 48.
I assume this variable would be a bit like Ans, right?
:A->pi->B
?
:A->B->pi
The ex command is only 1 byte whereas loading a 16 bit register is 2 bytes. And that statement could still be done like this:Code: [Select]:A->B->pi
Aha, I've been wanting this feature for a while, but I thought it might be too much trouble. It would help for interfacing with Asm(), I'm sure :)Agreed. Perhaps use another token to represent bc, "!" perhaps? It wouldn't be as optimized, because you have to use "ld b,h \ ld c,l" rather than "ex de,hl", but it would definitely help in interfacing with assembly and using bcalls. (Also, any possibility of using a?)
Perhaps. But realize that "!" is only used right before "If ". It could get another use ;)
. "xor" is the 16 bit plotstyle-box xor, not the actual word xor.
A xor B->A
A xor B->B
A xor B->A
just found something cool. if you *really* don't have any temp variables to exchange two values, the following code should do the trick:Code: [Select]. "xor" is the 16 bit plotstyle-box xor, not the actual word xor.
A xor B->A
A xor B->B
A xor B->A
A xor B->A xor B->B xor A->A
What about using 'e' instead of '!'? ('e' is [2nd] [/])Aha, I've been wanting this feature for a while, but I thought it might be too much trouble. It would help for interfacing with Asm(), I'm sure :)Agreed. Perhaps use another token to represent bc, "!" perhaps? It wouldn't be as optimized, because you have to use "ld b,h \ ld c,l" rather than "ex de,hl", but it would definitely help in interfacing with assembly and using bcalls. (Also, any possibility of using a?)
When you make these things official, commands will start having to have a "destroyed" field in the documentation ;D
A xor B->A xor B->B xor A->A
A-B->A+B->B-A->A
"appvblah"->Str1
GetCalc(Str1)->A
{A+100}
the same as"appvblah"->Str1
GetCalc(Str1,Y1)
{Y1+100}
besides the different locations of appvar blah?
3->{L1}
->{L1+1}
->{L1+2}
is more optimized than3->{L1}
Fill(L1,3)
Oh, and a feature request: automatically making things like Output(0,0) be equivalent to Output(0) (and Output(0,0,"ERKH") be equivalent to Output(0):Disp "ERKH"). In other words, making it automatically calculate the full two bytes as it compiles.I'm pretty sure Axe does this already. ;)
it's never really "easy" to make an RPG. no matter the language, it's a lot of work. granted, i'd think it's safe to say it's easier to make a better (in terms of speed and graphics, not gameplay) RPG in axe than basic. of course it takes awhile to get used to Axe, thoughIt depends, in BASIC, if the RPG is not super large (like 4 dungeons and one or two towns max) it can be much eaiser in BASIC, because you do not have to spend weeks trying to figure out how you will get something higher than 1 frames per second on a regular 83+ due to all enemies and ships moving around. In a RPG, almost everything is turn-based so you worry so much less about optimizing speed that it makes some RPGs easier to code than any other game in BASIC. However large RPGs are ridiculously long to create.
It *was* my contest entry, and I've never mentioned it on the forums, save a few references and my sig. It's physics driven and centers on moving around blocks. :) Once I work on it again, I'll post info on it. ;DQuite ironically, both Omni contests (2009 and 2010) had an entry called Blox in the works but none were finished for the contest. :P Is there a curse on the name or something? D: ({AP} was the one working on the 2009 one)
sub(L,1,2,3)
...
Text(0,0,r1>Dec
Text(0,10,r2>Dec
Text(0,20,r3>Dec
...
Lbl L
...
Return
sub(L,1,2,3)
sub(A)
Lbl A
Text(0,0,r1>Dec
Text(0,10,r2>Dec
Text(0,20,r3>Dec
Return
Lbl L
...
Return
also writes 1, 2 and 3 on the screen?
DJ Omnimaga is correct. one minor thing though is you would do Copy(GDB0,L6,768) instead of Copy(GDB0,L6,756). if you merely want to display the picture, you can also do Pic#->DispGraph.Well, that depends. If you stored the picture on calc, it'll only be 767 bytes in the memory menu, and you'll want to use Copy(GDB0,L6,756) because the 64th row is undefined. If you sent it from the computer, it might be 779 bytes in the memory menu, then you can use Copy(GBD0,L6,768) because the pic will contain the 64th row.
I'm pretty sure you can make it bigger, but I doubt all pictures sent from a comp are automatically changed to 779...Years ago I remember something about xLIB being able to create pictures as large as 2048 bytes, but then tr1p1ea changed it so sprite 96-192 is feteched from the next pic and 193 to 255 from the other one after. He thought about allowing using sprite/tile IDs up to 65536 but I forgot if he finally did. It has been so long since I last used xLIB.
I'm not sure if this is a bug, intentional, or what, but something interesting I just discovered: lowercase letters not in a string act like a period and turn the rest of the line into a comment. I don't see much of a use to this, but I found out when I was trying to optimize a program by changing a Fill() command to Copy(). The size savings when I did were much larger than I expected, so I was questioning how that was possible with the change I just made. I was using the TI Program Editor bundled with older versions of TI Connect to write the program, and I realized that I had literally written "Copy(" when the actual command was "conj(" which would explain some things. But I found it odd that it actually parsed successfully, treating the first "C" as the variable C and ignoring the rest of the line.
I'm not sure if this is a bug, intentional, or what, but something interesting I just discovered: lowercase letters not in a string act like a period and turn the rest of the line into a comment. I don't see much of a use to this, but I found out when I was trying to optimize a program by changing a Fill() command to Copy(). The size savings when I did were much larger than I expected, so I was questioning how that was possible with the change I just made. I was using the TI Program Editor bundled with older versions of TI Connect to write the program, and I realized that I had literally written "Copy(" when the actual command was "conj(" which would explain some things. But I found it odd that it actually parsed successfully, treating the first "C" as the variable C and ignoring the rest of the line.
That's TI-Connect-side, right?
In SourceCoder, I believe that if you type Copy, it recognize it as conj, so such thing may not happen in SourceCoder.
Runer, I can't replicate that effect, it just throws a BAD SYMBOL at the 'o' for me as I would expect. What version are you using?
Strange I thought Kerm implemented the new tokens already X.x. He said he might since he planned to make it for both Axe and BASIC.In SourceCoder, I believe that if you type Copy, it recognize it as conj, so such thing may not happen in SourceCoder.
The test I just did with SourceCoder disagrees with this. That would prevent you from typing the literal string "Copy" and SourceCoder isn't designed to be an Axe source editor anyways.
What is the max number of labels you can have in a program? Because Runer112 was trying to help me optimize Nostalgia's menu routine and he said he got a ERR:MAX SYMBOLS. Is there anyway around this?
[HEX]->Pic1 .player1
[HEX]->Pic2 .player2
[HEX]->Pic3 .player3
you can do[HEX]->Pic1 .player1
[HEX] .Pic1+8 refers to player2
[HEX] .Pic1+16 refers to player3
etc.
What is the max number of labels you can have in a program? Because Runer112 was trying to help me optimize Nostalgia's menu routine and he said he got a ERR:MAX SYMBOLS. Is there anyway around this?
[hex]→Pic1
[hex]→Pic2
Pt-On(X,Y, Pic1)
Pt-On(X,Y, Pic2)
to[hex]→Pic1
[hex]
Pt-On(X,Y, Pic1)
Pt-On(X,Y, Pic1+8)
I wonder if you can use a label as a pointer, like by doing lbl123+64You would never reliably be able to do this because future optimizations would mean that the spacing between some labels would change between every version of the parser. This would only work if the entire routine were written with an Asm() command so you would know the length of the subroutine ahead of time.
I wonder if you can use a label as a pointer, like by doing lbl123+64You would never reliably be able to do this because future optimizations would mean that the spacing between some labels would change between every version of the parser. This would only work if the entire routine were written with an Asm() command so you would know the length of the subroutine ahead of time.
Unfortunately there is no way around the 150 symbol limit to labels, but there are some things you can do to use less labels in general. First of all, if you aren't calling it as a subroutine, you probably don't need it as a label. You can instead use a combination of if's and while's to handle those situations properly (remember, most modern programming languages don't even have a goto command). Another thing, if you have labels that are never used, comment them out becasue they still take up space on the symbol table even if they are never called.
I've recently completed Warrior 2, another big RPG, in Ti-Basic with xLib. The only problem is that I have an 83+ so I cannot send it to the computer and upload it. I've also done several other projects but not any that I am still prowd of.
I've recently completed Warrior 2, another big RPG, in Ti-Basic with xLib. The only problem is that I have an 83+ so I cannot send it to the computer and upload it. I've also done several other projects but not any that I am still prowd of.
this is a bit off topic to respond and I'm sorry, but you CAN transfer it if you buy a certaqin type of cable, or type it up in source coder.
Alternatively, if someone else owns a TI-84 Plus or a TI-Nspire with 84+ keypad and you got a link cable, and that person lets you borrow his calc, just send your program to his calc, take a mini-USB to USB cable (a camera one will do) then use it to transfer it to the computer from the 84+ calculator. That's what I did with my 83 Plus since I did not have the appropriate cable for a while.I've recently completed Warrior 2, another big RPG, in Ti-Basic with xLib. The only problem is that I have an 83+ so I cannot send it to the computer and upload it. I've also done several other projects but not any that I am still prowd of.
this is a bit off topic to respond and I'm sorry, but you CAN transfer it if you buy a certaqin type of cable, or type it up in source coder.
okay. I'll do that.
Have you made use of the whopping 1094 bytes of effectively safe RAM starting at $8000?"Safe" I'd have to dispute... sure, all of RAM can be considered "safe" if you disable interrupts and never call any system routines. And if you're going as far as keyExtend, you're already trashing the keypad-scanning variables, so why stop there?
Have you made use of the whopping 1094 bytes of effectively safe RAM starting at $8000?"Safe" I'd have to dispute... sure, all of RAM can be considered "safe" if you disable interrupts and never call any system routines. And if you're going as far as keyExtend, you're already trashing the keypad-scanning variables, so why stop there?
[22:19:28] <Runer112> yeah, appdata is 8000h
[22:19:29] <Iambian> You're free to use that area regardless.
[22:19:44] <Runer112> appdata is completely safe for my purposes? whether or not i'm running an app?
[22:19:52] <Iambian> Thought you were talking about something that looks more important, like baseAppBrTab or something.
[22:20:21] <Iambian> Either way, this magic romcall that (I think) BrandonW found recovers most of it before you want to exit. bcall($5011) it is.
[22:20:52] <Iambian> It was noted in my source as "restores first 1087 bytes in RAM"
On an semi-unrelated note, would Axe programs be compilable for CrunchyOS?
For his purpose of parsing, during which key inputs aren't checked, it won't matter if he overwrites that. Although if he didn't want to overwrite it, I'm sure 1,093 bytes would be just as good. I've filled these 1,094 bytes of RAM with random data a few times before to see if it affects anything, and the calulator runs fine. I've actually been using the calculator to do other stuff since then, with this area of RAM having been filled with garbage, and no side affects have cropped up.If you don't have a solid understanding of what a RAM area is used for, when it's used, and what the consequences might be of modifying it, how can you say whether it's "safe" for your application?
EDIT: Or, just to be safe, I remembered that Iambian mentioned something about this on IRC a while ago (here (http://netham45.org/irc/EfNet/view.php?log=omnimaga.20100908)) when I was considering using this area as temporary storage:Quote[22:19:28] <Runer112> yeah, appdata is 8000h
[22:19:29] <Iambian> You're free to use that area regardless.
[22:19:44] <Runer112> appdata is completely safe for my purposes? whether or not i'm running an app?
[22:19:52] <Iambian> Thought you were talking about something that looks more important, like baseAppBrTab or something.
[22:20:21] <Iambian> Either way, this magic romcall that (I think) BrandonW found recovers most of it before you want to exit. bcall($5011) it is.
[22:20:52] <Iambian> It was noted in my source as "restores first 1087 bytes in RAM"
random question: is it worth it to put this code in a subroutine?
<exp>*22+GDB0+<constant>..... so it looks like sub(0r,<exp>,<const>).....lbl 0 : r1*22+GDB0+r2
I would almost always need the r when calling this routine, and I suspect that the size of calling sub(lblr) with two arguments to be loaded might be bigger than just typing it out every time. Can anyone confirm? Also, I will be using this snippet of code only around 15 times throughout
<exp>sub(22)+GDB0+<constant>
Lbl 22
Return *22
For his purpose of parsing, during which key inputs aren't checked, it won't matter if he overwrites that. Although if he didn't want to overwrite it, I'm sure 1,093 bytes would be just as good. I've filled these 1,094 bytes of RAM with random data a few times before to see if it affects anything, and the calulator runs fine. I've actually been using the calculator to do other stuff since then, with this area of RAM having been filled with garbage, and no side affects have cropped up.If you don't have a solid understanding of what a RAM area is used for, when it's used, and what the consequences might be of modifying it, how can you say whether it's "safe" for your application?
EDIT: Or, just to be safe, I remembered that Iambian mentioned something about this on IRC a while ago (here (http://netham45.org/irc/EfNet/view.php?log=omnimaga.20100908)) when I was considering using this area as temporary storage:Quote[22:19:28] <Runer112> yeah, appdata is 8000h
[22:19:29] <Iambian> You're free to use that area regardless.
[22:19:44] <Runer112> appdata is completely safe for my purposes? whether or not i'm running an app?
[22:19:52] <Iambian> Thought you were talking about something that looks more important, like baseAppBrTab or something.
[22:20:21] <Iambian> Either way, this magic romcall that (I think) BrandonW found recovers most of it before you want to exit. bcall($5011) it is.
[22:20:52] <Iambian> It was noted in my source as "restores first 1087 bytes in RAM"
(Experimenting and finding things that seem not to crash is really not a substitute for this level of understanding. To wit: I can infer from your comment above that either you have an 84+, or you never use Flash apps.)
"Restores first 1087 bytes in RAM" is cute, but wrong, and frankly, kind of a dangerous thing to go around telling people.
The term "safe" is meaningless without context: what is safe depends both on what type of program you're writing - i.e., the context in which it will be executed - and on what your program is going to do. By safe, we generally mean that
(1) a RAM area is not going to be modified by any system or library calls we intend to perform, or by the system interrupt routine, and
(2) the RAM are is not already in use at the time our program runs (so altering the data there will not have any effect on the system), or more specifically, it won't be expected to contain valid data at the time our program exits.
In some cases we may also want to consider areas where the RAM is already in use, but
(a) it can be easily reset to its default settings,
(b) we can reliably ensure the reset routine does get called, regardless of when or how our program terminates, and
(c) the user won't mind us trashing his or her data.
In brief: the RAM areas between 8000h and 843Dh (I'm going to go ahead and assume you didn't mean to include kbdScanCode and friends) are used by a lot of different system routines under a lot of different circumstances. As far as I know, all of this memory except for baseAppBrTab is scratch memory (it satisfies condition 2 for most execution environments), but whether it satisfies condition 1 is dependent on what system routines you're using, what hooks those routines might call, whether APD is possible, and whether silent linking is possible.
As for baseAppBrTab, it does not satisfy condition 2 at all, and it is absolutely essential that the table be correctly populated when your program exits. Realize that the primary purpose of the table is for performing application B_CALLs - so really, it ought to be correctly populated at any time when a hook might be called, or in a shell program, at any time when a shell library might be called. In practice, using that area is so dicey that I would not feel comfortable doing so at any time when any code outside my control might be executed.
Code: [Select]Lbl 22
Return *22
Code: [Select]Lbl 22
Return *22
Wow...didn't know you could do that. Thanks!
Code: [Select]Lbl 22
Return *22
Wow...didn't know you could do that. Thanks!
And also; what if I didn't need the r? Would it make a difference?
0→A→B
You're not actually saying 0→B, but because storing variables doesn't overwrite the "Ans of Axe," the value will remain and can be put in B. If you want to see a more advanced use of this, take this code for example, which I'm using in what I'm working on now:Vsub(DM3)
...
Lbl DM3
abs()-{r₁}
Return
The absolute value command doesn't even have an argument! But it doesn't care, it will operate on whatever is in "Ans." Entering an expression or value inside the parentheses would be a more logical way to put a value in "Ans" for the command to operate on, but if you don't enter anything there, "Ans" will simply stay as it was before the command was reached (in this case, with the value of V) and the absolute value of that will be calculated.On a related but not related note, how large are the Rect(), RectI(), Rect()r, and RectI()r routines?
On a related but not related note, how large are the Rect(), RectI(), Rect()r, and RectI()r routines?
...How big are the sprite routines?
On a related but not related note, how large are the Rect(), RectI(), Rect()r, and RectI()r routines?
Rect(): 114 bytes
RectI(): 114 bytes
Rect()r and RectI()r are just modified calls to the Rect() and RectI() routines, respectively....How big are the sprite routines?
Pt-On: 126 bytes
Pt-Off: 134 bytes
Pt-Change: 126 bytes
Like with the rectangle routines, back buffer calls are just modified calls to these routines.
Oh wait do you mean the weird fractal thing that occurs when it is negative? Quigibo posted a screenshot of it somewhere...
EDIT: On an off-topic note, awesome avatar Darl181. :D
that' not ASCII/homescreen based :P
that' not ASCII/homescreen based :P
You're forgetting that the full power of WFRNG was coded using only BASIC and the homescreen. BASIC can do anything, even beat the speed of Assembly!
*cough* sniper 101's super weapon *hack* happybobjr *wheeze*
...what? ;)
*cough* sniper 101's super weapon *hack* happybobjr *wheeze*
...what? ;)
cough cough... really, i am very sick. I bet i can make a missile that will eliminate all pedestrians.
It could cost 500 shop points, and take away 1000-2000 (or maybe 25 per pedestrian) score points. My current problem w/ sniper 101 is the lack of remaining variables. And i hate using L1 because that is where i use my pedestrian info. I suppose i could put it at the end of it though, as no one would go past lvl 200 in ffa mode (example: Phoenix )
this is after i am finished on two player shooter though.
I got my 7 foot cable, but i haven't got a chance to borrow a friends ti-84 because the cable came with a cold. Once again ti-strikes.
Plus the various holes in RAM that the OS has, if you feel like going into Assembly.
I wasn't aware of that area... what is it called in the .inc file?
Plus the various holes in RAM that the OS has, if you feel like going into Assembly.
You don't need to use assembly, as Axe is already capable of accessing any addressable RAM area. A good suggestion would be E8000, which has 256 bytes of space you can uses as temporary RAM.
random question: how many bytes is a name string? is the appv token 1 byte? are lower case letters 2 bytes still?As for your last question, yes, it should work that way. I did that in one of my programs at some point, I just forget which one.
so for example: how large is this name string: "appvAbcDE"
and also: can you open a file 'over' another file
ie if you had appvar 1 open in Y1, can you call GetCalc(Str2,Y1) and have the appvar pointed to in Str2 now open as Y1?
random question: how many bytes is a name string? is the appv token 1 byte? are lower case letters 2 bytes still?
so for example: how large is this name string: "appvAbcDE"
and also: can you open a file 'over' another file
ie if you had appvar 1 open in Y1, can you call GetCalc(Str2,Y1) and have the appvar pointed to in Str2 now open as Y1?
Actually, appvars and programs don't have a token before the name. So appv is actually one byte.random question: how many bytes is a name string? is the appv token 1 byte? are lower case letters 2 bytes still?
Name string is however many bytes you make it, just like any other string. The appv char is two bytes: one for the var type (appvar), one for the actual token. And all lowercase letters are one byte unless you convert them individually with T.
Actually, appvars and programs don't have a token before the name. So appv is actually one byte.random question: how many bytes is a name string? is the appv token 1 byte? are lower case letters 2 bytes still?
Name string is however many bytes you make it, just like any other string. The appv char is two bytes: one for the var type (appvar), one for the actual token. And all lowercase letters are one byte unless you convert them individually with T.
Code: [Select].Inefficient
This is probably unnoticeable slower, but its much smaller and the routine is a subroutine so using it more than once in your program will definitely be a large size optimization.
If (A=3 or (A=5) or (A=20) or (A=28) or (A=61))
.Some code
End
.Efficient
If A
If inData(A,Data(3,5,20,28,61,0))
.Some code
End
End
actually smaller than a single equality check:o
Bottom line:
- 1 equality check: !If VAR-CONST
- 2+ equality checks: If inData(VAR,Data(CONST,CONST,...))
And don't forget that you have to end your list of data with 0 so the routine knows when the end of the list is reached.
Reading that 0 being the end of data thing, I assume if we ever need to use those routines in a game for an item menu, for example, that we must make sure that no item ID are equal to 0, right? For example, for an empty item slot it would be 1, potion 2, elixir 3, etc?
|
|
Double-clicked? ;)
Anyway, that's a pretty clear explanation, thanks!
Either or.So, the whole statement is true only if one (i.e. A) is true and the other (i.e. B) is not? Or am I completely off?
As in, if A and B , then A or B is also true. A xor B is not true
the !If should apply to the whole statement.Either or.So, the whole statement is true only if one (i.e. A) is true and the other (i.e. B) is not? Or am I completely off?
As in, if A and B , then A or B is also true. A xor B is not true
Also, I was wondering about the !
Is
!If X=2 and C=3
the same as
If X=/=2 and C=/=3
or does the ! only apply to the first term?
Okay, I get it now. Thanks!No problem. Tis what we are here for. ;-)
Here's the description from the commands list:Ah ok, I was mostly confused at the InData(A+1,Data(1,2,3,4,0)) part. So we need to manually offset the Data stuff by 1 except the last 0?
inData(BYTE,PTR) Key: inString()
Searches for the byte in the zero-terminated data. If found, it returns the position it was found in (starting at 1). If not found, 0 is returned.
The first argument accepts a byte value. Because Axe variables and math functions return two-byte values, this means that the high byte will be discarded. This argument essentially accepts whatever you enter mod 256.
The second argument accepts a pointer to data. In this data should be a series of byte values which will be stepped through one by one and checked to see if they are equal to the first argument (mod 256). The end of the data is signified by a zero so the search doesn't continue infinitely. For this reason, zero has to be reserved for the terminator and cannot be a value you want to compare.
Breaking down a more specific example, like: If inData(A+1,Data(2,7,17,0))
In the first argument, A represents whatever 0-based number, say an item ID, that you want to check. However, because 0 is reserved for the terminator of the data, we add 1 to it to shift all the item IDs to essentially be 1-based.
The second argument isn't really data itself. The data is defined somewhere in the bottom of the program, and this argument is instead given the value of a pointer to that data. As noted earlier, this data that is pointed to should be a list of nonzero byte values to check if the first argument is equal with, and the data should be terminated with a 0. Because 1 was added to our first argument to account for the fact that 0 is reserved for the terminator, 1 would also be added to the values we want to compare against. In this case, I wanted to compare against the values 1, 6, and 16, which turn into 2, 7, and 17 when 1 is added to them.
Finally, when the routine is run, the data is stepped through byte by byte, checking to see if a byte from the data equals the first argument (mod 256). Let's say we wanted to check if a selected item was a consumable potion, and item IDs 1, 6, and 16 were the potions present in our game. If the selected item ID (A) was 16, this value would be increased by 1, giving 17 for the first argument. This would then be checked to see if it equals 2, 7, or 17, which are the item IDs of the potions all plus 1. It doesn't equal 2 or 7, but it does equal 16. The routine would return the position of the match value, in this case 3, because the third element matched. For our purposes, all we really needed to know is whether or not a match was present, but inData() returning the match position works for this. Any match position returned will be greater than or equal to 1, which will make our IF statement true. If the item ID were 5, it wouldn't match any of the three values in our list. Once the routine hit a zero byte, it would know the searching was done and return a 0 for no match, making our IF statement false.
I hope this helps clarify things a bit :)
I think in Illusiat 13, empty item slot is 20 :P. For some reasons, the engine won't support 0.I believe it was because you did a SortA() on the item list and wanted the blank items to be in the middle. :)
Sweet. I didn't know that. It should work, thanks.
Quick question - do I have to add brackets to anything, or will it work just as written?
If you want a really extreme optimization for or-ing the screen, here it is. It will be noticeably faster and smaller:Code: [Select].# represents the 16-bit or operation
L₆→A
While -768-L₆
{A}ʳ#{A+L₃-L₆}ʳ→{A}ʳ+1→A
End
For(Z,0,15)
Copy({Z*24+L6},{Z*16+L1},16)
End
but if anybody sees a problem (or has a better way of doing this), I'd be grateful.F32CWell that would actually be 2 bytes (so 4 nibbles and 16 bits). 1 bytes would be 8 bits. Otherwise, you were right.
I want to be able to treat it like this:
1111
0011
0010
1010
(Just to make sure I have my terminology down, this would be equal to 2 nibbles or 1 byte or 16 bits, yes?)
For(Z,0,63)
Copy(Z*8+L1,Z*12+L6,8)
End
You have 64 rows, numbered 0-63. 64 bits are 8 bytes, so we multiply Z by 8 then add it to L1. A row on the screen is 96 bits (and therefore 96/8=12 bytes), so we multiply Z by 12 and add L6. The 8 is for the same reason as two sentences ago.11110011
00101100
To manipulate bits, you need to use e (Euler's e) and e^(b00100000e2
which returns 1 because the 2nd bit, from left to right, indexed from 0, is a 1.e^(5)
which returns b00100000 because the 1 is in the 5th position, from right to left, indexed from 0.PRGM:AMENUSRC
.AMENU
Lbl MM
ClrHome
Fix 3
Disp " A GENERIC MENU "
.has to be 16 chars
Fix 2
Disp " Play Game",i," Options",i," Quit"
3→C
Sub(SEL)
If A=1
Disp "GAME"
.Game content here
.End of game, go to main menu
Goto MM
End
.Can nest as so
If A=2
Lbl OPT
Fix 3
Disp "Options "
Fix 2
Disp " Something",i," Something else",i," Get the point"
3→C
Sub(SEL)
.Responses, may contain more sub-menus
Goto MM
End
If A=3
.last option, has to be quit for it to work correctly
Return
End
Lbl SEL
1→A→B
Output(0,A,5►Char
Repeat getKey(54)
ReturnIfgetKey(15)
A+getKey(1)-getKey(4)→B
!If A=B
!IF B:C→B:End
If B=C+1:1→B:End
Output(0,A," "
.that's 1 space
Output(0,B,5►Char
B→A
Pause 475
End
End
ClrHome
.Return
It displays, I just can't get the ► to move up and down.
Code: [Select]If B=C+1:1→B:End
If C+1=B:1→B:End
That might be it...I'll try it.QuoteCode: [Select]If B=C+1:1→B:End
should beCode: [Select]If C+1=B:1→B:End
:P
Don't forget about (the lack of) order of operations :) You're old code added one to whatever the value of B=C was, so that For loop would ALWAYS be true; hence, why you couldn't move the cursor around (because B was getting reset to 1 every iteration)
Yeah, I have no idea of just how many times omnicalc has saved my rear end...about 1 time out of 30 it doesn't work properly though :(
(And yes, I've used it that much)
^nice.
Since my full mem clear two days ago, the only apps I have on my calc are Axe and a bunch of Ash:Phoenix builds :P
Pressing alpha-character jumps to program in compile menuso does that mean that, in order to use the alpha jump feature, one has to hold alpha while pressing a letter key? or do you mean just pressing a letter key on its own...
Manual backup key is now "Alpha"
I think the RAM Restore feature. (He programs in Axe, which can cause RAM clears)DrDnar posted a patch of Omnicalc allowing 2.53 support on UTI a while ago, but I forgot where is it, plus you need to register to download it I think. I wonder if that could solve the issue?
Too bad about 2.53 MP not allowing that. I don't use it because I only have 48KB of RAM. x.x
Axe ParserAWESOME! Glad to see the new version out! :)
Delta 0.4.6
No new commands, but a lot of new features.
New Features:
- Direct key support for the [On] key using getKey(41)
- Added new Axiom Tokens (but they aren't usable yet)
- Static data can be stored to variable pointer
- Pressing alpha-character jumps to program in compile menu
- Selector wraps around in the compile menu
Changed:
- Fixed bug that made some invalid syntax become comments
- Fixed Elseif bug
- Added new auto-optimizations
- Automatic backups only after finishing compile with no errors
- Compiling to apps always attempts a defragmentation
- App signature improved and resignable on-calc with external program
- Fixed program menu bug after manual backups
- Manual backup key is now "Alpha"
- Fixed sector boundary reading bug when reading large source from archive.
[On] key combos!!wut? ???
(http://www.dangerousminds.net/images/uploads/1269385664419_thumb.jpeg)
Z->input
"Static data can be stored to variable pointer."
How exactly does this work?
"0123456789ABCDEF"→A
Instead of having to previously have done something like:"0123456789ABCDEF"→Str1
Str1→A
Is there an Input command, I heard DJ saying it was something likeCode: [Select]Z->input
But maybe I misunderstood :S
You can now do:Code: [Select]"0123456789ABCDEF"->A
Instead of having to previously have done something like:Code: [Select]"0123456789ABCDEF"->Str1
Str1->A
THIS IS AWESOME!
You can now have more than 10 pictures! Also works for strings, right?
But maybe I misunderstood :S
Runer, thank you. IMO it would read better as "Inline strings now work for storing to variables" :D
Edit: On a completely unrelated note, I noticed that the manual still says "Not Reasonably" for editing ASM on-calc. Might want to change that ;D
It's not important; it's just something I noticed ;D
Text(0,,"Hi")
instead of "Hi"->Str1:Text(0,,Str1)
DelVar can be used to help avoid Max Symbol, if I understand right. :)No, that was gotten rid of several versions ago becasue no one used it. Now, its used for its more intuitive purpose which is to delete OS variables.
Hah yeah i remember thinking that i was never ever going to use Delvar to delete labels and symbols ;D I like its new use better ^^
Thanks for bringing this to my attention: this helps a lot for MFQTAxe Parser
Delta 0.4.6
Static data can be stored to variable pointer
just wondering: is it safe to embed random Asm(E5)'s and Asm(E1)'s into an axe program? (I mean other than the obvious problems of the stack not exiting the same as it entered)
btw, E5 and E1 are 'push hl' and 'pop hl', respectively
If not, I'm pulling out Mimas...
ok I can avoid using it in calls (or just use 'pop de/pop hl/push de' etc), and using it to store/recall the Ans is exactly what I'm using it for.
Also, I'll have a counter so that I know how many items are in the stack at a given time. Also gotta avoid using it in the middle of routines. like no Output(0,0,Asm(E1)>Dec), that'll probably cause an error
EDIT: also, while I'm here, "Str1" is sufficient for a GetCalc( filename, right?
If A=T+
Goto PL
End
If A=T-
Goto SB
End
...
ok I can avoid using it in calls (or just use 'pop de/pop hl/push de' etc), and using it to store/recall the Ans is exactly what I'm using it for.
On second thought, I could just check a 1-byte value against all my 1-byte tokens, and then, if i got no hits, load the second byte and check all the two-byte tokens...
But I don't want to have to look all my tokens up in a table... ah well... tibasicdev has a good table.
no no no no no!!!
I thought my hints were clear enough... I meant AFTER you press 2nd/Enter while the cursor is over the 'compile' option.
...and I'm not talking about the transition effect :P (epic fade effect dude, its almost faster than ASM)Spoiler For if my hints are insufficient:
Do you mean how the selection bar moves up and down smoothly? I could maybe dig up my xLIB xLIB Revolution menu code later, although it's in BASIC+xLIB. Maybe someone could convert it to Axe. :P
:For(A,0,9
:RectI(X,Y,width,height
:Y-W->Y
:RectI(X,Y,width,height
:End
Ah I see lookitsan00b, it wasn't too clear to me. I just couldn't find anything special to replicate past the title screen sequence. Also what is the transition effect? I never saw any on my 83+ or Nspire O.O
For(C,0,10)
Code...
If A
If B
Do something...
End
End
End
For(C,0,10)
Code...
If A and B
Do something...
End
End
If A
If B
Do stuff
End
End
still be the fastest way to evaluate it?
If A
If B
Do stuff
End
End
or...
If A!=0 and (B!=0)
Do stuff
End
If A
If B
Do stuff
End
End
If A and B
Do stuff
End
Keeping in mind what calcdude84se pointed out about A and B, if either A or B will sometimes be non-boolean values (anything besides 0 and 1), you want to use the two separate if statements. If they will always be booleans, however, compare the following two blocks of code:Code: [Select]If A
If B
Do stuff
End
End
- A is false: 34 t-states
- A is true: 68 t-states
Code: [Select]If A and B
Do stuff
End
- 66 t-states
The second one is only faster if A will be true at least 16/17 of the time.
Keeping in mind what calcdude84se pointed out about A and B, if either A or B will sometimes be non-boolean values (anything besides 0 and 1), you want to use the two separate if statements. If they will always be booleans, however, compare the following two blocks of code:Code: [Select]If A
If B
Do stuff
End
End
- A is false: 34 t-states
- A is true: 68 t-states
Code: [Select]If A and B
Do stuff
End
- 66 t-states
The second one is only faster if A will be true at least 16/17 of the time.
Thats excellent data! So what that means is that even if A is true 94% of the time, its still worth it to make the change to two if statements :D So as a general rule, the best thing to do is to use two different If statements if you are going for absolute speed. Unless A is only false like once in every 9000th cycle :P
:If B
: If A
: do stuff
: End
:End
If A__op__
If B__op__
Do stuff
End
End
If A__op__ and (B__op__)
Do stuff
End
Awesome, lots of nice commands added too. I hope not too many bugs are encountered so you don't have to release too many fixes. I probably will not help on beta-testing, though, because I haven't programmed Axe for several months.
EDIT: WOAH! Line is definitively faster! O.O
"Hello World Foobar"->Str1
is there a way to display only 6 characters at a time, so I can separately display "Hello "
"World "
"Foobar"
depending on a numerical input I give in?
:0->A->{L1+6}
:length(Str1)->L
:While A<L
:Copy(Str1+A,L1,6)
:Disp L1,i
:A+6->A
:End
*cough*landslide victory*cough*
If Kerm had waited til next year to upload DCS7...
we got 2 POTYs!
Woah, someone voted for cuberunner :o
Anyway, gratz Quigibo! Axe is just....amazing (notice how 4 of the featured programs this year were written in Axe ;) )
...since a stable version still isn't out yet.
Yeah I wish there would have been place for two wins, because DCS7 really deserved one too. I even went close to vote for it (I finally voted for Unity, Axe, Ndless and NewProg) because it's so great too. I thought it would get pretty close to Axe amount of votes. Regardless, congrats QUigibo, but congrats to Kerm as well for having gotten that many votes, still, and more importantly, congrats to EVERYONE who got nominated!*cough*landslide victory*cough*
If Kerm had waited til next year to upload DCS7...
we got 2 POTYs!
It's not so fine and dandy over on Ceme.
I can't tell about token names for now since I'm kinda tired but using the ones in an entire menu would be a good idea if it's all for the same thing, otherwise with all the renamed tokens it will get hard to find them in the CATALOG since they're not sorted alphabetically.Yes, that would be great. Is this possible? ;D
Yes, it is, but I'm not sure whether or how well it's been documented. What you want is the catalog hook(s). One or the other of them - I think it's the second - is the hook that language localization apps use to reorder the catalog. It's been years since I looked at that stuff, though.I can't tell about token names for now since I'm kinda tired but using the ones in an entire menu would be a good idea if it's all for the same thing, otherwise with all the renamed tokens it will get hard to find them in the CATALOG since they're not sorted alphabetically.Yes, that would be great. Is this possible? ;D
So the new Axiom SDK is out. If anyone wants to attempt one, you will definitely get to try it out on 1.0.0 before the official release. The inc file is not totally finished because I haven't added the new token equates yet, but I'll get to that soon. Let me know if you have any questions about the Axiom format, some things about it might be confusing. One thing I'll mention is what the "Stored to" command modifier is. EXP->DispGraph is a one argument version of this and EXP->float{EXP} is a 2 argument version.
Three words:
Best. App. Ever.
now, if I could only transfer the newest version to my calculator... *sigh*
Sweet. Good luck!
finish it all by Axe's 1-year anniversary from the first alpha version (Feb. 1st)How fitting.
This is why Quigibo needs to make InsertMem and DelMem functions. Seriously.^++
Yeah, but isn't that kinda hard, as changing the length of an appvar without going through the system routines would screw with other memory. Right?That's the thing, these are system routines. Axe just doesn't have any way to access them without inline asm.
to insert:
[ADDRESS] .put the address into HL
Asm(EB) . ex de, hl
[SIZE]
Asm(EF42F7)
Maybe what we need is an advanced memory handling Axiom? It could insert and delete memory, and could also handle advanced things like updating the vat, changing the size counters, and maybe even putting the calculator in program edit mode.
{L3+X+((L3+X>L3+767)*(P-L3+767))} -> Y
Disp Y >Dec
Quigibo, can you have the parser check Axioms first and then check the actual Axe code? This would allow redefinition of various Axe functions and allow different behavior. For instance, if you were writing some BrainFck in Axe and had an Axiom for it, you could use + in the way BrainFck requires it to be used in. :)
Would the picvar be required for the executable to run, or just to compile?
Another thing. You know how {E8447}+24 is the contrast level? What points to the Ans variable?
So, that would be like Getcalc(Ans)? The goal is to store a token, either two-byte or one-byte, into ans.
;---------> InsertMem <---------;
;B_CALL(_InsertMem) with checks to make sure there is enough RAM and the insertion address is okay
;
;INPUTS: Arg1: Pointer to start of variable according to GetCalc()
; Arg2: Offset in variable to insert RAM
; Arg3: Number of bytes to attempt to insert
;
;OUTPUTS: 0 if not enough RAM or Arg2 is out of range
; Nonzero if successful
p_InsertMem:
;REGISTERS: hl=Arg3
;STACK: | Ret | Arg2 | Arg1 | ...
B_CALL(_EnoughMem) ;Check if enough RAM
;REGISTERS: de=Arg3
;STACK: | Ret | Arg2 | Arg1 | ...
pop hl ;Rearrange arguments and stack
pop bc
ex (sp),hl
;REGISTERS: bc=Arg2 de=Arg3 hl=Arg1
;STACK: | Ret | ...
jr c,__InsertMemFail0Args ;Return failure if not enough RAM
dec hl ;Get current variable size
ld a,(hl)
dec hl
push hl
ld l,(hl)
ld h,a
;REGISTERS: bc=Arg2 de=Arg3 hl=current variable size
;STACK: | Arg1-2 | Ret | ...
sbc hl,bc ;Check if offset is outside of variable
jr c,__InsertMemFail1Arg ;Return failure if offset is outside of variable
add hl,bc
;REGISTERS: bc=Arg2 de=Arg3 hl=current variable size
;STACK: | Arg1-2 | Ret | ...
add hl,de ;Calculate final variable size
ex de,hl
ex (sp),hl
;REGISTERS: bc=Arg2 de=final variable size hl=Arg1-2
;STACK: | Arg3 | Ret | ...
ld (hl),e ;Store final variable size
inc hl
ld (hl),d
inc hl
;REGISTERS: bc=Arg2 de=final variable size hl=Arg1
;STACK: | Arg3 | Ret | ...
add hl,bc ;Calculate RAM insertion address
ex de,hl ;Prepare arguments for _InsertMem
pop hl
;REGISTERS: bc=Arg2 de=Arg1+Arg2 (RAM insertion address) hl=Arg3 (bytes to insert)
;STACK: | Ret | ...
B_CALL(_InsertMem) ;Insert memory
;REGISTERS: de=RAM insertion address hl=a lot (negative size of a VAT entry?)
;STACK: | Ret | ...
ret ;Result is always nonzero
__InsertMemFail1Arg:
pop hl
__InsertMemFail0Args:
ld hl,0
ret
__InsertMemEnd:
;---------> DelMem <---------;
;B_CALL(_DelMem) with checks to make sure that the deletion address and size are okay
;
;INPUTS: Arg1: Pointer to start of variable according to GetCalc()
; Arg2: Offset in variable to delete RAM
; Arg3: Number of bytes to attempt to delete
;
;OUTPUTS: 0 if Arg2+Arg3 is out of range
; Nonzero if successful
p_DelMem:
;REGISTERS: hl=Arg3
;STACK: | Ret | Arg2 | Arg1 | ...
pop af ;Rearrange arguments and stack
pop bc
pop de
push af
push hl
;REGISTERS: bc=Arg2 de=Arg1 hl=Arg3
;STACK: | Arg3 | Ret | ...
add hl,bc ;Calculate offset of end of deletion
jr c,__DelMemFail ;Return failure if offset+size was so big that it overflowed
ex de,hl
;REGISTERS: bc=Arg2 de=Arg2+Arg3 hl=Arg1
;STACK: | Arg3 | Ret | ...
dec hl ;Get current variable size
ld a,(hl)
dec hl
push hl
ld l,(hl)
ld h,a
;REGISTERS: bc=Arg2 de=Arg2+Arg3 hl=current variable size
;STACK: | Arg1-2 | Arg3 | Ret | ...
sbc hl,de ;Check if end is outside of variable
pop de ;Early pop to avoid having fail condition requiring 2 pops
;REGISTERS: bc=Arg2 de=Arg1-2 hl=current variable size - (Arg2+Arg3)
;STACK: | Arg3 | Ret | ...
jr c,__DelMemFail ;Return failure if end is outside of variable
add hl,bc ;Add back offset to get final variable size
;REGISTERS: bc=Arg2 de=Arg1-2 hl=final variable size
;STACK: | Arg3 | Ret | ...
ex de,hl ;Store final variable size
ld (hl),e
inc hl
ld (hl),d
inc hl
;REGISTERS: bc=Arg2 de=final variable size hl=Arg1
;STACK: | Arg3 | Ret | ...
add hl,bc ;Calculate RAM deletion address
pop de ;Prepare size argument for _DelMem
;REGISTERS: bc=Arg2 de=Arg3 (bytes to delete) hl=Arg1+Arg2 (RAM deletion address)
;STACK: | Ret | ...
B_CALL(_DelMem) ;Delete memory
;REGISTERS: de=Arg3 (bytes to delete) hl=a lot (negative size of a VAT entry?)
;STACK: | Ret | ...
ret ;Result is always nonzero
__DelMemFail:
pop hl
ld hl,0
ret
__DelMemEnd:
[noobish question]What are tilemaps, and how do I use them?[/noobish question]
The ultimate goal is to get a sort of smmothscrolling, specifically for Tio.
The ultimate goal is to get a sort of smmothscrolling
[Pic1r]->Pic000
Pt-On(10,10,Pic000)
Pt-On(18,10,Pic000+8)
Happy birthday Axe.
Not only Axe is 1 years old, it's the project that had the most attention in Omni history with 12000+ posts in its sub-forum. O.O (The second one was Ultima V, I think)
GetCalc("appvMOVIE")->P
Copy(P,L6,768)
Copy(P+768,L3,768)
Then you could just call DispGraphrr or DispGraphr in a loop or something to display the scene for a little.GetCalc("appvMOVIE")->Q
For(Z,0,3)
Z*1536+Q->P
Copy(P,L6,768)
Copy(P+768,L3,768)
Repeat getKey(54)
DispGraphr
End
End
For simplicity's sake, this just waits till you press 2nd before moving onto the second scene.GetCalc("appvMOVIE",number of frames * 1536)->P
...
Data for frames
Maybe they're in imported pics, or something
...
If you were gonna put the first scene into the appvar, then something like this:
Copy(pointer to front layer of first scene,P,768)
Copy(pointer to back layer of first scene,P+768,768)
Adding other scenes would follow the same pattern, just keep adding 768 to the appvar pointer.
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
000000000000000000000000
00001FF00000000000000000
000010100000000000000000
.It always messes up here^^, the second line where it has no zeroes
By the way, is asking for this kind of help on IRC discouraged?Not at all. That's one of the reasons the chat is there. :) Good luck. ;D
Those already exist ;)
Since 0.4.5, I think, although they were buggy until recently.
If A=1
.Do something
End
If A=2
.Do something
End
...
If A=(some_number)
.Do something
End
If A=1
.Do something
ElseIf A=2
.Do something
ElseIf ...(etc.)
.Do something
ElseIf A=(some_number)
.Do something
End
3->A
If A>1
Text(10,10,Str1)
End
If A>2
Text(10,20,Str2)
End
That would display both Str1 and Str2.3->A
If A>1
Text(10,10,Str1)
ElseIf A>2
Text(10,20,Str2)
End
That would display only Str1 because that was the first conditional to become true.
Really? Guess I went a tad bit overboard <.<
Glad you liked it though.
Are you talking about me? :P
Also, is there a way to compile a program externally?
Nope, that's been suggested several times, but someone would have to get Quigibo's permission (and the source for Axe) to make an off-calc compiler. You can use Wabbit, though.
That's what I thought too. :DNope, that's been suggested several times, but someone would have to get Quigibo's permission (and the source for Axe) to make an off-calc compiler. You can use Wabbit, though.I think he means compile a program externally, but still on calc. Like a hook or an entry point.
Code: [Select]If A=1
.Do something
End
If A=2
.Do something
End
...
If A=(some_number)
.Do something
End
This can be shortened toCode: [Select]If A=1
.Do something
ElseIf A=2
.Do something
ElseIf ...(etc.)
.Do something
ElseIf A=(some_number)
.Do something
End
If A=1
.Do something
Goto E
End
If A=2
.Do something
Goto E
End
...
If A=(some_number)
.Do something
End
Lbl E
The next beta has arrived! :)
Ah ok, nice for the update. Does Direct input remain the same if we want to use it normally?Yes, it originally was.
Btw, was requiring 6 MHz mode for DispGraph intentional? Runer112 pointed this out on IRC.
So, getKeyr returns the same values as Key Values → Direct Input in Calcsys? cool
Oh, so BASIC getkey?
This sounds pretty awesome, although I am a little worried that this will make programming in Axe less "authentic," if you know what I mean. Although I do see the merits as well. But is it even necessary to change the b prefix for binary to something else? When parsing, if the b is followed by a 1 or 0, treat it as an indicator of binary data. Otherwise, treat it as the b register.That's true, I guess I could do that.
.KBYCRACK Crackity Hack!
prgmDEFINE
DiagnosticOff
sub(RCL)
sub(SSP,3,35,Pic1)
sub(SSP,25,30,Pic2)
sub(SSP,47,30,Pic3)
sub(SSP,69,35,Pic4)
sub(SSP,3,48,Pic5)
sub(SSP,25,43,Pic5)
sub(SSP,47,43,Pic8)
sub(SSP,69,48,Pic8)
sub(SET)
Repeat getKey(54)
DispGraph
End
sub(W)
0→T→P
Repeat T=4
40→X
1→A
Repeat getKey(54) or (X=40 and (A=2))
If A=1
Line(2,X/2+2,4,X/2+2)
ElseIf A=2
ref(2,X/2+2,3,1)
rref(2,X/2+2,3,1)
End
DispGraph
If X=0:2→A:End
If A=1:X-1→X:End
If A=2:X+1→X:End
End
If getKey(54)
sub(W)
40-X→X
X*X*X/371+P→P
Else
sub(W)
End
T+1→T
sub(SET)
End
20→X
Repeat getKey(54) or (X=100)
sub(RCL)
sub(FSP,5,30,Pic63)
sub(FSP,5,X/2,Pic6)
X+1→X
DispGraph
End
20-abs(60-X)→X
If X<0:0→X:End
X*X*31/40+P→P
sub(W)
conj(Pic01,L₃,768)
conj(Pic02,L₆,768)
sub(Q)
ClrDraw
sub(Q)
ClrDraw
sub(W)
rand ^999→Q
rand ^999→R
rand ^999→S
If P>999:999→P:End
P→Z
If Q>Z
Q→Z
ElseIf R>Z
R→Z
ElseIf S>Z
S→Z
End
0→X→Y
Fix 5
Repeat Z=X
If P≥X:sub(TSP,4,40,Pic7+Y):End
If Q≥X:sub(TSP,26,40,Pic7+Y):End
If R≥X:sub(TSP,48,40,Pic7+Y):End
If S≥X:sub(TSP,70,40,Pic7+Y):End
If Y=0
32→Y
Else
0→Y
End
Vertical -
Vertical -
Vertical -
ref(0,48,96,10)
rref(0,48,96,10)
If X≤P:Text(4,55,XDec):End
If X≤Q:Text(26,55,XDec):End
If X≤R:Text(48,55,XDec):End
If X≤S:Text(70,55,XDec):End
If X>P:Text(4,55,PDec):End
If X>Q:Text(26,55,QDec):End
If X>R:Text(48,55,RDec):End
If X>S:Text(70,55,SDec):End
If X<(Z-25)
X+10→X
ElseIf X<(Z-10)
X+1→X
Pause 100
Else
X+1→X
Pause 200
End
DispGraph
End
DispGraph
Return
Lbl Q
0→A
Repeat A=8
DispGraph
Horizontal +
Horizontal +
Horizontal +
Horizontal +
Vertical +
Vertical +
Vertical +
Vertical +
DispGraph
Horizontal -
Horizontal -
Horizontal -
Horizontal -
Vertical -
Vertical -
Vertical -
Vertical -
A+1→A
End
Return
Lbl SET
ref(1,1,5,22)
ref(1,1,5,22)
rref(2,2,3,20)
rref(2,2,3,20)
Return
Lbl W
0→A
Repeat A=40
DispGraph
A+1→A
End
Return
Lbl TSP
Plot1(r₁,r₂,r₃)
Plot1(r₁+8,r₂,r₃+16)
Return
Lbl FSP
Plot1(r₁,r₂,r₃)
Plot1(r₁+8,r₂,r₃+16)
Plot1(r₁,r₂+8,r₃+32)
Plot1(r₁+8,r₂+8,r₃+48)
Return
Lbl SSP
Plot1(r₁,r₂,r₃)
Plot1(r₁+8,r₂,r₃+16)
Plot1(r₁+16,r₂,r₃+32)
Plot1(r₁,r₂+8,r₃+48)
Plot1(r₁+8,r₂+8,r₃+64)
Plot1(r₁+16,r₂+8,r₃+80)
Return
Lbl RCL
conj(Pic0,L₃,768)
conj(Pic00,L₆,768)
Return
If X≤P:Text(4,55,XDec):End
If X≤Q:Text(26,55,XDec):End
If X≤R:Text(48,55,XDec):End
If X≤S:Text(70,55,XDec):End
If X>P:Text(4,55,PDec):End
If X>Q:Text(26,55,QDec):End
If X>R:Text(48,55,RDec):End
If X>S:Text(70,55,SDec):End
becomesText(4,55,min(X,P)Dec)
Text(26,55,min(X,Q)Dec)
Text(48,55,min(X,R)Dec)
Text(70,55,min(X,S)Dec)
That sounds nice, but then for the contest somebody will have to help me judging entries, because I haven't coded Axe in almost one year and I'll need to scan every entry to make sure only a certain percentage of Asm() and your new ASM feature is used, and sadly I might not make the difference between Axsembly stuff and regular Axe code. ;D
2: ASM code must not compose more than 10% of your program code and the only allowed way to use assembly is via the Asm() command. The remaining 90% must be Axe or Axiom code. (See previous rule for Axiom information). Other languages such as TI-BASIC are NOT allowed.
:.TEST
:Str1 ;1 Symbol
:Str1 ;2 Symbols
:Str1 ;3 Symbols
:"H"->Str1 ;Now defined, so 1 symbol from now on
:Str1 ;1 Symbol
:Str1 ;1 Symbol
:Str1 ;1 Symbol
Perhaps an optional 4th pass for those of us that like to squeeze every bit of speed from everything we encounter?I think that's a great idea. I vote for three passes with an optional 4th.
It would also allow me to give a compile error now when you go over the limit. Currently I can't do that because I don't know how much is data and how much is code.Nice! I really want that. ^-^
The fourth pass would not actually reduce the size of programs, nor would it make them faster. The *only* thing it would do is move all the data to the end of the program so you get a little more edge when compiling for Shell, and you are almost at the size limit
I support the 4th pass.^^. I can think of about a hundred ways that would help me.
YAY Axe Parser 0.5.3 (http://ourl.ca/4060/213904) is out :D
So I'm thinking of talking to Kerm about it, I'm not sure how much space is left in DCS so I can't say for sure if this is possible, I think all the axe subroutines combined are under 3KB together.There isn't much space. I think he has a few hundred bytes on every page, or less.
But anyway, is this something you guys thing I should invest time in, regardless of if it ends up in a new Axe Shell or DCS? It could makes shells more useful than just the extra header.Definitely. It sounds like a great idea. :)
You could add a first pass for the sole purpose of finding user-defined constants. Not a terribly elegant solution, but it would work.That'd be the easiest way around it, but at the cost of compiling speed.
Perhaps I will make a rule like you cannot store to a static unless everything on the left hand side is declared already.I think that's the way to do it. :)
Just wanted to give everyone a quick update on progress.
This is day 6 of the rewrite. I can now parse simple programs and have data, labels, variables, and gotos working correctly. Though I still need to rewrite subs, interrupts, internal subroutines, and axioms. So currently, I cannot compile any large programs, but I'm almost at the point where I can. There is at least one extra MAJOR convenience feature that was requested a long time ago that will finally make it to the update, but I won't spoil what it is yet. ;) I still have no idea when it'll be finished because of all the inevitable unexpected issues to come, but hopefully before the end of the month.
Just wanted to give everyone a quick update on progress.Wow... You're doing a FULL rewrite?
This is day 6 of the rewrite. I can now parse simple programs and have data, labels, variables, and gotos working correctly. Though I still need to rewrite subs, interrupts, internal subroutines, and axioms. So currently, I cannot compile any large programs, but I'm almost at the point where I can. There is at least one extra MAJOR convenience feature that was requested a long time ago that will finally make it to the update, but I won't spoil what it is yet. ;) I still have no idea when it'll be finished because of all the inevitable unexpected issues to come, but hopefully before the end of the month.
More seriously, Ashbad's referring to inline functions, I presume, which probably aren't going to happen.
Yeah, I realize its not needed much now, but its going to become VERY necessary for another feature I'm adding: ;DSpoiler For Spoiler:
Actually it is listed there in small font. It said lambdas. Which was also mentioned by other posters on this page of this thread. I'm not even sure why you thought it would be necessary to turn off image blocker anyway, you can click through the spoilers and still read what it says without even messing with image blocker.
*edit*: Ok, it gives alternate text with image blocker on... how strange.
I don't think it will ever be "Finished". Its going to stay alive for a long time, the 1.0.0 will just be the largest, most improved, programming-style changing update to date. If I ever fear the Parser is starting to die due to real life stuff or boredom of working on the same project for so long, I will definitely pass it on to another programmer to continue, I wouldn't leave you guys hanging. :)
Actually it is listed there in small font. It said lambdas. Which was also mentioned by other posters on this page of this thread. I'm not even sure why you thought it would be necessary to turn off image blocker anyway, you can click through the spoilers and still read what it says without even messing with image blocker.
*edit*: Ok, it gives alternate text with image blocker on... how strange.
I had to zoom in my browser a zillion times to see that word. then I reasoned the pics might have been screenshots or something. allow images, add water and BOOM, instant headaches with half that screen flashing. It wouldn't have been an issue if I hadn't just zoomed in a couple dozen times.
I was warned of this too in my intro topic.
Ok, let me rephrase that.More seriously, Ashbad's referring to inline functions, I presume, which probably aren't going to happen.
Quigibo just said they were gonna happen, so I assume they are :P
@gravity = lambda {|cur_level|(cur_level%5==0)?(1):(2)} / air_density
@gravity = lambda {|cur_level|(cur_level%5==0)?(1):(2)} / air_density
if cur_level%5 == 0
Thing = 1
else
Thing = 2
end
Gravity = Thing / air_density
/me pays off people who didn't understand since they allowed him to finally see Axe's implementation :)
Map(λ(r12),L1,100)I have couple remarks on that :)
Well, as someone who uses them all the time in programming, I can say they are very useful in many situations. They can help reduce the number of methods needed to evaluate a certain value. DeepThought gives a decent example with different features per level, such as if you had two different levels of gravity:Code: [Select]@gravity = lambda {|cur_level|(cur_level%5==0)?(1):(2)} / air_density
So that every five levels the lambda would return 2 instead of 1. In that example you could take out the lambda and still be fine, but there are even bigger needs for it when you need to directly pass values as parameters into complex equations with highly varying outputs or when you go to attach them to variables directly so that a variable's state is defined by input parameters. Which brings me to ask, quigibo: are you thinking of adding full support for lambdas/procs with variable attachments and inlining functions, or just inlining?
EDIT: hmm, so the case here isn't just that many don't know how to use them, but that they also don't know what they are :P understandable. In a nutshell:
Lambdas are functions that stand in for single values (though in some cases they can return multiple values, but don't worry about that most languages don't even support it). They can take passed arguments and can contain code that'll evaluate expressions and return values accordingly. Very, very useful. For a decent background, here's the wikipedia link Qwerty pointed me to a long time ago that I found very helpful: http://en.wikipedia.org/wiki/Lambda_calculus
Map(λ(r12),L1,100)I have couple remarks on that :)
First of all, since we will presumably be able to make routines such as Map( ourselves, could you show us the syntax for calling a subroutine by address? (Something like sub(r1, ...)r, perhaps? (Where r1 is any expression))
Secondly, will inlining be supported? (In general, not just for Map() That is, if an anonymous subroutine (or lambda, whatever you want to call them) is passed to a routine and that routine has a call for it exactly once, will the compiler replace the call with the routine itself? Otherwise, your example, among other useful invocations, will be much slower than it should be. ;)
You guys already know how awesome you are, you don't need me to tell you that :hyper:
EDIT: How to join #omnimaga irc?
It may be unessicary, but I find it rather more organized and clean :).This is in the compiled code. You wouldn't notice. :P
Plus, I for one don't trust the whole RAM execution limit breaking idea, I haven't seen enough tests to be sure I would consider using it or wanting people making programs using it.It works perfectly. The only foreseeable problem is getting people to run a program which would make all RAM executable.
It may be unessicary, but I find it rather more organized and clean :).This is in the compiled code. You wouldn't notice. :PQuotePlus, I for one don't trust the whole RAM execution limit breaking idea, I haven't seen enough tests to be sure I would consider using it or wanting people making programs using it.It works perfectly. The only foreseeable problem is getting people to run a program which would make all RAM executable.
HELP!
My calc crashed! (because of Axe 1.0.0!)
I'd tried to do little changes:
0->{L1}^r
Fill(L1,58)
It took (my wohle game (compiled) ) 1914 bytes
Then I tried to use the new Fill( comand and compiled the game:
Fill(L1,58,0)
I have another question about the new version:When a program or app wants to write something to Flash, they can do it in two ways. The first ways is to use BCALLs. It's quite stable, but sometimes there are things that you can't do that way. The other way is to write every byte directly to flash. However, TI has protected flash so that you don't accidentally write to it. Before the program/app writes to flash, it must unlock flash, which can be quite tricky. If Axe doesn't lock flash afterwards, another program might write to flash accidentally (but most programs will normally not even attempt to do it, so it's not dangerous in normal cases).
In the changelog, you wrote:
"Flash is locked after quitting Axe for security reasons."
What does that mean?
You might want to hold off for a bit longer until some bugs are fixed. Axe 1.0.0 and 1.0.1 have a nasty ability to sometimes muck up flash. I've heard of effects ranging from having to resend Axe, to having to resend the OS, to having to clear all memory.Gasp!
You might want to hold off for a bit longer until some bugs are fixed. Axe 1.0.0 and 1.0.1 have a nasty ability to sometimes muck up flash. I've heard of effects ranging from losing data in some sectors of flash memory, to having to resend the OS, to having to clear all memory altogether.So that explains it...and I only got the Bad Flash err once x.x
You might want to hold off for a bit longer until some bugs are fixed. Axe 1.0.0 and 1.0.1 have a nasty ability to sometimes muck up flash. I've heard of effects ranging from losing data in some sectors of flash memory, to having to resend the OS, to having to clear all memory altogether.
I am back to 0.5.3 (which works fine :) ) and I noticed that compiling is much, much faster. Were that many new features added to Axe 1?Yes, and tons of new features were added, allowing variable names to be longer, forward referencing, a much, much higher variable limit, and other changes. This translates to slower parsing, but it's more flexible this way. :D
I am back to 0.5.3 (which works fine :) ) and I noticed that compiling is much, much faster. Were that many new features added to Axe 1?Yes, and tons of new features were added, allowing variable names to be longer, forward referencing, a much, much higher variable limit, and other changes. This translates to slower parsing, but it's more flexible this way. :D
It should eventually allow you to write code in a more natural way and then automatically convert it to code that is more "Runer Style" as I like to call it ;)Runer Style? I wonder why you call it that? <_<
I am back to 0.5.3 (which works fine :) ) and I noticed that compiling is much, much faster. Were that many new features added to Axe 1?Yes, and tons of new features were added, allowing variable names to be longer, forward referencing, a much, much higher variable limit, and other changes. This translates to slower parsing, but it's more flexible this way. :D
It should eventually allow you to write code in a more natural way and then automatically convert it to code that is more "Runer Style" as I like to call it ;)
0→A
1→B
ld hl,0
ld (A),hl
ld l,1 ;or even inc l if you can pull it off
ld (B),hl
Quigibo just released Axe0.0.21.0.2, it fixes all the bugs in the 1.0.1 :)
:If A
:If B
:If C
:<code>
:End:End:End
You can now inline the comparisons using the ternary::If A?B?C,,
:<code>
:End
If (A?(B?(C),<b is false>),<a is false>)
Basically it checks A, if A is false, there is no code, so it returns the last statement evaluated which is 0 since it was false. If true, it checks B and again returns false if B is false. Finally, if B is true, it just returns C's condition which will determine if the entire statement is true or false :)If A?,B
Pxl-On(A,B)
0→A
End
If A?,BPxl-On(A,B)
0→A
End
If A=3 and (B=6) and (C=7)
If A=3 ? B=6 ? C=7
willrandship, if I klick on the link in your signature, my avast! antivirus says, that this site wants to install malware on my pc X.xYeah, that happens for a m:oment, then disappear.
willrandship, if I klick on the link in your signature, my avast! antivirus says, that this site wants to install malware on my pc X.xYeah, that happens for a m:oment, then disappear.
Out of curiosity, about the dereferenced labels: Since (LFOO)() is the same as using FOO(), can you put constant pointers into the first parentheses to call shell and TI-OS subroutines (like (E0000)() to reset your RAM)? Because if so, that will be REALLY cool! :)
:Lbl Foo
:+1->B
:Disp B>Dec
:Return
p_CallHL:
.db 6
pop ix
ex (sp),ix
jp (ix)
No, I think he is saying that hl will remain intact as you call the subroutine.Fixed that for ya ;D
No, I think he is saying that hl will remain intact as you return from the subroutine.
.XYZ
Disp "HI"
I compiled it, then archived the compiled program. Then I recompiled... nothing bad happened.Axe apps still need to be signed to transfer to another calculator, but at least it won't delete itself.I can't remember if this was asked before, but how long would it take for someone to sign an app on calc, and how much extra space would it take to do so?
From the DuckSign (on calc app signer) documentation:Axe apps still need to be signed to transfer to another calculator, but at least it won't delete itself.I can't remember if this was asked before, but how long would it take for someone to sign an app on calc, and how much extra space would it take to do so?
Hashing the application will take about 4 seconds per page on a TI-83
Plus BE, or about 1 second per page on a TI-83 Plus SE or TI-84 Plus.
Once this is done, computing a new application signature will take
about 50 seconds on a TI-83 Plus BE, or about 20 seconds on a TI-83
Plus SE or TI-84 Plus.
From the DuckSign (on calc app signer) documentation:Axe apps still need to be signed to transfer to another calculator, but at least it won't delete itself.I can't remember if this was asked before, but how long would it take for someone to sign an app on calc, and how much extra space would it take to do so?Quote from: DuckSign ReadmeHashing the application will take about 4 seconds per page on a TI-83
Plus BE, or about 1 second per page on a TI-83 Plus SE or TI-84 Plus.
Once this is done, computing a new application signature will take
about 50 seconds on a TI-83 Plus BE, or about 20 seconds on a TI-83
Plus SE or TI-84 Plus.
Ashbad, good to see you again!
The problem is that some people do not have a computer at all (or any suitable access to one). JustCause comes to mind.
Well if he could sign on-calc, he could send the game from calc to calc.Ashbad, good to see you again!
QueThe problem is that some people do not have a computer at all (or any suitable access to one). JustCause comes to mind.
But then he can't distribute it anyways, so no problem there.
A->B:B->A
keep(B,A->B)->A
:Lbl FUN
:keep(r1,keep(r2,FUN(r1,r2)->r3)->r2)->r1
:Return r3
That seems like a pretty good way to safely implement stack usage. But could there also be commands for more experienced coders that simply equate to push hl, pop hl, and ex (sp),hl? Because your idea is great for casual coders, but crazy people like me like to be able to squeeze every last byte out of code. Something like you suggested here (http://ourl.ca/4057/195758) seems to be a good idea for syntax, and calc84maniac suggested a good syntax for ex (sp),hl here (http://ourl.ca/4057/195928). Of course you would want to warn users about the dangers of these commands in the command list, but I don't think it's too dangerous to warrant not adding. There are so many other ways a programmer can crash their calculator with Axe, adding a new one won't really change much.
That seems like a pretty good way to safely implement stack usage. But could there also be commands for more experienced coders that simply equate to push hl, pop hl, and ex (sp),hl? Because your idea is great for casual coders, but crazy people like me like to be able to squeeze every last byte out of code. Something like you suggested here (http://ourl.ca/4057/195758) seems to be a good idea for syntax, and calc84maniac suggested a good syntax for ex (sp),hl here (http://ourl.ca/4057/195928). Of course you would want to warn users about the dangers of these commands in the command list, but I don't think it's too dangerous to warrant not adding. There are so many other ways a programmer can crash their calculator with Axe, adding a new one won't really change much.Directly using pushing/popping can definitely cause problems in the middle of expressions, and in For(const) loops for example. There are too many things subject to change in the implementation of Axe for direct stack access not to be potentially buggy unless you know a lot about the inner workings of Axe. I think Asm() will suffice for crazy hackage.
Not good if someone wants that to happen thoughThat seems like a pretty good way to safely implement stack usage. But could there also be commands for more experienced coders that simply equate to push hl, pop hl, and ex (sp),hl? Because your idea is great for casual coders, but crazy people like me like to be able to squeeze every last byte out of code. Something like you suggested here (http://ourl.ca/4057/195758) seems to be a good idea for syntax, and calc84maniac suggested a good syntax for ex (sp),hl here (http://ourl.ca/4057/195928). Of course you would want to warn users about the dangers of these commands in the command list, but I don't think it's too dangerous to warrant not adding. There are so many other ways a programmer can crash their calculator with Axe, adding a new one won't really change much.Directly using pushing/popping can definitely cause problems in the middle of expressions, and in For(const) loops for example. There are too many things subject to change in the implementation of Axe for direct stack access not to be potentially buggy unless you know a lot about the inner workings of Axe. I think Asm() will suffice for crazy hackage.
Edit: Well, I suppose Axe could keep track of all pushes/pops as well as which ones are manual and which ones are internal. It could then error if it tries to internally pop a manual push or manually pop an internal push. That's fairly safe, I guess.
If you're at the point where you want to access internal Axe values, you're probably better off using Asm() since that would be Axe-version-specific behavior.Not good if someone wants that to happen thoughThat seems like a pretty good way to safely implement stack usage. But could there also be commands for more experienced coders that simply equate to push hl, pop hl, and ex (sp),hl? Because your idea is great for casual coders, but crazy people like me like to be able to squeeze every last byte out of code. Something like you suggested here (http://ourl.ca/4057/195758) seems to be a good idea for syntax, and calc84maniac suggested a good syntax for ex (sp),hl here (http://ourl.ca/4057/195928). Of course you would want to warn users about the dangers of these commands in the command list, but I don't think it's too dangerous to warrant not adding. There are so many other ways a programmer can crash their calculator with Axe, adding a new one won't really change much.Directly using pushing/popping can definitely cause problems in the middle of expressions, and in For(const) loops for example. There are too many things subject to change in the implementation of Axe for direct stack access not to be potentially buggy unless you know a lot about the inner workings of Axe. I think Asm() will suffice for crazy hackage.
Edit: Well, I suppose Axe could keep track of all pushes/pops as well as which ones are manual and which ones are internal. It could then error if it tries to internally pop a manual push or manually pop an internal push. That's fairly safe, I guess.
Any chance we will see 32 bit numbers soon ?
I think Runer112 posted a routine that allowed combining two numbers into one to make 32 bit ones, sort of.Yes. Here it is (http://ourl.ca/4129/155369).
Awesome! That bitmap command's exactly what I had in mind ^^
[A3]->GDB1
{GDB1}/256 == A or 3?
{GDB1}^256 == 3 or A?
Wouldn't you want to divide by 16 instead of 256 ??? ?Code: [Select][A3]->GDB1
{GDB1}/256 == A or 3?
{GDB1}^256 == 3 or A?
Tilemappers are hard until you've written at least six gazillion of them like i have :P I swear i've had to rewrite a tilemapper for every project i've ever done, even the ones that have died...idk why. I really should reuse more code.
Tilemappers are hard until you've written at least six gazillion of them like i have :P I swear i've had to rewrite a tilemapper for every project i've ever done, even the ones that have died...idk why. I really should reuse more code.
Another thing to keep in mind is that because a majority of the time spent rendering a tilemap is sprite drawing and not the tilemapping itself, any speed increase from this routine will be very tiny compared to if you wrote it in native Axe. Most of the advantage will come from reduced size of code and simplicity of the programming.
All drawing operations operate on a 768 byte buffer in memory.So there *must* be scaling if there are more than one logical unit (coordinate) per physical unit (pixel).
Release what?/me is expecting something awesomeI think he will release a new version of Axe Parser.
Awesome!! NEW AXEAnd I was the second!
I was the first person to download the new version :D
Now...I believe so.
Is absorbing appvars like
[pic1]->pic1
but for appvars?
And what are preprocessor conditionals?Instead of commenting out code like this:
Also, what does Single argument for loops can now take any expression as an argument mean?For(A) .loop A times
Also, yet another question, what isThis used to be an error (because it wouldn't work):
"Now able to use Return in a single argument for loop."
:P
Edit:Select(EXP1,EXP2) finds the value of EXP1, stores it into some secret place, then it evaluates EXP2, and lastly, it looks in that secret place and returns the original value of EXP1.
Yet another yet another question is:
What does select() do? I don't get what the commands list is saying
:P
prgmAA
:.A
:ClrHome
:[prgmAA]->A
:While {A}
:Disp >Tok
:A+1->A
:End
This one prints out its own source code. Try it :PSelect(A,B->A)->B
Swaps the values of A and B faster and without needing any extra temporaries.Select(A,+1->A)
This is the C style "A++" meaning it increments A but returns the value of A before you actually incremented it.:Lbl FOO
:Select(r1,Select(r2,MYLBL()->A)->r2)->r1
:Return A
:Lbl MYLBL
:<stuff including more calls to FOO>
You have now created a recursive subroutine that doesn't need to be called in any special format. Just call FOO(1,2) or whatever. Something similar to this will eventually replace the current "recursive subroutine" because it has way more advantages:This used to be an error (because it wouldn't work):That was super easy. I was already keeping track of how large the stack was. All I had to do was pop N times for every N nested for loops (the single argument variety) prior to returning. ;D
For(10)
If A+1→A=B
Return
End
End
Now, Quigibo has found some amazing way to make it work, so it is allowed ;D.
:If A=0:
:<code>
:ElseIf A=1:
:<code>
:ElseIf A=2:
:...and so on...
:MyTbl(A)
:
:Lbl MyTbl
: Z-Test(r1,A,B,C,...)
: <handle errors>
I don't know what you mean by that... but its just a command that takes label names for its arguments. The interrupt command also does this: fnInt(LBL,0) for instance.Oh.... silly me :P I didn't read it quite carefully, and parsed it (get it?) as:
Lbl FAKE
Z-Test(r1, 1, 2, 3)
Lbl 1
Lbl 2
Lbl 3
Return
Sorry for my mishap! :).SLCTTEST Select-like cmd test
.Should print "Hi!"
MyLbl(0)
Pause 2000
.Should print "Long time, eh?"
MyLbl(1)
Pause 2000
.Should print "Can't wait to!"
MyLbl(2)
Pause 2000
.Should print "Laugh out loud"
MyLbl(3)
Pause 2000
.Should print "It is now Friday"
MyLbl(4)
Pause 2000
Lbl MyLbl
.Just in case...
ClrHome
Z-Test(r1,HI,LTE,CWT,LOL,TGIF)
Return
Lbl HI
Output(0,0,"Hi!")
Return
Lbl LTE
Output(0,0,"Long time, eh?")
Return
Lbl CWTG
Output(0,0,"Can't wait to!")
Return
Lbl LOL
Output(0,0,"Laugh out loud")
Return
Lbl TGIF
Output(0,0,"It is now Friday")
Return
I think you can safely ignore whether or not the Axiom reference is in a comment. Even if it is, the program probably still uses commands from it somewhere in the source and the token replacement should be used for clarity whether or not it is commented out.Have you seen optimized Axe code? It is nothing but crazy!
EDIT: And if the programmer is doing crazy stuff like a conditional if-else comment to include only one of two Axioms that replace the same tokens... Well that's a little nuts and I think they can deal with that not being supported. :P
My suggestion is that AXF be released under a totally different name, even though the language it uses is called "Axe." I think AXF programs should be categorized separately from ordinary Axe programs (such as on ticalc), and if possible to have Axe and AXF games be considered two completely separate types of programs (such as in program descriptions).I agree with Deep here. The names AXE and AXF are too close to avoid confusion. The shell itself sounds cool, though.
I highly doubt you have to worry about anyone not using your stuff Quigbo, especially if it reduces their programs by 3000 bytes.I was referring to asm programmers not wanting to use it because usually they have different IO preferences and don't like dependencies. But I guess people did use the ion routines so maybe it could still be useful to them.
The ion header is, I feel, the best option for Axe programs because they are compatible with ALL shells and can still be run from the home screen with Asm().I saw the "ALL" in all caps and I felt the need to point out not all shells work; all major, current shells do, but I'm pretty sure shells like CrunchyOS do not.
Name Ideas:O.o
Tree
Hatchet
Chainsaw
anything on improving speed makes me happy :DI don't think it would make programs any faster, but I may be wrong. It could make them much smaller though.
Nope DCS7 is the only one still under active development. MirageOS 1.3 had no news since 2005 or so, Crunchy since 2004 and Ion since 2002 I think.And of those, only ion released the source, though it looks like BrandonW (or someone) disassembled MirageOS:
.nolist
#include "ti83plus.inc"
.list
#define p_GetArc $55E7
#define p_ReadArcApp $5658
#define p_CopyArc $568D
#define TokenHook_Temp appBackUpScreen-2
#define AxiomTokens appBackUpScreen
.org $71E0
TokenHook_NotAxe:
ld bc,('A'<<8)+(StrPROGRAM&$FF)
TokenHook_CheckIfChanged:
ld de,textShadow
ld a,(de)
xor b
ret nz
push hl
ld h,StrPROGRAM>>8
ld l,c
B_CALL(_Mov7B)
B_CALL(_saveShadow)
B_CALL(_rstrShadow)
pop hl
xor a
ret
TokenHook:
.db $83
ld a,(cxCurApp)
cp kPrgmEd
ret nz
ld bc,(EditTop)
ld a,(bc)
cp tDecPt
jr nz,TokenHook_NotAxe
TokenHook_MaybeAxe:
inc bc
ld a,(bc)
cp tDecPt
jr z,TokenHook_IsAxe
sub tA
cp tTheta-tA+1
jr nc,TokenHook_NotAxe
TokenHook_IsAxe:
push hl
push de
ld bc,('P'<<8)+(StrAXESRC&$FF)
call TokenHook_CheckIfChanged
call z,TokenHook_AxiomSearch
pop de
ld hl,AxeTokens
ld b,0
jr TokenHook_CompareLoop_Start
TokenHook_CompareLoop:
cp e
inc hl
jr z,TokenHook_LowByteMatch
TokenHook_NoMatch:
inc hl
ld c,(hl)
inc c
add hl,bc
TokenHook_CompareLoop_Start:
ld a,(hl)
or a
jr nz,TokenHook_CompareLoop
TokenHook_DoneNoMatch:
add hl,hl
ld hl,AxiomTokens
jr nc,TokenHook_CompareLoop_Start
pop hl
ret
TokenHook_LowByteMatch:
ld a,(hl)
cp d
jr nz,TokenHook_NoMatch
TokenHook_Match:
ld de,localTokStr
push de
ld c,17
ldir
pop hl
pop bc
ret
TokenHook_AxiomSearch:
ld hl,AxiomTokens
B_CALL(_BufClr)
ld hl,-768
ld (TokenHook_Temp),hl
ld de,(editTop)
push de
ld hl,(editCursor)
push hl
push de
B_CALL(_BufToBtm)
ld hl,(editCursor)
pop de
or a
sbc hl,de
inc hl
ld b,h
ld c,l
ex de,hl
call TokenHook_AxiomSearch_Loop
TokenHook_AxiomSearch_Done:
pop hl
ld (editTop),hl
B_CALL(_BufToTop)
pop hl
ld (editTop),hl
ret
TokenHook_AxiomSearch_CheckHeader:
call ReadArc
inc de
add a,c
ld bc,$C0DE
sbc hl,bc
ld c,a
ret z
pop bc
TokenHook_AxiomSearch_Loop__:
pop bc
TokenHook_AxiomSearch_Loop_:
pop hl
TokenHook_AxiomSearch_Loop:
ld a,tAsmComp
cpir
ret po
push hl
dec hl
dec hl
ld a,(hl)
cp t2ByteTok
jr nz,TokenHook_AxiomSearch_Loop_
TokenHook_AxiomSearch_Backtrack:
dec hl
ld a,(hl)
cp tSpace
jr z,TokenHook_AxiomSearch_Backtrack
sub tColon
cp tEnter-tColon+1
jr nc,TokenHook_AxiomSearch_Loop_
TokenHook_AxiomSearch_FindAxiom:
pop hl
push hl
push bc
dec hl
rst 20h
ld hl,OP1
ld d,AppVarObj
ld (hl),d
call p_GetArc+1
jr c,TokenHook_AxiomSearch_Loop__
TokenHook_AxiomSearch_FoundAxiom:
ex de,hl
ld c,b
call TokenHook_AxiomSearch_CheckHeader
ld b,32+1
TokenHook_AxiomSearch_ScanAxiom:
call ReadArc
inc de
ld a,h
or l
jr z,TokenHook_AxiomSearch_EndOfAxiom
add hl,de
ld de,5
add hl,de
ex de,hl
djnz TokenHook_AxiomSearch_ScanAxiom
TokenHook_AxiomSearch_EndOfAxiom:
call TokenHook_AxiomSearch_CheckHeader
call ReadArc
inc de
ld a,c
ld b,h
ld c,l
ld hl,(TokenHook_Temp)
add hl,bc
jr c,TokenHook_AxiomSearch_Loop__
ld (TokenHook_Temp),hl
sbc hl,bc
push bc
ld bc,appBackUpScreen+768
add hl,bc
pop bc
ex de,hl
call p_CopyArc+5
jr TokenHook_AxiomSearch_Loop__
ReadArc:
ex de,hl
xor a
cp c
jr z,ReadArc_RAM
push bc
push hl
call p_ReadArcApp+11
pop de
inc de
pop bc
ret
ReadArc_RAM:
ld e,(hl)
inc hl
ld d,(hl)
ex de,hl
ret
AxeTokens:
.db $F4,$03,5,"Copy("
.db $FE,$03,5,"Exch("
.db $0E,$04,5,"Freq("
.db $66,$01,5,"Buff("
.db $62,$01,5,"sign{"
.db $06,$00,5,Lconvert,"Char"
.db $08,$04,4,Lconvert,"Hex"
.db $02,$04,5,"Data("
.db $4E,$01,7,"Bitmap("
.db $02,$00,4,Lconvert,"Tok"
.db $80,$04,7,"#Axiom("
.db $04,$04,5,"Rect("
.db $06,$04,6,"RectI("
.db $58,$02,3,LrecurV,"ar"
.db $5A,$02,4,"app",LrecurV
.db $5C,$02,3,"grp"
.db $F6,$01,4,"port"
.db $52,$01,5,"Text "
.db $D8,$01,8,"Pt-Mask("
.db $DA,$01,7,"pt-Get("
.db $D0,$01,3,"Get"
.db $14,$04,5,"rotC("
.db $16,$04,6,"rotCC("
.db $18,$04,6,"flipV("
.db $1A,$04,6,"flipH("
.db $C8,$03,7,"inData("
.db $B8,$01,5,"input"
.db $74,$01,6,"float{"
.db $72,$01,4,"nib{"
.db $F6,$03,9,"#Realloc("
.db $68,$01,6,"#Icon("
.db $80,$01,2,Llambda,"("
.db $38,$03,5,"Load("
.db $3A,$03,5,"Next("
.db $14,$03,7,"Render("
.db $3C,$03,6,"DrawL("
.db $3E,$03,6,"DrawR("
.db $16,$03,6,"DrawS("
.db $82,$03,6,"Print("
.db $44,$03,3,"Up("
.db $46,$03,5,"Down("
.db $5C,$03,5,"Left("
.db $40,$03,6,"Right("
.db $42,$03,4,"New("
.db $5E,$03,7,"Delete("
.db 0
StrPROGRAM:
.db "PROGRAM"
StrAXESRC:
.db "AXE SRC"
#if (StrPROGRAM>>8) != (StrAXESRC>>8)
.error "StrPROGRAM and StrAXESRC must have the same MSB"
#endif
.nolist
#include "ti83plus.inc"
.list
#define cxPrevApp cxPrev+cxCurApp-cxMain
#define p_GetArc $55E7
#define p_ReadArcApp $5658
#define p_CopyArc $568D
#define TokenHook_Temp appRawKeyHandle
#define AxiomTokens statVars
#define AxiomTokens_End curGStyle
.org $71E0
TokenHook:
.db $83
ld a,(cxCurApp)
cp kPrgmEd
ret nz
ld bc,(EditTop)
ld a,(bc)
cp tDecPt
ret nz
inc bc
ld a,(bc)
cp tDecPt
jr z,TokenHook_IsAxe
sub tA
cp tTheta-tA+1
ret nc
TokenHook_IsAxe:
push hl
ld hl,cxPrevApp
ld a,kPrgmEd
cp (hl)
jr z,TokenHook_SkipAxiomSearch
TokenHook_AxiomSearch:
ld (hl),a
push de
ld hl,AxiomTokens
ld (iy+statFlags),h
B_CALL(_BufClr)
ld hl,AxiomTokens-AxiomTokens_End
ld (TokenHook_Temp),hl
B_CALL(_IsAtTop)
push de
push hl
B_CALL(_BufToBtm)
B_CALL(_IsAtTop)
sbc hl,de
ld b,h
ld c,l
ex de,hl
call TokenHook_AxiomSearch_Loop
pop hl
ld (editTop),hl
B_CALL(_BufToTop)
pop hl
ld (editTop),hl
pop de
TokenHook_SkipAxiomSearch:
ld hl,AxeTokens
ld b,0
jr TokenHook_CompareLoop_Start
TokenHook_CompareLoop:
cp e
inc hl
jr z,TokenHook_LowByteMatch
TokenHook_NoMatch:
inc hl
ld c,(hl)
inc c
add hl,bc
TokenHook_CompareLoop_Start:
ld a,(hl)
or a
jr nz,TokenHook_CompareLoop
TokenHook_DoneNoMatch:
add hl,hl
ld hl,AxiomTokens
jr nc,TokenHook_CompareLoop_Start
pop hl
ret
TokenHook_LowByteMatch:
ld a,(hl)
cp d
jr nz,TokenHook_NoMatch
TokenHook_Match:
ld de,localTokStr
push de
ld c,17
ldir
pop hl
pop bc
ret
TokenHook_AxiomSearch_CheckHeader:
call ReadArc
inc de
add a,c
ld bc,$C0DE
sbc hl,bc
ld c,a
ret z
pop bc
TokenHook_AxiomSearch_Loop__:
pop bc
TokenHook_AxiomSearch_Loop_:
pop hl
TokenHook_AxiomSearch_Loop:
ld a,tAsmComp
cpir
ret po
push hl
dec hl
dec hl
ld a,(hl)
cp t2ByteTok
jr nz,TokenHook_AxiomSearch_Loop_
TokenHook_AxiomSearch_Backtrack:
dec hl
ld a,(hl)
cp tSpace
jr z,TokenHook_AxiomSearch_Backtrack
sub tColon
cp tEnter-tColon+1
jr nc,TokenHook_AxiomSearch_Loop_
TokenHook_AxiomSearch_FindAxiom:
pop hl
push hl
push bc
dec hl
rst 20h
ld hl,OP1
ld (hl),AppVarObj
ld a,tRParen
ld bc,10
cpir
dec hl
ld (hl),b
ld l,OP1&$FF
call p_GetArc+1
jr c,TokenHook_AxiomSearch_Loop__
TokenHook_AxiomSearch_FoundAxiom:
ex de,hl
ld c,b
call TokenHook_AxiomSearch_CheckHeader
ld b,32+1
TokenHook_AxiomSearch_ScanAxiom:
call ReadArc
inc de
ld a,h
or l
jr z,TokenHook_AxiomSearch_EndOfAxiom
add hl,de
ld de,5
add hl,de
ex de,hl
djnz TokenHook_AxiomSearch_ScanAxiom
TokenHook_AxiomSearch_EndOfAxiom:
call TokenHook_AxiomSearch_CheckHeader
call ReadArc
inc de
ld a,c
ld b,h
ld c,l
ld hl,(TokenHook_Temp)
add hl,bc
jr c,TokenHook_AxiomSearch_Loop__
ld (TokenHook_Temp),hl
sbc hl,bc
push bc
ld bc,curGStyle
add hl,bc
pop bc
ex de,hl
call p_CopyArc+5
jr TokenHook_AxiomSearch_Loop__
ReadArc:
ex de,hl
xor a
cp c
jr z,ReadArc_RAM
push bc
push hl
call p_ReadArcApp+11
pop de
inc de
pop bc
ret
ReadArc_RAM:
ld e,(hl)
inc hl
ld d,(hl)
ex de,hl
ret
AxeTokens:
.db $F4,$03,5,"Copy("
.db $FE,$03,5,"Exch("
.db $0E,$04,5,"Freq("
.db $66,$01,5,"Buff("
.db $62,$01,5,"sign{"
.db $06,$00,5,Lconvert,"Char"
.db $08,$04,4,Lconvert,"Hex"
.db $02,$04,5,"Data("
.db $4E,$01,7,"Bitmap("
.db $02,$00,4,Lconvert,"Tok"
.db $80,$04,7,"#Axiom("
.db $04,$04,5,"Rect("
.db $06,$04,6,"RectI("
.db $58,$02,3,LrecurV,"ar"
.db $5A,$02,4,"app",LrecurV
.db $5C,$02,3,"grp"
.db $F6,$01,4,"port"
.db $52,$01,5,"Text "
.db $D8,$01,8,"Pt-Mask("
.db $DA,$01,7,"pt-Get("
.db $D0,$01,3,"Get"
.db $14,$04,5,"rotC("
.db $16,$04,6,"rotCC("
.db $18,$04,6,"flipV("
.db $1A,$04,6,"flipH("
.db $C8,$03,7,"inData("
.db $B8,$01,5,"input"
.db $74,$01,6,"float{"
.db $72,$01,4,"nib{"
.db $F6,$03,9,"#Realloc("
.db $68,$01,6,"#Icon("
.db $80,$01,2,Llambda,"("
.db $38,$03,5,"Load("
.db $3A,$03,5,"Next("
.db $14,$03,7,"Render("
.db $3C,$03,6,"DrawL("
.db $3E,$03,6,"DrawR("
.db $16,$03,6,"DrawS("
.db $82,$03,6,"Print("
.db $44,$03,3,"Up("
.db $46,$03,5,"Down("
.db $5C,$03,5,"Left("
.db $40,$03,6,"Right("
.db $42,$03,4,"New("
.db $5E,$03,7,"Delete("
.db 0
.nolist
#include "ti83plus.inc"
.list
#define cxPrevApp cxPrev+cxCurApp-cxMain
#define p_GetArc $55E7
#define p_ReadArcApp $5658
#define p_CopyArc $568D
#define TokenHook_Temp appRawKeyHandle
#define AxiomTokens statVars
#define AxiomTokens_End curGStyle
.org $71E0
TokenHook:
.db $83
ld a,(cxCurApp)
cp kPrgmEd
ret nz
ld bc,(EditTop)
ld a,(bc)
cp tDecPt
ret nz
inc bc
ld a,(bc)
cp tDecPt
jr z,TokenHook_IsAxe
sub tA
cp tTheta-tA+1
ret nc
TokenHook_IsAxe:
push hl
ld hl,cxPrevApp
ld a,kPrgmEd
cp (hl)
jr z,TokenHook_SkipAxiomSearch
TokenHook_AxiomSearch:
ld (hl),a
push de
B_CALL(_IsAtTop)
push de
push hl
B_CALL(_BufToBtm)
B_CALL(_IsAtTop)
sbc hl,de
ld b,h
ld c,l
ex de,hl
ld de,AxiomTokens
call TokenHook_AxiomSearch_Start
pop hl
ld (editTop),hl
B_CALL(_BufToTop)
pop hl
ld (editTop),hl
pop de
TokenHook_SkipAxiomSearch:
inc e
ld hl,AxeTokens
ld b,0
jr TokenHook_CompareLoop_Start
TokenHook_CompareLoop:
cp e
inc hl
jr z,TokenHook_LowByteMatch
TokenHook_NoMatch:
inc hl
ld c,(hl)
inc c
add hl,bc
TokenHook_CompareLoop_Start:
ld a,(hl)
inc a
jr nz,TokenHook_CompareLoop
TokenHook_DoneNoMatch:
add hl,hl
ld hl,AxiomTokens
jr nc,TokenHook_CompareLoop_Start
pop hl
ret
TokenHook_LowByteMatch:
ld a,(hl)
cp d
jr nz,TokenHook_NoMatch
TokenHook_Match:
ld de,localTokStr
push de
ld c,17
ldir
pop hl
pop bc
ret
TokenHook_AxiomSearch_CheckHeader:
call ReadArc
inc de
add a,c
ld bc,$C0DE
sbc hl,bc
ld c,a
ret z
TokenHook_AxiomSearch_Loop___:
pop bc
TokenHook_AxiomSearch_Loop__:
pop bc
TokenHook_AxiomSearch_Loop_:
pop hl
TokenHook_AxiomSearch_Loop:
ld a,tAsmComp
cpir
ret po
push hl
dec hl
dec hl
ld a,(hl)
cp t2ByteTok
jr nz,TokenHook_AxiomSearch_Loop_
TokenHook_AxiomSearch_Backtrack:
dec hl
ld a,(hl)
cp tSpace
jr z,TokenHook_AxiomSearch_Backtrack
sub tColon
cp tEnter-tColon+1
jr nc,TokenHook_AxiomSearch_Loop_
TokenHook_AxiomSearch_FindAxiom:
pop hl
push hl
push bc
dec hl
rst 20h
ld hl,OP1
ld (hl),AppVarObj
ld a,tRParen
ld bc,10
cpir
dec hl
ld (hl),b
ld l,OP1&$FF
call p_GetArc+1
jr c,TokenHook_AxiomSearch_Loop__
TokenHook_AxiomSearch_FoundAxiom:
ex de,hl
ld c,b
call TokenHook_AxiomSearch_CheckHeader
ld b,32+1
TokenHook_AxiomSearch_ScanAxiom:
call ReadArc
inc de
ld a,h
or l
jr z,TokenHook_AxiomSearch_EndOfAxiom
add hl,de
ld de,5
add hl,de
ex de,hl
djnz TokenHook_AxiomSearch_ScanAxiom
TokenHook_AxiomSearch_EndOfAxiom:
call TokenHook_AxiomSearch_CheckHeader
call ReadArc
inc de
ld a,c
push hl
ld bc,(TokenHook_Temp)
add hl,bc
ld bc,-AxiomTokens_End
add hl,bc
jr c,TokenHook_AxiomSearch_Loop___
ld hl,(TokenHook_Temp)
ex de,hl
pop bc
call p_CopyArc+5
res statsValid,(iy+statFlags)
pop bc
pop hl
TokenHook_AxiomSearch_Start:
ld (TokenHook_Temp),de
ld a,$FF
ld (de),a
jr TokenHook_AxiomSearch_Loop
ReadArc:
ex de,hl
xor a
cp c
jr z,ReadArc_RAM
push bc
push hl
call p_ReadArcApp+11
pop de
inc de
pop bc
ret
ReadArc_RAM:
ld e,(hl)
inc hl
ld d,(hl)
ex de,hl
ret
AxeTokens:
.db $F4,$03,5,"Copy("
.db $FE,$03,5,"Exch("
.db $0E,$04,5,"Freq("
.db $66,$01,5,"Buff("
.db $62,$01,5,"sign{"
.db $06,$00,5,Lconvert,"Char"
.db $08,$04,4,Lconvert,"Hex"
.db $02,$04,5,"Data("
.db $4E,$01,7,"Bitmap("
.db $02,$00,4,Lconvert,"Tok"
.db $80,$04,7,"#Axiom("
.db $04,$04,5,"Rect("
.db $06,$04,6,"RectI("
.db $58,$02,3,"var"
.db $5A,$02,4,"appv"
.db $5C,$02,3,"grp"
.db $F6,$01,4,"port"
.db $52,$01,5,"Text "
.db $D8,$01,8,"Pt-Mask("
.db $DA,$01,7,"pt-Get("
.db $D0,$01,3,"Get"
.db $14,$04,5,"rotC("
.db $16,$04,6,"rotCC("
.db $18,$04,6,"flipV("
.db $1A,$04,6,"flipH("
.db $C8,$03,7,"inData("
.db $B8,$01,5,"input"
.db $74,$01,6,"float{"
.db $72,$01,4,"nib{"
.db $F6,$03,9,"#Realloc("
.db $68,$01,6,"#Icon("
.db $80,$01,2,Llambda,"("
.db $38,$03,5,"Load("
.db $3A,$03,5,"Next("
.db $14,$03,7,"Render("
.db $3C,$03,6,"DrawL("
.db $3E,$03,6,"DrawR("
.db $16,$03,6,"DrawS("
.db $82,$03,6,"Print("
.db $44,$03,3,"Up("
.db $46,$03,5,"Down("
.db $5C,$03,5,"Left("
.db $40,$03,6,"Right("
.db $42,$03,4,"New("
.db $5E,$03,7,"Delete("
.db $FF
Some things I'm particularly curious about:
- The token numbers are difficult for developers to type in manually, any ideas of how I could generate a list of equates?
So the main thing I wanted to talk about in the new release is the new "Axe Fusion" compile option. I was previously calling this "Axe Framework" but fusion is more literal to what is going on, implies that it requires Axe, and sounds cooler.This seems interesting, does it means those programs would be dependent on Axe Parser presence on the calc? If so, then I guess a good idea would be for the programmer to publish both versions of his games, so those who have many Axe games can simply keep Axe on their calc and save a lot of space, kinda like how small some Doors CS programs are.
To reiterate, what this option does is not add ANY built-in Axe routine to your program. These include things like All DispGraphs, all Sprite commands, all drawing, advanced math, etc. Instead there is a tiny routine routine added to the start of the program that finds the Axe app and steals the routines from there (like a shell). The header in Fusion files is literally identical to the Ion header and it should still work in all major shells. In the end, this reduces code size a lot, usually over 10% sometimes higher than 20%.
Keep in mind that this is a beta feature, meaning it is very unstable right now. First of all, I would not recommend publishing Axe Fusion programs on sites targeted to end users because those programs may not work with future versions of Axe. Second of all, I'm not sure if it is working with Axioms right now, I didn't have time to check.
So basically, I added this feature prematurely so that you can all test it out and tell me what you think. How much is it reducing your code sizes? :)
It's definitely possible, but also likely to be less efficient, since Axe's routines are designed around the various quirks of the 84+. It would still run faster on the nspire, but probably not as fast as C, def. not as fast as assembly.Ok for "hardware things" but for example, I guess (I said "I guess") that Axe's mathematic operations won't need to be changed to run on the Nspire.
Least efficient, but most compatible way would be to have an 83+ emulator :PLol, yeah, but the color ? D:
axv_A =$9CFB
axv_B =$9CFD
axv_C =$9CFF
axv_D =$9D01
axv_E =$9D03
axv_F =$9D05
axv_G =$9D07
axv_H =$9D09
axv_I =$9D0B
axv_J =$9D0D
axv_K =$9D0F
axv_L =$9D11
axv_M =$9D13
axv_N =$9D15
axv_O =$9D17
axv_P =$9D19
axv_Q =$9D1B
axv_R =$9D1D
axv_S =$9D1F
axv_T =$9D21
axv_U =$9D23
axv_V =$9D25
axv_W =$9D27
axv_X =$9D29
axv_Y =$9D2B
axv_Z =$9D2D
axv_Theta =$9D2F
axv_R1 =$9D31
axv_R2 =$9D33
axv_R3 =$9D35
axv_R4 =$9D37
axv_R5 =$9D39
axv_R6 =$9D3B
axv_Y1 =$9D3D
axv_Y1Page =$9D3F
axv_Y2 =$9D40
axv_Y2Page =$9D42
axv_Y3 =$9D43
axv_Y3Page =$9D45
axv_Y4 =$9D46
axv_Y4Page =$9D48
axv_Y5 =$9D49
axv_Y5Page =$9D4B
axv_Y6 =$9D4C
axv_Y6Page =$9D4E
axv_Y7 =$9D4F
axv_Y7Page =$9D51
axv_Y8 =$9D52
axv_Y8Page =$9D54
axv_Y9 =$9D55
axv_Y9Page =$9D57
axv_Y0 =$9D58
axv_Y0Page =$9D5A
axv_SpriteBuff =$9D5B
axv_RandSeed =$9D63
axv_Y1t =$84EB
axv_Y2t =$84ED
axv_X1t =$84EF
axv_X2t =$84F1
axv_Y3t =$84F3
axv_Y4t =$84F5
axv_X3t =$84F7
axv_X4t =$84F9
axv_Y5t =$84FB
axv_Y6t =$84FD
axv_X5t =$84FF
axv_X6t =$8501
they aren'tOh, ok!
axv_Y4Page =$9D48
axv_Y5Page =$9D4B
Axe 1.2.0 isn't working on WabbitEmu or cemetech's jTIfied. Is this a bug in Axe or a bug with the emulators? Axe works on my calc.
Also, when's the next version of Axe gonna be out? It keeps getting better and better!
→XLine(,Y,X+3,Y+3)
Also what would happen if you did something like this?You'd get a syntax error.→XLine(,Y,X+3,Y+3)
Does this mean we might be able to have two-page Axe apps in the future?The error message for a too-large app is "ERR:MEMORY". It really should be something more descriptive, like say, "ERR:TOO BIG FOR ONE PAGE" or something.
And that is too big for one error message. Anyways this isn't really a bug, and you still knew what it meant so it seems like it's descriptive enough. Maybe you won't even see that error eventually. :P
Does this mean we might be able to have two-page Axe apps in the future?The error message for a too-large app is "ERR:MEMORY". It really should be something more descriptive, like say, "ERR:TOO BIG FOR ONE PAGE" or something.
And that is too big for one error message. Anyways this isn't really a bug, and you still knew what it meant so it seems like it's descriptive enough. Maybe you won't even see that error eventually. :P
Alrighty, then!Does this mean we might be able to have two-page Axe apps in the future?The error message for a too-large app is "ERR:MEMORY". It really should be something more descriptive, like say, "ERR:TOO BIG FOR ONE PAGE" or something.
And that is too big for one error message. Anyways this isn't really a bug, and you still knew what it meant so it seems like it's descriptive enough. Maybe you won't even see that error eventually. :P
Eventually I hope so, yes. But as I've mentioned in previous posts, it's a logistical nightmare so don't expect it any time soon.
Let's party!Does this mean we might be able to have two-page Axe apps in the future?The error message for a too-large app is "ERR:MEMORY". It really should be something more descriptive, like say, "ERR:TOO BIG FOR ONE PAGE" or something.
And that is too big for one error message. Anyways this isn't really a bug, and you still knew what it meant so it seems like it's descriptive enough. Maybe you won't even see that error eventually. :P
Eventually I hope so, yes. But as I've mentioned in previous posts, it's a logistical nightmare so don't expect it any time soon.
"Easy"->Str11
"Medium"->Str12
"Hard"->Str13
So that when i want to irritate through several strings separated by a '0' using stdDev(, I reference Str11."Easy*Medium*Hard"->Str1
Where * is some kind of special character that is replaced by the string termination character."Easy"->Str11
"Medium"[00]
"Hard"[00]
I'm of the opinion that your archive was just a bit messed up and that it wasn't Axe's fault. :P You should try Axe 1.2.2 again, and if it still doesn't work and you send over Calcsys as well, I can try to help debug it further.
Axe 1.2.2 | Axe 1.3.0 |
(http://i.imgur.com/0vKUjh3.gif) | (http://i.imgur.com/QlyqDyY.gif) |
In the process of completely recoding the menus, I added an option that I've heard asked for a couple of times: the ability to disable the token hook. But in doing so, I needed to add a second options page, which is currently barren. Give me suggestions for two new options!
Lol, I remember complaining about those ones :P
- Comments are now allowed and parsed correctly in a few places that they should have been before.
- Fixed a bug that resulted in the "APP TOO BIG" error being thrown when compiled code hit 16KB, regardless of target shell.
hello, i tried axe 1.3.0 and the speed is amazing, no bugs, great job !
The only thing is that the auto backup doesn't work (it can be on or off, it doesn't change anything).
I saw that you've done an update on July 1 so I used it to compile my tunnel game but I have something very weird: the programs compiled with axe 1.2.2 or axe 1.3.0 (first version) is 6877 bytes tall but the program compiled with axe 1.3.0 (2nd version) is only 6670 bytes, the source code is the same on each time with 5409 bytes.
And the result is bugged but it doesn't crash.
I don't know at all what happened but I hope you can fix it.
It is possible to have the source of Axe 1.2.2 because I don't find on this topic. (https://www.omnimaga.org/the-axe-parser-project/latest-updates-%28***do-not-post-here!***%29/)
Sorry for this triple post but I download the Axe 1.3.0 and it bugs :banghead:
So, I search an other version on the Google and I find this version (https://dl.dropboxusercontent.com/u/34812306/Axe.8xk).
I search source because I would ported to Ti 83 Premium CEPorting to the CE would require a major overhaul. It would take less time to just rewrite it. Especially since we don't have the app signing keys for the CE and we'd have to rewrite it as a group of programs.
I thought of making it under the shape of a asm programDoing so would basically require a complete rewrite of it. Not to mention most of the routines would have to be completely rewritten since the CE is a eZ80 and not a z80.
I know it but I would like ported to Ti 83 Premieum CE to rewritten the routine ;)It wouldn't be rewriting a routine. It would be rewriting the entire thing from scratch. There is little to no point to having the source.
Thank you for this response but I don't know rewrite completely Axe Parser for Ti 83 Premium CE :-\ ;)I know it but I would like ported to Ti 83 Premieum CE to rewritten the routine ;)It wouldn't be rewriting a routine. It would be rewriting the entire thing from scratch. There is little to no point to having the source.
How is Axe 1.3 coming along?I don't understand your post. Sorry :-\
Hey Runner, I know you are busy but how much time do you think it will take to finish Axe 1.3.0?
Therefore I think it's a shame that, with the source code closed, no one can ever either learn from this project (it must be a treasure trove of z80 writing) or pick it up again. The chance that either Quigibo or Runer112 are reading this is slim, however, I would want to call upon them to provide a final release with the source code, as a last hurrah for Axe.
@aeTIos
Runer112 gave me the source for either Axe 1.3.0 or 1.2.2 (I can't remember which and taking a quick peek at it I can't tell) a long time ago. If there is some very compelling evidence that he would be OK with me publishing it, I will.
Having looked at it more carefully, it is 1.2.2.