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.