Reprinted with permission. Copyright (c) 1996 Creative Micro Designs, Inc.
Various routines have been used over the years to allow programs to move from 128 mode to 64 mode without user intervention. With the advent of modified Kernal ROMs (JiffyDOS, RAMLink, and others) many of the methods that work on stock machines have either failed to do the job completely, and in some cases fail all together.
RUN64 is the answer to those users looking to worm their way into 64 mode without having to be concerned with the different Kernal ROMs. The program is presented here in two ways: as a BASIC program that will move to 64 mode and load the program you request, and as assembly language source for ML programmers.
BASIC Notes: The BASIC version uses the ML code produced by the assembly language source. This is found in the data statements beginning at line 660. When you run it, the program will ask for the file name, device number, and file load type (BASIC or ML). The first two parameters should be self-explanatory, but the load type may confuse you. If the file you're loading is itself a small loader (1, 2 or 3 blocks) then it will almost always be an ML program. Likewise, if you usually load the file with a ",8,1" at the end of the load statement, it's ML. If you're loading a larger file, or a file that you normally load with just a ",8", then use the BASIC option.
Also, if you remove the REM instructions from lines 150 through 180 the program becomes a dedicated loader. Just specify the file name and other options within those lines.
The code uses some indirect vectors (ibv, ibr and ibm) to overcome not having an indirect jsr opcode, and switches out BASIC ROM temporarily since the KERNAL finishes intializing by indirectly jumping through the address at $a000. Since the target application hasn't been loaded yet, the code must put its own address at $a000 to regain control.
To use the routine, just set up a file name at filename, put a device number in $ba, set the load type in sa1flag, then execute the routine.
100 rem run64.bas (c) 1996 creative micro designs, inc. 110 : 120 print "{CLEAR/HOME}run64" 130 print 140 : 150 rem f$="filename" : rem filename 160 rem dv=peek(186) : rem device number (8, 9, 10, etc.) 170 rem l$="a" : rem load type (a=basic, b=ml [,1]) 180 rem goto 310 190 : 200 input "filename";f$ 210 input "{2 SPACES}device";dv$ : if dv$="" then 230 220 poke 186,val(dv$) 230 dv = peek(186) 240 print 250 print "select a or b" 260 print "{2 SPACES}a. load";chr$(34);f$;chr$(34);",";right$(str$(dv),len(str$(dv))-1) 270 print "{2 SPACES}b. load";chr$(34);f$;chr$(34);",";right$(str$(dv),len(str$(dv))-1);",1" 280 get l$ : if l$<>"a" and l$<>"b" then goto 280 290 print 300 print l$;" selected" 310 print 320 print "going to 64 mode!" 330 : 340 : rem poke in main ml 350 : 360 i = 6144 370 read d 380 if d = -1 then 450 390 poke i,d 400 i = i + 1 410 goto 370 420 : 430 : rem poke in filename 440 : 450 for i = 0 to len(f$)-1 460 : poke 6356+i, asc(mid$(f$,i+1,1)) 470 next i 480 poke 6356+i,0 490 : 500 : rem poke in device number 510 : 520 if dv$="" then 570 530 poke 186,val(dv$) 540 : 550 : rem check load type 560 : 570 poke 6324,0 580 if l$="b" then poke 6324,1 590 : 600 : rem sys to ml 610 : 620 sys6144 630 : 640 : rem ml data 650 : 660 data 32,115,239,160,0,185,22,24 670 data 153,0,128,200,208,247,165,186 680 data 141,157,128,76,77,255,9,128 690 data 9,128,195,194,205,56,48,169 700 data 0,141,4,128,120,169,0,141 710 data 22,208,32,132,255,32,135,255 720 data 169,230,133,1,169,43,141,0 730 data 160,169,128,141,1,160,76,248 740 data 252,169,231,133,1,32,148,128 750 data 32,151,128,32,154,128,162,0 760 data 189,159,128,240,6,32,210,255 770 data 232,208,245,162,0,189,190,128 780 data 240,6,32,210,255,232,208,245 790 data 162,0,189,180,128,240,6,32 800 data 210,255,232,208,245,173,158,128 810 data 240,10,169,44,32,210,255,169 820 data 49,32,210,255,169,145,32,210 830 data 255,32,210,255,173,157,128,133 840 data 186,162,0,189,185,128,240,6 850 data 157,119,2,232,208,245,173,158 860 data 128,208,2,169,4,133,198,76 870 data 157,227,108,149,227,108,152,227 880 data 108,155,227,0,0,17,17,68 890 data 86,61,80,69,69,75,40,49 900 data 56,54,41,58,76,79,65,68 910 data 34,0,34,44,68,86,0,13 920 data 82,213,13,0,70,73,76,69 930 data 78,65,77,69,0,-1 ; RUN64.SRC ; Doug Cotton & Mark Fellows ; (c) 1996 Creative Micro Designs, Inc. ; .org $1800 .obj run64.obj run64 jsr $ef73 ; go slow ; ldy #0 ; copy cartridge - lda code,y ; code to $8000 sta $8000,y iny bne - ; lda $ba ; get device number sta dvtemp ; and store it ; jmp $ff4d ; go 64 ; code .byt $09,$80 ; cold start .byt $09,$80 ; warm start .byt $c3,$c2,$cd,$38,$30 ; cbm80 ; .off $8009 ; offset code ; lda #$00 ; disable sta $8004 ; cartridge code sei ; disable interrupts ; lda #$00 ; zero out sta $d016 ; VIC control Register ; jsr $ff84 ; initialize I/O jsr $ff87 ; initialize RAM lda #$e6 ; switch in RAM sta $01 ; at $A000 lda #reenter ; BASIC statup during sta $a001 ; initialization ; jmp $fcf8 ; let Kernal finish up ; reenter lda #$e7 ; back from Kernal, set sta $01 ; $A000 back to ROM ; jsr ibv ; initialize vectors jsr ibr ; initialize RAM jsr ibm ; initialize memory ; ldx #$00 ; output screen text - lda part1,x ; to form LOAD statement beq + jsr $ffd2 inx bne - ; + ldx #$00 ; print filename to be - lda filename,x ; loaded at end of beq + ; LOAD statement jsr $ffd2 inx bne - ; + ldx #$00 ; print device - lda part2,x ; variable at end beq + ; of LOAD statement jsr $ffd2 inx bne - ; + lda sa1flag ; check secondary beq + ; address flag for load lda #',' ; type, and print a jsr $ffd2 ; comma and a 1 at end lda #'1' ; of LOAD statement if jsr $ffd2 ; load type is ML ; + lda #$91 ; print two CRSR up jsr $ffd2 jsr $ffd2 ; lda dvtemp ; get device number sta $ba ; and store ; + ldx #$00 ; put [RETURN]rU[RETURN] - lda keydata,x ; into keyboard buffer beq + sta $0277,x inx bne - ; + lda sa1flag ; get load type and bne + ; branch if it is ML (1) lda #$04 ; if not ML, change .A + sta $c6 ; store kybd buffer NDX ; jmp $e39d ; enter BASIC ; ibv jmp ($e395) ; initialize vectors ibr jmp ($e398) ; initialize RAM ibm jmp ($e39b) ; initialize memory ; dvtemp .byt $00 ; device number temp sa1flag .byt $00 ; load type (1=ML, ; 0=BASIC) ; part1 .byt $11,$11 ; 2 CRSR up .byt 'dv=peek(186):load' .byt $22 ; quote .byt $00 ; part2 .byt $22 ; quote .byt ',dv' .byt $00 ; keydata .byt $0d ; [RETURN] .byt 'rU' ; shortcut for RUN .byt $0d ; [RETURN] .byt $00 ; filename .byt 'filename' ; name of file to load .byt $00 ; 00 byte must follow filename! ; .end