Programming:An example loader

From CPCWiki - THE Amstrad CPC encyclopedia!
Jump to: navigation, search
;; This example shows a disc loader program which is a executable binary
;; file.
;;
;; This loader can be run direct from BASIC using:
;; RUN"<loader> [RETURN]
;; replace <loader> with the name of the loader file
;; (e.g. RUN"SOLOMONS")
;;
;; 1. assemble the loader using MAXAM or other compatible assembler
;; 2. note the start and end addressess; use this to calculate the length of the data
;; 3. in BASIC type: SAVE"<loader>",B,<start>,<length>,<execution>
;;    replace <loader> with the name of the loader file
;;	          <start> with the start address of the loader file
;;			  <length> with the length of the loader file
;;			  <execution> with the execution/start address of the loader file
;;
;; Loader supports:
;; - loading from disc drive A and B.
;; - loading using AMSDOS and other DOSs (e.g. ROMDOS).
;;---------------------------------------------------------------------------

.scr_set_mode		equ &bc0e
.scr_set_border		equ &bc38
.scr_set_ink		equ &bc32
.cas_in_open		equ &bc77
.cas_in_direct		equ &bc83
.cas_in_close		equ &bc7a
.mc_start_program	equ &bd16
.kl_rom_walk		equ &bccb
;;---------------------------------------------------------------------------


org &100		   ;; example loader address
nolist			   ;; maxam command to stop listing of assembly

;;------------------------------------------------------------------------
;; store the drive number the loader was run from
ld hl,(&be7d)
ld a,(hl)                  
ld (drive+1),a

;;------------------------------------------------------------------------
ld c,&ff					;; disable all roms
ld hl,start					;; execution address for program
call mc_start_program		;; start it

;;------------------------------------------------------------------------

.start
call kl_rom_walk			;; enable all roms 

;;------------------------------------------------------------------------
;; when AMSDOS is enabled, the drive reverts back to drive 0!
;; This will restore the drive number to the drive the loader was run from
.drive ld a,0
ld hl,(&be7d)
ld (hl),a		  

;;------------------------------------------------------------------------
;; set screen mode 0
;; (replace this with the screen mode of your screen)

ld a,0
call scr_set_mode		  

;;------------------------------------------------------------------------
;; setup colours
call setup_colours

;;--------------------------------------------------------------------
;; sequence:
;; 1. load file
;; 2. decompress data (if compressed)
;; 3. relocate data (if required)
;; 
;; NOTE:
;; If data should be relocated to &A600-&BFFF then this must be done last
;; otherwise the firmware jumpblock will be corrupted and no more files can be loaded.
;;
;; If we have data to load which must be relocated we can do the following:
;; 1. set colours to black
;; 2. load data to screen area (not seen because all colours are the same)
;; 3. relocate data to destination address
;;
;; Normal load sequence:
;; - screen
;; - main file
;; - extra file to relocate to firmware jumpblock area
;; - execute program


;;--------------------------------------------------------------------
;; load block
call load_next_block		  

;; could have code here to decompress block if it is compressed, and
;; then relocate it


di				;; disable interrupts

; do any memory relocation here.

jp &103			;; and execute the code. (change this for the execution address
				;; used by your game)
				
;;------------------------------------------------------------------------
;; load the next block, updating filename for next block

.load_next_block
ld b,end_filename-filename
ld hl,filename
call load_block

;; update filename for next block
ld hl,end_filename-1	; add 1 to digit in filename
inc (hl)
ret

;;------------------------------------------------------------------------
;; B = length of filename
;; HL = address of filename
.load_block
ld de,&c000
call cas_in_open
ex de,hl		; load file to location stored in the file header
call cas_in_direct
call cas_in_close
ret

;;------------------------------------------------------------------------
;; setup colours
;;
;; HL = address of palette
;; 
;; order: pen 0, pen 1,...,pen15,border
.setup_colours

ld b,16			  ;; 16 colours
xor a			  ;; start with pen 0

.do_colours
push bc
push af
ld c,(hl)		  ;; colour value
inc hl
ld b,c			  ;; B=C so colours will not flash
push hl
;; A = pen number
;; B,C = colour
call scr_set_ink		  ;; set colour for pen
pop hl
pop af
pop bc
;; increment pen number
inc a
djnz do_colours

;; set border colour

ld c,(hl)
ld b,c
call scr_set_border	

ret

;;------------------------------------------------------------------------
;; set all colours to black

.set_to_black
ld b,16				;; 16 colours
xor a				;; initial pen index
.stb1
push af
push bc
ld bc,0				;; black
call scr_set_ink	;; set colour
pop bc
pop af
inc a				;; increment pen index
djnz stb1

ld bc,0				;; black
call scr_set_border	;; set border colour

ret

;;------------------------------------------------------------------------
;; a colour palette defined using firmware colour numbers
;; 
;; (replace this with your own colours)
;;
;; order: pen 0, pen 1,...,pen15,border

.colour_palette
defb 0,4,&10,&b,6,&1a,&18,&d,&c,&12,1,&b,4,&f,3,6,0

;;------------------------------------------------------------------------

;; name of first filename, next filename is SOLOMONS.BI1, then
;; SOLOMONS.BI2 etc...
;;
;; (replace this with your own filename)

.filename
defb "SOLOMONS.BI0"
.end_filename

list					;; maxam command to show listing
.end equ $+1			;; will show the last assembled address; we can use this
						;; to calculate the length of the data created