Omnimaga
Calculator Community => TI Calculators => Axe => Topic started by: Freyaday on February 24, 2011, 10:18:53 am
-
I'm doing something wrong here, because Axe keeps telling me that LM does not exist. And yes, I have made sure that LM does exist and is in RAM.
This is not the whole code. Just the relevant parts.
.READFAST
"[sub]L[sub]M"->Str0
GetCalc(Str0)->P
{P+5}[sup]rr[/sup]->D
-
Does Axe support the L token yet? If not you should mention that as a feature request.
Also, BBCode tags don't work in [code] blocks.
And welcome to Omnimaga (http://www.omnimaga.org/index.php?board=10.0), Freyaday!
-
Now you tell me (About the sub thing). I think Axe does support the L token now, or at least according to the documentation I have. And thank you.
-
Oh noes... I just have to say that there is a professor Dr. Frey at the university I go to... and tomorrow is Freyday... Other than that, have you tried L1? I think the reason for the problem is that the first token is not 5Dh in hex. I know in some of my programs that work with lists I need to have code that changes the first byte to 5Dh for it to be recognised.
(L1 and other list tokens have the 5Dh while named lists do not)
EDIT: Also, does this help:
.READFAST
"LM"->Str0
GetCalc(Str0)->P
{P+5}rr->D
EDIT in response to the edit in response to the former edit: Okay :D If you need to, you can quote this to view the BBCode I used (that is what it is called, right?).
-
If it's a problem with the first token, it's not that one. I looked at the the TI 83+ Developer's Guide and according to it, there is no difference between the way Named lists and L1-6 are stored. In the calc's eyes, L1-6 are user lists with the name of 1-6.
Edit in response to edit:
That's exactly what I'm doing now.
-
If it's a problem with the first token, it's not that one. I looked at the the TI 83+ Developer's Guide and according to it, there is no difference between the way Named lists and L1-6 are stored. In the calc's eyes, L1-6 are user lists with the name of 1-6.
Yeah, but the L token (in Axe) apparently doesn't include ListObj. That would be a suggestion for Quigibo.
-
Yeah, that is the problem, though :D The calc stores it the same way, so even though in the VAT the named list has a 5Dh as the start of the name, it doesn't automatically convert the L to 5Dh (which can be annoying). Instead of taking LM and storing the name as 015D4D00 it is stored as 01EB4D00 and yet it is stored with the former name.
-
So what do I do?
Edit:
The Documentation.pdf I have explicitly states that "LABC" is the Name String for the List ABC.
-
*cough* Magic :P *cough* Um, if you have tried L1 or some other token and that doesn't work, you cannot really do much at the moment. if it does work but you don't want to use a predefined list you can always go with a hacked token >_>
-
So where can I get this magical hatchet that hacks my tokens for me?
-
Well you could put the hex for ListObj in front of the string yourself.
-
There are a few ways, but here are two programs on TICalc that work:
http://www.ticalc.org/archives/files/fileinfo/391/39138.html
http://www.ticalc.org/archives/files/fileinfo/425/42505.html
Also, if you have something like Celtic 3 or BatLib there are commands that will return the token if you input hex (like det(17,"5D4D will return the list name that you need).
EDIT: Yeah, Deep Thought's way is probably better/easier/more practical :D
-
My brain's a little scrambled from all the documentation non-following, so what would that look like in code, exactly?
-
Try this:
[01]→GDB0
"ʟNAME"
[00]
GetCalc(GDB0)→P
-
Nope. Didn't work.:(
-
This seems to work for me:
[015D]"M"→Str1
GetCalc(Str1)→P
-
I thought ʟ got translated as $5D... Not sure anymore because I deleted Calcsys.
-
Not on the calc... that little L thingy is EB, but CheckFindSym does not read that as 5Dh, unfortunately, so you have to convert it in case like these. Whenever I copy a user string to OP1 as a name of a var, I have code that checks that byte and converts it if it is EB to 5D.
-
[015D]"M"→Str1
GetCalc(Str1)→P
It works for me, too! Thank-you muchly!
Edit:
Now if only I could figure out what, exactly, P is pointing to....
-
Not on the calc... that little L thingy is EB, but CheckFindSym does not read that as 5Dh, unfortunately, so you have to convert it in case like these. Whenever I copy a user string to OP1 as a name of a var, I have code that checks that byte and converts it if it is EB to 5D.
Ah, I thought Axe would read it as $5D like how it reads prgm as $05/$06.
-
Hehe, that is CheckFindSym doing the work there. bcall(_CheckFindSym) lets you interchange programs/protected, lists/complex lists, equ/new equ, and real/complex. So if you search for the complex list "L1" you can use either 01 or 0D as the type byte :D
-
Didn't know that. I used to set it up to check for both cases... This'll save some bytes :-\
-
Welcome on the forums Freyaday!
-
Didn't know that. I used to set it up to check for both cases... This'll save some bytes :-\
It is a very useful trick that I love taking advantage of ^-^
As another trick, rFindSym will not find programs or other named vars, but it doesn't need the type byte :D
Out of randomness, I created a routine that is like rFindSym except the name is in the register BC instead of in OP1 >_> It returns the same results, too :P
-
Didn't know that. I used to set it up to check for both cases... This'll save some bytes :-\
It is a very useful trick that I love taking advantage of ^-^
As another trick, rFindSym will not find programs or other named vars, but it doesn't need the type byte :D
Yep, it was one of the tricks 28 Days mentioned.
Out of randomness, I created a routine that is like rFindSym except the name is in the register BC instead of in OP1 >_> It returns the same results, too :P
I wonder why TI didn't do that. It wouldn't support named lists, though, right?
-
Edit:
Now if only I could figure out what, exactly, P is pointing to....
P points to the first element in the list. If the list is a real number list, you can find each 9-byte floating point element at N*9+P, where N is the element's index in the list (0-based). If it's a complex list, the elements will be at N*18+P. The 2 bytes immediately before the location P points to contain a value specifying how many values are in the list, which can be read with {P-2}r.
-
Whoops, missed that edit. And just for clarification on Runer112's post, use float{N*9+P} to get the value of an element :)
-
Out of randomness, I created a routine that is like rFindSym except the name is in the register BC instead of in OP1 >_> It returns the same results, too :P
I wonder why TI didn't do that. It wouldn't support named lists, though, right?
Right, but neither does rFindSym, unfortunately :(
-
Hmm... this is a bug then. The L token is supposed to translate to [015D]... I will fix this next version.
-
But I need to read the nibbles and I can't figure out which ones to read. That, and I somehow created an infinite for loop.
-
But I need to read the nibbles and I can't figure out which ones to read. That, and I somehow created an infinite for loop.
What nibbles do you need to read?
-
The way I understand it, each list element is like so: 00 82 VX XY Y0 00 00 00 00 where V is the instruction number and XX YY are 2 digit coordinates. But Axe's been telling me otherwise.
-
If I understand what you're saying correctly, then you appear to have a slight misconception. First of all, let's go over number systems. Hex is basically a compact way of representing binary. Each hex digit is equivalent to 4 bits and so on. That means that each 8 bit long byte is composed of two hex digits, which you clearly understand. Now, a nibble is a four bits or half of a byte. When things are stored on the calculator, they're stored in bytes. This means that you have a series of hex digits like 01 23 45 67 89 AB CD EF in continuous addresses. When you extract a nibble from RAM, you're actually extracting an entire byte and simply masking it off. Because of how Axe addresses nibbles, to extract the second nibble of byte 3, you'd have to double the pointer to address 3 and add 1 (the first nibble would simply omit the addition). This addressing is probably where your problem is.
Also, just so you know, nibbles are slower and more difficult to work with. Their only advantage is that they take up less space.
-
List elements are floats not nibble. You read them with float{<pointer>} to get their numeric value if they are integers between 0 and 65536. Otherwise, you would have to parse them some other way.
-
Wait, I thought he was talking about Axe "lists", not the OS list arrays.
-
Nooo.... I've been talkin' about the list created by my BASIC program Macro, LM...what have you been talking about?
-
Er, butterflies. You *are* using butterflies to program, right?
-
I've been using farfalle, Italian butterflies. You probably know them as bowtie pasta. Should I have been using fiori instead?
-
I'm lost about what is the discussion about now. O.O
To come back on-topic, did you have any luck Freyday with your program?
-
The way I understand it, each list element is like so: 00 82 VX XY Y0 00 00 00 00 where V is the instruction number and XX YY are 2 digit coordinates. But Axe's been telling me otherwise.
Nope, each list element is a floating point number, as I said. The first byte tells you if it's positive or negative and whether it's real or complex; the second byte is the exponentiation; and the rest of the bytes are the number itself, truncated to 14 digits where each digit takes up a nibble in BCD (binary-coded decimal).
From what you're asking it seems like you're trying to make your own routine to read the numbers, but Axe takes care of that with the float{ command.
-
Well, I got it to recognize that the list M exists, but because the Axe only allows integers and the list contains nonintegers, I can't use the float{ command. That, and the last time I tried running the program, it produced absolute garbage (not the album, unfortunately; that would have been sweet) and was still going half an hour later.
-
Wait, so what exactly are you trying to do? I have worked with FP numbers in assembly for various things.
-
Well, I got it to recognize that the list M exists, but because the Axe only allows integers and the list contains nonintegers, I can't use the float{ command. That, and the last time I tried running the program, it produced absolute garbage (not the album, unfortunately; that would have been sweet) and was still going half an hour later.
Why can't you use float{?
-
I can't use float{ because the numbers have fractional parts and multiplying the list to remove the fparts would put the list elements over 2^16 (to the power, not modulo)
-
I can't use float{ because the numbers have fractional parts and multiplying the list to remove the fparts would put the list elements over 2^16 (to the power, not modulo)
float{ gets only the significand (non-fractional part), no matter what power it's taken to (as long as it fits).
If you need the mantissa, you'll have to write your own routine :-\ Remember how FP numbers are stored (http://ourl.ca/9343/178675).
-
Is there a particular reason you need to use the fractional part? In BASIC that can be useful, but in assembly it usually isn't needed or can be worked around, I believe... Unless you are making a math program... :D
-
I'm using the decimal point to make the math for creating and using the elements compact. But if I get rid of the decimal point by multiplying the list by 100, that'll put commands 7&8 out of commission & half of command 6.
-
Hmmm something doesnt sound right here. Lists can only hold 14 digits, no matter where the decimal place is, multiplying by 100 should not make you lose any data at all.
-
But Axe doesn't allow anything >2^16-1.
-
So what is the fractional part being used for?
-
Hmmm no i see the problem now. The problem is unfortunately that Axe can only hold a max of 4.5 digits, and he is using all 14. In that case, you would have to write your own routine to extract each digit individually, since it sounds like you aren't looking for the whole number anyway?
-
Well, I'm not using all the digits, just 5. I'm using the fpart for the y coordinates
-
Ah, okay! Is this a carry over technique from TI-BASIC?
-
Yes. The program that generates the list is writ in Basic.
-
Oh, I see.
The problem is that when you store as a floating-point number, it's always stored in scientific notation (such as 3.2x10^1 as opposed to 32). So when you read from the number, you can't just read the first two digits and expect them to be the two digits before the decimal point. Sure, it would work for 3.2*10^1 (since the 3 and 2 are both in front of the decimal), but it fails for numbers below 10, since there's only one digit before the decimal (reading the first two digits of 9.0*10^0 gives you 90, not 9.0).
The exponent in this case is stored in the second byte of the floating point number ($82 in your example). Take that value and subtract $80, and that'll be the number of digits before the decimal point. So 3.2*10^1 would be stored as 00 82 32 00 00 00 00 00 00, while 9.0*10^0 would be stored as 00 81 90 00 00 00 00 00 00.
Hope this helps.
-
Ah, okay. Well if you are working in Axe it is much easier to simply make a list that uses 2 separate elements. However, it is even better if you can find a way to store the coordinates as bytes. You will need an assembly program (like an Axe program) to store the data as bytes, but it is easier and faster for assembly programs to work with bytes instead of floating point numbers.
EDIT: Ninja'd (ish)
-
*Sigh* So how do I create a persisting Appvar?
-
Sorree... I may be able to work out a hex code... would that be useful?
-
Well, I need the ability to dymamically (that is such a cool word) lengthen and store to the Appvar whilst simultaneously making sure I don't scribble over anything.
-
*Sigh* So how do I create a persisting Appvar?
GetCalc("appvNAME",2) would create an appvar with two bytes.
You can't really dynamically change its size, but you can make a new appvar with a larger size and copy the bytes over.
-
I do not know how to do that in Axe... but for the number converter, how large are the numbers? I am working on a converter right now...
-
V[1,8] X[0,94] Y[0,62] (interval notation)
I still need the ability not to scribble over anything.
-
Okay, so the best idea I have is to store the number as V/100+X/10000+Y/1000000 and I can come up with a code for ya :D
And how do you want the output?
-
I'll get started on it. Does anyone know how to display the back buffer instead of the...front? buffer?
-
L3→DispGraph
-
Remind me what L3 is in Axe? That is a right arrow, correct? It just shows up as a box on my screen. And will that overwrite the front? buffer?
-
Okay, I had to go do some real life stuff, but I am back... Does anybody know how to return the pointer of a floating point number in HL or some other register (in Axe)? I have a code that right now takes Ans and can convert the number (stored to HL for Axe).
-
Remind me what L3 is in Axe? That is a right arrow, correct? It just shows up as a box on my screen. And will that overwrite the front? buffer?
L3 is the back-buffer, and yes, that's a store arrow. L3→DispGraph is basically the same as just DispGraph except that it uses the graph buffer, so it won't affect any data at all. (In fact, L6→DispGraph is exactly the same as DispGraph.)
-
Okay, so apparently this should work (where A is the list element):
A*9+GetCalc(<<ListName>>)
Asm(2323E5
0 ;This tells which 2 digit pair to read. V=0, X=1, Y=2
Asm(D1194EAF060407CB013002C60A10F74F7EE60F8126006F
-
What's the Asm for?
-
The Asm( inserts pure hex assembly into the code. The hex happens to be what converts the data :D
-
That's not what I was asking....What is the machine code doing?
-
Oh, the code grabs a pair of numbers out of a floating point number and converts them from decimal to hex and stores it to HL (Ans in Axe). That was why I suggested you store the numbers that way :D
-
Freyaday, here is a solution which doesn't use inline assembly. I also added comments which should hopefully make it a little bit easier to understand.
.., INITIALIZATION ,..
[015D]"M"→Str0L
GetCalc(Str0L)→L
.Example call to get the V value from the Nth list element:
Nsub(V)
.., SUBROUTINES ,..
.Get the V value from the specified list element
Lbl LV
.Calculate offset in list
*9
.Goto byte retrieval function
Goto LB
.Return
.Get the X value from the specified list element
Lbl LX
.Calculate offset in list
*9+1
.Goto byte retrieval function
Goto LB
.Return
.Get the Y value from the specified list element
Lbl LV
.Calculate offset in list
*9+2
.Return
.Get a byte from the list element and convert from BCD to hex
Lbl LB
.Get byte from list
{+L+2}→r₆
.Convert high nibble from base 10 to base 16
*16/256*10
.Add low nibble
+(r₆ and b00001111)
Return
Each list element should contain data such that the V element is multiplied by 10N, the X element is multiplied by 10N-2, and the Y element is multiplied by 10N-4. For instance, you could format data like V*10000+X*100+Y.
-
My current method looks something like this (P is the start of the list)
for(Q,1,{P-2}
nib{Q*9+4->V
10*nib{Q*9+5}+nib{Q*9+6->X
10*nib{Q*9+7}+nib{Q*9+8->Y
...snip...
DispGraph
End
UnDirty GraphScreen machine code
Edit:
I just realized something: I don't need a dynamic AppVar. I just use Axe's GDB0 and keep track of how long it's getting, then create the AppVar at the very end.
*Sigh.*
Gloves.
-
Edit:
I just realized something: I don't need a dynamic AppVar. I just use Axe's GDB0 and keep track of how long it's getting, then create the AppVar at the very end.
*Sigh.*
Gloves.
GDB0 isn't dynamic either. It's just bytes reserved as data in the program itself.
-
But because GDB0 is not an actual OS variable, I can store to the end of it without fear, and then I have Axe create the AppVar for me.
-
Just make sure you allocate sufficient memory for GDB0 at the beginning, since it's even harder to resize than an OS var.
-
Wait...what?
-
GDB0 is not a memory location, its a pointer to a spot that is inside of your Axe program. Whenever you create a string of data like [00000000]->GDB0, all Axe does is add this onto the end of your program. GDB0 is just a number that points to where this data starts. This means that there is only as much memory there as you first set it as, and writing past it without care is likely going to get you a corrupted program or worse.
-
Oohh. That's what all the buisness is about adding something to program memory.
-
So, after adding 6k bytes to program memory with Zeros(6000), how do I find the start of all those zeros? And then, at the end of the program, how do I create an AppVar with the appropriate length in Archive and copy all the used bytes to the AppVar?
Edit:
Anybody got any suggestions for additional drawing commands? I have Pxl-change, Line on/off, Circle on/off, and RectI. I can put in two more.
-
To find the location, do this. Zeros(6000)->GDB1. GDB1 now holds the start location of all the zeros. To create an appvar, you could do something like this:
GetCalc("appvNAME",6000)->P
Copy(GDB1,P,6000
Archive "appvNAME"
Oh and for new ideas? Flood Fill >:D
-
What's flood fill? And do you have any suggestions for another command?
-
Yes its the paint bucket :P And for another idea what about a filled circles?
-
Layers, channels, alpha... J/k, but how about regular polygons? That should be easier than some other stuff :)
-
Filled circles...now that's a good idea! Paint Bucket would only be one command because there's only two colors, and it would thus essentially be a Bucket of Inverse.
Edit:
I have eaten my words. The circles were weird because I forgot the way order of operations works in Axe.
Edit 2:
Does anyone have an idea on how to implement a flood fill? I read the Wikipedia page, but I can't figure out a method of implementation that would work on the calculator.
-
Use L1 for a queue and make it wrap around to the beginning when it runs out of space. (Thanks to Builder for teaching me ;D)
-
I think someone needs to write a flood fill tutorial. I've tried and failed, and I'd like to know how to do it without using too much memory. :)
-
I'll have to find that explanation I gave to Deep Thought and make it more detailed and post it :D
-
I think that was on IRC :-\
-
I took another look at my code, and I realized that I can have up to 255 drawing commands. I'm reserving command #0 for an undo feature. And as for a paint bucket, I'd like to have two: an 8-way flood fill and a 4-way flood fill, and any tips on either would be greatly appreciated.