Gremlin GBH

Found on:
"Greg Norman's Ultimate Golf"
"Impossamole"
"Lotus Esprit Turbo Challenge"
"Switchblade"


Loader files:
ROM Header 1
Contains only filename
ROM Data 1
Autostart code. Loads turbo loader using standard Kernal loader
ROM Header 2
Contains only filename
ROM Data 1
Turbo loader

Encoding:
Endianess:MSbF
Threshold:0x300/0x1b3
Lead-in:2400/1000 x '1' + single '0'
Sync:None

Structure:
Header:Yes, separate file
Checksum:No
Threshold:
Threshold starts as 0x300 and is used for the lead-in. When lead-in is done the threshold is changed to 0x1b3.

Lead-in:
Loader checks that there are a certain numbers of '1's followed by a single '0' bit.
Impossamole has 2400 '1' bits preceeding data and checks that there are at least 1200 in a row before first '0' bit.
Greg Norman and Lotus only have 1000 lead-in bits and checks for 500.

Header:
Header file is used very differently amongst the titles found so far.
The header size varies from title to title.

Impossamole:
First file is a combination of header and data/code. Header part is for the following file.
Header/first file is hardcoded to load to area after loader.
First 4 bytes ara the actual header data.

00-01 Load address (Low-High order)
02-03 Load end address (Low-High order) (Exclusive)

Greg Norman:
Header contains filename. Loader does not use the header at all.

Lotus, Stryker & Switchblade:
Header contains filename. Loader checks filename against the name in the header.
It also picks up two bytes at the end of the header and uses these as the number of bytes to load.

0x12-0x13 Load size (Low-High order)
// Autostart code Impossamole
C02a7:lda#0
 sta$d020
 sta$d021
 sta$d011
 lda#0
 jsrSETNAM
 lda#0
 jsr$ff90
 lda#1
 tax
 tay
 jsrSETLFS
 lda#0
 ldx#$ff
 ldy#$ff
 jsrLOAD
 jmp$c118

D02cf:.text"part 2"
 .byte0,0,0,0,0,0,0,0,0,0
 .byte0,0,0,0,0,0,0,0,0,0
 .byte0,0,0,0,0,0,0,0,0,0
 .byte0,0,0,0,0,0,0,0,0,0
 .byte0,0,0,0
D0300:.word$e38b,$02a7
// Autostart code Greg Norman
C02db:lda#$13
 jsrCHROUT
 lda#1
 tax
 ldy#0
 jsrSETLFS
 lda#0
 tax
 tay
 jsrSETNAM
 lda#0
 ldx#$20
 ldy#$05
 sta$0a
 jsrLOAD// to $0520
 lda#$2b
 sta$d011
 jmp$05b9

D0302:.word$02db
    
// Autostart code Lotus
C02d7:sei
 lda#0
 sta$9d
 lda#0
 ldx#1
 ldy#1
 jsrSETLFS
 lda#6
 ldx#$fa
 ldy#$02
 jsrSETNAM
 lda#0
 ldx#0
 ldy#4
 jsrLOAD// to $0400
 jmp$0400

D02fa:.byte$05
 .text"LOTUS"
D0300:.word$e38b,$02d7




// Impossamole turbo loader source
.label EXTCOL = $d020
.label CIAICR = $dc0d
.label CIACRA = $dc0e
.label TI2ALO = $dd04
.label TI2AHI = $dd05
.label CI2ICR = $dd0d
.label CI2CRA = $dd0e
.label CI2CRB = $dd0f

.pc = $c118

// Autostart code jumps here
START:sei
 lda#$35
 sta$01// Switch out Kernal ROM

// Copy loader to $f010
 ldx#0
copy:lda$c147,x
 sta$f010,x
 lda$c247,x
 sta$f110,x
 lda$c347,x
 sta$f210,x
 lda$c447,x
 sta$f310,x
 dex
 bnecopy

 lda#$0b
 sta$d011
 lda#$01
 staEXTCOL
 jmp$f010


.pc = $f010

Loader:jmpCf038

Df013:.byte0,0
savedZP1:.byte0,0,0
bits2Load:.byte0
loadDone:.byte0
pilotCountLow:.byte0
pilotCountHigh:.byte0
Df01c:.byte0
pilotDone:.byte0
Df01e:.byte0
TA_Countdown:.byte0// Set to '1' by NMI when Timer A has reached zero
loadedByte:.byte0,1,0,0,0

delay:ldx#0
d1:ldy#0
d2:nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 dey
 bned2
 dex
 bned1
 rts

Cf038:sei
 lda#0
 staEXTCOL
 sta$d021
 staloadDone
 stapilotDone
 stapilotCountLow
 stapilotCountHigh
 staTA_Countdown
 lda#$07
 stabits2Load
 lda$01
 and#$d8
 ora#$05
 sta$01// Switch out Kernal ROM
 stasavedZP1
 jsrdelay
 lda#$27
 sta$0

// Clear screan and color RAM
 ldx#0
 txa
clrScr:sta$0400,x
 sta$0500,x
 sta$0600,x
 sta$0700,x
 sta$d800,x
 sta$d900,x
 sta$da00,x
 sta$db00,x
 dex
 bneclrScr

 lda#$1b
 sta$d011
 jsrCf1f9// Init, sets load address, size and loading variables
 jsrload// start loading
 jsrCf22a// Init, sets load address, size and loading variables
 jsrload// start loading
 sei
 lda#$35
 sta$01
 lda#$7f
 staCI2ICR
 staCIAICR
 ldaCI2ICR
 ldaCIAICR
 lda#0
 sta$d01a
 sta$d019
 jmp$0500

load:lda#$08
 staCI2CRA// Stop Timer 2 A
 ldaCI2CRB
 and#$fe
 staCI2CRB// Stop Timer 2 B
 lda#0
 staCIACRA// Stop Timer A
 lda#$fa// New IRQ vector $f0fa/IRQ
 sta$fffe
 lda#$f0
 sta$ffff
 lda#$ee// New NMI vector $f1ee/NMI
 sta$fffa
 lda#$f1
 sta$fffb
 lda#$e0// Timer A value/threshold, $00e0
 staTI2ALO
 lda#0
 staTI2AHI
 lda#$90// Enable FLAG IRQ
 staCIAICR
 lda#$81// Enable Timer A count down IRQ
 staCI2ICR
 lda#0
 staCIACRA
 cli
waitLD:ldaloadDone
 beqwaitLD
 rts


IRQ:pha
 ldaCIAICR
 and#$10
 bneCf109// Branch if FLAG IRQ
 ldaloadDone
 beqCf109// Branch if loading not finished
 pla
 rti

Cf109:lda#$08
 staCI2CRA// Stop Timer 2 A
 ldapilotDone// Inititialized to zero
 bneCf125
 lda#0// New Timer A value/threshold, $0300
 staTI2ALO
 lda#3
 staTI2AHI
 lda#9// Start timer A one-shot mode
 staCI2CRA
 jmpCf134

Cf125:lda#$b3// New Timer A value/threshold, $01b3
 staTI2ALO
 lda#1
 staTI2AHI
 lda#$09// Start timer A one-shot mode
 staCI2CRA
Cf134:ldapilotDone
 bneCf185
 ldaTA_Countdown
 beqCf163
 ldapilotCountLow
 cmp#$b0
 bneincPilotCount
 ldapilotCountHigh
 cmp#$04
 bneincPilotCount
 jmpexitIRQ

incPilotCount:
 ldapilotCountLow
 clc
 adc#1
 stapilotCountLow
 ldapilotCountHigh
 adc#0
 stapilotCountHigh
 jmpexitIRQ

Cf163:ldapilotCountLow// Initialized to zero
 cmp#$b0
 bneCf176
 ldapilotCountHigh
 cmp#$04
 bneCf176
 lda#$01
 stapilotDone
Cf176:lda#0
 stapilotCountLow
 stapilotCountHigh
exitIRQ:lda#0
 staTA_Countdown
 pla
 rti

Cf185:ldaTA_Countdown
 beqzeroBit
 sec
 rolloadedByte
 jmpCf195

zeroBit:clc
 rolloadedByte
Cf195:ldabits2Load
 and#$01
 beqCf1a4
 lda#$07
 staEXTCOL
 jmpCf1a9

Cf1a4:lda#0
 staEXTCOL
Cf1a9:decbits2Load
 bplCf1e7
 lda#$07
 stabits2Load
 lda$01
 pha
 lda#$34
 sta$01
 ldaloadedByte
Cf1bd:sta$4000// SMC, store address
 pla
 sta$01
 ldaCf1bd+1// Alter stora address
 clc
 adc#1
 staCf1bd+1
 ldaCf1bd+2
 adc#0
 staCf1bd+2
// Check if we have reached end of load
 ldaCf1bd+1
Cf1d7:cmp#$fe// SMC
 bneCf1e7
 ldaCf1bd+2
 cmp#$63// SMC
 bneCf1e7
 lda#$01
 staloadDone
Cf1e7:lda#0
 staTA_Countdown
 pla
 rti

// Occurs on Timer 2 A countdown
NMI:pha
 ldaCI2ICR
 lda#1
 staTA_Countdown
 pla
 rti

// Initialization for loading file 1, header (and some code as well).
Cf1f9:lda#$5f// Change sta @ $f1db
 staCf1bd+1
 lda#$f2
 staCf1bd+2
 lda#$8f// Change cmp @ $f1d7
 staCf1d7+1
 lda#$f2// Change cmp @ $f1de
 staCf1de+1
 lda#0
 staEXTCOL
 sta$d021
 staloadDone
 stapilotDone
 stapilotCountLow
 stapilotCountHigh
 staTA_Countdown
 lda#$07
 stabits2Load
 rts

// Initialization for loading file 2
Cf22a:ldaDf25f
 staCf1bd+1
 ldaDf260
 staCf1bd+2
 ldaDf261
 staCf1d7+1
 ldaDf262
 staCf1de+1
 lda#0
 staEXTCOL
 sta$d021
 staloadDone
 stapilotDone
 stapilotCountLow
 stapilotCountHigh
 staTA_Countdown
 lda#$07
 stabits2Load
 rts

Df25f:.byte0
Df260:.byte0
Df261:.byte0
Df262:.byte0