Here's another feature idea which will be useful, and this time I'm pretty sure it isn't implemented yet . Well, I hope so, because I've spent a quite big part of the afternoon writing the assembly code and debugging it, and if this feature was already available, I would have liked to use it before.
The idea is making a function a bit like GetCalc(, but which allows the developer to insert/remove bytes in a variable. I suggest using the ClrTable token, as it won't have any utility in Axe, and it's just next to GetCalc(. The token could be rename MemManage(, and take the following arguments : Variable,Offset,Size. If size is positive, memory is added, otherwise, it's removed from the offset. Using one token only has a big advantage : if the size is calculated by a formula, the developer doesn't have to test if it's positive or negative and use the corresponding function.
Spoiler For Code and information:
Variable is a pointer to the variable's name
The two first args must be in the stack, the last one (the size) in HL
The code checks if the variable exists, is unarchived, etc.
Returns 0 if it didn't worked, or else the offset in the file where bytes where inserted/removed
I haven't tried it with size=0. It'll try to add zero bytes to the variable... It might crash, or do nothing.
Don't try to use this routine with lists/matrix/numbers/etc, only with programs/appvars/strings/...
;p_IntNeg xor a sub l ld l, a sbc a, a sub h ld h,a
MemDelete: POP DE ;Offset to remove EX (SP), HL ;Variable name (SP = size) PUSH DE RST rMov9ToOP1 BCALL(_ChkFindSym) ;Look in the VAT, DE set to pointer to size bytes of variable) JR C, Error_Pop2 ;ERR: NOT FOUND XOR A OR B JR NZ, Error_Pop2 ;ERR: ARCHIVED
POP HL ;Offset to remove memory POP BC ;Memory needed PUSH HL ;Offset to remove memory PUSH BC ;Memory needed PUSH DE ;Pointer to size bytes INC DE ;Skip size bytes INC DE
EX DE, HL ;HL = pointer, DE = bytes ADD HL, DE LD D, B \ LD E, C ;Memory needed
BCALL(_DelMem) ;Delete the memory
POP HL ;Pointer to size bytes PUSH HL ;Pointer to size bytes
BCALL(_LdHLInd) ;HL = size of variable
POP DE ;Pointer to size bytes POP BC ;Memory needed XOR A SBC HL, BC ;Decrease size bytes
EX DE, HL LD (HL), E INC HL LD (HL), D INC HL
POP BC ;Offset to remove memory ADD HL, BC RET MemInsert: BCALL(_EnoughMem) ;Check if enough memory (stores value in DE) JR C, Error_Pop2 ;ERR: MEMORY LD B, D \ LD C, E ;Memory needed
POP DE ;Offset to insert memory POP HL ;Variable's name PUSH DE ;Offset to insert memory PUSH BC ;Memory needed RST rMov9ToOP1 BCALL(_ChkFindSym) ;Look in the VAT, DE set to pointer to size bytes of variable) JR C, Error_Pop2 ;ERR: NOT FOUND XOR A OR B JR NZ, Error_Pop2 ;ERR: ARCHIVED
POP HL ;Memory needed EX DE, HL POP BC ;Offset to insert memory PUSH BC PUSH DE ;Memory needed PUSH HL ;Pointer to size bytes INC HL ;Skip size bytes INC HL ADD HL, BC EX DE, HL
BCALL(_InsertMem) ;Insert the memory
POP HL ;Pointer to size bytes PUSH HL ;Pointer to size bytes
BCALL(_LdHLInd) ;HL = size of variable
POP DE ;Pointer to size bytes POP BC ;Memory needed ADD HL,BC ;Increase size bytes
EX DE, HL LD (HL), E ;Write new size INC HL LD (HL), D INC HL ;Pointer to data
POP BC ;Offset to insert memory ADD HL, BC PUSH HL ;Pointer to data
BytesInit: LD (HL), $41 ;Write 'A' INC HL DEC BC LD A, B OR C JR NZ, BytesInit
POP HL ;Pointer to data RET Error_Pop2: POP HL POP HL Error: LD HL, 0 RET
I'll probably make an Axiom with some useful stuff like this code, StoreLCD, #ApdOn and #ApdOff, push and pop, since we can't use all this currently in Axe.
As far as I can tell, you don't need to do anything special for APD to work properly besides enabling it and having the OS interrupt running. I imagine the hardest part of using APD successfully would be making sure other commands used while it's running don't turn it off, whether by disabling interrupts or actually turning off the APD running flag. And yes, APD does write the contents of the screen to L1 when turning the calculator off. I'm pretty sure that's unavoidable.
So if I want to use it I just need to use the OS's BCALLs EnabledAPD and DisableAPD ? Good to know. As L1 is 768 bytes long, I believe the APD uses it to store a copy of the LCD ? Like StoreLCD(L1) does ? Hmm... it'd be great to find a way to exchange L1 and L6 just before and after the APD runs.
The current iteration of Axe is entirely built around HL doing everything, so no, this wouldn't be very feasible to add right now. It's been suggested at least once before and is on a to-do list, but is waiting for for the theoretical Axe 2.0 with support for actual data types to break the shackles of everything being a 16-bit int.
Being able to remove all temporary variables is of course very easy to implement because it's just B_CALL(_CleanAll). But to be cautious of feature overload, may I ask in what context you imagine an Axe programmer would use this command?
If the temporary variables are removed before and after the program's execution, then there's no problem.
As for initializing all free RAM areas (to zeroes, I'm assuming): why? I can't imagine a case where this would be necessary. I can only think of a few use cases in which you'd need to initialize any single RAM area to zeroes, and I can't imagine them being needed so severely as to use all six free RAM locations.
I don't know why it'd be needed, but it may be used one day, as it's not completely useless. I had this idea when I saw the token ClrAllLists, as sometimes clearing RAM areas to zeroes is needed, and sometimes programs use several RAM areas.
Optimizing if statements that simply perform jumps has been looked into before, but the compiler currently lacks lookahead parsing and a strong peephole optimizer. If either of these is added (which isn't too likely to happen soon because I'm still quite unfamiliar with how the compiler works), then this optimization will surely be added as well.
In short, achieving adding a lookahead ability would improve the parser a lot
These all sound very shell-y, which Axe does not aim to natively provide features for. There would be too many features that would need to be added to allow for this very specific type of program to be made in vanilla Axe.
Like 8-bit ints, floating point data types would be added in the theoretical Axe 2.0. You could then name your floating point variables whatever you wanted, like basically every other language.
Ah... Nevertheless, for code readability, differentiation of types in the variable's name would be better.
The token Clear Entries (found in the MEMORY menu) could remove temporary variables (I think that the result of input is stored in a temporary variables, isn't it ?). Also, ClrAllLists could be used to initalise the free RAM areas, from L1 to L6. (See the BCALLs CleanAll and BufClr.)
I found two different ideas of use for Then : either it could be used to say that the following tokens of the same line should be interpreted only if debugging (by debugging I mean compiling with Zoom), or it could be used to optimize conditional jumps. In this last case, the Then should be used right after a If condition, and should be followed by a Goto instruction : this is roughly the equivalent of ReturnIf, but for jumps. There are some optimizations in assembly to do when Ifs are used to jump only.
What else... Adding a token (something like FullString) to ignore the split-screen modes, a token to generate custom error messages (I can't rememer the BCALL's name), why not using a token like Param which returns the calculator's type (TI-83+, 83+ SE, 84+, ...), another to check the battery level... I think I haven't forgotten anything !
By the way, if one day floating numbers are added to Axe, the tokens associated with the variables could be the matrix tokens (from [A] to [J], that is to say 10 variables, and 90 bytes required).
Although having the ability to do this across multiple lines seems appealing for optimization purposes, providing fully manual stack access would be a language design disaster. Ideally, the compiler will eventually be smart enough itself to make the kind of optimizations that tempt this design.
Yes, it's a dangerous command, but advanced developers would then be able to optimize their codes where the compiler isn't smart enough... But this level of optimization isn't probably needed when using Axe.
APD control is a nice idea. AxesOn/AxesOff sort of works due to starting with "A" but otherwise don't really sound right. I also sort of like PwrReg/PwrRegr due to actually meaning something about power. If I were to add this, I'd probably also want to add the ability to instantly power the calculator off, so I'd need to think about some way to represent that as well.
Yes, but then there's the problem of removing the copy of the program (or at least removing its reference inside the VAT, if it's pointed to in the VAT). And there's also another problem : the APD uses the RAM area L1, doesn't it ?
I was just about to say that this is easily doable... and then I remembered that the signed minimum and maximum commands, min(A,B)r and max(A,B)r, exist. That instantly makes it much harder, because the compiler wouldn't know if normal or signed comparisons are needed until after it has compiled all but the final comparison.
Ah, I see ! Neither did I think of it.
Something else : would it be easy (I don't think so, but I still want to write the idea) to add instructions a bit like #ExprOn and #ExprOff, called #1byte and #2bytes, who force Axe Parser to use A instead of HL for calculations ? Because sometimes only 1 byte is needed, for example and E3C becomes (instead of AND $3C) :
EDIT : I wrote "use A instead of HL", which means that accessing memory with the curvy brackets {} won't be possible, exceptions being if there's something like {...+GDB0}, where "..." is necessarily a one byte value. Also, it would still be possible to use the variables.
Considering that almost half of the keys don't correspond to actual tokens and couldn't be looked up in this fashion, it doesn't really seem worth doing this to me.
Well, if we take the letters as the key's token, approximately one third of the keys won't be covered... yes, it's still too much. Or maybe use i followed by a number, which is the keycode in TI-Basic ? because they're easy to remember, and it'll help people who programmed in TI-Basic to get into Axe.
Some other ideas : rename the RecallGDB and StoreGDB tokens RecallLCD and StoreLCD, and parse them as "L6:Asm(EF7B4C)" and "L3:Asm(EF7B4C)". They would respectively copy the LCD in the main buffer and in the back-buffer, which has many applications and I'm pretty sure it isn't currently possible in pure Axe.
Also, equivalents of the assembly push and pop instructions could be useful (maybe use the nPr and nCr tokens). Using the APD could be great. Also, Axe Parser could parse "min(A,B,C)" like "min(A,B):min(,C)" instead of generating the "WRONG # OF ARGS" error (same for other functions like this one).
EDIT : "Asm(EF7B4C)" is "BCALL(_SaveDisp)" in assembly, and destroys all registers. "save" and "load" could be nice names for push and pop. Additionally, the execution of the APD could be enabled and disabled during the code, so why not using two tokens, a bit like #ExprOn and #EprOff. And allowing three arguments for min( obviously means allowing as many args as needed by the user
Well I thought that "n" for newline and "i" or "!" to escape was good, not because newline starts with an "n" but because "n" looks like "\n" and "i" and "!" look like "\".
I slept on it, and now thinks that I could be good to replace progressively the i token by n for newlines. By the way, here's another idea of feature : i could be used before a token to return the key's index the token is on. We could write "!If K-i5" instead of "!If K-27" and having to learn all the key's indexes. Additionally, "ir5" would return the key's index of the getKeyr function.
The ! idea crossed my mind as well, and would also be a contender for an escape character. But the issue I have with it is that I'd ideally want it whatever token is chosen to be used for other escape sequences as well; being able to use it to include special characters in string data comes to mind. But I'd imagine that it isn't uncommon for ! to be found in string data, and the semantic change would instantly break some or all strings that used it.
Yes, but... there aren't so many solutions, are there ? We could still find tricks like doubling the ! token means to include it once in the string.
Maybe then you can use one of the tokens that we can find in the "Caractères" menu (available when we use a translating app) ? like the "¿" or the "¡" (not an "i", a reversed "!") for example ?
I don't think this is a good idea : to use these tokens, people would have to install a translating app, 16kb lost, and tokens translated, which is not very convenient for English people. Otherwise, Axe could automatically add this menu in the catalog, which would be a great thing.
Not only beginners unfortunately. What's great with France is that 15MHz calc are (were) not many so French Axe coders seem to avoid the Full command
*Faints.*
That's not false, but it'd also be great if all french Axe coders had 15 MHz calcs and were able to use the Full command. For instance, I'd need it in an old math program I made with Axe... it was quite slow.
Well I never use Disp so I never use i, so I don't really care if it is renamed n Plus the fact you said n is more logical for a newline.
I also like Zemmargorp's idea about the "!", which not only lets Disp untouched but also lets you an open door for your complexes
You never use Disp ?
Yes, n is more logical for a newline, but would i be more logical for a token not to be interpreted by the parser ? And people are used to i to insert a new line, to introduce a new line, to *lack of ideas*...
Using ! as the escape token would also let a new token free : n. We don't really care about the complex numbers yet, as we don't even have access to reals, and when they will be included (if they will be one day) there will probably be major syntax/token changes.
For short, you mean some beginners think the "Full" command exists to make games faster instead of optimizing them... Argh ! *Thinks to bytes not saved, extra battery/CPU use, incompatibility with TI-83+...* I know, its use is to make games faster but... if they can be optimized instead...
EDIT: One "clever idea" I thought of was changing the primary method of displaying a new line on the homescreen to Disp n and claiming i for this.
Why not, but the i token is easier to reach than the n token, and newlines will be more used than the escape token. Except if you choose that Disp i will always be a valid syntax and won't be deprecated, but this is a bit weird. I thought using n as the escape token was a good idea... Otherwise, it's still possible to find another token like ! which is only used in conditionals, and which could be used (outside conditionals) as the escape token.
Actually no offense to any Flappy Bird calc remake authors, but unless they use grayscale or 3D, I would hope that their games is at least 6 MHz, considering Supersonic Ball still runs at 13-15 FPS at 6 MHz even with parallax scrolling and collision detection.
Of course most calc Flappy Bird games are good, but I mean it's possible to get monochrome Axe games with minimal physics and simple collision to run fast enough on a regular 83+
I am totally agree with you. There's no point in making small minigames like this one (without 3D/grayscale/animations/etc.) if they require 15 MHz to run correctly !
Regarding the pipes, I think you are not alone to have used Super Mario v2.0 pipes because other clones had identical or very similar-looking pipes. It's because as you said, the original Flappy bird game used sprites from Mario, though
If I was you, I would make it as simple as BASIC did, but perhaps with extra options and the ability to have more than 7 items at once. In BASIC, for example, it's impossible to make the title so that it uses black text on white background like the rest, and you are limited to a maximum of 7 menu items. Of course it would depend how much space there is for this, though.
It'd be better to have the title in inverted color, but currently, the only way I found to display the title is in black on white. And I'd love to find a way to have more than 7 items, but adding items beyond 7 makes it crashing...
Thanks for helping to demonstrate for me how this stuff works. I'll try to implement those kind of simple menus into native Axe. I haven't been able to think of an easy/elegant way to allow for inclusion of the mode menu style selections or window menu style numerical inputs, so those may be left out.
I had an idea of syntax to implement it in Axe Parser. But you can decide to implement it like in TI-Basic (I'll give you the source code), and change it later (in Axe 2.0 ?). Additionally, numerical inputs returns floating point numbers... (it might be possible to change the parsing method, but... it would be some work too).
This is awesome Zemmargorp, but as a future advice I would recommend avoiding reposting the same message multiple times in different topic, as this could be considered spam. The two other messages (in the axiom thread and your new topic should be enough)
Thank you ! I know three messages is a lot, but as I posted earlier information about this axiom in this topic, I wanted to write I finished it, in case somebody here saw the other messages and wondered if the project was made or not. But you're right : the way I posted it looks a bit like an ad !