6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Apr 27, 2024 5:38 am

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: Adding Commands
PostPosted: Sun Sep 22, 2013 3:19 am 
Offline
User avatar

Joined: Sun Dec 29, 2002 8:56 pm
Posts: 449
Location: Canada
I'd like to try adding a 'BYE' command to the basic which causes the basic interpreter to quit and exit back to the operating system.

Any tips on how to implement this ?

_________________
http://www.finitron.ca


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sun Sep 22, 2013 5:27 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8144
Location: Midwestern USA
Rob Finch wrote:
I'd like to try adding a 'BYE' command to the basic which causes the basic interpreter to quit and exit back to the operating system.

Any tips on how to implement this ?

Timesharing business BASICs (e.g., MAI BB86, Thoroughbred Dictionary-IV) have a RELEASE verb that terminates the session and exits to the OS. The syntax RELEASE 4 would return the 4 as an exit value to the shell.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sun Sep 22, 2013 6:57 am 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
I've just been glancing at the source code, I don't know for sure, but adding a command should be reasonably straight forward. All of this is supposition, I don't know.

The first step is defining a TOKEN value for it. This is done around line 296, you can see all of the token values defined. It starts with TK_END, and a value of $80, then rest build incrementally from there.

Couple of issues that I don't know of the top of my head.

1) is there even any room for another token, I assume a token must start with the high bit set, and there are a lot of tokens here, so there may well not even be room for another token. I would run the assembly listing and then look for the value of TK_MIDS. If it's less than $FF, then you should have room. If not, then you'll need to remove something.

2) I don't know if the order of the tokens matter. I sense not, but I'm not sure. He has them broken up in to primary commands, secondary commands, operators, and functions. It appears to be simply organization, rather than architecture. In theory, to be consistent, you would insert TK_BYE after TK_NMI, and update the definition for TK_TAB. But I'm not sure if you MUST do this, since you're defining a primary command.
Code:
TK_BYE  = TK_NMI+1
TK_TAB  = TK_BYE+1

Moving on...

Next, you need to define the code that is invoked when the command is executed. These are identified by LAB_XXX labels. In your case, LAB_BYE would be appropriate. (Mind, LOTS of things are identified by LAB_XXX, but within that set are the actual command runtime routines.). Since your code is just an escape, it should be a straight forward JMP to some known place, or a BRK, or whatever, so you don't have to know anything about the actual BASIC runtime here. Just make sure you cold start BASIC if you try to come back, or you'd likely be in trouble.

You'd probably, again for consistency, put your code just before LAB_MAX, which comes after all of the interrupt code and runtime for LAB_NMI.

Next...

Add your runtime routine to the command table, at LAB_CTBL. This list is in TOKEN order, so, again, you would put your entry just after LAB_NMI, and it would look something like:
Code:
.word LAB_BYE-1

Continuing...

Add the command to the command text table. Since the name of your command is BYE, you would put this in the B section, identified by TAB_ASCB. These lists are ALPHABETICAL, but BYE is going to be at the end anyway, so add your entry after LBB_BITTST. It will look like:
Code:
LBB_BYE   .byte "YE", TK_BYE    ; BYE

Then...

Add the entry for the LIST command decode table at LBB_KEYT. This is in TOKEN order, so your entry will be after NMI, again, and will look like:
Code:
.byte 3,'B'
.word LBB_BYE


And that should be it.

Good luck, let us know if I guessed right. I only looked at this thing for a couple minutes.


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sun Sep 22, 2013 4:07 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1681
Location: Sacramento, CA
I added the SYS command to my EhBASIC's to allow you to go back to the Monitor. These are my notes from the change log:

Code:
add these lines after TK_NMI
; added tokens
TK_SYS      = TK_NMI+1      ; SYS token
Just below this line, modify TK_TAB with the new TK_SYS pointer
TK_TAB      = TK_SYS+1      ; TAB token

At bottom of table LAB_CTBL, add this line
   .word   SYSjmp-1      ; SYS


Right below label LBB_SWAP, add this line:
LBB_SYS
   .byte   "YS",TK_SYS   ; SYS  **Added
   .byte   $00

At the bottom of the table with label LAB_KEYT, add these line2:
   .byte   3,"S"         ;
   .word   LBB_SYS         ; SYS


I don't recall many details, but I think there are two groups - Primary commands and secondary. This is a primary command. I was able to figure it all out from the comments in the code.

I hope this helps!

_________________
Please visit my website -> https://sbc.rictor.org/


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sun Sep 22, 2013 7:29 pm 
Offline

Joined: Sat Oct 20, 2012 8:41 pm
Posts: 87
Location: San Diego
See the 5th post down. --> viewtopic.php?f=5&t=1341


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Mon Sep 23, 2013 4:11 am 
Offline
User avatar

Joined: Sun Dec 29, 2002 8:56 pm
Posts: 449
Location: Canada
Thanks for the tips, I think I've got it working.

The command exits EhBASIC and returns to my OS, bit sometimes the OS reboots as a result.
The OS is still buggy...

_________________
http://www.finitron.ca


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sat Feb 01, 2014 2:33 pm 
Offline
User avatar

Joined: Wed Sep 03, 2003 6:53 pm
Posts: 150
Location: Long Island, NY
All --

Adding to this thread a bit, how would you recommend dealing with optional parameters? For example, my Commodore IEC extensions can have an optional device number for the disk drives. Device 8 is assumed unless otherwise specified. Here's the code:

Code:
   ldx #$08   ; default to unit 8
   stx CMD_DEV   ; save default device for current command

   jsr LAB_SCGB   ; check for "," and get byte to X
   cpx #$08   ; Below 8?
   bmi DSERR   ; yes...error
   cpx #$0b   ; above 11
   bcs DSERR   ; yes...error
   stx CMD_DEV   ; overwrite default device
  {code continues}


LAB_SCGB automatically returns Syntax Error if the comma isn't found. So, is there a better routine buried within EhBASIC that deals with this?

Also, a few disk commands require both numeric and string parameters -- any recommendations on parsing those?

Thanks!

_________________
Rich Cini
Build Master and maintainer of the Altair32 Emulation project
http://cini.classiccmp.org
http://altair32.classiccmp.org


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sat Feb 01, 2014 4:02 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
Before calling LAB_SCGB you could check for end of statement with LAB_GBYT. LAB_GBYT returns Z=1 if end of statement (null or ":") and you can skip the call to LAB_SCGB with a simple BEQ.

Generally LAB_PRINT is a good place to check how to implement parsing as it works with any mixture of variables but of course also with none.

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sat Feb 01, 2014 4:17 pm 
Offline
User avatar

Joined: Wed Sep 03, 2003 6:53 pm
Posts: 150
Location: Long Island, NY
Great, Klaus, thank you. Just made the change and it works fine.

I will check out _PRINT as well.

I'm also adding an "LLIST" command which will echo to the printer.

_________________
Rich Cini
Build Master and maintainer of the Altair32 Emulation project
http://cini.classiccmp.org
http://altair32.classiccmp.org


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sun Feb 23, 2014 3:47 am 
Offline
User avatar

Joined: Wed Sep 03, 2003 6:53 pm
Posts: 150
Location: Long Island, NY
All --

I've made some good progress in the last week or two. The boards I had made work fine so I'm going to do a larger quantity order.

I'm presently working on adding more commands to EhBasic...LLIST is the command I'm working on right now. It works...mostly...but I've discovered an anomaly that I'm sure relates to me not fully understanding how EhBasic dispatches commands.

While LIST will work with no command line parameters, LLIST doesn't. But, if I "LLIST 10-100" it works fine. So, even though I'm saving the registers, something is getting messed up.

Here's the code:
Code:
LAB_LLIST

   pha
   txa
   pha
   tya
   pha

  {code deleted - it just initializes the printer; uses only .A)

GOLIST            ; device exists, so list program
   lda    VEC_OUT      ; save current output vector $2e
   sta    LPVP
   lda    VEC_OUT+1
   sta    LPVP+1
   lda    #<CIOUT      ; trap vector and redirect
   sta    VEC_OUT      ;$0207
   lda    #>CIOUT      ; character to output is in .A
   sta    VEC_OUT+1
   pla
   tay
   pla
   tax
   pla
   jsr    LAB_LIST   ; go list it
   lda    LPVP      ; restore output vector
   sta    VEC_OUT
   lda    LPVP+1
   sta    VEC_OUT+1
   rts


What am I missing here? I figured that saving the registers would do it, but it doesn't. A fresh set of eyes would be helpful and much appreciated Thanks!

_________________
Rich Cini
Build Master and maintainer of the Altair32 Emulation project
http://cini.classiccmp.org
http://altair32.classiccmp.org


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sun Feb 23, 2014 2:56 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
Maybe you should save the processor status as well (PHP PLP).

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Sun Feb 23, 2014 3:57 pm 
Offline
User avatar

Joined: Wed Sep 03, 2003 6:53 pm
Posts: 150
Location: Long Island, NY
Klaus2m5 wrote:
Maybe you should save the processor status as well (PHP PLP).

Yes, that was it. Works perfectly now. I guess I have to be extra-careful in saving the processor context.

Thanks Klaus!

_________________
Rich Cini
Build Master and maintainer of the Altair32 Emulation project
http://cini.classiccmp.org
http://altair32.classiccmp.org


Top
 Profile  
Reply with quote  
 Post subject: Re: Adding Commands
PostPosted: Mon May 11, 2020 1:45 pm 
Offline

Joined: Mon May 11, 2020 1:07 pm
Posts: 1
Hi Everyone, sorry for posting in an old thread but I'm having difficulty figuring this out myself and need some advice.
I figured out most of what I needed to do with the tables / token etc. though, I originally added the vector to LAB_FTBL and had no success at all.
After reading through this thread, I moved the vector to LAB_CTBL and changed the token placement to match, now, I can get it to run without a syntax error so I know I'm on the right track but adding arguments always results in a syntax error. Out of desperation, I even tried this:
.word LAB_PRINT-1 ; PRINT <-----------------------The original "PRINT" entry
.word LAB_CONT-1 ; CONT
.word LAB_LIST-1 ; LIST
.word LAB_CLEAR-1 ; CLEAR
.word LAB_NEW-1 ; NEW
.word LAB_WDTH-1 ; WIDTH new command
.word LAB_GET-1 ; GET new command
.word LAB_SWAP-1 ; SWAP new command
.word LAB_BITSET-1 ; BITSET new command
.word LAB_BITCLR-1 ; BITCLR new command
.word LAB_IRQ-1 ; IRQ new command
.word LAB_NMI-1 ; NMI new command
.word LAB_PRINT-1 ; TESTFUNC <----------------------My new function, pointed to LAB_PRINT
it's in the same table as PRINT so I figure it should essentially work as PRINT but it still gives a syntax error if I add arguments, ie:
testfunc <------Works
testfunc "hello" <------Syntax Error

It's as if there should be some sort of pre-process like in the case of a 'function' but there's no such table.
I basically need to create a function which is provided a string so modelling it on Print seems to be a logical approach.
Can anyone please suggest what I have missed here?


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: