Detokenize BASIC7.0 text

Started by MIRKOSOFT, July 22, 2010, 04:35 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

MIRKOSOFT

Hi!


I have utility which can detokenize text in keyboard buffer ($0200...).
So, I tried to detokenize BASIC7.0 text, only what I changed was address $0200 to $1c01 and load any BASIC program to $1c01.


I used this code:

.pc=$1300 "Detokenizer"

line:
ldx #01
jsr setbnk
lda #146
jsr toscreen
lda #<$1c01
sta $61
lda #>$1c01
sta $62
ldy #0
jsr detoken
lda #00
sta $ff00
rts


But output is nothing. I tried to change $1c01 to $1c03 where is stored BASIC line number and tried again, also output is nothing.


Can anybody explain to me where is my error?


Many thanks.


Miro
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

LokalHorst

This seems not correct:
ldx #01
jsr setbnk

If the 'jsr detoken' uses rom-code (as with list) it won't see things stored to ram1 (bank1)
- basic text is expected to be found in ram0

MIRKOSOFT

#2
Hi!


Yes, I forgot this... but also DETOKENIZE output is nothing... or changes color of characters to e.g. red...


I think if is not needed to skip links to next line (links meaning vectors of address where begins next line).



Can you help me?


Many many thanks.


Miro
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

MIRKOSOFT

So, I want to detokenize text of more computers and its versions:


address/computer/Basic v
$0401    PET - 4.0
$1001    VIC (unexpanded) - 2.0
$1201    VIC - 2.0
$0801    C64 - 2.0
$1001    Plus/4 - 3.5
$1C01    C128 - 7.0
$4001    C128 (using GRAPHICs) - 7.0
I want to load BASIC program to RAM1 (whole program) at $0400.
Then by copy some part to RAM0 and start detokenizing, after end, copy block again and detokenize again until ends program.
As is known start address of files is two first bytes, there I can recognize for which machine is BASIC program written.
The best option is that all Commodores have lower version than C128 BASIC 7.0
But why with this routine works not with BASIC text, I'm sure that works with keyboard buffer 'cause I created "clipboard" where entered text is copied to other location and when is used PASTE, this copied text is detokenized and shown on screen, little part of code is here:



.var detoken = $5149


start:
 lda #<address
sta $61
 lda #>address
sta $62
ldy #0
jsr detoken



So, how to continue?


Thanks for every reply.


Miro
MIRKOSOFT of megabytes

Commodore 64 was great, Commodore 128 is bigger, better, faster and more!!!

http://www.mirkosoft.sk

LokalHorst

#4
sorry for the delay - I was on a (too short) holiday trip to the Netherlands.

back to the topic - I've tried a few different things, but the only working solution is to copy each basic line to a buffer in ram0 and trick the basic list routine in thinking there's just one line (btw. your detokenize-call decodes just one byte at location $61/$62).
Another thing is the original load addr. of the basic-prog. (you'll like to analyze) - if you load to an user-specified addr. (here to bank1 $0401) the kernal doesn't save the file's first two bytes anywhere, so to get these, 1st open the file, then read & save the first 2 bytes, close the file, set-up to load to addr. 0401 in bank1 and finally call the kernal-load routine.

The following program-snippet expects to find a already loaded program-file in bank1 @ $0401 & that the system rom's are enabled on entry (start), it will list the program from 1st to the last basic-line.

;ZP-adresses used:
;user define
srcptrlo = $FB
srcptrHi = $FC
buffer = $FE00 ;top-most page of ram0 likely unused.

;fixed (used by rom-code)
llinelo = $16 ;used to limit the line no. range
llinehi = $17
wrklo = $61
wrkhi = $62 ;used by the list routine as pointer to actual location

curline = $EB ;current screen line - see note(s)
sh_flags = $D3 ;shift flags

;subroutine fetch from ram1
FTINIT:
STA $02AA ;adj. ZP pointer
Fetch_r1:
LDX #$7F  ;RAM1 MMU config
JMP $02A2 ;fetch

;INIT pointers
START:
LDA #$00  ;buffer $FE00 - $FEFF
LDX #>buffer  ;hi byte of buffer, page aligned
STA wrklo
STX wrkhi
TAY ;A = Y = $00
STA (wrklo),Y ;init byte before link ptr.
DEY
STA (wrklo),Y ;end of prog marker
DEY
STA (wrklo),Y
TYA
LDY #$01
STA (wrklo),Y ;link ptr lo (buffer)
INY
TXA
STA (wrklo),Y ;link ptr hi (buffer)

LDA #$01 ;src start (ram1)
LDX #$04
STA srcptrlo
STX srcptrhi
LDA #$FF ;list unconditional
STA llinelo
STA llinehi

;new (next) line
next:
LDY #$01  ;set lo buffer start adr. + index to link hi
STY wrklo
LDA #srcptrlo  ;ZP loc. to use for fetch (immediate value)
JSR FTINIT    ;read linelink hi
BEQ finish    ;if zero -> end of prog.

INY
JSR Fetch_r1  ;basic line # lo
STA (wrklo),Y
INY
JSR Fetch_r1  ;basic line # hi
copyl:
STA (wrklo),Y

;copy to buffer until 00 = end of basic line

INY
JSR Fetch_r1
BEQ copyend ;skip if end of line
CPY #$FC   ;overflow check
BCC copyl  ;loop if not
LDA #$00   ;line too long condition

copyend:
STA (wrklo),Y

INY
TYA
CLC
ADC srcptrlo    ;advance src. pointer to next line (link)
STA srcptrlo
BCC no_ih
INC srcptrhi
no_ih:

JSR $50E5  ;basic list rom-routine entry

DEC curline ;undo additional linefeed

;simplistic scroll stopper - halts as long as <CBM>,<CTRL> or <Shift> keys pressed
halt:
LDA sh_flags
BNE halt

JMP next ;repeat with next line

;end marker of src. reached
Finish:
BRK ;continue your code here (or RTS)

Notes:
- during the list portion ($50e5) the rom-code checks for Run/Stop key and if pressed exits to Basic (ready vector) - to avoid this, set SEI before the call or redirect the ready-vector.
- as this routine tricks basic in thinking only one line (the currently copied) exist, the rom-code inserts an additional linefeed after each line (hence the 'DEC curline zp-loc. $EB)

revised/simplified version

Hydrophilic

Excellent reply, LokalHorstMirkosoft, I don't know why your code doesn't work... it works for me... the address must point to the first token (after line-link/pointer and after line-number).  And like LokalHorst said, the data must be copied into Bank 0, and it only prints one line.

One thing to note is that after calling "Detoken" ($5149) is that the MMU will be set to configuration $01 which means Bank0 RAM (below $4000), all ROMs active (at/above $4000), and no I/O registers... this is likely to crash programs that don't know this!

Another important thing to note, more important in my opinion, is that Commodore changed some of the tokens!  Damn you, damn you, damn you!!  Ooooh, sorry about that, it's not your fault... or did you write BASIC for Commodre?  In that case, double damn you!  ::)

I appologize for the venting, but it's almost as bad as changing the KERNAL!  On this machine, JSR $FFD2 will print a character, but on this other machine, JSR $FFD2 will clear all RAM.  Or something stupid like that...

Anyway, most PETs and BASIC3.5 (Plus/4 and Commodore 16) and BASIC7.0 (C128) have the handy disk commands, but these are most of the ones that were changed!


TOKEN BASIC4(PET) BASIC3.5(Plus/4) BASIC7(C128)
$CC   CONCAT      RGR()            RGR()
$CD   DOPEN       RCLR()           RCLR()
$CE   DCLOSE      RLUM()           extended (2-byte token) function
$CF   RECORD      JOY()            JOY()
$D0   HEADER      RDOT()           RDOT()
$D1   COLLECT     DEC()            DEC()
$D2   BACKUP      HEX$()           HEX$()
$D3   COPY        ERR$()           ERR$()
$D4   APPEND      INSTR()          INSTR()
$D5   DSAVE       ELSE             ELSE
$D6   DLOAD       RESUME           RESUME
$D7   CATALOG     TRAP             TRAP
$D8   RENAME      TRON             TRON
$D9   SCRATCH     TROFF            TROFF
$DA   DIRECTORY   SOUND            SOUND
...
$EE   n/a         DIRECTORY        DIRECTORY
$EF   n/a         DSAVE            DSAVE
$F0   n/a         DLOAD            DLOAD
$F1   n/a         HEADER           HEADER
$F2   n/a         SCRATCH          SCRATCH
$F3   n/a         COLLECT          COLLECT
$F4   n/a         COPY             COPY
$F5   n/a         RENAME           RENAME
$F6   n/a         BACKUP           BACKUP
...
$FE0C n/a         n/a              CATALOG
$FE0D n/a         n/a              DOPEN
$FE0E n/a         n/a              APPEND
$FE0F n/a         n/a              DCLOSE
...
$FE12 n/a         n/a              RECORD
$FE13 n/a         n/a              CONCAT

It should be obvious this is only the "standard" commands... it gets even worse if you include BASIC extensions like Simon's BASIC, LOGO, SAM, etc...  In other words, if BASIC version is 2.0 (C64/VIC-20), 3.5, or 7.0 then you can use the standard ROM routine (except token $CE of V3.5).  But if it is BASIC 4.0 (PET) then you have to either modify the tokens in RAM (a tricky process to be sure) or change the "iqplop" routine via vector at $0306...

I hope some part of this is helpful...
I'm kupo for kupo nuts!