;; Here is some code to initialise the firmware and load a file
;; it is very useful to use this in a multiload game to load the
;; levels (after you have cracked it and saved them out).
;; 
;; I do not authorise cracking software and piracy. 
;;
;; NOTE:
;;
;; 1. Routine cannot be in &0000-&3fff (lower rom initialised into this 
;;    area)
;; 2. You cannot load a file into a area used by firmware (0000-&0040)
;;    or &a600-&c000. If the program requires this, then load it to
;;    somewhere else and LDIR/LDDR it to it's place.
;; 3. This code will initialise the firmware for it's loading, so you
;;    must copy the data areas used by the firmware, load the file,
;;    and copy them back, (or the game will crash).
;;    Use the screen memory or the 2nd bank of 64k.
;; 4. Put this code where the loader for the levels is in the original game
;; 5. Dont forget to modify this code appropiatly. This is just an example.


.routine_address          equ &FE00

org routine_address

let mode=1                          ;screen mode

.km_initialise            equ &bb00
.txt_output               equ &bb5a
.km_wait_char             equ &bb18
.cas_in_open              equ &bc77
.cas_in_direct            equ &bc83
.cas_in_close             equ &bc7a
.cas_in_abandon           equ &bc7d

.kl_init_back             equ &bcce
.kl_l_rom_disable         equ &b909

;; ** STORE DATA USED BY PROGRAM THAT WILL BE CORRUPTED BY INITIALISATION OF **
;; ** FIRMWARE **

di
ld (stack+1),sp             ;save stack used by program
ld sp,&c000                 ;new stack used by firmware and load routines

LD BC,&7FC7 ;; Activo 16 KBytes extras en &4000
OUT (C),C
LD HL,&FB00
LD DE,&7B00
LD BC,&500
LDIR

LD BC,&7FC5 ;; Activo 16 KBytes extras en &4000
OUT (C),C

;; ** SAVE DATA OVERWRITTEN BY FIRMWARE **
;; !!EXAMPLE!!

;ld hl,&a800                 ;upper firmware area (&a800?-&c000)
ld hl,&af80                 ;upper firmware area (&a800?-&c000)
ld de,&4000

ld a,4
.next push af
push de
ld bc,&600
ldir
pop de
ld a,d
add a,8
ld d,a
pop af
dec a
jr nz,next

ld h,&00                    ;firmware lower jumpblock (&0000-&0040)
ld l,0
ld c,&40
ldir

;; ** INITIALISE ALTERNATE REGISTER SET FOR FIRMWARE **

LD BC,&7FC0 ;; Desactivo 16 KBytes extras
OUT (C),C

exx
ld bc,&7f00+%10001000+mode  ;initialise lower rom and select mode
out (c),c                   ;this routine must be located above &4000
exx  
ex af,af'
xor a
ex af,af'

;; ** INITIALISE FIRMWARE **

call &0044                  ;initialise lower jumpblock (&0000-&0040)
                            ;and high kernal jumpblock (&b800-&bae4)
call &08bd                  ;initialise firmware jumpblock entries
                            ;(&bb00- ...)
call km_initialise          ;initialise keyboard manager
call kl_l_rom_disable       ;disable lower rom

;; ** INITIALISE DISK ROM FOR LOADING/SAVING **

ld c,7                      ;disk rom
ld de,&0040                 ;lowest useable byte of memory
ld hl,&b0ff                 ;highest useable byte of memory
call kl_init_back           ;initialise disk rom

xor a                       ;select drive (A)
ld (&ac00),a

ld a,&ff
ld (&be78),a                ;turn of disc error messages

ld a,&c9
ld (txt_output),a           ;prevent printing of text characters
                            ;don't get error messages corrupting screen


LD a,(fpos)
dec a
JP z,nextspace
forspace:
call km_wait_char
cp #20
jp NZ,forspace
nextspace:
;; ** LOAD FILE USING FIRMWARE **

ld b,end_filename-filename  ;length of filename
ld hl,filename              ;address of filename in memory
ld de,&0600          ;address to put file/2k buffer to use (unused since
                            ;read direct used
push de
call cas_in_open            ;open file
pop hl                      ;HL = load address, BC = length of file
jp nc,forspace

call cas_in_direct          ;read it
call cas_in_close           ;close it

LD BC,&7FC1 ;; Activo 16 KBytes extras en &C000
OUT (C),C

ld b,end_filename-filename  ;length of filename
ld hl,filename+3              ;address of filename in memory
ld a,(hl)
inc a
ld (hl),a
ld hl,filename
ld de,&C000           ;address to put file/2k buffer to use (unused since
                            ;read direct used
push de
call cas_in_open            ;open file

pop hl                      ;HL = load address, BC = length of file
call cas_in_direct          ;read it
call cas_in_close           ;close it



;; ** RESTORE DATA WHICH WOULD HAVE BEEN OVERWRITTEN BY FIRMWARE **
;; !!EXAMPLE!!
di
LD BC,&7FC1 ;; Activo 16 KBytes extras en &C000
OUT (C),C   ;; Zona para firmware

ld hl,&C000
ld de,&7600
;ld bc,&4000
ld bc,&3F80-&600
ldir

LD BC,&7FC5 ;; Activo 16 KBytes extras en &4000
OUT (C),C   ;; Zona para firmware

ld hl,&4000                 ;copy back data
;ld de,&a800
ld de,&af80                 ;upper firmware area (&a800?-&c000)

ld a,4
.next2 push af
push hl
ld bc,&0600
ldir  
pop hl
ld a,h
add a,8
ld h,a
pop af
dec a
jr nz,next2

ld d,&00                    ;copy back &0000-&0040
ld e,0
ld c,&40
ldir  

LD BC,&7FC0 ;; Reactivada RAM normal
OUT (C),C

ld hl,filename+1              ;la siguiente vez, bloque 1
ld a,(hl)                     ;Pero siguiente nivel
inc a
ld (hl),a
xor a
ld d,a
ld hl,fpos
ld a,(hl)
ld e,a
inc a
inc a
ld (hl),a
add hl,de
ld a,(hl)
ld e,a
inc hl
ld a,(hl)
ld d,a
push de
pop hl
xor a
ld (hl),a
inc hl
ld a,&fe
ld (hl),a

.stack ld sp,0              ;old stack back and...
JP &0640                    ;...exit to program!!

.filename
defb "F1P1.BIN"
.end_filename
.fpos db 1
fases:
dw &526a
dw &4dd6
dw &5519
dw &53bc
dw &5025