Show Posts

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 - E37

Pages: [1] 2 3 ... 23
1
The Axe Parser Project / Re: Axe Parser
« on: November 19, 2022, 11:42:55 am »
Therefore I think it's a shame that, with the source code closed, no one can ever either learn from this project (it must be a treasure trove of z80 writing) or pick it up again. The chance that either Quigibo or Runer112 are reading this is slim, however, I would want to call upon them to provide a final release with the source code, as a last hurrah for Axe.

@aeTIos
Runer112 gave me the source for either Axe 1.3.0 or 1.2.2 (I can't remember which and taking a quick peek at it I can't tell) a long time ago. If there is some very compelling evidence that he would be OK with me publishing it, I will.

Having looked at it more carefully, it is 1.2.2.

2
Axe / Re: Game optimizations?
« on: August 04, 2022, 05:09:12 pm »
@Batprime11
Sorry for taking so long, whenever an Axe question pops up I somehow manage to forget to check Omnimaga for a couple of days. Speed optimizations are my specialty but I'll see what I can do for size.

.DINO
#Icon(007E00FF00DF00FF00F000FE81F883F8C7FEFFFAFFF83FF00FE0066004400660)
41→Q→Z
Pic1DINO1→N
.ANIM 1
Goto MENU

...
Any kind of comments or explanation of what each bit of code does would really help
You seem to be trying to optimize the size of the source as much as the executable
As it is, I don't know what each letter variable means and don't want to play a guessing game
So I am just going to point out the inline optimizations rather than any logic ones
I put a some spacing in places I thought were logical breaks just to help myself read it. You can ignore them
...

prgmTILESPRT

Lbl TXXT
Text(20→B*256+3
...
*256 translates to ld h, l \ ld l, 0 which is 3 bytes
+3 translates to inc hl (x3) which is also three bytes
So it is more space efficient to just do
20→B
Text(20*256+3)
Basically, +3 on its own takes up just as much space as a constant would so there is never any reason to use it to produce a constant result
same thing with *256. Remember that numeric constants are just 3 bytes
I believe only times you can beat numeric constants for size is push/pop hl, +-1, +-2, and 0, or 255, *2, *4. I might be missing one or two but I think that is a complete list. Division is, of course, completely out of the question as / 2 takes up 4 bytes. There are a lot more operations that tie with a numeric constant but at that point it is better to use the constant. I recommend pulling up a list of assembly instructions for doing optimizations like this. Thinking out what logic translates to in assembly makes it a lot easier to see what could or could not save you space.
...
Text r₁
Text(6659
Text r₂
Text(8195
Text r₃
Return

Lbl PAUSE
For(35565) .do you mean 65535? Not that it matters but 35565 is a strange number. Also, -1 (negative 1)  works and is easier to type out
End
Return

.Axe doesn't require constants/variables to be declared before they are used like in C or most other languages. You can move this data to the bottom of the program if you want. I find that doing so makes it nicer to scroll through
[0000000000004143→Pic1DINO1
[7EFFDFFFFFF0FCE0
[677F7F3F1F0C080C
[E0F8E8C080C00000
.ANIM 2
[0000000000004143→Pic1DINO2
[7EFFDFFFFFF0FCE0
[677F7F3F1F080C00
[E0F8E8C0C0C080C0
.CACTUS
[001858D8D8DADBDB→Pic1CACT1
[DB7E3C1818181818

Lbl OPTN .You can use lowercase letters for variable and function names as long as they don't start with one
ClrDraw
PAUSE()
TXXT("Min Dist","Min Offset","Back"
Text(40*256)
Text "Ducking coming soon!
IRect(3,20,32,6
Text(20*256+33
Text Z►Dec
Text(26*256+35
Text Q►Dec
DispGraph

While 1

If B=26 and getKey(2) .The '?' and '??' operators take up the same amount of space as 'and' and 'or' but they also short circuit and don't have bitwise problems. I would use '?' and '??' as drop in replacements for any time you use 'and' and 'or' respectively. Just make sure the short-circuiting doesn't mess any logic up
Text(26*256+35

Text max(Q-1,1)→Q►Dec
PAUSE()
End

If B=26 and getKey(3) .Fun fact: Axe only reads the lower byte of the value passed in here so getKey(X*256+3) would always work the same as getKey(3)
Text(26*256+35
Text min(Q+1,65534)→Q►Dec .The optimization that I did for the same operation on Z applies here too
PAUSE()
End

...
All of your 'If B=# and getKey(#)' statements can be optimized to
!If B-#??getKey(#)-1
This is because getKey always returns 1 or 0. Doing -1 on its result effectively inverts it
...
If B=20 and getKey(2)
Text(20*256+33

...
Text max(Z-1,1)→Z►Dec can be optimized to
Z--??+1→Z
Text ►Dec
For 2 bytes off
...
Text max(Z-1,1)→Z►Dec

PAUSE()
End

If B=20 and getKey(3)
Text(20*256+33
...
Like previously, Text min(Z+1,65534)→Z►Dec can be optimized to
Z++??-1→Z
Text ►Dec
For 2 bytes off. It does limit the max value to 65535 instead of 65534 but I think that is probably fine in your use case
...
Text min(Z+1,65534)→Z►Dec
PAUSE()
End

If getKey(15) or (B=32 and getKey(54)) .Luckily for you, Axe ignores the parenthesis
Pause 400 .Pause <constant> is 10 bytes while your PAUSE() function is only 3 bytes to call. Since this wait is isn't very sensitive, just use PAUSE() here if the timing is close enough.
Goto MENU
End

If getKey(4)
3
Asm(E5 .By pushing/popping here you only gain one byte. Is it really worth the readability hit? Then again, your code is already so unreadable I guess it doesn't matter
IRect(,B,30,6
Asm(E1
IRect(,max(B-6,20)→B,30,6
PAUSE()
End

If getKey(1)
3
Asm(E5
IRect(,B,30,6
Asm(E1
IRect(,min(B+6,32)→B,30,6
PAUSE()
End

DispGraph
End

Lbl MENU
ClrDraw
Fix 5
RectI(0,16,*2+1,26
RectI(1→D,17,31,24
TXXT("PLAY!","OPTIONS","QUIT")
IRect(3,20,27,7

While 1
If getKey(4)
3
Asm(E5
IRect(,B,27,7
Asm(E1
IRect(,max(B-6,20)→B,27,7
D++
PAUSE()
End

If getKey(1)
3
Asm(E5
IRect(,B,27,7
Asm(E1
IRect(,min(B+6,32)→B,27,7
D--
PAUSE()
End

DispGraph

If getKey(15)
Fix 4 .Fix 4 takes up 4 bytes + the return makes it 5. doing a goto to the Fix 4 and return below saves 2 bytes
Return
End

EndIf getKey(54)
!If B-32
Fix 4
Return
End

!If B-26
Goto OPTN
End

Lbl MLOOP
ClrDraw
196→I
47*256→C→B→A
15→F→D→J-2→E→H .What do all these variables mean?
#ExprOn
...
I doubt you are getting much speed boost from #ExprOn. Axe's built in text command is so slow basically invalidates any speed optimizations by itself. (it is just a call to Ti-OS's Text function which is horribly inefficient - so great for size but not for speed) I believe #ExprOn lets Axe pick an unrolled version of Horizontal- below but besides possible other small optimizations it likely doesn't do anything. But again, Axe's built in Text command is horribly slow.
...

While 1
RectI(0,63,95,1
RectI(31,23,65,1
RectI(31,0,+1,22
!If H--
Rect(90,0,+2,23
rand^Q+Z→H
End

...
I could be wrong but the following If statement looks like you are bit testing from the screen. If you are, {22*12+L₆+3}ʳ and 128 (or whatever bit mask you need. add 1 to the address if you need the high byte) is much more space and speed efficient. Also 1 byte reads for non-constant addresses are better than 2 byte ones. (So in most cases leave off the ʳ if you don't need the high 8 bits) In your case, you are reading a constant address so that ʳ is fine.
That won't return the same value as [e] but it will more than make up for you having to hardcode whatever value TS( is expecting
...
If I++ and {22*12+L₆+3}ʳ[e]7
TS(,+1,88,47,Pic1CACT1 .What does TS do? Put a sprite on the screen?
⁻3→I
End

Lbl JUMP
...
Signed operations take up more space than unsigned ones. I believe that ({oD+1} and 128) does the same thing as (D << 0) where that o is the degrees sign. 'xor' works if you want to invert. It's 2's complement so you can just check the most significant bit for the sign
You may want to shift all your operations on D up by some constant value like 65536 / 2. That way you can check below zero without using the signed operators
...
If C-47 or (D<<0)
D+E→D+B→B
End

...
Depending on the expected value of C you can do this
!If C-47
12→E
Else!If /256 .Check to see if the high byte of the last calculation is non-zero if so, it overflowed and C is less than 47
-1→D .subtraction not negative
12→E
12032→B
End
...
If C>47
-1→D
12→E
12032→B
Else!If C-47
12→E
End

...
You can move the 12→E into this if block like this
If C≥47?Select(getKey(4), 12→E)
-350→D
End

If you add the constant 0 as the last entry in both branches of the previous optimized if statement, it will always have hl as non-zero if both branches fail and 0 if they pass so you can remove the C≥47 from the upcoming if block completely. Each 0 constant takes up 3 bytes but C≥47 takes up 11. Additionally you can use the 'and 0' trick described below on the 12→E block for a total of 6 bytes saved (or do a push/pop hl pair in each to save the zero from the conditional if you really hate whoever is reading your code for 7 bytes saved)
...
If C≥47 and getKey(4)
⁻350→D
End

.I would recommend changing this to ':getKey(1)?50→E' just to condense your code a little so more could fit onscreen.
If getKey(1)
50→E
End

...
IIRC, there is no reason to ever use DS< it just expands to what code you would normally replace it with. When I tested it a while ago, I couldn't find any cases where it was faster or more space efficient than just doing '!If F--:20→F:<code>:End'
...
DS<(F,20) .Thanks for closing the parenthesis on most commands after here. Every little bit helps

...
Instead of that if-else block do:
(N-Pic1DINO1?Pic1DINO1,Pic1DINO2)→N (10 byte savings)
...
If Pic1DINO1=N .You kinda dropped the ball on this one. Why not '!If N-Pic1DINO' here? You used that trick several other places.
Pic1DINO2→N
Else
Pic1DINO1→N
End

End

.You may be able to assume something about the value of hl at the end of the DS< block.
2
Asm(E5
TS(,,-2,C,N)
DispGraph
Asm(E1
TS(,,-2,C,N)
RectI(0,63,95,1)
RectI(31,23,65,1)
WRect(31,0,+1,21) .Axe will replace an 'and 0' with ld l, 0 which is only 2 bytes so you can replace this statement with WRect(31,and 0,+1,21). 'or 255' works the same way. Remember that that just affects the lower 8 bits so you have to be sure the high 8 are in a state you want them to be in
Horizontal-
B/256→C

EndIf pxl-Test(15,C+4) or pxl-Test(8,*2+C) or pxl-Test(4,C+16) or getKey(15)
...
If you are feeling especially energetic, you could replace those pxl-Tests with constant bit tests on L6. Since your X value is a constant you wouldn't have to worry about shifting your bit mask. All you would have to do is add C*12 to the offset. I'm not sure if you would come out ahead but it could be worth a shot. You would certainly lose for individual tests but if you could eliminate all 3 you wouldn't have the weight of including the function.
...
Goto MENU

There are quite a few places where using 'and 0' instead of the constant '0' would save a byte. I didn't mention them to avoid comment clutter. They are easy to spot once you know what to look for.

That is probably between 30 and 80 bytes off the total at the cost of whatever readability your code had left. The reality is that the majority of your size is probably just calls to the OS or Axe so there really isn't too much to do to begin with. I would be very careful when optimizing anything larger than this program that aggressively for size because of the risk of logic bugs creeping in during the optimization. I haven't tested these optimizations because you didn't give me the full source so you should double check they work before using them.
I would also suggest getting really comfortable with '?' and '??' because when used correctly they can be your best friends and are better than the bitwise 'and' and 'or' in pretty much every case. Taking advantage of the fact they short circuit to condense a really fat series of if blocks can be nice. You can also do single line conditionals like ':A=3?5→A' which would set A to 5 if it held 3 before which is a lot more readable on the limited space of a calculator screen than the 3 lines usually given for an if block.

Overall, you did some pretty solid optimizations. I would take a serious look at your flow of logic as you are likely to get more gains from reordering and reworking than one-off optimizations unless you already have one of the best possible logic paths. If you implement whatever of my suggestions you want add some comments I'd be thrilled to do another pass.

Here are a couple of other tricks that I didn't get to use but you may find useful:
Built in Axe functions and Axioms do a 'push hl' for commas meaning you can't safely push/pop across them but user functions that use r1-r6 don't so it is safe to push/pop there
If you do a pop <any register> you can then safely goto inside the single argument For( loop. Axe won't let you but you can code it in assembly like Asm(C3(LLabel)) where that is the little L for label address
Assign custom constants. They might slightly slow down compile time but they make the code so much easier to read. You can even rename letter variables like ':oB→oYPos' so after that you can use YPos instead of B. (where the o is the degrees symbol)
While I don't really know what is going on with your logic, I suspect that you could cut down on a lot of calls to [WI]Rect( by just doing DispGraphClrDraw and reworking graphics accordingly. Rectangles that span the width of the screen (like I assume you have for the ground) could be turned into a Fill( command which would save on speed and maybe space too. The value argument of Fill( works great with the 'and 0' and 'or 255' trick I mentioned since it only uses the lower byte.
When given the option always do <Variable>-<Constant> (like X-5) and not <Constant>-<Variable> (like 5-X) the second case is 2 bytes larger.
You can use the colon (':') to separate lines on the same line anytime you want to pack a couple statements on the same line. ':3:Asm(E5)' is a good example but it work for all parts of an If statement. In fact, in the last example, the colon is optional and ':3Asm(E5)' works!

3
Axe / Re: A* Star and Min Heap Help
« on: July 11, 2022, 09:44:57 pm »
I took a long look through your code and couldn't really figure out how your shifting code was supposed to work. Are you trying to work around Axe's lack of a working backwards copy? It looks to me like you are pushing a node to the end of the stack and then bubble-sorting it down to its proper place. If so, it would be way easier to find the correct place to put the node, and use a backwards copy (Asm or Axe loop) to shift all the other nodes up to make room.

Here is the code I used to push a node onto the open stack for my A* implementation:
Code: [Select]
:.N2X, N2Y are the x and y of the new node.
:.N2VAL is the calculated weight of the node. Each node is 6 bytes
:
:Pxl-On(N2X, N2Y, oGB7) .I set pixels for each tile so I don't create duplicate nodes. Since my map is 64x64, drawing commands work perfectly
:Select(Open, *6+oOpenS->X) .Open holds the number of nodes on the open stack, X will now hold the pointer to the end of the stack
:If
:For()
:    {X-6}r >= N2VAL                 .Loop backwards until we come across a node that has more weight than the one about to be inserted
:    ? Asm(C1C3(L PushNext))    .If true, pop BC and goto PushNext (pop BC lets me use goto in this type of For loop. Axe won't let me use a goto in the loop so I wrote it in asm instead
:    .Once push next has been called, the function will never return here
:    .The only reason PushNext isn't in the loop is the fall-through case of the new node being the last one or an empty stack
:    X-6->X
:End
:
:.Pass through to the copy if no spot has been found
:
:Lbl PushNext   .This just sets up a backwards copy (lddr). DE, HL, BC are the same arguments (in the same order) as Axe's copy but it starts at the end and works backward
:
:Open++*6+OpenS    .Increment the count of nodes on the stack. Get the pointer to the end in HL
:Asm(E5) .push HL (will be popped as DE)
:-6 .Move 6 bytes back because we are shifting 6 bytes up
:Asm(E5) .push HL (will be popped as HL)
:+6-X .Get the total amount of bytes to move
:Asm(E5) .push HL (will be popped as BC)
:Asm(C1E1D178B12802EDB8) .Pop BC, HL, DE and copy
:
:.Copy the 6 byte node to the area pointed to by X now that everything above has been shifted up 6 bytes
:Copy(oN2VAL, X, 6) .I'm not really sure why I used copy for only 6 bytes. Maybe it was more efficient or something
:Return

While that code is very heavily optimized, a simpler version using the same logic shouldn't be too hard to implement.

Most of my Axe code isn't anywhere that nasty but I really needed a fast pathfind.

4
Axe / Re: A* Star and Min Heap Help
« on: July 10, 2022, 11:20:38 am »
You are calling DelVar correctly. If nothing is happening, then either it doesn't exist or you have memory corruption going on. And since I assume that it exists for you to know the deletion doesn't work it may be memory corruption.

As for your GetCalc issues, try displaying the value it returns when you first create it and when you have to call it again a second time. They should be the same. If they differ, something you are doing is moving memory around and there isn't anything you can do besides call GetCalc again a second time like you do.

As for custom variables holding variables to hold function labels, that is perfectly fine.
Code: [Select]
:L Label->Variable .Store the address of the function to the 2-byte variable Variable
:(Variable)(1, 2) .Call the function pointed to by Variable, passing 1, 2 as arguments. No arguments is valid
:(L Label)() .The same as doing :Label()
The L followed by the space is the little uppercase L used for getting the address of a label. I can't put subscripts in code. It should be LLabel

I don't have my calculator on me at the moment as I left it at work. I will bring it back with me on Monday and check out your A* bug then. What is your shift functions supposed to do? It looks like you are placing a node in a sorted list. Is that correct?

5
Axe / Re: Axe Q&A
« on: July 06, 2022, 08:57:31 am »
Your issue with GetCalc isn't an Axe bug. I have worked with 6+ appvars at once and had no trouble. Since all Axe is doing with GetCalc is asking the os for a pointer, it would be a ti-os bug and I very much doubt that ti-os would have such a problem. If you post your code I may be able to find what the problem was.

6
Axe / Re: Axe Q&A
« on: July 05, 2022, 09:57:35 pm »
Does Axe not allow you to manipulate more than one appvar at a time? I'm getting some really strange bugs when I do. I have 2 appvars that I create in RAM. One is the appvar for the current generated floor in my game. The second appvar is supposed to be another map that I am going to use in my AI calculation that I call DistMap. I running across several strange bugs with Axe when I do this. If I create both appvars at the same time, I am no longer able to manipulate the DistMap appvar if I do anything with the Floor appvar. In this case all I am trying to do is fill it with some value for now. If I instead create the DistMap appvar whenever I press a button (down in this case), the tilemap gets corrupted somehow. Or rather, it seems as if the 2 pointers are getting mixed up somehow. Because when I try to move down a bunch of corrupted tiles are scrolled in instead. Any ideas?

Some code to see exactly what is going on would be helpful. Here is a summary of what GetCalc( does which may be helpful.

Everything in ram is stored between 0x9D95 and the VAT which is at the top couple hundred bytes of memory. The VAT (Variable Allocation Table I believe) holds information about everything in RAM that isn't locked down to a fixed address. It also holds information on where archived stuff is in flash is but that doesn't matter for your problem. When you use GetCalc() to open an existing program/appvar/other that is in ram, what it is actually doing is going to the VAT to look up where in memory the file is and returning that pointer. Since the file is in memory, ti-os may move the file whenever needed. Any time you create or destroy a file, you should assume any pointers you got from GetCalc() are outdated and that you need to get them again. There are rules as to what moves when, but unless you are really, really hurting for speed, just do it anyway. I don't think that existing files move when you make a new one but it doesn't hurt to make sure. Resizing almost always moves stuff around.
Since each file is nothing but a reserved space in memory, simply reading/writing to it is no different than manipulating a normal area in memory. From your description of the problem my guess would be that you are resizing or creating and deleting appvars which causes them to move in memory and throws off your pointers. If you are, remember that creation/deletion/resizing can be slow because it likely has to copy kilobytes of memory around. That shouldn't cause slowdowns if you do it once or twice a second, but I would avoid it in a loop. I would suggest using existing memory areas before resorting to appvars. There is a lot of built in memory if you look. Take a look at this if you want to to beyond what Axe's L1-L6 give you. It is pretty outdated in where it says Axe's variables are located so ignore those. For example 0x8000 gives you 256 bytes of memory and as long as you don't turn your calc off, it is perfectly free to use. (although it overlaps somewhat with the 756 byte buffer L4-512)

Here are some other fun facts that probably won't help you but may be interesting:
Appvars and programs are the same thing (as far as I know) and they only differ by one byte which tells what they are.
Pretty much any name is legal for a program/appvar as long as you don't intend on interacting with it through ti-os. You can make and edit programs with lower case names. Axe will even allow you to include and compile programs with lowercase names just like normal ones. Ti-os won't let you run a program with a lowercase name but as long as you compile to an uppercase program you will be fine. When transferring these programs to and from a computer, the ti-connect will irritatingly capitalize all the names.
"prgm#" and "prgm!" are special programs that hold recently entered stuff on the home screen. I don't remember exactly what each one does, but they exist. I'm not 100% sure on their names but I'm pretty sure those are it.
When you run a program, it gets moved to 0x9D95 (0x9D93 is the 2-byte size of the program) and then executed. So if you want to run a program from within an app, you can copy it there and just :Goto E9D95. Since there could be appvars there already, you should use some calls that aren't part of standard Axe to move anything that is there out of the way.

7
Math and Science / Re: A faster Newton's Method Square Root
« on: June 30, 2022, 08:54:36 pm »
Unless I am reading this wrong, float64's (or doubles as I will call them) get between 15 and 17 digits of precision compared to the 14 of a 9 byte BCD float. Wouldn't it be easier to use doubles then? Any 14 digit number the user enters can be represented perfectly. Sure, there will be some precision the user doesn't see but isn't that already the case since the OS only prints out 9 (10?) digits? I can't think of case where a double would cause a rounding error where a BCD wouldn't also. And that isn't taking into account that the OS uses 9 bytes and not 8.

Off topic note because I can't be bothered to find my Discord login: what emulator do you use? I have always used Wabbitemu but it tends to crash when I mess with flash.

8
Math and Science / Re: A faster Newton's Method Square Root
« on: June 29, 2022, 09:17:22 pm »
That is pretty neat! In all your dealing with floats did you come across a reason why ti-os uses 11 byte BCD floats? (with one whole byte for sign IIRC)
Is it just because BCD helps prevent any incremental errors?

Its a pity that I have (pretty much) finished my big z80 projects because there is several places I could have really used some floating points. I'm terrified by how close it's average of 1165 cycles is to a workaround I made a while ago using abs, min and max to calculate distance. I really need to set aside a weekend and add in floating points.

Testing gave me an average of 800 cycles for Axe's 16 bit integer square root. That's not much slower than your 32 bit floating point square root. Do floats just lend themselves to that kind of math?

Your link to GMP is broken...

9
Introduce Yourself! / Re: Hello!
« on: June 28, 2022, 08:36:00 pm »
Welcome! And here are some obligatory peanuts:
!peanuts

Zeda and myself are probably the two most active members with experience in Axe. Somehow I always manage to show up late to all the Axe related questions though. I blame Zeda for being too fast.

10
Ndless / Re: Ndless sdk toolchain not building
« on: May 15, 2022, 08:39:29 pm »
I googled and found this github page. I assume that is what you are using.

I'm not sure what the sdk is supposed to do, but I went ahead and just tried to get that file to run. I have a Debian partition and not Cygwin so any differences may of course be caused by the OS. I had a couple errors from libraries that weren't installed but after I installed them it got started for me. It errored out after ~30s of compiling due something or other. But it spit out a bunch of text.

I would suggest adding an echo to various lines so you can see how far it gets before exiting. That may give you an idea of what is causing the problem. Alternatively you can try setting up a virtual machine or using WSL and see if either gives better results. I haven't messed with Cygwin but I kinda doubt that it is the problem by itself but a fresh start may work if there is some system config that is causing the problem. If you give me a more detailed account of what you did I may be able to be more helpful. I don't know if @Vogtinator is still around...

Off topic, but why did you choose Cygwin over WSL?

11
Axe / Re: Looping Through an Array in Axe
« on: February 19, 2022, 07:20:09 pm »
@Ki1o
Wow... that's... the most beautifully formatted Axe code I have ever seen. It's not super efficient but who cares for level generation anyway. (and why ruin a work of art?)
I assume by [r1] you mean r1 and not {r1}.

I can't put my finger on the problem without the full source but I do see one thing that might be causing the problem.

In Connect to you do:
Code: [Select]
:If [r1]=°Below
:...
:Stuff
:...
:End
:If [r1]=°Right
:...
:Other stuff
:...
:End
You call subroutines in the first if block which modify r1. By the time you get to :If [r1]=°Right, r1 almost certainly doesn't hold its original value.


Here are a couple wild guesses and observations. They probably aren't right but who knows? Maybe...

The line :If AdjacentRoomY-1-{°RoomY+Room}+{°RoomHeight+Room}>4 bugs me. Do you want :If abs(AdjacentRoomY-1-{°RoomY+Room}+{°RoomHeight+Room})>4 ? I don't know what kind of values you are expecting but if you get -1 it will underflow to 65535 and return true. Values < -4 will act like expected but -1, -2, -3 might be a problem if they can ever happen.

The lines :Rand()^1->P :If P   don't do anything since any number ^1 is 0. I get it is probably for debugging but I thought you might have meant ^2 instead. The optimizer in me compels me to tell you that :If Rand() ^ 1 would be the same as those two lines and wouldn't use a variable. (But again, you probably already know that)

Once, when I was working on random level generation, I came across a bug that had me tearing out my hair for a week. I tracked it down to (usually) a crash when writing to OP1 which is free scrap memory. It moved around quite a bit - making it extra confusing. The crashing code was used many other places and didn't have any attached special conditions. I eventually found out that it was zStart's custom font causing Axe to incorrectly compile my code. I turned off my custom font and everything worked fine. (I had used that font for years by then and all 16 other programs in that project compiled perfectly - making it super weird) If you have a custom font, try disabling it. If Axe's font doesn't screw up and show garbage during compilation then you are fine. (It had done that for that specific program for years at that point so I didn't think anything of it)

I'm not super familiar with Axe's 3 argument For loop because I always use the 1 argument (because I am horny for optimizations) but it looks like in Connect you are filling 1 extra byte in the Fill command compared to the For loop.

If all else fails, try adding code to Connect to check every byte to make sure it is in bounds before writing it. If out of bounds, pause and display variables. Also draw the whole map in pixels to the screen every write (and maybe even slow it down so you don't miss anything) and make sure it is doing what you want.

12
Axe / Re: Questions with commands
« on: February 19, 2022, 06:30:30 pm »
hello
i just started using axe yesterday and wrote a simple program, and don't understand how "if" works. I've come here from Ti basic
here is my code
input"BRUH"->Str1
"BRUH"->Str2
GetCalc(Str2)->A
GetCalc(Str1)->P
If P=A
Disp"YAY"
End
!If P=A
Disp"NO"
End

I want it to only display "YAY" when "BRUH" is input, but for some reason it always outputs "YAY" no matter the input.
i am confused

@chucktheduck
Transitioning from BASIC to Axe is a pretty big jump. Although Axe's syntax looks like BASIC, it works in a completely different way. Very, very few segments of code work in both Axe and BASIC. You should be familiar with how pointers work. If you aren't, you should really spend 10-20 minutes reading about them because Axe uses them heavily. If you don't understand them, Axe will be one frustrating mess to use.


Code: [Select]
input"BRUH"->Str1 While this is valid syntax, it won't do what you think it does. It actually translates to:
Code: [Select]
:input
:"BRUH"->Str1
Which means it gets the user's input, does nothing with it and then stores the pointer of the string "BRUH" to Str1. Names like Str1 or GDB1 are constants. Their value can't change once the program has compiled. (The data they point to can change) This means they can't hold any value that you can't figure out when the program is compiled. Use variables to do that instead. Doing input->Str1 won't work because the value input returns may change, instead you need to use a variable like A. So: input->A


input returns a pointer to tokens. Tokens are different than characters because they can be 1 or 2 bytes long. I won't explain how they work because it is a bit complex. But if you stick to uppercase letters and numbers you will be safe because they are all 1 byte.

When debugging it is always useful to print the values of variables. Even if you are sure what they are, it is never a bad idea. :Disp A will try to print a string so it will look like gibberish. Instead, use Disp A>Dec to display it as a number. In your case, no matter what you input A and P will both hold 0. GetCalc returns a pointer to a file if the file exists in RAM or 0 otherwise. GetCalc("YAY") or GetCalc("BRUH") both return 0 because there is no file with either of those names. (So P = A) Files are things like "prgmTEST" or "appvSOMEDATA" You can use GetCalc to read and write to programs and appvars. I'm not sure what you are trying to do with it, but the documentation for it isn't very clear so I assume you misunderstood what it does.


Here is some code that should do what you want. I haven't tested it but I'm pretty sure it will work.
Code: [Select]
:.Comments start with a period. You don't need to include them in your code
:input->A            .Get a pointer to the entered tokens
:"BRUH"->Str2        .Get the pointer to the characters B, R, U, H. This line can be put anywhere in the program and it will function the same. I like to put my data at the end but that is up to personal preference.
:                  .If you want to test if two strings are equal, you need to loop over them and compare every byte.
:0->X                  .X holds where we are in the string. To compare equality, you need to loop over every byte in the string and compare it. (This is what other languages do too, they just hide it from you)
:1->Y                 .Y holds 1 for true. If we find an inequality, we should set it to 0 because the strings aren't equal
:For(length(Str1))         .Loop for the 'length' of Str1 Since input returns tokens and not characters, this may not work correctly if you use anything besides uppercase letters and numbers. (I won't explain why now because tokens are pretty complex)
:                              .The single argument for loop just runs the given amount of times. For(5) will run the body of the loop 5 times.
:!If {A + X} = {Str1 + X} .If the characters aren't equal save the value 0 to Y so we know they aren't the same
:0->Y
:End
:X++            .Increment X to the next character
:End
:
:If Y            .If Y is not 0 then the strings are equal
:Disp "YAY"
:Else
:Disp "NO"
:End


Additionally you can use Equ>String(A, Str1) to do the same thing as the loop. It is a good idea to understand how the loop works. Note that Equ>String returns 0 if the strings ARE equal and non zero if they ARE NOT.


If you haven't already, install a shell like zStart or DoorsCS7 to allow you to edit your code from archive. (this isn't a recommendation, its practically a must) Messing up in Axe means your calculator resets RAM so any programs left there will be deleted. I recommend zStart because it lets you press ON+Zoom to compile and run your code from within the editor as well as use ON+Vars to show a list of all Lbl's that you can then teleport your cursor to. Much easier than Alpha scrolling for large programs.


That was a lot. Hopefully I explained it all clearly. (If not, I am happy to explain more - I get really excited talking about Axe!)

13
Axe / Re: Looping Through an Array in Axe
« on: December 15, 2021, 07:31:06 pm »
I agree with Xeda about the parenthesis. I did notice you called main() and didn't return after that. Instead you fall through and run main() a second time and quit the program with its return. Since all main only does something when you hit enter, it shouldn't matter. Without picking through your logic, I can't say more.

Here are some tips for your code. What you have will work, but there are better ways for some things.

I would strongly recommend using the ? and ?? operators for 'and' and 'or'. The 'and' and 'or' you are using are bitwise. This means "1 and 2" returns false. The ? and ?? operators work like && and || in C and even short circuit which is nice. (the same left to right order of operations still apply) This means you can rewrite:
Code: [Select]
If (RoomX≥XMin and RoomX≤XMax) and (RoomY≥YMin and RoomY≤YMax)as
Code: [Select]
If RoomX≥XMin ? (RoomX≤XMax) ? (RoomY≥YMin) ? (RoomY≤YMax) .I omitted the first pair of parenthesis because of order of operations. You can add it in if you want, it will be compiled out
Using →→ is the same as → if the constant hasn't been declared before. No reason to change it if you don't want to. Just be careful you don't double declare constants as you won't get an error!

You can chain constant declarations together to make them easier to read.
Code: [Select]
L₄+12→→°XMin
L₄+14→→°XMax
L₄+16→→°YMin
L₄+18→→°YMax
L₄+20→→°Rooms
can become
Code: [Select]
L₄+12→°XMin+2→°XMax+2→°YMin+2→°YMax+2→°Rooms
Nice work on making a custom text routine! If all you are after is speed and flexibility, I made a super fast text axiom that can draw to any buffer.

As for putting rooms in the map, making a rectangle collision routine would probably make things a lot smoother. Here is one, I haven't tested it, but it is a translation of one that I wrote in C so it should work. It assumes the rectangles are in the format top_left_x, top_left_y, width, height.
Code: [Select]
Lbl Intersect
...
Since each rectangle is made of 4 points and we only have 6 parameters max, I will use A, B, C, D for the second rectangle. Change them to whatever you want
r1, r2, r3, r4 = the first rectangle
A, B, C, D = the second rectangle
returns 1 if the 2 intersect anywhere
...
max(r1, A) < min(r1 + r3, A + C) ? (max(r2, B) < min(r2 + r4, B + D))
Return

14
TI Z80 / Re: Elimination: An RPG inspired by Earthbound / Pokemon
« on: October 25, 2021, 05:40:41 pm »
That's pretty cool. Writing a project that large in asm must be really time consuming. Less than 10 app pages? That seems kinda large. My biggest project comes out to almost 16 pages but that is because it was compiled in Axe and is in greyscale. Do text and sprites eat most of that?

15
Other Calculators / Re: Darkblasters: A new graphical TI-84+/SE BASIC RPG
« on: September 22, 2021, 05:42:22 pm »
This looks great indeed!
I wonder, would it be possible (not too hard) to port it to the 'TI-84 Plus CE Color' to show us some of the game "true colors"?

I doubt a port would add much since the sprites are done by mixing characters. Also I think I remember hearing somewhere that 84ce text characters include a white background that would ruin it. But I dont have any color calcs so I don't know too much about them.

Pages: [1] 2 3 ... 23