Jiffy Fast-Load

Found on:
"Evil Dead"
"Jungle Quest"
"Monkey Magic"
"Munch Man"
"Robin to the Rescue"
"Special Operations"


Loader files:
ROM Header
Contains only filename
ROM Data
Turbo loader, autostarts

Encoding:
Endianess:MSbF
Threshold:0x0f0 or 0x138
Lead-in:3072 x 0x10
Sync:None
Trailer:0x00,0xff, ... , 0x01

Structure:
Header:Yes, 6 bytes
Checksum:No
Threshold:
"Evil Dead" uses the shorter 0x0f0 threshold, thre rest use 0x138.

Lead-in:
First 0x10 always seems to be incomplete. Seven bits, missing the MSb. But since the loader rotates bits into a memory location starting at value 0, it will be detected as a valid lead-in byte. Also the loader fetches lead-in bytes until one doesn't match 0x10. This last byte is not used. So there will always be one non 0x10 byte between the lead-in and the header.

Header:
00-01 Load address (High-Low order)
02-03 Load end address (High-Low order) (Exclusive)
04-05 Start of BASIC Program Text (High-Low order)

Trailer:
The data is expected to be followed by the 256 byte trailer. If any one byte is wrong, the loader hangs.
.label loadedByte = $fb

.pc = $0316

D0316:.word$fec1,$fec1,$f34a,$f291,$f20e,$f250,$f333,$f157
D0326:.wordC0344//IBSOUT. CHROUT routine
D0328:.word$e68e,$f13e,$f3f2
D032e:.wordC0344//USRCMD. RUN/STOP, BRK routine
D0330:.word$f4a5,$f5ed

// Fakes a cartridge entry
C0344:ldx#$09
copy:lda$03ff,x
 sta$7fff,x
 dex
 bnecopy

 stx$b9
 jsr$ff8a// Restore default IO
 jsrLoad
C0347:jsr$5d00
 jsr$a68e// Resets BASICs Text pointer to start at the new location set by the loader
 jmp$a7ae// Sets up BASIC for the next instruction to execute

Load:lda#$0b
 sta$d011
 lda#$17
 sta$01
 lda#$ff
 sta$c0

delay:dey
 bnedelay
 dex
 bnedelay

 sei
 iny
 ldx#$19
 lda#$38
 sta$dd06// Timer threshold 0x0138
 sty$dd07
findSync:jsrgetBit
 rolloadedByte
 ldaloadedByte
 cmp#$10
 bnefindSync
nextSByte:jsrgetByte
 cmp#$10
 beqnextSByte
// Fetch header
 ldy#$06
nextHByte:jsrgetByte
 sta$00ab,y
 dey
 bnenextHByte
loadData:jsrgetByte
 sta($b0),y
 inc$b0
 bneC0397
 inc$b1
C0397:lda$b1
 cmp$af
 bccloadData
 lda$b0
 cmp$ae
 bccloadData
// Check trailing sync sequence, 0x00,0xff .. 0x01
C03a3:jsrgetByte
 cpyloadedByte// Y=0 on first hit, so first byte after data is expected to be a 0x00
C03a8:bneC03a8
 dey
 bneC03a3

 ldx#$03// Change ILOAD vector to $0350
 stx$0331
 lda#$50
 sta$0330
 lda#$e6// Restore ISTOP vector to default
 sta$0329
 lda#$8e
 sta$0328

// Clear part of the Turbo loader
 lda#$ea
 sta$0343,x
 dex
 bne$13c1

 lda$b9// Was set to 0 at the beginning. Secondary device address
 bneC03d6
// Set 'Start of the BASIC Variable Storage Area' from header bytes 02-03 (Load end address)
// Set 'Start of BASIC Program Text' from header bytes 04-05
 ldx#$04
C03cf:lda$ab,x
 sta$2a,x
 dex
 bneC03cf
C03d6:sty$02a0
 clc
 jmp$fc93// Restore default IO. Returns to C0347

getByte:inc$d020
 lda#$08
 sta$fc
nextBit:jsrgetBit
 rolloadedByte// ROL=MSbF
 dec$fc
 bnenextBit
 ldaloadedByte
 rts

getBit:lda#$10
wFLAG:bit$dc0d// Wait for FLAG IRQ
 beqwFLAG
 lda$dd0d
 stx$dd0f
 lsr
 lsr
 rts

// $0244 is the more correct $0344 in other versions of this loader.
D0400:.word$0244,$0344
D0404:.byte$c3,$c2,$cd,$38,$30//CBM80
// Unused bytes
D0409:.byte$20,$9b,$82,$96,$92,$9c,$8e,$40,$88,$82,$a8,$82,$5c