breakintoprogram / next-bbc-basic

A port of BBC Basic for Z80 to the Spectrum Next
zlib License
35 stars 3 forks source link

Feature Request to implement *SPOOL [OUTFILE.TXT] and *EXEC INFILE.TXT #6

Open dbolli opened 1 year ago

dbolli commented 1 year ago

As of V0.16 there is no support for SPOOL [OUTFILE.TXT] and EXEC INFILE.TXT which makes it difficult to get BBC BASIC source code in and out of the emulator from NextZXOS text files given that the .bbc binary format is different to Acorn BBC BASIC binary files.

Implementing *SPOOL [OUTFILE.TXT] would allow

*SPOOL OUTFILE.TXT
LIST
*SPOOL

to save a text file to NextZXOS

and *EXEC INFILE.TXT would allow a text file BASIC listing to be read into the emulator

SimonGoodwin commented 1 year ago

Ideally (from an interoperability point of view) this very useful capability would use CR (CHR$ 13) to terminate lines of the text file, consistent with the host OS and previous ZX Spectrums. But ISTR that the Beeb OS saved a couple of bytes in ROM by using the exceptionally eccentric LF/CR combo, rather than the 1970s printing-terminal CP/M legacy of CR/LF.

I recommend we follow the tolerant on read, strict on write paradigm and allow EXEC to support any of CR, CR/LF, Acorn's LF/CR or just LF, as used on Sinclair Qdos, Unix and Linux, while using only CR as line termination on SPOOL. But I've not tried this on a real Beeb, or Z88, or Amstrad NC. If ALL of those use LF/CR that's the way to go, otherwise we should accept this is a moveable feast and prioritise compatibility with the port host.

To avoid the risk of making a muddle worse, I've checked that Next's browser copes with CR, LF or CR/LF (the NextZXOS distro includes files using all three terminations) and found that if LF/CR is used in that order, as e.g. an Acorn Atom or original BBC Model B would do, unintended double-spacing is the result.

dbolli commented 1 year ago

I have tested this on macOS b2 emulator and *SPOOL does create files with LF/CR line endings ($0A$0D) in both DFS and ADFS

*SPOOL TEST
THIS IS A TEST
*SPOOL
*DUMP TEST

I agree that unless an extra setting is implemented to set the line endings, CR ($0D) seems to be the best option even though it is not as implemented on the Beeb.

I also agree with your tolerant approach to *EXEC as described above ๐Ÿ‘

SimonGoodwin commented 1 year ago

While we wait for text input and output I have written a couple of NextBASIC 2.08 procedures to address one of the underlying issues, the incompatibility of Acorn tokenised BASIC files, which are widely available, with the format of tokenised BBC BASIC expected by Richard Russellโ€™s interpreters such as this port.

You will need the latest version of NextZXOS from gitlab to run these procedures as they use new features of NextBASIC added for the imminent Kickstarter release.

1175 REM Convert Z80 BBC BASIC token file to Acorn BBC BASIC 1180 DEFPROC BBCz80 2 Acorn(in$,out$="") 1190 IF out$="" THEN out$=in$(1 TO LEN in$-3)+"BBC" 1200 PRINT in$;" to ";out$ 1210 LOCAL t$,%i,%n,%c 1220 CLOSE # 4: OPEN # 4,in$ 1230 CLOSE # 5: OPEN # 5,"o>"+out$ 1240 REPEAT 1250 %c= NEXT #4 1260 WHILE %c 1270 %n= NEXT #4+256 NEXT #4 1280 t$="" 1290 FOR %i=1 TO %c-4 1300 t$+= INKEY$ #4 1310 NEXT %i 1320 IF 13<> NEXT #4 THEN PRINT "Not BBC BASIC Z80": GO TO 1400 1330 ;PRINT "Scanned line ";%n 1340 PRINT #5; CHR$ 13; CHR$ (%n>>8); CHR$ (%n&255); CHR$ (%c);t$; 1350 REPEAT UNTIL 0 1360 PRINT #5; CHR$ 13; CHR$ 255; 1370 IF INKEY$ #4+ INKEY$ #4<> CHR$ 2552 THEN PRINT "Bad End" 1380 IF POINT #4<> DIM #4 THEN PRINT "End junk" 1390 IF POINT #4<>1+ POINT #5 THEN PRINT "Bad sync" 1400 CLOSE # 5: CLOSE # 4 1410 ENDPROC

1450 REM Convert Acorn BASIC token file to Z80 BBC BASIC 1460 DEFPROC Acorn 2 BBCz80(in$,out$="") 1470 IF out$="" THEN out$=in$(1 TO LEN in$-3)+"BAC" 1480 PRINT in$;" to ";out$ 1490 LOCAL t$,%i,%n,%c 1500 CLOSE # 4: OPEN # 4,in$ 1510 CLOSE # 5: OPEN # 5,"o>"+out$ 1520 REPEAT 1525 IF 13<> NEXT #4 THEN PRINT "Not Acorn BBC BASIC": GO TO 1680 1530 %n= NEXT #4 1540 WHILE %n<>255 1550 %n= NEXT #4+(%n<<8) 1555 %c= NEXT #4 1560 t$="" 1570 FOR %i=1 TO %c-4 1580 t$+= INKEY$ #4 1590 NEXT %i 1610 ;PRINT "Scanned line ";%n 1620 PRINT #5; CHR$ (%c); CHR$ (%n&255); CHR$ (%n>>8);t$ 1630 REPEAT UNTIL 0 1640 PRINT #5; CHR$ 0; CHR$ 255*2; 1660 IF POINT #4<> DIM #4 THEN PRINT "End junk" 1670 IF POINT #5<>1+ POINT #4 THEN PRINT "Bad sync" 1680 CLOSE # 5: CLOSE # 4 1690 ENDPROC

dbolli commented 1 year ago

I have partially tested this on an .mmc file based on tbblue-master and can confirm that a file converted from BBC Z80 to Acorn and then back again runs correctly ๐Ÿ‘

I needed to make a couple of tweaks so my text to Next BASIC converter of choice would work

1180 DEFPROC BBCz802Acorn(infile$,outfile$="")

and

1460 DEFPROC Acorn2BBCz80(infile$,outfile$="")

I also changed all occurrences of in$ to infile$ and out$ to outfile$ as it didn't like string names that were keywords ๐Ÿ™„

and I added the following lines to the start of the program

20 RUN AT 3

30 PROC BBCz802Acorn( "tests/shadows.bbc", "testout.acn" )
40 PROC Acorn2BBCz80( "testout.acn", "testout.bbc" )

500 STOP

The testout.bbc file runs successfully and I will also test that the testout.acn file runs in the b2 BBC Micro emulator and report back ๐Ÿ‘