Gremlin GBH
Found on:
Loader files:
Encoding:
"Greg Norman's Ultimate Golf"
"Impossamole"
"Lotus Esprit Turbo Challenge"
"Switchblade"
"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
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:Threshold:0x300/0x1b3
Lead-in:2400/1000 x '1' + single '0'
Sync:None
Header:Yes, separate file
Checksum:No
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)
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
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
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
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
.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