I know why my Axiom didn't work... and it was not even my fault ! Its name was "AXIOM", and when I renamed it (by chance) "AXIOM2", it worked ! That means Axe Parser doesn't behave correctly when the Axiom used is named "AXIOM". You should fix it quickly, because other people may write Axioms and call them "AXIOM".
Wait ! It works ! I don't know what it changed, but thanks !
I take back what I said !(I'm kidding, of course I thank you : without you I would still have this error.)
No, the error didn't come from the compiler ! It was strange to me, because the two compilers generated the same output in the ".bin" file. In fact, when I compiled the source for the second time, I renamed the file "AXIOM2", instead of "AXIOM". And it made the difference ! There's a bug in Axe Parser I'm gonna immediately add to the bugs report list : you can't use Axioms if their name is "AXIOM", and this doesn't generate the error "INVALID AXIOM", but "INVALID TOKEN" wherever you use a command of the Axiom.
.org physically moves PC, as in, if you do .org $+8, the final compiled program will effectively have 8 zero bytes in the middle. I don't think TASM can do anything else related to PC, so I strongly recommend you using another assembler. I use SPASM, whose .org directive works the way you intend it to.
Downloading... Editing the "compile.bat" file... Compiling... Adding the file "AXIOM.8XP" generated to TI-Flash debugger... Wait ! It works ! There's no more "INVALID TOKEN" error ! I don't know what it changed, but thanks ! Now I can really start writing the Axiom...
What assembler are you using ? The .org preprocessor instruction have different behaviors depending on assemblers.
I'm using TASM. I know it has issues with the org directive, but I don't think it's the cause of my problem... I removed it, and I still have the same "INVALID TOKEN" error.
I'm not sure what shell you're trying to compile this for, but right now your shell compatibility byte is 0xCF = 0b11001111. That means that it's incompatible with applications and Axe fusion. If that isn't the issue, I can't say what the issue is by looking at that.
I'm trying to compile it to "No shell", as I always do - I never compile either to apps or to Axe Fusion (as it's buggy). I also tried other values : 0xFF for compatibility, and 0x01 for arguments, but it doesn't work, and I can't figure out why. I'll disassemble some Axioms to see how it works... But right now, I don't understand why I get the error "INVALID TOKEN".
As for increasing the number of arguments allowed, I'll look into it. Although I had a quick glance at the Axiom parsing code and was absolutely clueless about how it even checks the number of arguments, so it might not be easy for me to figure out.
Thanks. And it seems that Axe Parser doesn't recognize Axioms which starts with the header of compiled programs, even if then follows the Axiom header. It would be great to allow it.
I suspect the problem you're having is that Wabbitemu requires a copy of the boot code/certificate from a real calculator to run 100% accurately. As long as you have a link cable, you should be able to get this easily enough by going to Help > Re-run setup wizard...
And I've never used TI's flash debugger, but I suspect that Wabbitemu's debugging capabilities are as good or better.
I've reinstalled Wabbitemu, if one day I want to take an animated screenshot. Oh, I never noticed it had a debugger, which is quite nice, by the way. But I'm used to TI's flash debugger, and it runs faster on my computer (Wabbitemu is a bit laggy).
By the way, I tried launching programs from a bunch of shells, and I'm not sure how reliable writeback would be. I found tricky things like DoorsCS and CalcUtil putting the name of their appvars in OP1, and Ion sometimes leaving the name of the program in OP1 but pointing to something that's all zeroes... it all seems a bit too unreliable to me.
I've been playing with this for a while now. It seems that, at least for simple menus, this should be totally capable. But one problem I've run into so far is that, if I move the cursor into and then out of the number entry field, the dialog glitches out. Does this happen for you too, and/or do you have any idea why this would be happening?
Yes, it works very good for simple menus. We just need to create a function which will create automatically the menu structure into ramCode. I've not currently tested the number input (I'll do it later), and I don't know why this happens... I'm trying to make a MENU Axiom, but I have got a problem (see the spoiler). Also, it would be great to increase the maximum arguments for a command to 8 instead of 6 ! By the way, in the code I posted above, I've noted all the things the routine changes and doesn't restore. Do you think some of them can be annoying, and we should find a way (even if it takes some more bytes) to restore them ?
Spoiler For Problem:
EDIT : I don't know why, but I'm not able to create an Axiom using the Menu( token (and also using any other token) ! I tried the following simple code, and when I include this Axiom into an Axe source, I get the error "INVALID TOKEN" on the token "Menu(".
.dw $C0DE .dw routineStop-routineBegin ;size of the command .db $CF ;compatibility = all .db $E6, $00 ;token to match = menu .db $00 ;command type = inline .db $00 ;arguments count = zero .org $0000 routineBegin: ex de, hl ;this is just for testing routineStop: .dw $0000 ;no more commands
EDIT 2 :I don't know why, but I used TASM as compiler, and changing to SPASM solved the problem. EDIT 3 : In fact, you can't use any Axiom called "AXIOM". If you call it "AXIOM2" though, it's fine.
There are two RAM pages ; page 0 is mapped in $8000-$BFFF and page 1 is mapped in $C000-$FFFF. Else you would have 16kb of RAM, not 32kb ! (although only 24 are usable). It's just that ChkFindSym returns DE > $BFFF and B = 0 if the variable is in page 1. That's why it says B=0 is RAM.
Thanks for this explanation... So the instruction "in a, (6)" is here to make sure the page needed is mapped before making the bcall. But then, how could we restore the previous page mapped ? because the command should restore it before returning !
And the following code can be optimized into "ld hl, ($8006)"... Indeed, it works ! Great optimization ! Good old Zemmargorp, using bcalls to read from RAM...
The OS's all-input routines use the raw key scanning commands along with raw key hooks, so those latters must be saved before and restored after calling such BCALLs.
Ok. I don't know if it's that useful, because this hook isn't probably changed all the time, but I'll let it.
Port 6 controls the flash page currently mapped to $4000-$7FFF. I guess the BCALL maps another page to this zone, so the current page (retrieved with in a, (6)) must be saved in A for future restore. That's only supposition though.
Thanks, so that's the reason why the selection's index is stored there.
As I said above, the BCALL may map a specific flash page to $4000-$7FFF, so there's no reason why it wouldn't write the answer to an equally specific page. Also, page 1 is not flash but RAM, actually the only memory allowing for write.
I thought RAM was page 0 ?... A lot of bcalls, like "FindSym", returns B=0 if the value is in RAM, and else the page's number the variable is in. In fact, you mean they return B=0 if it's in the current flash page mapped, and B>0 otherwise ? But then I should be able to get this value without using bcall(_LoadCIndPaged) ? I didn't achieved to do it...
I found a way, which is in my opinion reliable, to use the system DIALOG bcalls to make custom menus, like in TI-Basic. And it may be added to Axe ! Currently, if you want to use it, download it here
The OS does not expose a very simple way to generate menus, which is why the feature does not exist. But if any assembly wizards want to provide the majority of a solution, I'll happily include it! That is, if I can fit it.
;Note : If the users presses [2nd] and [quit], the number returned will be the choice highlighted.
;It'd be great to find a way to backup the text screen and restore it later. ;There are other things this routine changes and doesn't restore, see the end of the code.
;The following lines backup the current "rawKeyHookPtr", which will be replaced. ;It uses the stack... it could use any RAM safe area, but they may be already used. ld hl, rawKeyHookPtr - 1 ld b, 4 hookBackup: inc hl ld a, (hl) push af djnz hookBackup ;Backups some settings, still using the stack ld a, (flags+34h) ;rawKeyHook active flag push af ld a, (cxCurApp) ;what kind of app is currently running push af ld a, 58h ld (cxCurApp), a ;Sets value to 58h=kExtApps="External Applications."
;Copy menu structure ld hl, structStart ld de, ramCode ld bc, structEnd-structStart ldir
;Prepares dialog : ld hl, dialogCallback in a, (6) ;Does any of the following bcalls changes the flash page mapped ? bcall(_DialogInit) bcall(_runIndicOff)
;Starts dialog bcall(_StartDialog)
;End of dialog bcall(_cursorOff) bcall(_clrLCDFull) ;I discovered that the choice's index is located into RAM, at $8006. I conjecture it is always stored here. ld hl, ($8006) bcall(_DispHL) ;Show the chosen item's index
;Restores previous settings res appCurWord, (iy+appFlags)pop afld (cxCurApp),a pop af ld (flags+34h), a ;Restores previous rawKeyHook ld hl, rawKeyHookPtr+5 ld b, 4 hookRestore: dec hl pop af ld (hl), a djnz hookRestore
;Some changes are not restored : ;- the indicator and the cursor are set off ;- "ramCode" and the text screen have been modified ;- appCurWord flag is reset
;Dialog's callback : dialogCallback: xor a ret
;Is it compatible with all shells (some shells might use ramCode) ?
Spoiler For Menu structure:
The menu structure is enough easy to be written by hand, but I've made a script to generate it automatically (see the download link at the beginning of this message). Here's how it works :
structStart: ;To make the title, there are three $01 bytes, followed by a pointer to the string. ;Note : you can add other titles anywhere in the menu, by using the same structure. .db 1 \ .db 1 \ .db 1 \ .dw sTitle-structStart ;Then, for the first choice, put the bytes $05, $01, $01 again, and the pointer to the string. .db 5 \ .db 1 \ .db 1 \ .dw sChoice1-structStart ;To add other items inside the menu, continue adding the $05 and $01 bytes, but increment the third byte for each new item, as it corresponds to the choice's index. Note : You can use numbers (from 0 to 9) randomly, and use the same number twice, but the number returned by the Menu( function will be the choice's row's index. .db 5 \ .db 1 \ .db 2 \ .dw sChoice2-structStart .db 5 \ .db 1 \ .db 3 \ .dw sChoice3-structStart .db 5 \ .db 1 \ .db 4 \ .dw sChoice4-structStart ;Note : You can't put more than 8 items (including the title). ;When it's done, add $00. .db 0 ;The strings must be added after the structure, and preceded by their length. ;Note : you can write them in the order you want ; you may not respect the menu's choices order. sTitle: .db 7, "COMPILE" sChoice1: .db 6, "Cancel" sChoice2: .db 7, "Noshell" sChoice3: .db 3, "Ion" sChoice4: .db 8, "MirageOS" structEnd: ;The menu is made.
Using TI's flash debugger, eh? I'd recommend grabbing a much better community-made emulator. My emulator of choice is Wabbitemu. I'll probably run these checks, too.
I've already installed Wabbitemu, but it's not so stable (for me, the latest Axe version doesn't work on it). And TI's flash debugger has a lot of useful features for assembly developers : disassembly, see RAM, etc. No, don't run these checks, it's a bit pointless since there's no ideal way to provide a reliable write-back.
That's great! Go ahead and make a new topic in this board with your developments so far. I can somewhat figure out how this all works too, we can get it polished up and ready to go into Axe.
Maybe I (or you) can round up all the main shells (MirageOS, DoorsCS, CrunchyOS, Noshell, CalcUtil, and zStart) and test this.
I've tried "Disp e8478" with some of these shells, plus Ion you forgot , and here are the results : it works without any shell, with Noshell, with Mirage OS (v1.2), with zStart (v.1.3.013_83). I wasn't able to download CrunchyOS (I don't know why). Unluckily, CalcUtil and DoorsCS don't work in the emulator I'm using. It doesn't works with Ion (at least for v1.6), but Ion clears OP1's value, so there's no problem.
Regarding the OS's DIALOG bcalls, I've achieved to find a way to know which item was chosen by the user, in menus like TI-Basic provides. I just need to improve a little the code source... I'll publish it somewhere, but not now.
After two hours of bug-tracking, I've solved a problem I had with the "TI-83+ Flash Debugger". Good to know : sometimes it says some data is located into RAM, whereas it's in Flash ! Nevertheless, I think I've got a stable menu routine ! There's still some little work to do, but I've got a great base (thanks to Brandown and his DIALOG notes and program). Where can I publish it ? Do I make a new topic inside "The Axe Parser project" ? Because if we want to be able to use these bcalls in a reliable way, I'll probably need help from experimented assembly programmers...
Yeah, I guess the store arrow doesn't close parentheses in Axe. Come to think of it, it doesn't close curly braces either. I'm not sure how big I'd be on changing this now, though, since it's been this way forever and there haven't been any other problems reported with the way it is. If I did want to change this behavior, I'd probably do it in the theoretical Axe 2.0, since lots of other language grammar changes would be made as well and I'd want to lump them all together.
No, seriously, like said Matrefeytontias, don't change this ! It's way better like it is ! Even in an Axe 2.0, even if there are others grammar changes ! When I said "But, unlike TI-Basic, the store arrow doesn't close the parentheses", it was only a remark ! Axe Parser is better than TI-Basic ! How could you write "X*2+(A*3+Y→Z)+GDB0" if the store arrow already closes the parentheses ?
I assume the bug we're talking about is the slight freeze? Are you sure this happens every time and not only when you've changed a setting in the options menu or the compile target type?
However, the potential problem I see is that, when run by a shell, it may not be the case that OP1 contains the name of the program being executed. Best case scenario, it doesn't contain the name of a variable, and no writeback occurs. Worst case scenario, it contains the name of another variable, perhaps Ans or some shell appvar, and then the writeback clobbers RAM. Maybe I (or you) can round up all the main shells (MirageOS, DoorsCS, CrunchyOS, Noshell, CalcUtil, and zStart) and test this. If OP1 turns out not to be reliable, it would be worth checking progCurrent, progToEdit, and nameBuff. EDIT: Alternatively, it may be possible to detect if the OS or a shell launched the program.
I know. It's risky. And even if it may be possible to detect if it's a shell which launched the program, it maybe also be possible that the shell hasn't got write-back enabled. And if this shell doesn't set OP1 = program's name... And there's a lot of shells to try. And we can't assure a complete reliable routine, which will works for future shells ! Rather hope the user uses a shell with write-back enabled, especially if the write-back feature is used to save the game's best score.
Regarding the OS's DIALOG bcalls, I've achieved to find a way to know which item was chosen by the user, in menus like TI-Basic provides. I just need to improve a little the code source... I'll publish it somewhere, but not now.