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

All times are UTC




Post new topic Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Tue Feb 19, 2013 2:16 am 
Offline

Joined: Tue Feb 19, 2013 12:29 am
Posts: 32
Location: Marlborough, Ma
Hello people.
My name is Paul. I have been working a renumber program for Commodore 64 basic
I am nearly complete. I parse the basic program and set the line numbers. I also have parsed the line to get GOTO GOSUB and THEN but I don't do anything with it yet. I need to add 1) a symbol table fix GOTO's etc. 2) a routine to add characters to a line of basic in case the new line is 3 digits and the old line is 2. I also have code but will not post yet, code to add the RENUM command to basic itself. I was wondering if anyone is interested in helping me finish this project as I have been busy with my real job programming Windows in WPF in C#. I have been using a real commodore 64c and Abacus Assembler. I have a ZooomFloppy on order to remedy that thank God.

NOTE about the code: I am not done documenting yet. I am using the X register as a flag for in a quote

Cheers
Code:
;  WRITTEN BY PAUL BAXTER
;
; .TITLE "RENUM"
.OPT N,OO : .SYM 2
;
*=$C000
;
;************
;*          *
;* SYMBOLS  *
;*          *
;************
;
CHROUT = $FFD2
PLOT = $FFF0
BSTART = $2B ; START OF BASIC
TXTOFF = $04; OFFSET TEXT
LNOFF = $02 ; OFFSET LINE NUMBER
NXOFF = $00 ; OFFSET NEXT ADDRESS
;
; ZERO PAGE USAGE
;
NXTLN = $FC ; PTR NEXT STATEMENT
LNUM = $FE  ; NEXT LINE NUM TO USE
INCR = $A3  ; LINE NUM INCREMENT
BNVAR = $4E ; NUM TO CONVERT TO BCD
BCDSTR = $57; BCD STRING RESULT
BCD = $5C
;
; BASIC TOKENS
;
GOTO = $89
GOSUB = $8D
THEN = $A7
QUOTE = $22
;
;************
;*          *
;* STORE.W  *
;*          *
;************
;
STORE.W .MAC AD,NUM
   LDA #<NUM
   STA AD
   LDA #>NUM
   STA AD+1
.MEND
;
;************
;*          *
;*  MOVE.W  *
;*          *
;************
;
MOVE.W .MAC SRC,DST
   LDA SRC,
   STA DST,
   LDA SRC+1
   STA DST+1
.MEND
;
;************
;*          *
;*   ADD.W  *
;*          *
;************
;
ADD.W .MAC AD1,AD2,DST
   CLC
   LDA AD1
   ADC AD2
   STA DST
   LDA AD1+1
   ADC AD2+1
   STA DST+1
.MEND
;
;************
;*          *
;* STZPIY.W *
;*          *
;************
;
STZPIY.W .MAC ZP,YVAL,AD
   LDY #YVAL
   LDA AD
   STA (ZP),Y
   LDA AD+1
   INY
   STA (ZP),Y
.MEND
;
;************
;*          *
;* LDZPIY.W *
;*          *
;************
;
LDZPIY.W .MAC ZP,YVAL
   LDY #YVAL
   LDA (ZP),Y
   TAX
   INY
   LDA (ZP),Y
.MEND
;
;************
;*          *
;* SHFT3BYT *
;*          *
;************
;
SHFT3BYT .MAC SRC,DST
   ASL SRC+0
   ROL SRC+1
   LDA DST+0
   ADC DST+0
   STA DST+0
   LDA DST+1
   ADC DST+1
   STA DST+1
   LDA DST+2
   ADC DST+2
   STA DST+2
.MEND
;
;************
;*          *
;* BCD2STR  *
;*          *
;************
;
BCD2STR .MAC SRC,DST
   LDA SRC
   AND $F0
   LSR
   LSR
   LSR
   LSR
   ORA #$30
   STA DST
   LDA SRC
   AND #$0F
   ORA #$30
   STA DST+1
.MEND
;
;************
;*          *
;* START    *
;*          *
;************
;
; INIT START OF BASIC PROGRAM
;
   'MOVE.W BSTART,NXTLN
;
; INIT LINE NUMBER
   'STORE.W LNUM,100
;
; INIT LINE NUMBER INCREMENT
   'STORE.W INCR,10
;
; GET THE TEXT OF THE LINE
NEXTLN LDY #NXOFF
   LDA (NXTLN),Y
   BNE PRLN
   INY
   LDA (NXTLN),Y
   BEQ GETLN
PRLN SEC
   JSR PLOT
   LDY #01
   CLC
   JSR PLOT
   JSR PRNTLINE
;
GETLN LDY #TXTOFF -1
   LDX #00
NXTCH INY
   LDA (NXTLN),Y
   BEQ STLN
;
; CHECK FOR QUOTE
CHKQUOTE CMP #QUOTE
   BNE CHKTOK
   CPX #00
   BNE INQUOTE
   LDX #01
   BNE NXTCH
;
INQUOTE LDX #00
   BEQ NXTCH
   BNE CHKTOK ; NEVER SHOULD GET HERE? REMOVE
;
;************
;*          *
;* BRANNEX  *
;*          *
;************
; BRANCH ISLAND
BRANNEX BNE NEXTLN
   BEQ NEXTLN
;
; SEARCH FOR GOTO GOSUB THEN
CHKTOK CMP #GOTO
   BNE CHKGOSUB
FINDLINE CLC
   BCC NXTCH
;
CHKGOSUB CMP #GOSUB
   BEQ FINDLINE
   CMP #THEN
   BEQ FINDLINE
   BNE NXTCH
;
; SET NEW BASIC LINE NUMBER
STLN 'STZPIY.W NXTLN,LNOFF,LNUM
   LDA #' '
   JSR CHROUT
   LDA #'='
   JSR CHROUT
   LDA #'>'
   JSR CHROUT
   JSR PRNTLINE
;
; INCRMENT LINE NUMBER
   'ADD.W LNUM,INCR,NUM
;
; GET POINTER TO NEXT BASIC LINE
   'LDZPIY.W NXTLN,NXOFF
;
; SAVE POINTER TO NEXT LINE
   STX NXTLN
   STA NXTLN+1
;
; CHECK FOR END OF PROGRAM
   CPX #00
   BNE BRANNEX
   CMP #00
   BNE BRANNEX
   RTS
;
;************
;*          *
;* PRNTLINE *
;*          *
;************
;
PRNTLINE LDA #LNOFF ; CAN BE REMOVED
   LDY #LNOFF
   LDA (NXTLN),Y
   STA BNVAR
   INY
   LDA (NXTLN),Y
   STA BNVAR+1
   JSR BINBCD16
   LDY #00
PBCD LDA BCDSTR,Y
   JSR CHROUT
   INY
   CPY #05
   BNE PBCD
   RTS
;
;************
;*          *
;* BINBCD16 *
;*          *
;************
;
BINBCD16 SED
   LDA #00
   STA BCD+0
   STA BCD+1
   STA BCD+2
   LDY #16
CNVBIT 'SHFT3BYT BNVAR,BCD
   DEY
   BNE CNVBIT
   CLD
   'BCD2STR BCD+0,BCDSTR+3
   'BCD2STR BCD+1,BCDSTR+1
   LDA BCD+2
   AND #$0F
   ORA #$30
   STA BCDSTR+0
   RTS
   .END


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 20, 2013 3:34 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 411
Location: Minnesota
Renumbering utilities for C64 BASIC are not hard to find, especially ones which renumber the entire program rather than a subset of it. There's no reason you can't write another one, but it should probably be approached with the attitude of having fun and learning something new (they're like 6502 assemblers that way :) ).

Have you thought about what you'll do if you run out of room to make changes? If you've already partially altered the program text you might have difficulty salvaging the situation.

You might consider a muti-pass design:

1) scan the program looking for GOTO (which can also be spelled "GO TO", if you want to handle that), GOSUB and THEN keywords followed by line numbers. You can determine what the new line number will be by counting. For example, if you have "GOTO 503", start at the first line of the program and look for line #503, adding the new line number increment to the new first line number until you find line #503. Now you know what the new line number will be. Don't change anything yet; just keep track of what the difference in size between the old and new line numbers will be.

2) when you've scanned the whole program you'll know what the difference in size between the original and renumbered program will be. If the renumbered program won't fit, this is the time to say so and get out.

3) if the renumbering fits, run the original scan again, except this time make the changes to the line numbers in the program text. That is, for each GOTO, etc, determine what its new line number will be by counting from the first line with the new first line number and new line number increment. Once you know what it is (again), make the change.

4) now the program text is renumbered but the line numbers in the line headers are still the originals. You're finally in a position to fix that and complete the renumbering. This step will be a lot faster.

One sneaky way to handle (3) is to list each line you're changing to the screen, with its original line number but with any GOTOs, etc., followed by their new line numbers. Use the "dynamic keyboard" technique to get the C64's screen editor to feed that new line to the BASIC interpreter for tokenization and replacement. Because it has the original line number it'll go to the same place in the sequence of lines; because the BASIC interpreter is doing the replacement you don't have to worry about moving text around yourself. The ease of use comes at a cost of taking longer, but if speed was what you were interested in you wouldn't be playing with this technology anyway, right?


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 20, 2013 10:24 pm 
Offline

Joined: Tue Feb 19, 2013 12:29 am
Posts: 32
Location: Marlborough, Ma
Thanks for the reply. All of my C64 stuff is just for fun. My day job is a senior software engineer at http://www.intervalzero.com. I work on an RTOS Real Time Operating System (used in aircraft, robotics, mixing boards etc and military). Winner of Windows Embedded Product of the year 4 years running. I am working on this because I currently have to use an assembler that has line numbers and to re familiarize myself with C64 and 6502 I do have a zoomfloppy on order so I can then use my pc to write code.

I am going to make this a 2 pass system and I will try to expand the lines myself just so I can learn how.


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 21, 2013 3:23 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Welcome, pebmeister -- nice to have you with us.
Quote:
All of my C64 stuff is just for fun.
Your day job looks like fun, too! Real Time Operating Systems? Interesting stuff!

cheers,
Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 21, 2013 6:52 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
My recollection of BASIC 2 renumberers is hazy but I seem to recall that a table was built in RAM consisting of line number references (16 bits) and the absolute addresses where these references were used. Once the table had been construction, the renumberer read the table, located each line number and added to or subtracted from it with an offset. The final step was to call the BASIC ROM's linker that fixes up the internal program references.

That all said, what would be really a worthwhile project would be to add to the interpreter so line labels could be used as GOTO and GOSUB targets, as is done in Business BASIC interpreters.

teamtempest wrote:
1) scan the program looking for GOTO (which can also be spelled "GO TO", if you want to handle that), GOSUB and THEN keywords followed by line numbers.

Keywords, such as GOTO (GO TO is a Commodore-unique feature that tokenizes as CB 20 A4), are not stored in human-readable format in the program text. What the utility would be seeking is the token for the keyword ($89 for GOTO), followed by the PETSCII form of the target line number, that is, the byte sequence 89 31 32 33 34 for the statement GOTO 1234.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 22, 2013 6:41 am 
Offline

Joined: Tue Feb 19, 2013 12:29 am
Posts: 32
Location: Marlborough, Ma
Did you see the comments in the code

Code:
;
; BASIC TOKENS
;
GOTO = $89
GOSUB = $8D
THEN = $A7
QUOTE = $22
;



also if the token are found they goto the label
FINDLINE

which currently does nothing but should start parsing the line and storing it in a table


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 22, 2013 11:23 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Last edited by White Flame on Sat Feb 23, 2013 12:24 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 22, 2013 11:49 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
edit: eh, reading teamtempest's post again, that's already an in-place solution. Use that if you don't want to monkey with tables or risk their size penalty.

What teamtempest was mentioning is that you've got the GOTO token, but forgot about TO on its own, which is valid C64 BASIC. However, you have to distinguish its use in FOR .. TO .. NEXT vs GO TO. If you find GO on its own, skip spaces, skip TO, skip spaces, and then you get your linenum; don't look for TO's token directly.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 23, 2013 7:13 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
pebmeister wrote:
Did you see the comments in the code

Code:
;
; BASIC TOKENS
;
GOTO = $89
GOSUB = $8D
THEN = $A7
QUOTE = $22
;


also if the token are found they goto the label
FINDLINE

which currently does nothing but should start parsing the line and storing it in a table

I have a difficult time reading the code sections because they are in a light green that contrasts poorly with the white background. It was recently discovered that I have cataracts in both eyes, something I had suspected for a while because of the worsening contrast problem. So don't be surprised if I miss something in code sections.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun Mar 03, 2013 7:37 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
teamtempest wrote:
One sneaky way to handle (3) is to list each line you're changing to the screen, with its original line number but with any GOTOs, etc., followed by their new line numbers. Use the "dynamic keyboard" technique to get the C64's screen editor to feed that new line to the BASIC interpreter for tokenization and replacement. Because it has the original line number it'll go to the same place in the sequence of lines; because the BASIC interpreter is doing the replacement you don't have to worry about moving text around yourself. The ease of use comes at a cost of taking longer, but if speed was what you were interested in you wouldn't be playing with this technology anyway, right?


This would most likely not work. What if the new line number collides with an existing (old) one? The old one would be overwritten.
Besides it being horribly slow compared to just change the values in-place. To make place for larger line numbers, you should probably move the program to the end of memory, then copy it, line by line, back to the front of memory, replacing the GOTO etc references on the way.

Andre

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 04, 2013 6:24 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 411
Location: Minnesota
Quote:
This would most likely not work. What if the new line number collides with an existing (old) one? The old one would be overwritten.


Mmm, I don't believe that can happen. Although you quoted, perhaps it was not clear to you what I was saying. I meant changing something like this:

Code:
47 IF A=B THEN 97


to something like this:

Code:
47 IF A=B THEN 1010


If a BASIC interpreter did anything with that besides replacing line 47, I'd consider it broken. Is there something I'm overlooking?

Quote:
Besides it being horribly slow compared to just change the values in-place


I believe I mentioned that as well in the part you quoted:

Quote:
The ease of use comes at a cost of taking longer


Because the BASIC interpreter replaces lines by first deleting the old one, then opening up space for the new one, copying it there, and then re-building the line link chain, yes. But not only is the method I propose simpler (and likely smaller code size), I've seen it at work in a commercial utility. I just never really thought about what it was actually doing until this thread came up.


Top
 Profile  
Reply with quote  
PostPosted: Fri May 31, 2013 1:36 am 
Offline

Joined: Tue Feb 19, 2013 12:29 am
Posts: 32
Location: Marlborough, Ma
I have made the code public and uploaded it to
http://sourceforge.net/projects/c64renumber/

:lol:


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 27 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: