This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Messages - Runer112
Pages: 1 ... 95 96 [97] 98 99 ... 153
1441
« on: March 04, 2011, 12:23:48 am »
I have been tearing my hair out trying to get this to work. No matter how many different things I try, I cannot figure out how to run a simple command line GIMP script. I keep getting errors like the following: GIMP-Error: Opening 'c:\Program Files (x86)\GIMP-2.0\bin\0)'' failed: No such file or directory It seems that any arguments I enter, it tries to parse them as files in GIMP's \bin\ directory. I've tried using the exact examples used in GIMP's batch mode tutorial, but they have the same problem. Any ideas? In case this information will help:
1442
« on: March 03, 2011, 10:51:30 pm »
The problem is not your code. When I looked through MemKit.z80 a while ago to see if I could optimize anything, one thing I noticed was that the code for dim()rr had a problem. It is currently programmed to read the length of the variable's name instead of the page it's on. I have already pointed this out to Quigibo and hopefully the next Axe release will include an updated MemKit.8xk.
1443
« on: March 03, 2011, 02:55:10 pm »
but how would you store the "input" data to a string? would it be input->p copy(p,str1,length(p))
Why would you need to copy the string somewhere else? It already exists in RAM at the location pointed to by the output of input. Also, copying the string to a static pointer could be dangerous if the string that the user entered is larger than the space you allocated for the Str1 pointer. How many buffers are there, and how do I use them in Axe?
There are 3 buffers built into the operating system. L6 points to one, which is usually treated as the "main" buffer by programmers because that's the buffer the OS treats as the main buffer. This is also the buffer used with Axe's DispGraph by default. Another buffer is pointed to by L3, which Axe treats as the second buffer for grayscale images. Axe also has the option to use most of its drawing commands to this buffer in addition to the normal L6, which could be useful whether or not you're using grayscale. The final buffer allocated by the OS is L1, the last 54 bytes of which are used by the Axe variables by default. However, you can redefine the variables to point somewhere else and then use this whole buffer. And of course, you can always define your own buffers by just allocating 768 bytes of RAM for one. You could do that by adding 768 bytes of data to your program or making a 768-byte appvar.
1444
« on: March 03, 2011, 02:50:10 pm »
Ah right, my TI-BASIC skills are quite rusty so I didn't see that potential for optimizing to not(. But I got the general idea down well.
1445
« on: March 03, 2011, 02:38:26 pm »
Original routine using Z: 94 bytes Routine without using Z: 110 bytes This routine I just made that doesn't use Z and handles the zero case correctly: 92 bytes Ans→A " →Str0 A Repeat Ans=0 Ans→A sub("0123456789",abs(A-10iPart(.1A))+1,1)+Str0→Str0 iPart(.1A End Str0 If A<0 "⁻"+Ans sub(Ans,1,length(Ans)-1
1446
« on: March 02, 2011, 09:49:29 pm »
aeTIos, do you have TI Connect installed? Because I believe the program editor depends on some mutual files from TI Connect. It doesn't have to be a certain version of TI Connect, you could just grab the version currently on TI's site.
1447
« on: March 01, 2011, 06:21:01 pm »
Axe actually checks if there's already a Return at the end. If there is, it isn't added.
I was pretty sure it didn't check if the code already ends in a Return. Upon quickly double-checking this, it appears that Axe will always add a final Return whether or not your code ends in one. Do you get different results?
1448
« on: March 01, 2011, 05:13:50 pm »
Why is post-check more optimized than a Repeat loop, though?
I think I remember mentioning why this is in a previous post somewhere... ah yes, here it is: Speaking of optimizing control structures, any chance for Do...While loops?
I'd like Switch cases more than Do...While loops, but I don't really know how the second works.
Do...While loops are a lot like While...End loops, except that the check to advance to another iteration of the loop is at the end instead of the beginning. This turns out to be more optimized. Whereas a While...End loop has two jumps, one to exit the loop if the condition is false and one to jump back to the beginning, a Do...While combines the two into one jump that jumps back to the beginning if the condition is true.
I don't know how good that explanation was, but perhaps this pseudocode will help clarify it. Numbers in brackets indicate the number of bytes the real code takes:
While...End loop | | Do...While loop | ;While [x] Loop condition [2] Check if loop condition is true or false [3] Exit the loop if false
;Loop contents
;End [3] Jump back to the beginning of the loop
| | ;Do ;[0] Start of the loop, takes no actual code
;Loop contents
;While [x] Loop condition [2] Check if loop condition is true or false [3] Jump back to the beginning of the loop if true
|
I like leaving the last Return in because it helps code readability, and it makes it easier to add new subroutines after it. It doesn't actually affect the compiled code, right?
I agree that it improves readability, but because Axe automatically adds a return to the end of programs it's redundant and a waste of 1 byte. You can always improve readability while maintaining optimization by keeping the final Return, but commenting it out.
1449
« on: March 01, 2011, 01:52:03 am »
Awesome tutorial! But because I'm OCD about optimization, I feel like optimizing this. Since this is a tutorial, feel free to not include these optimizations, as they'll probably just make the code more confusing. But I want to try to optimize it anyway. :.SHMUP An awesome game. :prgmASHMUPD :prgmASHMUPI :Repeat getKey(15) :C+1→C :prgmASHMUPK :prgmASHMUPM :ClrDraw :If B :For(I,1,B) :Pt-On({I*4+L₄-2→J},{J+1},Pic0) :End :End :Pt-Change(X,Y,GDB0) :DispGraph :End :prgmASHMUPR
| | :.SHMUP An awesome game. :prgmASHMUPD :prgmASHMUPI :Repeat 0 :C+1→C :prgmASHMUPK :ClrDraw :B :While :-1→I :!If {*4+L₄+2→J+1}+{J-1}→K*4-256<996 :Pt-On({J},K,→{J+1}Pic0) :Else :Isub(RSB) :End :I :End :Pt-On(X,Y,GDB0) :DispGraph :EndIf getKey(15) :Return :prgmASHMUPR
| Optimization notes (savings listed in brackets): - [3 bytes, 10 cycles per iteration] – Main getKey(15) loop changed to post-check format
- [31 bytes, ~104 cycles per bullet] – prgmASHMUPM merged into the already existing bullet drawing loop, removing the need for 2 separate loop structures
- [8 bytes] – Removed check that B≠0 before the bullet loop; it is unnecessary because the loop already handles this properly
- [8 bytes, ~38 cycles per bullet] – Bullet loop structure optimized
- [3 bytes, 16 cycles] – Due to the bullet loop no longer being a For() loop, the value of the loop variable can now be carried into the first function inside the loop
- [3 bytes, 12 cycles] – Bullet velocity added to y value instead of subtracted from y value
- [⁻3 bytes, ⁻26 cycles] – Bullet offscreen check changed from <127 to *4-256<996; this is a more compact emulation of (VALUE<64) or (VALUE>248) which would appear to me to be an improved logic statement for this scenario
- [9 bytes, 57 cycles] – J value when checking bullet y value reused to get x value for Pt-On() simply with {J}
- [6 bytes, 43 cycles] – Reused the value stored in J from the offscreen check to get the x coordinate for Pt-On()
- [4 bytes, ~18 cycles] – Stored the bullet y value into a variable when checking the y value to avoid needing to retrieve again later in the Pt-On() command; also moved the code to store the new y value to the bullet's data in the middle of the Pt-On() command so the fact that it returns a pointer doesn't disrupt calculations
- [3 bytes, 16 cycles] – sub(RSB) called without saving the argument into r1 first
- [126 bytes] – Player sprite drawn with Pt-On() instead of Pt-Change(), removing the need for a second bulky sprite routine
- [-1 bytes, ? cycles] – A Return added after the main loop, before prgmASHMUPR; without it, after the user presses clear, program execution would just continue into the first subroutine in prgmASHMUPR, potentially causing big problems
:..KEYS :If getKey(1) :Y+2→Y :End :If getKey(2) :X-2→X :End :If getKey(3) :X+2→X :End :If getKey(4) :Y-2→Y :End :If getKey(54) :!If C^8 :sub(ASB,1,3,X+3,Y-4) :End :End
| | :..KEYS :!If ^8 :If getKey(54) :sub(ASB,,⁻3,X+3,Y-4) :End :End :!If getKey(3)-getKey(2)+1*2+X :+2 :End :min(-2,88)→X :!If getKey(1)-getKey(4)+1*2+Y :+2 :End :min(-2,56)→Y
| Optimization notes: - [3 bytes, 16 cycles] – Weapon fire checking moved to the top and the counter check moved before the key check, allowing for the counter value to be carried from the previous statement in prgmASHMUP
- [3 bytes, 10 cycles] – Omitted the bullet type from sub(ASB), as a 1 can be carried from the getKey(54) check
- Bullet velocity changed from 3 to ⁻3, as the velocity is now added to the y value instead of subtracted from it
- [⁻22 bytes, too lazy to calculate cycles] – New approach to movement key checking; also makes sure the ship doesn't leave the screen
:..ROUTINES :Lbl ASB :If B<80 :r₄→{r₃→{r₂→{r₁→{B+1→B*4+L₄-4}+1}+1}+1} :End :Return :Lbl RSB :Copy(r₁*4+L₄+4,-4,B-1→B-r₁*4+1) :Return
| | :..ROUTINES :Lbl ASB :Return!If B-80 :r₄→{r₃→{r₂→{r₁→{B+1→B*4+L₄-4}+1}+1}+1} :Return :Lbl RSB :Copy(→r₁*4+L₄+4,-4,B-1→B-r₁*4+1)
| Optimization notes: - [2 bytes, ~5 cycles] – Changed the check that the number of bullets is not too high from an if statement into a conditional return statement
- [5 bytes, 20 cycles] – Changed If B<80 to !If B-80; the second is an optimized version of If B=80, which should work equally well because B can be 80 but should never be greater than 80
- [1 byte] – Removed the last Return, as Axe automatically adds a Return at the end of the program
Confusing enough? Ask me if you have questions about any of this and I might be able to remember what the hell I was thinking.
1450
« on: February 26, 2011, 08:44:28 pm »
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.
1451
« on: February 25, 2011, 10:03:48 pm »
Because Axe source code is compiled into the same assembly language as a "normal" assembly program, there is no surefire way to determine the origins of an assembly program. However, you can make a very accurate educated guess by looking at the disassembled code. Here are a few differences I can think of that should be fairly noticeable between a "normal" assembly program and one generated by Axe: - Axe programs have a strong foundation in the hl register. A very high amount of h/l usage (and also a very low amount of b/c usage) should hint to a program compiled by Axe parser. This is probably the strongest indicator.
- Axe programs also rely on storage of values in memory, often in the range from saveSScreen+714 to saveSScreen+767. Values are only carried from block to block in either memory or hl. (Or on the stack for subroutines)
- Axe programs will have a lot of conditional branches following the format ld a,h \ or l \ jp (n)z,$XXXX. Very rarely will you see a conditional absolute jump that does not follow the above format or does not use the z flag.
1452
« on: February 24, 2011, 04:28:27 pm »
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.
1453
« on: February 24, 2011, 03:26:18 pm »
This seems to work for me:
[015D]"M"→Str1 GetCalc(Str1)→P
1454
« on: February 23, 2011, 11:58:09 am »
A helpful optimization hint: always put constants last! {P+A}: 11 bytes, 61 cycles {L1+A}: 11 bytes, 55 cycles {A+L1}: 10 bytes, 51 cycles Ok, thanks I'm guessing reading from the archive takes longer, but is it a large slowdown?
Reading a single byte or word from the archive is about 30 times slower; it takes about 1600 cycles. If your program regularly reads from a relatively small amount of archived data at any one time, like the tilemap for a level, the best thing to do is Copy() the data from archive into RAM somewhere and read it from there. You can then access this data from RAM much more quickly during gameplay, and copy new level data from archive as necessary. Yeah it is slower, but unfortunately it seems Runners documentation is lacking in that regards
You are right, I have not documented the speed of the archive reading commands. Reading from the archive uses OS routines so it is a bit harder to calculate the speed of, as I can't look at the code and simply calculate speed based on the instructions that make it up.
1455
« on: February 22, 2011, 11:19:01 pm »
Alright, spent about 2 hours on this, I think that's enough. I promise once you've gone for about a minute your adrenaline really gets pumping, this game gets insanely hard. At that point you can't even tell where you are in the tunnel when the screen is shifting, you just have to guess and move up and down based on the contours of the blur on the screen. CRAZYTUN.8xp is the game. It's bloody insane, I'm still shaking from playing it. This is seriously the most invigorating calculator game I have played. Ever. CRAZYSRC.8xp is the Axe source file.
Pages: 1 ... 95 96 [97] 98 99 ... 153
|