On Mon, Sep 06, 2004 at 12:03:28PM +0300, Karri Kaksonen wrote: > What I would like to do is to create a small set of resident functions in > a segment and be able to access these routines from my code in another > segment that gets switched in and out during the play. [...] > How do I tell the compiler what the starting address of level_one will be? > Do I have to do it manually in the lynx.cfg file or is there a way to find > out this from the compilation of the resident_code part. Code placement is done by the linker. For your purpose, you will probably have to use memory areas, which unfortunately means that the start address of the banked areas cannot be floating. > How do I find the entry addresses of my resident routines (play_tune, > read_file_from_cart) when I link my game at level_one or level_two? Symbol values are resolved by the linker. This means that you don't have to care about the addresses of the routines, because the linker will resolve them. The only thing you have to guarantee is that your code doesn't call routines that aren't loaded. > Or do I have to write a jump table at the start of the module to all > routines I want to access in another code segment? Are you talking about loadable modules? If the load address of a piece of code is known in advance (as in your case) I wouldn't use loadable modules, but simple binary images created by the linker. In the latter case, all symbols are resolved by the linker at link time, because it knows at which address the code is loaded. Your own code is responsible for loading the levels at runtime. Here is a small example for such a memory configuration: MEMORY { ZP: start = $00, size = $1A, type = rw, define = yes; RESIDENT: start = $1000, size = $3000, define = yes, file = "resident.bin"; BANK1: start = $4000, size = $4000, define = yes, file = "bank1.bin"; BANK2: start = $4000, size = $4000, define = yes, file = "bank2.bin"; } SEGMENTS { STARTUP: load = RESIDENT, type = wprot; LOWCODE: load = RESIDENT, type = wprot, optional = yes; CODE: load = RESIDENT, type = wprot; RODATA: load = RESIDENT, type = wprot; DATA: load = RESIDENT, type = rw; BSS: load = RESIDENT, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; # Bank1 stuff CODE_1: load = BANK1, type = wprot; RODATA_1: load = BANK1, type = wprot; DATA_1: load = BANK1, type = rw; BSS_1: load = BANK1, type = bss, define = yes; # Bank2 stuff CODE_2: load = BANK2, type = wprot; RODATA_2: load = BANK2, type = wprot; DATA_2: load = BANK2, type = rw; BSS_2: load = BANK2, type = bss, define = yes; } FEATURES { CONDES: segment = RODATA, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; CONDES: segment = RODATA, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__; } SYMBOLS { __STACKSIZE__ = $800; # 2K stack } Using this config, the linker will generate three output files: One named resident.bin that must be loaded at $1000, and two others named bank1.bin and bank2.bin that must be loaded at $4000. Runtime and C library support goes into the RESIDENT memory area and is used by both overlays. All symbols are resolved by the linker, so all code can freely call each other (of course no routine can be called when it is not loaded). If you're using C code in the banked areas, static variables will loose their values when reloaded. This can be avoided by placing the data and bss segments of the banked code into the resident memory area. Regards Uz -- Ullrich von Bassewitz uz@musoftware.de ---------------------------------------------------------------------- To unsubscribe from the list send mail to majordomo@musoftware.de with the string "unsubscribe cc65" in the body(!) of the mail.Received on Mon Sep 6 12:25:53 2004
This archive was generated by hypermail 2.1.8 : 2004-09-06 12:26:02 CEST