Omnimaga
Calculator Community => TI Calculators => Axe => Topic started by: Aichi on October 18, 2010, 02:01:14 pm
-
Hey Omnimaga Community,
is it possible to change a type 5 program into a type 6 to lock the program code, just with a Getcalc("prgmLOCKME")→P pointer?
External levels in my actual project will be stored and loaded as program data and it isnt looking nice if you can view the code in the TI Basic IDE of the TI OS.
Regards,
Aichi
-
Well the issue is that even if you lock them, people can still open them in SourceCoder on Cemetech or with Doors CS 7. There's no way to permanently block a program content on the calculator, except maybe from people with zero experience with calcs. I am kinda curious how to we change the program type, though. I think we need to edit the VAT but I'm not sure anymore.
-
It is possible i think, although im not quite sure how to do it... Might i suggest an alternate solution and just have them as appVars?
-
Hey Omnimaga Community,
is it possible to change a type 5 program into a type 6 to lock the program code, just with a Getcalc("prgmLOCKME")→P pointer?
External levels in my actual project will be stored and loaded as program data and it isnt looking nice if you can view the code in the TI Basic IDE of the TI OS.
Regards,
Aichi
Oh, Assembly programs can't be viewed in the native OS IDE. Since Axe compiles to ASM, you don't need to worry about that.
-
Actually they can. You can easily unlock them with SourceCoder or CODEX (the later is on-calc). It just looks like random tokens.
-
Hm, I wasn't aware that you could view ASM in the TI-OS IDE. It's not a problem though because even TI-BASIC games which are entirely viewable aren't tampered with.
-
I will use appvars instead of progs since I found a way to archive appvars. But I am still interested wether there is a way to lock progs without the VAT.
@ DJ
I know there are a lot of ways to unlock the code later. I want to make it unable for people without TI experience to edit the level data. My game will be crashed if there are data which the game cant deal with.
@ Qwerty
Sorry if my question wasnt clear. I searched for a way to lock not my game, but lock a program with level data that was created in the level editor in my game.
-
Ah ok. Hopefully someone with VAT knowledge can answer later.
-
Well, you would need to manually search the vat for your program, then change the type byte, to... I think 13, but whatever it is to lock it. I made a shell that could do this, so if you want to look at some of the code I used to get the vat etc. here:
:.ASHELL
:"000000000"→Str1
:"prgmASHELL"→Str2
:"UnrealShell"→Str3
:[F88C8EB2AAB2A2FEF88C8E92AABAAAFE]→Pic1
:[3844447C6C446C7C]→Pic2
:[44AACEAA0050A88844AAECAA60808060]→Pic3
:DiagnosticOff
:Fix 5
:{E9830}r→θ
:{E982E}r→Z
:{GetCalc(Str2)-2}r→R
:sub(LP) // Sub that loads the locations of all programs in the memory into a list
:0→P→X→Y
:
:
:
:While 1 // This is the main loop i used for selecting programs, no need for you to worry much about this =P
:sub(DP) //Just draws the program names and icons. You might want to look at this one to find where program info is relative to the start =P
:3→W
:sub(IC)
:P→Q
:While P=Q
:X→W:Y→Z
:If getKey(15):Goto FN:End
:
:If getKey(51) // Archive/unarchive toggle
:{Y*2+X+(P*8)+1*2+L2}r→A
:If {A}∙E001F=21:21→{Str1}:Else:5→{Str1}:End
:A-7→A
:For(B,0,{A+1}-1
:{A-B}→{B+1+Str1}
:End
:0→{B+2+Str1}
:If {A+2}:UnarchiveStr1:Else:ArchiveStr1:End
:3→W
:sub(DP)
:End
:
:If getKey(52) // Lock/unlock toggle
:{Y*2+X+(P*8)+1*2+L2}r→A
:If {A}∙E001F=6:5→{A}:Else:6→{A}:End
:3→W
:sub(DP)
:End
:
:If getKey(53) // Appvar/program switch
:{Y*2+X+(P*8)+1*2+L2}r→A
:If {A}∙E001F=21:5→{A}:Else:21→{A}:End
:3→W
:sub(DP)
:End
:
:P-getKey(11)+getKey(10)→P
:P=65535-(G=P)+P→P
:X-getKey(2)+getKey(3)→X
:Y-getKey(4)+getKey(1)→Y
:X=65535*2-(X=2*2)+X→X
:Y=65535*4-(Y=4*4)+Y→Y
:!If X=W*(Y=Z):sub(IC):End
:End
:End
:
:
:
:Lbl LP
:2→B
:Repeat θ≤Z
:If getKey(15):Goto FN:End
:{θ}∙E001F→A
:If A=5+(A=6)+(A=21)
:θ→{L2+B}r
:B+2→B
:End
:θ-6→θ
:θ-{θ}-1→θ
:End
:B-2→{L2}r
:B/2/8+1→G
:Return
:
:
:
:Lbl DP
:0→B→A→C
:ClrDraw
:Repeat B=4+(P*16+C≥{L2}r)
:{P*16+C+L2+2}r→θ
:{θ}∙E001F→H
:Pt-Off(A*40+2,B*16,Pic1)
:Pt-Off(A*40+20,B*16,Pic3)
:If H=21:Pt-Off(A*40+2,B*16,Pic1+8):End
:If {θ-5}:Pt-Off(A*40+20,B*16,Pic3+8):End
:If H=6:Pt-Off(A*40+11,B*16,Pic2):End
:θ-6→θ
:{θ}→H
:0→J
:For(D,0,H-1)
:θ-1→θ
:Text(J+(A*40)+2,B*16+9,{θ}►Frac)
:J+4→J
:If {θ}=105:J-2→J:End
:If {θ}=108+({θ}=115)+({θ}=116):J-1→J:End
:If {θ}=122:J+1→J:End
:End
:A+1→A
:If A=2:0→A:B+1→B:End
:C+2→C
:End
:{E9828}r-{E9824}r+R→E
:89→A:0→B
:For(J,1,5)
:0→F
:Repeat E/10*10=(E-F):F+1→F:End
:Text(A,B,F►Dec
:sub(ST)
:E/10→E
:B+4→B
:End
:80→A:0→B
:Fix 1
:For(J,0,10)
:Text(A,B,{10-J+Str3}►Frac
:sub(LT)
:B+6→B
:End
:Fix 0
:DispGraph
:Return
:
:
:
:Lbl IC
:For(A,0,15)
:Pxl-Change(X*40,Y*16+A)
:Pxl-Change(W*40,Z*16+A)
:End
:For(A,1,39)
:For(B,0,1)
:Pxl-Change(X*40+A,Y*16+8+B)
:Pxl-Change(W*40+A,Z*16+8+B)
:End
:End
:DispGraph
:Return
:
:
:
:Lbl ST
:For(C,0,3)
:For(D,0,5)
:pxl-Test(C+A,D+B)→{D*4+C+L1}
:Pxl-Off(C+A,D+B)
:End
:End
:For(C,0,3)
:For(D,0,5)
:If {D*4+C+L1}:Pxl-On(D+A,3-C+B):End
:End
:End
:Return
:
:
:Lbl LT
:For(C,0,5)
:For(D,0,7)
:pxl-Test(C+A,D+B)→{D*6+C+L1}
:Pxl-Off(C+A,D+B)
:End
:End
:For(C,0,5)
:For(D,0,7)
:If {D*6+C+L1}:Pxl-On(D+A,3-C+B):End
:End
:End
:Return
:
:
:
:Lbl FN
:Fix 4
:ClrDraw
:ClrHome
I can go into detail if you want about how to do this, but... Meh, I personally like looking at code, so I'll leave you with this :P
EDIT: I realized commenting code is useful =P
-
I'd like to apologize, that post sounded kind of elitist now that I reread it. So I'll try to explain everything now. With like, explanations. :P
Ok, so to start, you have the VAT(variable allocation table) right? It starts for programs and appvars at the memory location 0x9830, $9830, 9830h, or E9830 depending on what language you need to reference it in. Since you are using axe though, i will stick with the E9830. So the vat contains lots of entries, one for each program/appvar, each one containing this info for each program: The name, a pointer to where the actual program data is, the variable type, whether its archived (and what page its on if it is), and the version, and the length of the name. It might be useful at this point to mention that he VAT is written backwards. So, to unlock/lock progams, there's only three relevant pieces of information. 1. The program name 2. The name length 3. The type, since A. We need to know whether its an appvar or program, then to lock/unlock it, we only need to change the type. First, lets define what these values can be. The name length is an number between 1 and 8. For the type, we only need the bottom 4 bits, because those are the ones that actually define the type. So we'll want to AND it with E001F, then the two values we care about are 5, for program, and 6, for locked program. The name should simply be whatever you named your program. =P So, we'll say you wanted to be able to use the GetCalc(Str1) for your program, thogh, since we have to find it in the vat anyways to change the type, we could just grab it from there. Actually, this will be easier for m example, lets just do this. Your string will then look like this for program LEVELNOM "MONLEVEL"->Str1 (Which is why I decided not to use it with GetCalc, otherwise it would look like "prgmLEVELNOM"->Str1 instead, which is harder to compare when you're being lazy like me) We will now proceed to search the vat for your program.
"MONLEVEL"→Str1 // The name of our program, in reverse order (Remember? The vat is backwards.)
{E9830}r→θ // The location where the vat starts stored as a variable for easy manipulation. (This is actually the end, but remember?...)
{E982E}r→Z // The end of the vat. (This is actually... Meh, you get the point :P)
0→C // C Will be our condition of whether or not the program was found
Repeat θ≤Z+C // Loops until the end of the vat is found or your program is found.
If getKey(15):Return:End // Umm, if I screwed up or something... Normally I include this in loops like this so I can just quit by pressing Enter if something happens.
{θ}∙E001F→A // Puts the value of the lower 4 bits of the object type into A for testing.
If A=5+(A=6) //If its a locked or unlocked program... Yay! See if it's the one we want!
θ→T // Temporary storage FTW!
{T-6}→U // Go to where the name length is (6 bytes back from the type, where T currently is) and store the value there to U
While U>0 // Check each byte of the name
{Str1-U}={T-U-6}+C→C //If byte X of the name is equal to byte X of the vat entry...
U-1→U //Go to the next character!
End
C=U→C // If every character matched, then good! C now reflects that a program was found!
End
θ-6→θ // Go to where the name length is (6 bytes back from the type, where θ currently is)
θ-{θ}-1→θ // Skip past the name now that we know the length, and one additional byte to start the next entry.
End
(I'm just assuming your program was found, not that the end of the vat was reached. You can add more code to check for that if y{T}-5
{T}-5=0+5→{T} // Umm... Inverts the lock/unlockness of your program?
6→{T} // Or youc ocould just lock it, if no toggling is neccessary ;P
That should be it I think... Let me know if you run into any difficulties with that code or need more help!
-
@ cooliojazz
Thank you very much! This is really helpful.
Actually I have some trouble by storing a VAT entry name into a string.
Would be nice if you have a solution for me.
I need to store a VAT entry name into a string to output it correct on the buffer and to use Getcalc( .
The problem is that I have to set the string lenght to the entry name lenght, but I have no way to do this.
.VAT2STR
"appv"->Str9
. P is the pointer to the entry start (or rather the end of the entry :) )
. Now I have to redefine the lenght of Str9
{P-6}+1->lenght(Str9) . How is this feasible? <.<
For(X,1,{P-6})
{P-7-X}->{Str9+X} . Not sure wether it works by using this way
End
Getcalc(Str9)->A
Fix 5
Text(1,1,Str9)
Fix4
Return
-
I just first want to mention that I forgot at the end you could just put a {T-3}r which you could use instead of GetCalc. But, if you really wanted to just use the forward-formatted string with the prefix, first... What is
For(X,1,{P-6})
{P-7-X}->{Str9+X} . Not sure wether it works by using this way
End
For? ???
-
In this part of the code the Vat entry name should be copied into the string Str9.
For( [Loop Counter X] ,1, [VAT Entry name lenght] )
{ [Entry pointer] - 7 - [Loop Counter X] } -> { Str9 + [Loop Counter X] }
End
The Forloop sets the variable X to value 1. Then it copies the X-th character of the entry name into the X-th Byte of Str9. This will be reapeted until [Loop Counter X] = [VAT Entry name lenght] )
The name should be in a string because I want to output the string correctly on the buffer.
-
I mean, I got that it copied it to the string, but... Wouldn't you already have the name of a program if to find its location?
-
I would have just the characters, but I cant output single characters.
For(X,1,{P-6}+1)
Text(X*4 , 0 , {P-7-X}<Char
End
That would be possible, but I work with Appvars, that are able to have lowercase letters.
After a character X would jump 4 pxl right, but what about an 2pxl "i" or a 6pxl "m" ?
The pen jumps through the correct lenght right after outputting a font sprite, if I output strings.
-
ok, you have String A that looks like $4F,$01,$02,$04,$05 and String B which looks like $05,$04,$02,$01 and you want your output to look like $01,$02,$04,$05 right? So what's the advantage of using String B?
-
I use just Str9. The name I need to store into Str9 is [Pointer - 7] until [Pointer - 6 - Name lenght] .
But I think I found a solution already. Thanks anyway. :)
-
It is redundant to get the NAME of the entry and then search the symbol table again to find the entry with that name using GetCalc()
The data pointer can be found at {entry-4}rr. You can then add 2 to that pointer to skip over the size bytes in the data to mimic how the getcalc() works.
-
Ok, Ill use the VAT data pointer instead of Getcalc( .
I am having still trouble by outputting an Appvar Entry with the small font.
I thought this is possible:
.VAT2STR
{e9830}r -> P . VAT start Pointer
Repeat getkey(15)
ClrDraw
""[CE]" "->Str9 . [CE] is the "..." Character for representing loading, then Space character by seven times
If {P}=21 . If current entry has type 'appvar'
For(X,0,{P-6}-1)
{P-7-X}->{Str9+X} . This doesnt work. :/ It should copy the entry name into Str9
End
Else . If the type isnt 'appvar' then Str9 is still "..."
P-{P-6}-7-> P . Go to the next entry
End
If getkey(3) and (P>=VAT end
P-{P-6}-7-> P
End
Fix 5
Text(1,1,Str9) . Str9 is always "..."
Dispgraph
End . Loop End
Fix 4
Return
-
first, I notice "{P-7-X+1}->{Str9+X}" should be "{P-7-X}->{Str9+X}" since P-7 is the first entry, not P-6, which is what yyou got by adding 1 back at the end... I'll go over it more later when I have time to see what els...
-
first, I notice "{P-7-X+1}->{Str9+X}" should be "{P-7-X}->{Str9+X}" since P-7 is the first entry, not P-6, which is what yyou got by adding 1 back at the end...
Youre right. I removed the mistakes from the code in the last post.
Here is a screenshot showing what happens if I output appvar names character by character with 4 pxl gaps.
-
first, I notice "{P-7-X+1}->{Str9+X}" should be "{P-7-X}->{Str9+X}" since P-7 is the first entry, not P-6, which is what yyou got by adding 1 back at the end...
Youre right. I removed the mistakes from the code in the last post.
Here is a screenshot showing what happens if I output appvar names character by character with 4 pxl gaps.
Why do it character by character? Didn't you just have code for storing it and displaying it as a string?
-
@ Runer
Yes, thats what Im trying to do, but currently Im having trouble by copying the entry name into a string.
For(X,0,{P-6}-1)
{P-7-X}->{Str9+X} . This doesnt work. :/ It should copy the entry name into Str9
End
Seems like this code does nothing.
-
Well your code has no errors, but the problem is that your program is compiled as an application. Apps exist in ROM so they can't use self-modifying code, which is what storing to internal pointers like Str9 really is, so that's why that does nothing. What you need to do is instead allocate a section of safe RAM to hold the string and copy and display the string from there.
-
Ooh, yep, that's exactly it! Good job Runner! :P
-
Oh, I see. I will probably go back to use programs for storing level data like I did at the start of this topic.
Thank you, Runer.
-
Wait, why are you going back to using programs? This isn't a problem inherent in the fact that level data is stored in appvars, it's a problem inherent in the fact that your main program is compiled as an application.
-
Or more specifically, trying to change a string while compiling to an application...
-
Wait, why are you going back to using programs? This isn't a problem inherent in the fact that level data is stored in appvars, it's a problem inherent in the fact that your main program is compiled as an application.
I wanted to output the entry name as a string to dont get pen moving problems like in the screenshot.
Program names are just Uppercase, so all font sprites would be have a defined width of 4pxl, so I could
output program names char by char without having to use strings. I think everything else would be not as efficient as this way, especially because I have to take a look on my remaining memory size.
-
Simply replace "Str9" with "L1" or some other free ram. Then you can call "Disp L1" later. Don't forget to add the null character at the end of the string.
-
@ Quigibo
Ah, thanks. Using Free Ram works.