Page 8 of 10

Re: <2kbyte 6502 Tiny Basic?

Posted: Mon Oct 23, 2023 9:34 am
by Chromatix
It might, if I need it - but there are more important things to deal with first.

Re: <2kbyte 6502 Tiny Basic?

Posted: Mon Oct 23, 2023 11:33 am
by drogon
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.

Code: Select all

10 !&500 = A : !&502=B : !&504 = C : CALL &9000 : M = !&500 : REM MulDiv:- M=A*B/C
Same for maybe some scaled trig, etc. Feels a bit cheaty, but stranger things have been done in the past...

-Gordon

Re: <2kbyte 6502 Tiny Basic?

Posted: Mon Oct 23, 2023 1:41 pm
by Chromatix
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.)

Re: <2kbyte 6502 Tiny Basic?

Posted: Mon Oct 23, 2023 3:47 pm
by barrym95838
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.

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 4:45 am
by Chromatix
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?

Posted: Tue Oct 24, 2023 9:22 am
by Chromatix
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.
FizzBuzz.png

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 10:28 am
by drogon
Excellent!

Here it is in my TinyBasic:
Screenshot_2023-10-24_11-13-48.png
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

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 10:35 am
by Chromatix
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 !.

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 10:43 am
by drogon
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 !.

If only there was a standard... but wait, there is....

https://xkcd.com/927/

-Gordon

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 12:31 pm
by Chromatix
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.

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 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:
BaudRates.png

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 3:51 pm
by Chromatix
And, what I'm sure you've all been waiting for:
Mandelbrot.png

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
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…

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 5:04 pm
by gfoot
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?

Posted: Tue Oct 24, 2023 5:32 pm
by Chromatix
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.

Re: <2kbyte 6502 Tiny Basic?

Posted: Tue Oct 24, 2023 9:27 pm
by Chromatix
This is much better:
Mandelbrot2.png

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

Re: <2kbyte 6502 Tiny Basic?

Posted: Sun Jan 21, 2024 7:10 am
by barrym95838
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 ...