From: Ullrich von Bassewitz (uz_at_musoftware.de)
Date: 2002-10-10 12:31:50
On Wed, Oct 09, 2002 at 02:14:12PM -0700, Shawn Jefferson wrote: > I also was thinking that you could use the original $4000-7FFF for code, as > long as that code does not try to bank in the other banks, doesn't contain > screens or display lists, and your other code banks it back in after accessing > any extended memory. It would be a little complex, but no real problem I > don't think. You can also use cc65 to write code for systems with banked memory. Just a little manual work is needed. The rodata, data, and bss segments have to go into a common area, together with the part of the code that contains the cc65 runtime and C library functions needed by your program. In addition to that, small wrappers for banked functions must also go into common memory. Assume that you have three banks, each with just one function that has to be called (it is easy to extend this to more complex systems). The actual functions are named f1_bank1, f2_bank2 and f3_bank3 and reside in bank 1, bank 2 and bank 3 respectively. Now, generate short wrapper functions in assembler looking similar to this one: .code .export _f1 .proc _f1 sta tmp1 ; Save A lda bank_register ; Load current bank pha ; Save current bank lda #1 ; Target bank number sta bank_register ; Switch to target bank lda tmp1 ; Restore A jsr _f1_bank1 ; Call function in bank 1 pla ; Get old bank sta bank_register ; Restore old bank rts ; Return to caller .endproc Because all the wrapper functions look very similar, one can easily use a macro to save some typing. Of course, C code in other banks needs to call the wrapper function f1() instead of the real function f1_bank1(). While the wrappers have to reside in common memory, the actual functions go into separate banks. Since the runtime and C library together with all data is located in common memory, calling it from each of the banks is not a problem. Banking is somewhat expensive in terms of CPU cycles, and (at least when implemented as shown above) it needs 3 additional bytes on the return stack, so it is best to group complete subsystems into one bank, preferrably with just one entry point. Grouping stuff together is easily done by placing the code into a segment with a common name, and then tell the linker to relocate this segment to the base address of the banked memory. An example would be a printing subsystem that is called whenever the user chooses to print some text. It has just one entry point but many functions used to implement the necessary functionality, and all of these functions reside in one bank. There is exactly one wrapper function for the entry point, so the overhead in terms of additional code needed is not too large. Regards Uz -- Ullrich von Bassewitz uz_at_musoftware.de ---------------------------------------------------------------------- To unsubscribe from the list send mail to majordomo_at_musoftware.de with the string "unsubscribe cc65" in the body(!) of the mail.
This archive was generated by hypermail 2.1.3 : 2002-10-10 12:32:18 CEST