;; Here is some code to initialise the firmware and save a file.
;; It is very useful for saving files when the firmware has been disabled
;; such as in a tape or disc loader.
;;
;; I do not authorise cracking or piracy of games.
;;
;; NOTE: 
;;
;;  1. Firmware is not present, so we must initialise it. But, areas
;;	   used by firmware must be saved before the firmware is 
;;	   initialised or the game will crash when we return to it.
;;	   Problem here is where do we store this data? Screen memory?
;;	   In the second bank of 64k?
;;	2. This code must be short if you want to replace an existing loader
;;	   in another program.
;;	3. If the original loader is in the range &0000-&3fff we need to
;;	   relocate this loader because the lower rom is switched in
;;	   when the firmware is initialised.

let mode=0                          ;screen mode

.start_address             equ &c000 ;address to put file

.km_initialise            equ &bb00
.txt_output               equ &bb5a
.cas_out_open              equ &bc8c
.cas_out_direct            equ &bc98
.cas_out_close             equ &bc8f


.kl_init_back             equ &bcce
.kl_l_rom_disable         equ &b909

;; ** STORE DATA USED BY PROGRAM THAT WILL BE CORRUPTED BY INITIALISATION OF **
;; ** FIRMWARE **


.save_code
di
ld (stack+1),sp             ;save stack used by program
ld sp,&c000                 ;new stack used by firmware and load routines

;; ** INITIALISE ALTERNATE REGISTER SET FOR FIRMWARE **

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

;; ** LOAD FILE USING FIRMWARE **


ld a,(filename+9)	    ; this code is ideal if there is only 9 levels
inc a			    
ld (filename+9),a

; otherwise for many more levels use this code:
;
; ld a,(level)		    ; variable holding level number
; ld b,a
; and &f
; add a,&41
; ld (end_filename-1),a
; ld a,b
; and &f0
; add a,&41
; ld (end_filename-2),a

ld b,end_filename-filename  ;length of filename
ld hl,filename              ;address of filename in memory
ld de,start_address          ;address to put file/2k buffer to use (unused since
push de                            ;read direct used
call cas_out_open            ;open file
pop hl
ld de,file_length
ld bc,0
ld a,2	                      ;HL = load address, BC = length of file
call cas_out_direct          ;read it
call cas_out_close           ;close it


;; ** RESTORE DATA WHICH WOULD HAVE BEEN OVERWRITTEN BY FIRMWARE **
;; !!EXAMPLE!!
di

.stack ld sp,0              ;old stack back and...
ret                         ;...exit to program!!

.filename
defb "LEVEL.0"
.end_filename
