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
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
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
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
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
Excellent reply, LokalHorst. Mirkosoft, 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...