This was created by disassembling the executable retrieved from the floppy discs, and the compiled machine code is byte-for-byte identical.master
parent
000445bfec
commit
979c2343ce
@ -0,0 +1,561 @@ |
||||
10REM This program provides a formatted listing of a BASIC program, |
||||
11REM in particular, indenting loops and splitting multiple statements |
||||
12REM out onto separate lines. |
||||
13REM Since it calls into the BASIC ROM, it requires BASIC 2. |
||||
14 |
||||
20REM It lives at &08C0-0AFF, which is normally used for the following: |
||||
21REM 800-8FF: sound workspace & buffers, printer buffer, envelope storage |
||||
22REM 900-9FF: envelope storage, RS423/speech/cassette output buffers |
||||
23REM A00-AFF: cassette/RS423 input buffers |
||||
24 |
||||
30REM Run this program to assemble it, and save the generated machine code. |
||||
31 |
||||
40REM Enter LIST commands as normal, but with a trailing period e.g. |
||||
41REM LIST 100,200. |
||||
42REM LIST ,200. |
||||
43REM LIST 100,. |
||||
44REM LIST. |
||||
45 |
||||
50REM NOTE: Page references in the source code are for "The BBC Micro |
||||
51REM Compendium", by Jeremy Ruston. |
||||
52 |
||||
100REM === VARIABLES ======================================================= |
||||
101 |
||||
102REM We borrow some zero-page locations normally used by BASIC (p170). |
||||
103 |
||||
110REM When when we're parsing the input command, this points into |
||||
111REM the keyboard buffer (&0700-07FF), then we switch to the program code |
||||
112REM when we start printing the listing. |
||||
113pinput = &4B : REM and &4C |
||||
114 |
||||
120REM This points into the program code being listed (only while |
||||
121REM we're parsing the input command). |
||||
122pcode = &3B : REM and &3C |
||||
123 |
||||
130REM This holds the current line# being listed. |
||||
131curr_lineno = &2A : REM and &2B |
||||
132 |
||||
140REM This holds the last line# to be listed. |
||||
141last_lineno = &2E : REM and &2F |
||||
142 |
||||
150REM This holds the current indent. |
||||
151REM The first 5 columns are used for the line#, followed by a space, |
||||
152REM then the code itself starts at col.6 |
||||
153curr_indent = &30 |
||||
154 |
||||
160REM This flags if we are in a REM statement. |
||||
161in_rem = &31 |
||||
162 |
||||
170REM This flags if we are in a double-quoted string. |
||||
171in_quotes = &32 |
||||
172 |
||||
180REM This flags if we are in BASIC code (0 means we are in assembly code). |
||||
181in_basic = &33 |
||||
182 |
||||
190REM This flags if we are in an assembly label. |
||||
191in_asm_label = &34 |
||||
192 |
||||
200REM This flags if the current line has not been indented yet. |
||||
201indent_pending = &35 |
||||
202 |
||||
900osbyte = &FFF4 : oswrch = &FFEE : osnewl = &FFE7 |
||||
910 |
||||
1000FOR opt = 0 TO 3 STEP 3 |
||||
1010BASE = &08C0 : P% = BASE |
||||
1020[ OPT opt |
||||
1030 |
||||
1100\ === MAIN ENTRY POINT ==================================================== |
||||
1101 |
||||
1102\ Adding a trailing "." to a LIST command will generate a syntax error, |
||||
1103\ so we replace the default BRK error handler with ours, so that we can |
||||
1104\ check for this. |
||||
1105 |
||||
1110\ install our custom BRK handler |
||||
1120LDA #(brkHandler MOD 256) |
||||
1130STA &0202 |
||||
1140LDA #(brkHandler DIV 256) |
||||
1150STA &0203 |
||||
1160 |
||||
1170\ beep, then exit |
||||
1180LDA #7 |
||||
1190JMP oswrch |
||||
1200 |
||||
1500\ === CUSTOM ERROR HANDLER ================================================ |
||||
1501 |
||||
1502\ We check for our special LIST command here. |
||||
1503 |
||||
1510.brkHandler |
||||
1520\ check for a "Bad program" |
||||
1530JSR &BE6F |
||||
1540 |
||||
1550\ if the error was not "Syntax error" (error code 16), then jump to |
||||
1551\ the normal BRK handler |
||||
1560LDY #0 |
||||
1570LDA (&FD),Y |
||||
1580CMP #16 |
||||
1590BEQ P%+5 |
||||
1600.defaultBRK |
||||
1610JMP &B402 |
||||
1620 |
||||
2000\ initialize our variables |
||||
2001\ PINPUT <- &0700 |
||||
2002\ PCODE <- PAGE |
||||
2003\ CURR_INDENT <- 6 |
||||
2004\ IN_BASIC <- &FF |
||||
2005\ LAST_LINENO <- &7FFF (in case a line# isn't explicitly set) |
||||
2010STY pinput |
||||
2020STY pcode |
||||
2030LDA &18 |
||||
2040STA pcode+1 |
||||
2050LDX #7 |
||||
2060STX pinput+1 |
||||
2070DEX |
||||
2080STX curr_indent |
||||
2090DEY |
||||
2100STY in_basic |
||||
2110STY last_lineno |
||||
2120LDY #&7F |
||||
2130STY last_lineno+1 |
||||
2140 |
||||
2150\ if the next non-space byte in the keyboard buffer is not the LIST keyword, |
||||
2151\ then jump to the normal BRK handler |
||||
2160JSR skipSpaces |
||||
2170CMP #&C9 |
||||
2180BNE defaultBRK |
||||
2190 |
||||
2200\ if the next non-space byte is a ".", then skip parsing line numbers (the user |
||||
2201\ wants to "LIST." the entire program) |
||||
2210JSR skipSpaces |
||||
2220CMP #&2C |
||||
2230BEQ parseEndLineNo |
||||
2240 |
||||
2250\ if the byte is &8D (pseudo-keyword for a line#), then decode the line# |
||||
2251\ into CURR_LINENO |
||||
2260CMP #&8D |
||||
2270BNE endParseInput |
||||
2280JSR decodeLineNo |
||||
2290 |
||||
2300\ find the start of the specified line in the program code |
||||
2301\ NOTE - Program lines are stored as follows |
||||
2302\ &0D |
||||
2303\ line# (MSB, LSB) |
||||
2304\ line length (1 byte, the count includes the 3 leading bytes) |
||||
2305\ The end of the program is stored as |
||||
2306\ &0D &FF |
||||
2310.checkNextLine |
||||
2320\ check if we've found the first line to be listed (i.e. the line# of |
||||
2321\ the line pointed to by PCODE is >= CURR_LINENO) |
||||
2330LDY #2 |
||||
2340LDA (pcode),Y \ this is the LSB of the current line# |
||||
2350SEC |
||||
2360SBC curr_lineno |
||||
2370DEY |
||||
2380LDA (pcode),Y \ this is the MSB of the current line# |
||||
2390BPL P%+5 \ negative line# MSB = end-of-program marker |
||||
2400JMP done |
||||
2410SBC curr_lineno+1 |
||||
2420BPL foundFirstLine |
||||
2430\ nope - move to the next line |
||||
2440LDY #3 |
||||
2450LDA (pcode),Y \ this is the line length |
||||
2460CLC |
||||
2470ADC pcode |
||||
2480STA pcode |
||||
2490BCC P%+4 |
||||
2500INC pcode+1 |
||||
2510JMP checkNextLine |
||||
2520 |
||||
2530.foundFirstLine |
||||
2540\ if the next non-space byte in the keyboard buffer is ",", then parse |
||||
2541\ the end line# |
||||
2550JSR skipSpaces |
||||
2560CMP #&2C |
||||
2570BEQ parseEndLineNo |
||||
2580 |
||||
2590\ if the byte is not ".", then jump to the normal BRK handler |
||||
2600CMP #&2E |
||||
2610BNE defaultBRK |
||||
2620 |
||||
2630\ the input was of the form "LIST 12345.", so set the last line# |
||||
2631\ to be the same as the first line# |
||||
2640LDA curr_lineno |
||||
2650STA last_lineno |
||||
2660LDA curr_lineno+1 |
||||
2670STA last_lineno+1 |
||||
2680JMP parseEOL |
||||
2690 |
||||
2700.parseEndLineNo |
||||
2710\ if the next non-space byte in the keyboard buffer is &8D (pseudo-keyword |
||||
2711\ for a line#), then decode the line# into LAST_LINENO |
||||
2712\ NOTE - While decodeLineNo stores the result in CURR_LINENO (thus |
||||
2713\ corrupting it), the main loop extracts the line# each time it starts |
||||
2714\ a new line of program code, and so will restore it when it starts |
||||
2715\ processing the first line. |
||||
2720JSR skipSpaces |
||||
2730CMP #&8D |
||||
2740BNE endParseInput |
||||
2750JSR decodeLineNo |
||||
2760STA last_lineno+1 |
||||
2770LDA curr_lineno |
||||
2780STA last_lineno |
||||
2790JSR skipSpaces |
||||
2800 |
||||
2810.endParseInput |
||||
2820\ check for the trailing "." |
||||
2830CMP #&2E |
||||
2840BEQ P%+5 |
||||
2850JMP defaultBRK |
||||
2860 |
||||
2870.parseEOL |
||||
2880\ check for the terminating CR |
||||
2890JSR skipSpaces |
||||
2900CMP #&0D |
||||
2910BEQ P%+5 |
||||
2920JMP defaultBRK |
||||
2930 |
||||
2940\ start taking input from the program code i.e. PINPUT <- PCODE |
||||
2950LDA pcode |
||||
2960STA pinput |
||||
2970LDA pcode+1 |
||||
2980STA pinput+1 |
||||
2990 |
||||
5000\ === MAIN LOOP =========================================================== |
||||
5001 |
||||
5002\ We now start printing the listing, by stepping through each byte of |
||||
5003\ the program code, deciding how to print it out, until we go past LAST_LINENO. |
||||
5004 |
||||
5010.processNextByte |
||||
5020\ check if we're at the start of a line in the program code |
||||
5030JSR getNextByte |
||||
5040CMP #&0D |
||||
5050BNE printCode |
||||
5060 |
||||
5070\ yup - print a newline, save the line# in CURR_LINENO |
||||
5080JSR osnewl |
||||
5090JSR getNextByte |
||||
5100STA curr_lineno+1 |
||||
5110JSR getNextByte |
||||
5120STA curr_lineno |
||||
5130 |
||||
5140\ skip over the line length byte |
||||
5150JSR getNextByte |
||||
5160 |
||||
5170\ check if we're done (CURR_LINENO > LAST_LINENO) |
||||
5180LDA last_lineno |
||||
5190SEC |
||||
5200SBC curr_lineno |
||||
5210LDA last_lineno+1 |
||||
5220SBC curr_lineno+1 |
||||
5230BMI done |
||||
5240 |
||||
5250\ figure out how many digits the current line# has (by subtracting |
||||
5251\ each power of 10), then print enough spaces so that the line# |
||||
5252\ will be right-adjusted when we print it out |
||||
5260LDX #3 |
||||
5270.checkPow10 |
||||
5280LDA curr_lineno |
||||
5290SEC |
||||
5300SBC tensLSB,X |
||||
5310LDA curr_lineno+1 |
||||
5320SBC tensMSB,X |
||||
5330BMI P%+5 |
||||
5340DEX |
||||
5350BPL checkPow10 |
||||
5360INX |
||||
5370JSR indent |
||||
5380 |
||||
5390\ print the current line# |
||||
5400JSR &991F \ this prints the IAC (&2A/2B) as a 16-bit number |
||||
5410 |
||||
5420\ print a space |
||||
5430LDA #&20 |
||||
5440JSR oswrch |
||||
5450 |
||||
5460.startNextLine |
||||
5470\ initialize for the next line of program code, then loop back for the next byte |
||||
5471\ IN_REM <- 0 |
||||
5472\ IN_QUOTES <- 0 |
||||
5473\ IN_ASM_LABEL <- 0 |
||||
5474\ INDENT_PENDING <- &FF |
||||
5480LDX #0 |
||||
5490STX in_rem |
||||
5500STX in_quotes |
||||
5510STX in_asm_label |
||||
5520DEX |
||||
5530STX indent_pending |
||||
5540BMI processNextByte |
||||
5550 |
||||
5560.done |
||||
5570\ we're all done - warm-start BASIC |
||||
5580JSR osnewl |
||||
5590JMP &8AF3 |
||||
5600 |
||||
5610\ LSB/MSB's for 10000, 1000, 100, 10 |
||||
5620.tensLSB |
||||
5630EQUB &10 : EQUB &E8 : EQUB &64 : EQUB &0A |
||||
5640.tensMSB |
||||
5650EQUB &27 : EQUB &03 : EQUB &00 : EQUB &00 |
||||
5660 |
||||
5670\ we now print out the next byte of program code (in A) |
||||
5671 |
||||
5680.printCode |
||||
5690 |
||||
5700\ if we have a line# (pseudo-keyword &8D), then decode and print it out |
||||
5710CMP #&8D |
||||
5720BNE P%+11 |
||||
5730JSR decodeLineNo |
||||
5740JSR &991F \ this prints the IAC as a 16-bit number |
||||
5750JMP processNextByte |
||||
5760 |
||||
5770\ if we have a double-quote, then toggle the IN_QUOTES flag |
||||
5780CMP #&22 |
||||
5790BNE P%+10 |
||||
5800LDA in_quotes |
||||
5810EOR #&FF |
||||
5820STA in_quotes |
||||
5830LDA #&22 |
||||
5840 |
||||
5850\ if we are currently in a quoted string or a REM statement, |
||||
5851\ then output the current byte verbatim |
||||
5860BIT in_rem |
||||
5870BMI P%+6 |
||||
5880BIT in_quotes |
||||
5890BPL P%+5 |
||||
5900JMP outputByte |
||||
5910 |
||||
5920\ if we have a colon, then print a newline, indent, print a colon |
||||
5930CMP #&3A |
||||
5940BNE P%+18 |
||||
5950JSR osnewl |
||||
5960LDX #5 |
||||
5970JSR indent |
||||
5980LDA #&3A |
||||
5990JSR oswrch |
||||
6000JMP startNextLine |
||||
6010 |
||||
6020\ if we are currently in assembly code, then jump to handle that |
||||
6030BIT in_basic |
||||
6040BPL checkAssembly |
||||
6050 |
||||
6060\ if we have a REM token, then update the flag |
||||
6070CMP #&F4 |
||||
6080BNE P%+6 |
||||
6090LDX #&FF |
||||
6100STX in_rem |
||||
6110 |
||||
6120\ check if we have a NEXT or UNTIL token |
||||
6130CMP #&ED |
||||
6140BEQ P%+6 |
||||
6150CMP #&FD |
||||
6160BNE postNextUntil |
||||
6170\ yup - decrease the current level of indentation |
||||
6180JSR dedent |
||||
6190\ if we have a NEXT token, and the next program byte is a ",", then dedent again |
||||
6191\ NOTE - We peek ahead at the program bytes, and don't consume them. |
||||
6200CMP #&FD |
||||
6210BEQ postNextUntil |
||||
6220LDY #0 |
||||
6230.checkForComma |
||||
6240LDA (pinput),Y |
||||
6250INY |
||||
6260CMP #&2C |
||||
6270BNE P%+5 |
||||
6280JSR dedent |
||||
6290\ if we don't have a colon or the start of the next program line, |
||||
6291\ then loop back to check for another "," |
||||
6300CMP #&3A |
||||
6310BEQ P%+6 |
||||
6320CMP #&0D |
||||
6330BNE checkForComma |
||||
6340LDA #&ED \ restore the NEXT token |
||||
6350 |
||||
6360.postNextUntil |
||||
6370\ if the byte is "[" (start assembly code), then indent to col.24, flag that |
||||
6371\ we are not in BASIC code |
||||
6380CMP #&5B |
||||
6390BNE P%+11 |
||||
6400LDX #24 |
||||
6410JSR indent |
||||
6420LDX #0 |
||||
6430STX in_basic |
||||
6440 |
||||
6450\ if we need to indent, then make it so |
||||
6460BIT indent_pending |
||||
6470BPL P%+7 |
||||
6480LDX curr_indent |
||||
6490JSR indent |
||||
6500 |
||||
6510\ if we have a FOR or REPEAT token, then increase the indent |
||||
6520CMP #&E3 |
||||
6530BEQ P%+6 |
||||
6540CMP #&F5 |
||||
6550BNE outputByte |
||||
6560INC curr_indent |
||||
6570INC curr_indent |
||||
6580BNE outputByte |
||||
6590 |
||||
6600.checkAssembly |
||||
6610 |
||||
6620\ if we haven't indented yet, and we have a ".", then flag that we are |
||||
6621\ in an assembly label |
||||
6630BIT indent_pending |
||||
6640BPL P%+10 |
||||
6650CMP #&2E |
||||
6660BNE P%+6 |
||||
6670LDX #&FF |
||||
6680STX in_asm_label |
||||
6690 |
||||
6700\ if we haven't indented yet, and are in a label, and we've found |
||||
6701\ the end of the label, then update the "in label" flag |
||||
6710BIT indent_pending |
||||
6720BPL postAsmPrefix |
||||
6730BIT in_asm_label |
||||
6740BPL P%+10 |
||||
6750CMP #&20 |
||||
6760BNE postAsmPrefix |
||||
6770LDX #0 |
||||
6780STX in_asm_label |
||||
6790 |
||||
6800\ if we have something other than a space, then indent to col.24 |
||||
6810CMP #&20 |
||||
6820BEQ postAsmPrefix |
||||
6830LDX #24 |
||||
6840JSR indent |
||||
6850 |
||||
6860.postAsmPrefix |
||||
6870\ if we have a "\" (start of comment), then indent to col.41 |
||||
6880CMP #&5C |
||||
6890BNE P%+7 |
||||
6900LDX #41 |
||||
6910JSR indent |
||||
6920 |
||||
6930\ if we have a "]" (end of assembly code), then flag that we are in BASIC code |
||||
6940CMP #&5D |
||||
6950BNE outputByte |
||||
6960LDX #&FF |
||||
6970STX in_basic |
||||
6980 |
||||
6990.outputByte |
||||
7000JSR &B50E \ this prints the character or token in A |
||||
7010JMP processNextByte |
||||
7020 |
||||
8000\ === SUPPORT ROUTINES ==================================================== |
||||
8010 |
||||
8020\ get the next byte from PINPUT (keyboard buffer or program code) |
||||
8030 |
||||
8040.getNextByte |
||||
8050LDY #0 |
||||
8060LDA (pinput),Y |
||||
8070INC pinput |
||||
8080BNE P%+4 |
||||
8090INC pinput+1 |
||||
8100 |
||||
8110\ check for Escape |
||||
8120BIT &FF |
||||
8130BPL P%+14 |
||||
8140BRK |
||||
8150EQUB &17 |
||||
8160EQUB &0A : EQUB &0D : EQUS "Escape." : EQUB 0 |
||||
8170 |
||||
8180RTS |
||||
8190 |
||||
8200\ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
||||
8201 |
||||
8202\ print spaces until the cursor is at the column specified in X |
||||
8210 |
||||
8220.indent |
||||
8230PHA |
||||
8240\ NOTE - PCODE is only used when parsing the keyboard input, |
||||
8241\ and we re-use that byte here. |
||||
8250STX pcode |
||||
8260 |
||||
8270\ get the current text cursor position |
||||
8280LDA #&86 |
||||
8290JSR osbyte |
||||
8300 |
||||
8310\ subtract the requested column position to get the number of spaces |
||||
8311\ we need to print (this won't work properly if the indent is so large, |
||||
8312\ it wraps). |
||||
8320TXA |
||||
8330SEC |
||||
8340SBC pcode |
||||
8350BPL indentDone |
||||
8360 |
||||
8370\ print the spaces |
||||
8380TAX |
||||
8390LDA #&20 |
||||
8400JSR oswrch |
||||
8410INX |
||||
8420BNE P%-4 |
||||
8430 |
||||
8440.indentDone |
||||
8450\ flag that the current line has been indented |
||||
8460LDA #0 |
||||
8470STA indent_pending |
||||
8480 |
||||
8490PLA |
||||
8500RTS |
||||
8510 |
||||
8520\ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
||||
8521 |
||||
8522\ get the next non-space byte from PINPUT (keyboard buffer or program code) |
||||
8530 |
||||
8540.skipSpaces |
||||
8550JSR getNextByte |
||||
8560CMP #&20 |
||||
8570BEQ skipSpaces |
||||
8580 |
||||
8590RTS |
||||
8600 |
||||
8610\ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
||||
8611 |
||||
8612\ decode a line number in the 3 bytes at PINPUT, and store it in CURR_LINENO. |
||||
8613\ Adapted from the BBC BASIC ROM &97EB (p334). See p174 for details |
||||
8614\ on how these are encoded. |
||||
8620 |
||||
8630.decodeLineNo |
||||
8640JSR getNextByte |
||||
8650ASL A |
||||
8660ASL A |
||||
8670TAX |
||||
8680JSR getNextByte |
||||
8690STA curr_lineno |
||||
8700JSR getNextByte |
||||
8710STA curr_lineno+1 |
||||
8720TXA |
||||
8730AND #&C0 |
||||
8740EOR curr_lineno |
||||
8750STA curr_lineno |
||||
8760TXA |
||||
8770ASL A |
||||
8780ASL A |
||||
8790EOR curr_lineno+1 |
||||
8800STA curr_lineno+1 |
||||
8810 |
||||
8820RTS |
||||
8830 |
||||
8840\ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
||||
8841 |
||||
8842\ decrease the level of indentation (to a minimum of 6) |
||||
8850 |
||||
8860.dedent |
||||
8870DEC curr_indent |
||||
8880DEC curr_indent |
||||
8890 |
||||
8900LDX #6 |
||||
8910CPX curr_indent |
||||
8920BCC P%+4 |
||||
8930STX curr_indent |
||||
8940 |
||||
8950RTS ` |
||||
8960 |
||||
10000] : NEXT opt |
||||
10010PRINT |
||||
10020PRINT "To save the generated machine code:" |
||||
10030PRINT " *SAVE lst2 " + STR$~(BASE) + " " + STR$~(P%) |
||||
10040PRINT |
||||
10050PRINT "To activate it now:" |
||||
10060PRINT " CALL &" + STR$~(BASE) |
||||
10070PRINT "Or to reload it at a later time:" |
||||
10080PRINT " *lst2" |
||||
|
@ -0,0 +1,57 @@ |
||||
This program provides a formatted listing of a BBC BASIC program, by splitting multiple statements out onto separate lines, indenting loops, etc. Assembly language also gets nicely formatted. |
||||
|
||||
I was doing a lot of work on the BBC Micro in the late 80's, and recently managed to retrieve a lot of it from floppy discs. The discs were in relatively good condition, given that they were nearly 40 years old (!), but it was still a challenge reading them (they were shedding so much oxide, we had to clean the disk heads after each use :-)). |
||||
|
||||
This program was incredibly useful, but we were only able to get a binary executable off the floppies, not the source code, so I disassembled it, annotated it, and have made it available here. |
||||
|
||||
Working on the BBC Micro was not easy, since you only had, at best, 24¾KB of memory (!) (5¾KB if you were using hi-res graphics), so saving every byte of memory possible was really important. Since BASIC is an interpreted language, and each line had a 3-byte overhead, you could save quite a few bytes by cramming as many statements onto each line as possible, separated by a colon, thus saving 2 bytes for each statement. |
||||
|
||||
Of course, this made the code very difficult to read, so I wrote this listing formatter, which converts something like this: |
||||
``` |
||||
807DEFPROCsp LOCALT%,I%,P%,S$:PROCblip(100):REPEATUNTILNOTINKEY-99:REPEAT:PRINTTAB(0,24)SPC10f$B$bk$Y$"Press SPACE "bb$SPC10;:PROCfx21:T%=INKEY500:IFT%=esc T%=FNesc(T%):GOTO810:ELSEIFT%=32ORT%<>-1ORRND(500)>1GOTO810 |
||||
809P%=msgs+1:FORI%=1TORND(?msgs):S$=$P%:P%=P%+LENS$+1:NEXT:prvb=prvb+1:PRINTTAB(0,24)CHR$(128+RND(7))SPC38;:I%=1:REPEAT:PRINTTAB(1,24)MID$(STRING$(39," ")+"Ancient proverb #"+STR$prvb+": "+S$+STRING$(50," "),I%,38);:I%=I%+1:UNTILI%=70+LENS$ORNOTINKEY20 |
||||
810UNTILT%=32:PRINTTAB(0,24)SPC39;:ENDPROC |
||||
``` |
||||
into this: |
||||
``` |
||||
807 DEFPROCsp LOCALT%,I%,P%,S$ |
||||
:PROCblip(100) |
||||
:REPEATUNTILNOTINKEY-99 |
||||
:REPEAT |
||||
: PRINTTAB(0,24)SPC10f$B$bk$Y$"Press SPACE "bb$SPC10; |
||||
: PROCfx21 |
||||
: T%=INKEY500 |
||||
: IFT%=esc T%=FNesc(T%) |
||||
: GOTO810 |
||||
: ELSEIFT%=32ORT%<>-1ORRND(500)>1GOTO810 |
||||
809 P%=msgs+1 |
||||
: FORI%=1TORND(?msgs) |
||||
: S$=$P% |
||||
: P%=P%+LENS$+1 |
||||
: NEXT |
||||
: prvb=prvb+1 |
||||
: PRINTTAB(0,24)CHR$(128+RND(7))SPC38; |
||||
: I%=1 |
||||
: REPEAT |
||||
: PRINTTAB(1,24)MID$(STRING$(39," ")+"Ancient proverb #"+STR$prvb+": "+S$+STRING$(50," "),I%,38); |
||||
: I%=I%+1 |
||||
: UNTILI%=70+LENS$ORNOTINKEY20 |
||||
810 UNTILT%=32 |
||||
:PRINTTAB(0,24)SPC39; |
||||
:ENDPROC |
||||
``` |
||||
|
||||
To get the fully authentic Beeb experience, you can type the program in from the listing :-), but as a convenience, a `.ssd` file is provided with the source code, together with a binary executable. |
||||
|
||||
Load the program into memory like this: |
||||
``` |
||||
*LST2 |
||||
``` |
||||
|
||||
And then enter LIST commands as normal, but with a trailing period e.g. |
||||
``` |
||||
LIST 100,200. |
||||
LIST ,200. |
||||
LIST 100,. |
||||
LIST. |
||||
``` |
Loading…
Reference in new issue