Neolithic Tiny Basic

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: Neolithic Tiny Basic

Post by Yuri »

Yuri wrote:
barnacle wrote:
p.s. shame the 6502 doesn't have a complement carry instruction...
Maybe something like so?

Code: Select all

is_alpha:
    ora #$20
    cmp #$7B
    ror
    eor #$80
    rol
    rts
EDIT: I'll get the right values in there sooner or later... @_@

Blah, still flawed with values less than 'A', feel like you don't need 4 compares tho....

Here we go, few more tweaks:

Code: Select all

is_alpha:
	cmp #'A'
	bcc not_letter
	
	ora #$20
	cmp #$7B

	ror
	eor #$80
	rol
	
not_letter:
	rts
I presume you want carry set if it is a letter, and clear if not.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

First make it work, then make it smaller/faster/prettier/more elegant!

Neil

p.s. my initial take covered all the 'is' routines with a 96-entry table with the appropriate bits set for isalpha, isspace, isupper etc but it turns out smaller this way; most of the options aren't actually required.

p.p.s.

Code: Select all

isalpha:
   ora #$20        ; make it lower case
   cmp #'a'
   bcc is_no
   cmp #'z' + 1
   bcc is_yes            ; it's alpha
might be a quick optimisation.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Neolithic Tiny Basic

Post by barrym95838 »

I think you may be flirting with the optimal ASCII solution Yuri, but I don't have time to assist right now ... dumb job always ruining the fun!
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

I think Yuri's approach will work, but I already have is_yes and is_no for other 'is...' tests close to this one.

Neil
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: Neolithic Tiny Basic

Post by Yuri »

barrym95838 wrote:
...dumb job always ruining the fun!
They can be pesky like that. :mrgreen:
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

It looks as if assignment of both variables and the string $ are now working. That enabled me to continue and I think complete print, which includes unformatted and column-aligned variables, and the string $ and a zero-based index $ which prints the ith character of $.

That's pretty much all of the immediate commands finished. Now for the hard bit...

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

We have some progress.

I can enter and list a program, in any order, and delete or replace existing lines correctly.
I can print complex expressions in immediate mode (i.e. without a line number) and assign them to a numeric variable.
Ditto for setting the string variable and printing it either as a whole or printing an indexed character therein.
I can run a program... provided it uses only assignment or printing (all I've written so far), and with an odd bug: a second assignment doesn't seem to assign. More investigation required.

Neil

edit: ah, it's not doing assignments at all, if running. Should be easier to find. They work fine in immediate mode.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Well that was easy. I didn't use the formal 'let' for assignment, and the default of not using 'let' is handled by code which calls assignment and not by assignment itself. And while I had written that test (if the line starts with alpha, call assignment) in the immediate mode, I hadn't yet got around to it in the execution loop.

Oops :mrgreen:
Screenshot from 2025-02-08 08-08-27.png
Next steps: add that default handling, then start on the loop constructs.

Neil

(it is remarkable both how easy and how frustrating it is to translate a working C program by hand, as it were. I _know_ that the logic is correct, but I still make silly errors like forgetting an # in an instruction. And some of the primitives appeared to work the first time around but turned out to have subtle flaws - see the discussion of 'isalpha' recently.)
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

1) ' (rem) works
2) end works
3) goto works

Now everything else needs an equivalence routine, so I'd better get on with that. I just excised a load of helper code, which isn't required now I'm using Symon, and the current code size is 3084 bytes.

Neil

Neil
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Neolithic Tiny Basic

Post by drogon »

barnacle wrote:
1) ' (rem) works
2) end works
3) goto works

Now everything else needs an equivalence routine, so I'd better get on with that. I just excised a load of helper code, which isn't required now I'm using Symon, and the current code size is 3084 bytes.
Not bad!

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Finally got gosub working:
Screenshot from 2025-02-11 22-35-37.png
That took a long time to debug... this while statement originally had an issue in that depending on the values of Y and A it might fail to pull one of them from the stack, so the bug appeared depending exactly on the basic code I wrote.

Code: Select all

;	while ((NULL != where) && (ERR_NONE == err));
	lda err
	bne gos_99		; ERR_NONE == 0 so bne = an error
	pla
	sta maths1
	ply
	sty maths1+1	; where is now in maths1
	ora maths1+1	; NULL?
	beq gos_99		; yup, break
	lda maths1		; Y:A should have 'where'
	phy
	pha
	jmp gos_1
Can't help feeling there's a way to check that Y:A isn't zero without killing one or the other, or as I've done here, used a spare pair of variables. (gos_1 is above this and contains the bit where a line is interpreted by the gosub routine).

It might be that I can refactor the C version to check things in different places...

Neil
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Neolithic Tiny Basic

Post by barrym95838 »

Yuri wrote:
barnacle wrote:
p.s. shame the 6502 doesn't have a complement carry instruction...
Maybe something like so?

Code: Select all

is_alpha:
    ora #$20
    cmp #$7B
    ror
    eor #$80
    rol
    rts
EDIT: I'll get the right values in there sooner or later... @_@

Blah, still flawed with values less than 'A', feel like you don't need 4 compares tho....
I haven't tested it yet, but I think we can do it with one compare (please correct me if I whiffed on any of the magic constants):

Code: Select all

isalpha:
    pha             ; (optional)
    ora  #$20       ; xlate upper to lower
    clc
    adc  #$85       ; 'z' should be $ff now
    cmp  #$e6       ; only 7-bit ASCII alphas should set carry
    pla             ; (optional)
    rts
P.S. Here are a few more, untested of course:

Code: Select all

islower:
    pha             ; (optional)
    clc
    adc  #$85       ; 'z' should be $ff now
    cmp  #$e6       ; only 7-bit ASCII lowers should set carry
    pla             ; (optional)
    rts

isupper:
    pha             ; (optional)
    clc
    adc  #$a5       ; 'Z' should be $ff now
    cmp  #$e6       ; only 7-bit ASCII uppers should set carry
    pla             ; (optional)
    rts

isdigit:
    pha             ; (optional)
    clc
    adc  #$c6       ; '9' should be $ff now
    cmp  #$f6       ; only 7-bit ASCII digits should set carry
    pla             ; (optional)
    rts

isxdigit:
    pha             ; (optional)
    clc
    adc  #$c6       ; '0' = $f6 ... '9' = $ff
    cmp  #$f6       ; only 7-bit ASCII digits should set carry
    bcs  isxdigit9
    ora  #$20       ; xlate upper to lower
    adc  #$d3       ; 'a' = $fa, 'f' = $ff
    cmp  #$fa       ; only 'A' - 'F' or 'a' - 'f' should set carry
isxdigit9:
    pla             ; (optional)
    rts
P.S. Bah, I got a little too big for my britches on isxdigit ... it looks like it's going to treat ctrl-P to ctrl-Y as valid hex digits unless I rearrange slightly ... done, I reckon.
Last edited by barrym95838 on Sun Feb 16, 2025 1:09 am, edited 11 times in total.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Hmm, seven bytes instead of ten; it's worth looking at, thanks.

Um - what happens to $00 to $40?

Neil
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Neolithic Tiny Basic

Post by barrym95838 »

barnacle wrote:
Um - what happens to $00 to $40?
They should clear the carry if I'm not horribly mistaken.

$40 | $20 = $60
$60 + $85 = $e5
$e5 < $e6, clears carry

(I think I might have an off-by-one in my magic constants ... if I get it figured out during my lunch break I'll correct my code above ... done.)
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Yeah, I'll check later. Trying to quantify a year's incomings and outgoings at the moment :)

Neil
Post Reply