Hello
I am developing a big game (occupying almost all memory) and have problems with loading next game level.
Some basic information:
- game is written using cpctelera - mostly C but some routines are in SDCC assembly
- individual modules are loading and running correctly
- have problems with loading next level from completed level
modules (levels) load address is 0x1ff and they end 0xa6xx
simple loader alone works OK, but when I try to include it in the module - I cant make it work
THIS WORKS OK:
loader.s
;;.area _LOADER (ABS)
_loadlevel::
;;.org 0xA650
filename: .asciz "LEVEL2.BIN"
ld c,#0xff ;; disable all roms
ld hl, #_dummy ;; execution address for program
call #0xbd16 ;;mc_start_program ;; start it
_dummy:: nop
call #0xbccb ;;kl_rom_walk ;; enable all roms
ld c,#0x07
ld hl,#_loader
call #0xbd13 ;;mc_boot_program
_loader:: ;; this is a loader which loads fileto specific address and returns start addr in (HL)
ld b, #10 ;;filename length
ld hl,#filename ;;pointer to filename string
ld de, #0x0 ;; 2k buffer - anything in this case
call #0xbc77 ;;cas_in_open
;
LD L, #0x00
LD H, #0x03
;; read file
call #0xbc83 ;;cas_in_direct
;; firmware function to close a file opened for reading
call #0xbc7a ;;cas_in_close
LD L, #0xf7
LD H, #0x9e
;;scf
ret
main.c
void loadlevel(void);
void main(void) {
loadlevel();
while (1) {
}
}
Loader loads above highest game address so it is not overwritten
WHAT DOESN'T WORK:
While trying to add loader to game level, it fails - resulting in reboot or hanging.
Of course I am setting things in a way that loading next level doesn't overwrite memory where loader is, so it theoretically can complete and continue to starting loaded code.
What I tried to do was to place loader in a different area (above next level highest address) than the game (game loads at 0x1ff)
.area _LOADER (ABS)
_loadlevel::
.org 0xA650
Is my approach/idea correct? Or maybe I am doing something wrong? What is the proper/best way of loading next level?
I need to perform something similar to BASIC command RUN"LEVEL2.BIN" when LEVEL1 completes.
ANy help / suggestions appreciated as I am sort of stuck with it ...
You put some Data at the beginning of the code, namely the string "LEVEL2.BIN",0.
Hence, it will be considered as code by the Instruction pointer when it reaches it.
This is what the Z80 will see:
org &a650
filename:
ld c,h ;;"LEVEL2.BIN",0
ld b,l
ld d,(hl)
ld b,l
ld c,h
ld (&422e),a
ld c,c
ld c,(hl)
nop
ld c,&00ff
ld hl,la663
call &bd16
la663:
nop
call &bccb
ld c,&0007
ld hl,la66f
call &bd13
la66f:
ld b,&000a
ld hl,la650
ld de,&0000
call &bc77
ld l,&0000
ld h,&0003
call &bc83
call &bc7a
ld l,&00f7
ld h,&009e
ret
A byte at offset 422Eh will be overwritten.
Simply move the string at the end of your code.
Thanks a lot, will try it, hopefully it will solve the problem.
But question though - why the WORKING scenario (with the small loader placed high in memory) does not have these problems? Filename data is also in the beginning of the code ...
Have not much experience with assembly and it's memory management so any hints highly appreciated :-)
I think I have solved the issue.
I moved the filename to the end of the string - it did not help.
Then I looked at memory map after compilation - and "loadlevel" routine was misplaced at 000000.
I have changed the order of first 3 lines from:
.area _LOADER (ABS)
_loadlevel::
.org 0xA650
to
.area _LOADER (ABS)
.org 0xA650
_loadlevel::
and it started to work :)
so it seemed to be a silly error ...