Blue Ribbon

Found on:
"Hi-Q-Quiz"
"Ice Temple"
"International Hockey"
"Steve Davis Snooker"
"Syntax"
"Video Card Arcade"
"Wulfpack"

Loader files:
ROM Header
Loader code
ROM Data
Autostart code

Encoding:
Endianess:LSbF
Threshold:0x014d or 0x01a0
Lead-in:256 x 0xA5
Sync:0x0A,0x09,0x08,0x07,0x06,
0x05,0x04,0x03,0x02,0x01


Structure:
Header:6 bytes
Checksum:Yes
Threshold:
This seems to vary.
Snooker uses 0x014d.
Wulfpack and International Hockey uses 0x01a0

Lead-in:
Actual count not checked by loader, only one is required to exist.
All titles so far seems to use 256.

Header:
00-01   Load start address (Low-High order)
02-03   2's complement of number of bytes to load (Low-High order)
04-05   Start address of game (Low-High order), or when loading multiple files can be used to start intro etc.
            Set to 0x0000 if no subroutine call needed.

Checksum:
EOR of all bytes excluding header. First byte after data is checksum byte.

Statistics:
 01
Steve Davis Snooker235 µs ($1D)433 µs ($35)
Wulfpack344 µs ($2A)533 µs ($42)
International Hockey334 µs ($29)532 µs ($42)
.label checksum   = $ab
.label loadedByte = $bd
.label EXTCOL     = $d020
.label CIAICR     = $dc0d
.label CI2ICR     = $dd0d
.label CI2CRA     = $dd0e

.pc = $033c

.byte $03,$a7,$02,$04,$03,$05
.text "SNOOKER "

.pc=$033c

.byte $03,$00,$03,$33,$03

// $351. Autostart code changes $fffe vector to this address
IRQ:pha
 lda#$91
 staCI2CRA
 ldaCIAICR
 ldaCI2ICR
 lsr // Shift out bit indicating if Timer A has counted down, '1' bit
 rorloadedByte// Rotate in bit to loaded byte, ror=LSbF
 ldaloadedByte
 decEXTCOL
 dey // Autostart code sets Y=1 from start, bits to load
chgBEQ:beqleadIn// Will be changed to point to the various stages of loading
 pla
 rti

leadIn:cmp#$a5// Lead-in 0xa5?
 bnenotLeadIn
 lda#$0d// First lead-in byte found
 stachgBEQ+1// Change beq @ $0366 to $375/liBytes
 bneexitIRQ

liBytes:cmp#$a5
 beqexitIRQ// Lead-in? Fetch next byte
 cmp#$0a// Sync 0x0a?
 beqsyncCheck
error:lda#$02// Not lead-in or sync, restart search for lead-in
 stachgBEQ+1
notLeadIn:iny
 pla
 rti

// Lead-in and sync byte 0x0a found, look for rest of sync sequence
syncCheck:lda#$29// Change beq @ $0366 to $391/chgCMP
 stachgBEQ+1
 lda#$09// Change cmp #0 to cmp #$09
 stachgCMP+1
 bneexitIRQ

// Looking for sync sequence 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01
chgCMP:cmp#0// Will be changed to 0x09, 0x08, 0x07 ...
 bneerror// 0x09 not found, restart search for lead-in
 decchgCMP+1// Decrease cmp value
 bneexitIRQ
 lda#$40// Change beq @ $0366 to $3a8/chgSTA
 stachgBEQ+1
 lda#$fa// set sta $fa address
 stachgSTA+1
exitIRQ:ldy#$08
 pla
 rti

// Sync sequence found, get header, 6 bytes
chgSTA:sta$fa
 incchgSTA+1
 bneexitIRQ
 lda#$50// Change beq @ $0366 to $3b8/load
 stachgBEQ+1
 stychecksum
 bneexitIRQ

// Header read, Store loaded bytes
load:sta($fa),y
 eorchecksum
 stachecksum
 inc$fa
 bnenoWrap
 inc$fb
noWrap:inc$fc
 bneexitIRQ
 inc$fd
 bneexitIRQ
 lda#$6b// Loading done, change beq @ $0366 to $3d3/cksum
 stachgBEQ+1
 bneexitIRQ

// Loading done, next byte should be checksum byte
cksum:eorchecksum
 beqchkOK
 lda#$37// Checksum failed, reset computer
 sta$01
 jmp$fcf2// System reset routine + 0x10

// Checksum okay
chkOK:lda#$01
 staEXTCOL
 dec$f9// Signal autostart code that loading is done
 bneerror
 lda#$37
 sta$01
 jsr$ff84// IOINIT
 pla
 rti

.byte $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20