Omnimaga

Calculator Community => Major Community Projects => The Axe Parser Project => Topic started by: Zemmargorp on August 02, 2014, 12:34:44 pm

Title: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 02, 2014, 12:34:44 pm
Good news, everyone !

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 (http://www.omnimaga.org/the-axe-parser-project/menu(-command-using-os's-bcalls-need-assembly-help/msg391091/#msg391091)  ;)

(http://www.omnimaga.org/the-axe-parser-project/menu(-command-using-os's-bcalls-need-assembly-help/?action=dlattach;attach=17914)

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.  :P



If you want to see how it works :

Spoiler For Asm code:
Here's the main part of the source code. Most of it comes from the program of Brandonw (http://brandonw.net/calcstuff/ddemo.zip).

;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.

Title: Re: Menu( command using OS's bcalls - need help
Post by: Matrefeytontias on August 02, 2014, 09:04:46 pm
Quote
;Does anyone knows why it's actually required to change these flags for a menu ?
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.

Quote
;<-- What does this line exactly does ?
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.

Quote
;Is it always the case ? Does anyone know why ?
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.

Quote
;What does this line does ?
According to WikiTI :
Quote from: WikiTI
Official Name: appCurWord

Set to have the text cursor cover the entire token.

Quote
;There must be an easier way to do this.
textShadow is $8508 and only 128 bytes large, so :
Code: [Select]
  ld hl, $8508
  ld de, $8509
  ld (hl), 0
  ld bc, 127
  ldir
Actually, this only erases the screen's backup. The job of textShadow is to hold a copy of the large-font chars that were on your screen before you changed context (by entering a menu for example).

Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 03, 2014, 09:06:35 am
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...

The job of textShadow is to hold a copy of the large-font chars that were on your screen before you changed context (by entering a menu for example).
So we should use it to backup the screen before the menu is set, and restore it later.

Thanks for your help. I'll update the source as soon as I can.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Matrefeytontias on August 03, 2014, 12:22:32 pm
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.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 03, 2014, 12:54:52 pm
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  ;D  ! Good old Zemmargorp, using bcalls to read from RAM...  ::)
Code: (Very bad code) [Select]
ld b, 1
ld hl, $8006
bcall(_LoadCIndPaged)
ld h, 0
ld l, c
Title: Re: Menu( command using OS's bcalls - need help
Post by: Runer112 on August 03, 2014, 09:10:12 pm
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?

EDIT: A bit of testing seems to suggest that it's some compatibility issue with Omnicalc and/or zStart. My guess would be a hook; probably the parser hook, which parses things like numerical input.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 04, 2014, 10:27:14 am
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(".
Code: (Axiom source) [Select]
.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
Code: (Axe source) [Select]
.ERROR
#Axiom(TEST)
Menu(
Spoiler For Problem solved !:
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.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Runer112 on August 04, 2014, 03:53:45 pm
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.

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.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 05, 2014, 08:37:54 am
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.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Matrefeytontias on August 05, 2014, 08:52:55 am
What assembler are you using ? The .org preprocessor instruction have different behaviors depending on assemblers.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 05, 2014, 09:10:58 am
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.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Matrefeytontias on August 05, 2014, 09:24:17 am
.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.

Download SPASM : http://wabbit.codeplex.com/releases/view/45088
Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 05, 2014, 09:56:59 am
.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.

Download SPASM : http://wabbit.codeplex.com/releases/view/45088 (http://wabbit.codeplex.com/releases/view/45088)
Downloading... Editing the "compile.bat" file... Compiling... Adding the file "AXIOM.8XP" generated to TI-Flash debugger... Wait !  :o  It works ! There's no more "INVALID TOKEN" error ! I don't know what it changed, but thanks !  :thumbsup:  Now I can really start writing the Axiom...
Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 05, 2014, 10:55:27 am
Wait !  :o  It works ! I don't know what it changed, but thanks !  :thumbsup: 
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.
Title: Re: Menu( command using OS's bcalls - need help
Post by: Zemmargorp on August 06, 2014, 09:15:20 am
*Currently working hard on an Axiom that doesn't work very well (http://www.omnimaga.org/the-axe-parser-project/bug-reports/msg391024/#msg391024)...*

EDIT : Finally, I've solved the big problems I had ! First, I wrote somewhere ".db" instead of ".dw", (which is, for the compiler, unforgivable) and then, it seems that Axe Parser doesn't like when you put data (and not code) inside an appvar. I'm happy that's done. Now, well, let's code !
Title: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 07, 2014, 01:34:42 pm
I've finally finished the Menu( axiom !

You can only use it like in TI-Basic, by writing Menu("WHO ARE YOU?","A BOY","A GIRL","A CALC"). Note you can't use labels as arguments. The function returns the selected choice's index. But there's a readme to explain it, and even its french translation.

EDIT : I improved the readme and translated it in french. No changes have been made to the axiom.

EDIT 2 : No more beta ! Final version released  :)
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Matrefeytontias on August 09, 2014, 03:50:03 pm
Wait, that means you can only have up to 5 choices right ?

Also, maybe you can display the title in inversed font, like Basic menus.

Apart from this, well done ! I'm sure many persons were waiting for this to pop out :)

Les Français vaincront ! :D
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Keoni29 on August 09, 2014, 04:53:33 pm
YES finally! A quick alternative to creating your own menu system every time you write an axe program! This slipped under my radar, but I am glad I see it now!
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 09, 2014, 05:46:32 pm
Wait, that means you can only have up to 5 choices right ?

Also, maybe you can display the title in inversed font, like Basic menus.

Apart from this, well done ! I'm sure many persons were waiting for this to pop out :)

Les Français vaincront ! :D
No ! You can have up to 7 choices ! If you had downloaded the zip (nobody did, but I got two points of karma : that's funny !), you'd have seen I provided an alternative which consists of generating data corresponding to the menu (I've made a generator in the zip), and sending an pointer to the data using this syntax : "Menu(GDB0)rr".

Yes, but I don't know how to display the title in inversed font, because it's the OS routine which draws the menu.

Probably, and I hope it will be useful !

Pourquoi pas, ça m'irais bien !  ;D


YES finally! A quick alternative to creating your own menu system every time you write an axe program! This slipped under my radar, but I am glad I see it now!
In fact, I published it today, so you're one of the first people to see it !
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: DJ Omnimaga on August 14, 2014, 01:02:56 am
This is interesting. I will most likely not use it since I don't code in Axe anymore but I know some people might not necessarily need complex menus in their games and might just want to use the default TI-OS ones.  In BASIC too it was pretty convenient and not too intrusive, game-design-wise, so it's good that they can now be used in Axe too. :)
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 14, 2014, 12:32:22 pm
This is interesting. I will most likely not use it since I don't code in Axe anymore but I know some people might not necessarily need complex menus in their games and might just want to use the default TI-OS ones.  In BASIC too it was pretty convenient and not too intrusive, game-design-wise, so it's good that they can now be used in Axe too. :)
Thank you. And, yeah, I'm one of these people who might not necessarily need complex menus...



I'm thinking of the syntax of the Menu( command, for Axe... First, I think it'd be better that this functions returns the selected item's index, instead of jumping to a specified address. Sometimes you don't need to jump : this is the case if the menu is used in a game to ask the number of players. Additionally, it would be a shame to have menus limited to one title and only two choices, as for now commands are limited to six arguments. If you want it to jump to labels, you can use it in combination with Z-Test. But there are still different ways to include it :
What do you think ? (Personally, I think using both would be a waste, but I don't know which solution is better.)
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: DJ Omnimaga on August 14, 2014, 01:10:30 pm
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.
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 16, 2014, 06:44:22 am
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...
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Hayleia on August 16, 2014, 06:54:42 am
Couldn't you use set 3,(iy+5) before writing the title, then res 3,(iy+5) after writing it to have it written in inverted color ?
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 16, 2014, 08:36:05 am
Couldn't you use set 3,(iy+5) before writing the title, then res 3,(iy+5) after writing it to have it written in inverted color ?
No, I thought of it, but the menu is written in one fell swoop by the OS's routine, which must configure all the flags before.
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 27, 2014, 05:39:28 am
As I'm not working on this axiom anymore (even though I had ideas of improvements), I decided to share the source code with you. In "you", I include ISSOtm who asked me the source code, and Runer112 if he wants to add it to Axe. However, either if you're going to download it or if you're one of the two people mentioned before, I recommend you to read the notes I wrote in the two spoilers of the first post of this topic (http://www.omnimaga.org/the-axe-parser-project/menu(-command-using-os's-bcalls-need-assembly-help/msg390729/#msg390729).

And I hope the 5 people who downloaded the final axiom were happy to be able to use this feature in Axe  ;D
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: ISSOtm on August 27, 2014, 09:27:08 am
It seems there is a conflict between your axiom and zStart (which would be quite annoying, because it is a very common shell) :

I had zStart installed (with every options activated), and I ran the following program (once compiled with Axe) :
Code: [Select]
.BUGGY
#Axiom(MENUS)
Menu("TITLE SCREEN","CHOICE1","CHOICE2","CHOICE3")

The program worked fine, but after the execution, almost every zStart's hooks were off : only the custom font was still on.
Title: Re: [Axiom] Menu( using OS's bcalls (finished !)
Post by: Zemmargorp on August 27, 2014, 09:46:10 am
It seems there is a conflict between your axiom and zStart (which would be quite annoying, because it is a very common shell) :

I had zStart installed (with every options activated), and I ran the following program (once compiled with Axe) :
Code: [Select]
.BUGGY
#Axiom(MENUS)
Menu("TITLE SCREEN","CHOICE1","CHOICE2","CHOICE3")

The program worked fine, but after the execution, almost every zStart's hooks were off : only the custom font was still on.

Like you said, it's a bit annoying, as zStart is a common shell. I suppose you've downloaded the axiom's source code : as you can see, most of the ram areas (including hooks) modified by the routine are restored after displaying the menu, the only noticeable exception being ramCode, located at $8100, and 304 bytes long. If zStart uses this area to store his hooks (which is weird because ramCode is used when the OS is writing to Flash and to store graphical data), then we know why you encountered this problem.

Does anyone knows what causes the problem, or if zStart uses ramCode ?

EDIT : Just remembered that Runer112 already had this problem (but with number inputs, not basic menus) :
A bit of testing seems to suggest that it's some compatibility issue with Omnicalc and/or zStart.