<2kbyte 6502 Tiny Basic?
Re: <2kbyte 6502 Tiny Basic?
It might, if I need it - but there are more important things to deal with first.
Re: <2kbyte 6502 Tiny Basic?
One thing I have considered (still am, somewhat) is an optional "library" of code with the intention of it being called by poking input values into a fixed location, calling the routine then peeking the result - rather than extend the interpreter (which is costly in terms of time in TinyBasic) so e.g.
Same for maybe some scaled trig, etc. Feels a bit cheaty, but stranger things have been done in the past...
-Gordon
Code: Select all
10 !&500 = A : !&502=B : !&504 = C : CALL &9000 : M = !&500 : REM MulDiv:- M=A*B/C-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: <2kbyte 6502 Tiny Basic?
Good news: while implementing an absolutely minimalist PRINT statement and working through the resultantly exposed bugs, the code actually got slightly smaller. Most of this was from finding some code I'd prepared for implementing PRINT later, which performed a conditional negate without using the more recent DoNegate subroutine. Cutting out the duplicate code and using the subroutine as intended saved more space than adding the partial PRINT statement used up.
The interpreter is now able to run simple programs involving variables, expressions, comparisons, and printing out single integers. Not everything has been thoroughly tested yet, but I did check most of the basic functionality and some important corner cases.
Next step is to complete the feature set of PRINT. My goal here is string literals and more than one integer per statement, divided by semicolons (no space) or commas (one space), with a final semicolon or comma suppressing the newline. How much change will I have from the present 56-byte margin? (NB: this is not a hard limit, as I can go to 3.5KB of code before running into the configured I/O area, but I'll be looking to cut excess beyond 2KB for the sake of bragging rights.)
The interpreter is now able to run simple programs involving variables, expressions, comparisons, and printing out single integers. Not everything has been thoroughly tested yet, but I did check most of the basic functionality and some important corner cases.
Next step is to complete the feature set of PRINT. My goal here is string literals and more than one integer per statement, divided by semicolons (no space) or commas (one space), with a final semicolon or comma suppressing the newline. How much change will I have from the present 56-byte margin? (NB: this is not a hard limit, as I can go to 3.5KB of code before running into the configured I/O area, but I'll be looking to cut excess beyond 2KB for the sake of bragging rights.)
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: <2kbyte 6502 Tiny Basic?
I don't think that you explicitly stated it, but I saw something a few pages back hinting that you were using the Kowalski simulator for your development. Its I/O is rather simplified and flexible, but it also has some annoying quirks with linefeeds if you want to copy and paste BASIC source into it. Klaus2m5 figured it out for me, but you may already know all of this.
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)
Mike B. (about me) (learning how to github)
Re: <2kbyte 6502 Tiny Basic?
I did notice it went weird when I pasted a program in, yes. I suspect it's pasting LF characters after each CR, whereas pressing Return just sends CR. If that's what it is, I can work around it without too much difficulty.
Re: <2kbyte 6502 Tiny Basic?
As you can see here, the FizzBuzz program I wrote earlier is now running. It takes about 2.5 million cycles, which isn't too bad considering this really isn't a performance-oriented interpreter.
Re: <2kbyte 6502 Tiny Basic?
Excellent!
Here it is in my TinyBasic:
With an interesting note... In the old TinyBasic documents I had, the NOT operation was defined as Ones Compliment... So that's what I implemented... And it made my initial version of this fail... Because at (e.g.) X=3 :-
(Y OR Z) returnes (1 OR 0) which is 1 and NOT 1 is -2.
True/False is defined as Non-zero/Zero, so
NOT (1 OR 0) is NOT 1 which is -2 which is TRUE.
Which is correct, but not the expected result...
I changed my implementation of NOT to make 0 -> 1 and anything non-zero return 0 and it worked.
Or did it - which was right? It's an interesting conjecture...
I also fear we're losing the art of translating programs from different dialects - which many of us did back in the 70's/80's when typing into our plethora of little micros, all different at the time...
-Gordon
Here it is in my TinyBasic:
With an interesting note... In the old TinyBasic documents I had, the NOT operation was defined as Ones Compliment... So that's what I implemented... And it made my initial version of this fail... Because at (e.g.) X=3 :-
(Y OR Z) returnes (1 OR 0) which is 1 and NOT 1 is -2.
True/False is defined as Non-zero/Zero, so
NOT (1 OR 0) is NOT 1 which is -2 which is TRUE.
Which is correct, but not the expected result...
I changed my implementation of NOT to make 0 -> 1 and anything non-zero return 0 and it worked.
Or did it - which was right? It's an interesting conjecture...
I also fear we're losing the art of translating programs from different dialects - which many of us did back in the 70's/80's when typing into our plethora of little micros, all different at the time...
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: <2kbyte 6502 Tiny Basic?
I adopted the BBC BASIC convention of making "true" results from comparison operators be -1. This means that bitwise operators can also be used for logical operations, including NOT. I don't think it requires significantly more code than producing a 1 result, as for both "false" and "true" a single byte value is replicated to all four result positions.
C doesn't do this - it has separate operators for bitwise and logical operations. So bitwise complement is ~ and logical complement is !.
C doesn't do this - it has separate operators for bitwise and logical operations. So bitwise complement is ~ and logical complement is !.
Re: <2kbyte 6502 Tiny Basic?
Chromatix wrote:
I adopted the BBC BASIC convention of making "true" results from comparison operators be -1. This means that bitwise operators can also be used for logical operations, including NOT. I don't think it requires significantly more code than producing a 1 result, as for both "false" and "true" a single byte value is replicated to all four result positions.
C doesn't do this - it has separate operators for bitwise and logical operations. So bitwise complement is ~ and logical complement is !.
C doesn't do this - it has separate operators for bitwise and logical operations. So bitwise complement is ~ and logical complement is !.
If only there was a standard... but wait, there is....
https://xkcd.com/927/
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: <2kbyte 6502 Tiny Basic?
Another program showing off interesting features of the interpreter. Note that the code is not presented in execution order, but when pasted in it will effectively be sorted by line number. This takes approximately 1.2 million cycles to complete, and then executing the program takes several million more. The main features thus demonstrated/exercised are the memory management for program code, the use of 32-bit internal arithmetic to support fixed-point, and nested subroutine calls. In a more complete and conventional BASIC interpreter, this would be a natural place to use DATA and READ, which I don't have - nor is there an END or STOP, but a contrived GOTO past the end of the program also works.
The output is a table of the baud rates for my "improved ACIA" proposal:
Code: Select all
5000 PRINT D,"|",(18432*100)/(D*16);
5010 F=(18432*10000/(D*16))-(18432*100/(D*16))*100
5011 GOSUB 4000
5020 PRINT " |",(24576*100)/(D*16);
5030 F=(24576*10000/(D*16))-(24576*100/(D*16))*100
5031 GOSUB 4000
5040 PRINT " |",(18432*200)/(D*16);
5050 F=(18432*20000/(D*16))-(18432*200/(D*16))*100
5051 GOSUB 4000
5060 PRINT
5070 RETURN
4000 IF F PRINT ".";F/10;F-(F/10*10);
4010 RETURN
10 D=1
20 D=2
30 D=3
40 D=4
50 D=6
60 D=8
70 D=12
80 D=16
90 D=24
100 D=32
110 D=48
120 D=64
130 D=96
140 D=128
150 D=192
160 D=256
170 D=384
180 D=512
190 D=576
200 D=768
210 D=856
220 D=1047
230 D=1142
240 D=1396
250 D=1536
260 D=1713
270 D=2048
280 D=2095
290 D=2304
300 D=2534
310 D=3072
320 D=3379
15 GOSUB 5000
25 GOSUB 5000
35 GOSUB 5000
45 GOSUB 5000
55 GOSUB 5000
65 GOSUB 5000
75 GOSUB 5000
85 GOSUB 5000
95 GOSUB 5000
105 GOSUB 5000
115 GOSUB 5000
125 GOSUB 5000
135 GOSUB 5000
145 GOSUB 5000
155 GOSUB 5000
165 GOSUB 5000
175 GOSUB 5000
185 GOSUB 5000
195 GOSUB 5000
205 GOSUB 5000
215 GOSUB 5000
225 GOSUB 5000
235 GOSUB 5000
245 GOSUB 5000
255 GOSUB 5000
265 GOSUB 5000
275 GOSUB 5000
285 GOSUB 5000
295 GOSUB 5000
305 GOSUB 5000
315 GOSUB 5000
325 GOSUB 5000
330 GOTO 65535
The output is a table of the baud rates for my "improved ACIA" proposal:
Re: <2kbyte 6502 Tiny Basic?
And, what I'm sure you've all been waiting for:
I haven't got a timing for this, but it does run and produce reasonable results. I did have to correct a serious oversight in the division routine, related to the handling of negative arguments…
Code: Select all
0 S=2048
10 A=S*-21/10
20 B=S*3/2
30 C=S*3/2
40 D=S*-3/2
50 E=200
60 F=(B-A)/128
70 G=(C-D)/48
80 L=C
90 REPEAT
100 K=A
110 REPEAT
120 V=0
130 U=0
150 O=0
160 REPEAT
170 X=U*U/S
180 Y=V*V/S
190 V=U*V/(S/2)+L
200 U=X-Y+K
210 O=O+1
220 UNTIL O >= E OR X+Y > 4*S
230 IF O<E AND O>9 VDU 64
240 IF O<10 VDU O+48
250 IF O=E VDU 32
260 K=K+F
270 UNTIL K >= B
280 PRINT
290 L=L-G
300 UNTIL L < D
Re: <2kbyte 6502 Tiny Basic?
Hooray! There are some overflows though, I think, e.g. the noise in the top and bottom right corners, and between zones 3 and 4. I'd guess U*U/S or V*V/S is overflowing before the division, so you might need to do range checks on U and V as well, perhaps, and decide how to act if they're already above a threshold.
Re: <2kbyte 6502 Tiny Basic?
I have a suspicion that those aren't really overflows, but might be due to a subtle bug in the interpreter which would only show up with large-magnitude numbers. The near-threshold iterates in those regions should not be overflowing 32 bits with the scale factor I've selected, but might overflow 24 bits. I'll investigate…
EDIT: Well, there's no problem in the intermediate values, but it's more likely that the stored variables are overflowing. With some extra bailout tests on the inner loop, I can successfully hide these, though the shape of the exterior gradient changes.
EDIT: Well, there's no problem in the intermediate values, but it's more likely that the stored variables are overflowing. With some extra bailout tests on the inner loop, I can successfully hide these, though the shape of the exterior gradient changes.
Re: <2kbyte 6502 Tiny Basic?
This is much better:
Code: Select all
0 S=4096
5 T=S*4
10 A=S*-21/10
20 B=S*3/2
30 C=S*3/2
40 D=S*-3/2
50 E=200
60 F=(B-A)/128
70 G=(C-D)/48
80 L=C
90 REPEAT
100 K=A
110 REPEAT
120 V=L
130 U=K
150 O=-1
160 REPEAT
170 Z=(U*U-V*V)/S
190 V=U*V/(S/2)+L
200 U=Z+K
210 O=O+1
220 UNTIL O >= E OR U*U+V*V > T*S
230 IF O<E AND O>9 VDU 64
240 IF O<10 VDU O+48
250 IF O=E VDU 32
260 K=K+F
270 UNTIL K >= B
280 PRINT
290 L=L-G
300 UNTIL L < D
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: <2kbyte 6502 Tiny Basic?
A fellow by the name of Will Stevens has recently implemented a 1012 byte tiny BASIC, with signed 16-bit arithmetic, tokenization, a single numeric array, FOR/NEXT/STEP, ABS(), USR() and RND(). The only trouble (at least for me) is that it's for the 8080, and I quickly developed a headache trying to grok his assembly code. All of those LXI, SHLD, DCX, RST, XTHL, XCHG, SPHL, PCHL instructions certainly pack a punch, but I've never heard of a non-trivial 8080 program being half the size of an equivalent 6502 program, so it's quite possible that some valuable insights could be gained from Will's code related to the subject at hand, for someone brave enough to take the dive. I haven't given up entirely, but I also haven't gathered sufficient courage yet ...
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)
Mike B. (about me) (learning how to github)