Jump to content
IGNORED

Critique my first basic program on my 800XL


Recommended Posts

35 minutes ago, bent_pin said:

...

 

That's what I figured. It's how I wrote my first AVR basic interpreter, before moving onto a binary trees, and eventually a recent-priority dequeue.

 

I write my assembly code the same way.

I have written binary trees, hash tables, min-heaps, tries, Quicksorts, etc., in various Basics, not so much in assembly. 😄 I mostly use X11 Basic for my own projects, which started off as a clone of GFA Basic for the Atari ST / Frost Basic for 8-bit, so mentioning it here hopefully isn't completely off topic. No line numbers, plus decent looping constructs and various other structured goodies to make you forget all about GOTO. In the binary tree code, I got the idea to rotate the currently accessed node up one level towards the root of the tree. It played havoc with attempts to keep the tree as a whole relatively balanced, but frequently accessed nodes were kept handy without constantly rearranging the entire thing

Link to comment
Share on other sites

2 hours ago, yetanothertroll said:

I have written binary trees, hash tables, min-heaps, tries, Quicksorts, etc., in various Basics, not so much in assembly.

In assembly, the only thing that you have to add is a heap in memory, as far from the stack as possible, and when you've done it a few times, you can eliminate stack usage for everything but subroutines and achieve objectivity. Doing so on a 6502 with 64k is going to be a new and interesting challenge for me, but the mountain is there, therefore we must climb it.

Link to comment
Share on other sites

2 hours ago, yetanothertroll said:

In the binary tree code, I got the idea to rotate the currently accessed node up one level towards the root of the tree. It played havoc with attempts to keep the tree as a whole relatively balanced, but frequently accessed nodes were kept handy without constantly rearranging the entire thing

Try making a dequeue with an indexable pop. Enqueue the lines, in order. Then, push nodes when finished. Keeps most used in front in order of last used. I got the idea from how I kept my filing cabinet when I ran a construction company. Only works with a language with line numbers, and only if you collapse the line numbers and their references and you enqueue them.

Link to comment
Share on other sites

3 hours ago, yetanothertroll said:

Did you know you can edit program listings?  Use the arrow keys to navigate up to the line, have your way with it, then while still at that line hit Enter/

I did, discovered by a happy little accident.

 

3 hours ago, yetanothertroll said:

Also, another really sketchy way to exit FOR loops:

That's not too sketchy, you just gave it a ceiling. It's a fakakta while loop. And condition could be used as a rip cord. Not sure my dyspepsia would allow me to use it, but we'll see what we see.

Link to comment
Share on other sites

Much easier way to exit GOSUB's and FOR loops using TRAP and POP

Have a look at this :)

 

1 TRAP 199:REM CATCH REURN ERROR
10 X=20
20 X=X-1
30 IF X=5 THEN GOSUB 90
40 GOTO 20
90 PRINT "X=";X
100 X=X-1
110 IF X=0 THEN POP :RETURN 
120 GOTO 100
199 TRAP 230:? "ERROR GOT US HERE"
200 FOR I=1 TO 10
205 ? I
210 IF I=5 THEN POP 
220 NEXT I
230 ? "FINISHED, I=";I
240 TRAP 40000:REM TURN OFF TRAP

  • Thanks 1
Link to comment
Share on other sites

6 hours ago, bent_pin said:

I did, discovered by a happy little accident.

 

That's not too sketchy, you just gave it a ceiling. It's a fakakta while loop. And condition could be used as a rip cord. Not sure my dyspepsia would allow me to use it, but we'll see what we see.

What ceiling lol

 

Screenshot_20240227-074625.png

Screenshot_20240227-074703.png

Link to comment
Share on other sites

3 hours ago, bent_pin said:

Oh I see what you meant now. Maybe instead of 1e97 I should have used something actually reachable as a failsafe "ceiling," but then again, I guess the 1e97 makes it pretty obvious it's a FOR EVER AND EVER AND EVER UNTIL THE HEAT DEATH OF THE UNIVERSE loop :)

 

If you're ever interested in an Atari emulator for Android to go along with the excellent Altirra emulator for Windows, check out Colleen. It hasn't been updated in forever, but it still works just fine for most purposes. Apparently legally downloadable copies of the OS and BASIC ROMs can be found here https://atari800.github.io/download.html Some carts, including Atari Logo, don't like being loaded from dumps on diskette, so track down ROMs in .CAR format if you can, or since you're using real hardware, dump yours to .CAR if you want to use them with Colleen.

Edited by yetanothertroll
Colleen and Logo quirks
Link to comment
Share on other sites

1 hour ago, thank you said:

Hello

 

I don't think anybody mentioned you can do like this:

 

90 GOTO 2*(GUESS<LOW)+4*(GUESS>HIGH)+6*(GUESS<SECRET AND GUESS>=LOW)+9*(GUESS>SECRET AND GUESS<=HIGH)

 

I remember learning this idea from a joystick reading routine.

That's right, "Booleans" are just integers, not a distinct data type, either 0 or 1 in Atari BASIC. Other Basics usually set "True" to -1

Screenshot_20240227-2024142.thumb.png.0fcfae728b055dcc8777d300edcdba9b.png

 

That GOTO expression looks too scary and nasty to debug or modify for me. What happens if you renumber your lines? It looks like it should be at least converted to an ON GOTO, buuuuut there'd probably be a speed hit. Anyone know for sure?

  • Like 1
Link to comment
Share on other sites

1 hour ago, yetanothertroll said:

That's right, "Booleans" are just integers, not a distinct data type, either 0 or 1 in Atari BASIC. Other Basics usually set "True" to -1

Screenshot_20240227-2024142.thumb.png.0fcfae728b055dcc8777d300edcdba9b.png

 

That GOTO expression looks too scary and nasty to debug or modify for me. What happens if you renumber your lines? It looks like it should be at least converted to an ON GOTO, buuuuut there'd probably be a speed hit. Anyone know for sure?

Any time you have compound statements on a single line in an interpreted language, they must be unrolled by order of operations, that's a series of stack operations and extra memory usage, then evaluated with more stack operations. The fastest processing in all conventional interpreted languages is to limit compound statements or avoid them if possible. It is possible that multiple line saves to a single variable can be a touch slower than a compound statement, but not usually.

 

Even though I wouldn't use it as presented, I still value the comment's addition to the discussion as it makes me aware of the capability.

  • Confused 1
Link to comment
Share on other sites

Where to next? A Matrix-like demo? https://github.com/neilk/apple-ii-matrix A Mandelbrot set generator? https://hackaday.com/2020/06/23/boot-to-basic-box-packs-a-killer-graphics-engine/ A Mandelbrot generator that draws in columns, top-down, mostly in green, Matrix style?

 

 

Link to comment
Share on other sites

On 2/26/2024 at 11:53 PM, yetanothertroll said:

This one was an attempt to copy diskette files to cassette tape because some of my Logo programs were getting too big and that 4KB taken up by DOS was beginning to hurt. I abandoned it when copying from disk to tape only resulted in corrupted tapes. Maybe crazy buffering would do the trick? Hmm

 

10 DIM S$(16),D$(16),L$(4096)
100 OPEN #1,4,0,"D2:TEMP.LG"
110 OPEN #2,8,0,"C:"
120 REM OPEN #2
140 REM 
150 INPUT #1,L$
160 PRINT L$
170 PRINT #2;L$
180 GOTO 140
190 REM CLOSE
200 OPEN #1,4,0,"C:"
240 REM 
250 INPUT #1,L$
260 PRINT L$
280 GOTO 240
290 REM CLOSE

The problem with this one is the INPUT, PRINT method. It's not precise enough to do this job. One issue that jumps out right away also is there should be a semicolon after the PRINT #2 command or it will add a Carriage Return to the destination file. A better way would be to use GET, PUT so you get down to the byte level. To copy from disk to cas would be like this: (in BASIC this would be pretty slow)

 

1 REM Numerical variable 'A' does not need to be DIMed

10 OPEN #1,4,0,"D2:TEMP.LG"

20 OPEN #2,8,0,"C:"

30 TRAP 100: REM EOF Will cause error if not TRAPed

40 GET #1,A:REM Read a byte from the disk file

50 PUT #2,A:REM Write the byte to the cassette

60 GOTO 40:REM Repeat until error (which hopefully is generated by the EOF. Lol)

99 REM End Of File error takes us here

100 CLOSE#1:CLOSE #2:END: REM Close all IOCBs to flush buffers. End program.

 

 

 

Edited by Houdini
  • Like 1
Link to comment
Share on other sites

1 hour ago, Houdini said:

The problem with this one is the INPUT, PRINT method. It's not precise enough to do this job. One issue that jumps out right away also is there should be a semicolon after the PRINT #2 command or it will add a Carriage Return to the destination file. A better way would be to use GET, PUT so you get down to the byte level. To copy from disk to cas would be like this: (in BASIC this would be pretty slow)

 

...

 

The files I wanted to transfer were either BASIC LISTings or Logo saves, each of which are ATASCII formatted plain text, not tokenized or binary, so line input and print should have been fine. I actually asked about the issue in one of the Altirra threads, and according to @phaeron if I understand correctly, POKEY is used for SIO by both the cassette handler and DOS, and DOS will clobber the tape if invoked before the first record is written to the cassette.

Link to comment
Share on other sites

1 hour ago, yetanothertroll said:

The files I wanted to transfer were either BASIC LISTings or Logo saves, each of which are ATASCII formatted plain text, not tokenized or binary, so line input and print should have been fine. I actually asked about the issue in one of the Altirra threads, and according to @phaeron if I understand correctly, POKEY is used for SIO by both the cassette handler and DOS, and DOS will clobber the tape if invoked before the first record is written to the cassette.

Yes, it's a known bug/limitation in the OS:

image.thumb.png.4f291ecfd8c4137107941f5fd228f6d9.png

GET/PUT wouldn't be any better, unless you buffer enough data to ensure that the first cassette record is written before DOS fetches another sector.

 

  • Thanks 1
Link to comment
Share on other sites

If they are BASIC listings, then you can Load them, and then Save them to Disk.

Is there a problem with

booting DOS,

going to BASIC,

Loading or Entering a tape,

once it's loaded stopping the tape,

  then saving or listing to disk?

How could it clobber the tape if it's not set to record or the tape mech isn't engaged?

Edited by _The Doctor__
Link to comment
Share on other sites

1 hour ago, _The Doctor__ said:

If they are BASIC listings, then you can Load them, and then Save them to Disk.

Is there a problem with

booting DOS,

going to BASIC,

Loading or Entering a tape,

once it's loaded stopping the tape,

  then saving or listing to disk?

How could it clobber the tape if it's not set to record or the tape mech isn't engaged?

Unfortunately, in this particular case it wasn't a BASIC listing but a Logo project that had grown a little too big. It appears it's possible to edit, run, and save a large project but then run out of memory when reloading it later, even after a cold reset. I was hoping to copy it to tape, reboot without DOS gobbling up that precious 4KB, and trim it down to where I could save it back to tape, reboot again with DOS loaded, and reload the project.

Link to comment
Share on other sites

Well, the initial test drawing in graphics mode 11 for the Mandelbrot set generator went well. It's actually kind of hypnotic to watch, but don't worry, lines 900-980 ought to jolt you out of it 😄 

Testpattern.thumb.png.07fc4601e6d8e82506f74aa1d8c2ee3d.png

100 XMIN=-2:XMAX=0.5:YMAX=1.15
110 WW=80:WH=192:HH=INT(WH/2)
120 DIM X0(WW-1),X1(WW-1),Y1(HH)
130 FOR X=0 TO WW-1
140 X0(X)=X:REM SHUFFLE IT LATER
150 X1(X)=XMIN+(X*(XMAX-XMIN)/(WW-1))
160 NEXT X
170 FOR Y=0 TO HH
180 Y1(Y)=YMAX-((Y/HH)*YMAX)
190 NEXT Y
200 GRAPHICS 11:REM GTIA 80*192*16
300 FOR X=WW-1 TO 0 STEP -1
310 R=X*RND(0)
320 T=X0(X):X0(X)=X0(R):X0(R)=T
330 T=X1(X):X1(X)=X1(R):X1(R)=T
380 X0=X0(X)
390 XSCALE=X1(X)
400 FOR Y=0 TO HH
480 Y0=Y:REM Y0 = Y0(Y)
490 YSCALE=Y1(Y)
700 COLOR (X+Y)-(16*INT((X+Y)/16))
710 Y1=WH-1-Y0
720 PLOT X0,Y0
730 IF Y0<Y1 THEN DRAWTO X0,Y1
800 NEXT Y
810 NEXT X
900 FOR Y=0 TO 255
910 SOUND 0,Y,10,8
920 FOR X=1 TO 3
930 SOUND X,Y,2*INT(8*RND(0)),8
940 NEXT X
950 NEXT Y
980 FOR X=0 TO 3:SOUND X,0,0,0:NEXT X
990 REM GRAPHICS 0
999 END 

 

Mandel Graphics 11 test.BAS

Edited by yetanothertroll
Remove a failed attachment upload
Link to comment
Share on other sites

On 2/27/2024 at 5:53 AM, yetanothertroll said:

Interesting use of the first few lines, treating them almost like page zero. The original Atari Basic does search the entire program from the beginning each and every time for any and all jump targets, whether it's GOTO, GOSUB, IF/THEN 999, most likely for TRAP as well. Maybe even NEXT and RETURN? Later third-party Basics are smarter.

Yes, also NEXT and RETURN only take line numbers + line offsets from the stack, and that's even true for Turbo-Basic. It just has a smarter search strategy. Basic++ is smarter and stores an address.

  • Thanks 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...