6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 10:47 pm

All times are UTC




Post new topic Reply to topic  [ 136 posts ]  Go to page Previous  1 ... 5, 6, 7, 8, 9, 10  Next
Author Message
PostPosted: Mon Oct 23, 2023 9:34 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
It might, if I need it - but there are more important things to deal with first.


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 23, 2023 11:33 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
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:
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

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 23, 2023 1:41 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.)


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 23, 2023 3:47 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
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)


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 4:45 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 9:22 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.

Attachment:
FizzBuzz.png
FizzBuzz.png [ 33.41 KiB | Viewed 35287 times ]


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 10:28 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
Excellent!

Here it is in my TinyBasic:

Attachment:
Screenshot_2023-10-24_11-13-48.png
Screenshot_2023-10-24_11-13-48.png [ 14.14 KiB | Viewed 35283 times ]


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/


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 10:35 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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 !.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 10:43 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
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

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 12:31 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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:
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:
Attachment:
BaudRates.png
BaudRates.png [ 24.26 KiB | Viewed 35275 times ]


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 3:51 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
And, what I'm sure you've all been waiting for:
Attachment:
Mandelbrot.png
Mandelbrot.png [ 107.57 KiB | Viewed 35256 times ]
Code:
   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…


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 5:04 pm 
Offline

Joined: Fri Jul 09, 2021 10:12 pm
Posts: 741
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 5:32 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 24, 2023 9:27 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
This is much better:
Attachment:
Mandelbrot2.png
Mandelbrot2.png [ 91.04 KiB | Viewed 35225 times ]
Code:
   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


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 21, 2024 7:10 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
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)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 136 posts ]  Go to page Previous  1 ... 5, 6, 7, 8, 9, 10  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 12 guests


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: