banking in cc65 and large program (and a text adventure)

All aspects of programming on the Commander X16.
Post Reply
Xiphod
Posts: 568
Joined: Thu Apr 15, 2021 8:05 am

banking in cc65 and large program (and a text adventure)

Post by Xiphod »

To experiment with a "large program" (over 32K, or even over 64K) and also perhaps get a text adventure ported to the X16 - I tried compiling a C port of Zork1.

A more authentic port is here: (it is an auto-generated conversion from the original FORTRAN to C using f2c)
https://github.com/devshane/zork
(and true, there was technically a version before the FORTRAN- but it was a MDL mainframe language; I think the original authors were part of the FORTRAN port, so it's canon enough - the FORTRAN version is what ran on unix originally)
This version isn't compatible with cc65 as things stand today (it uses C99 stuff, that allows you to declare variables within the code instead of just at the top of functions; and since it is a ton of auto-generated code, it's a real chore to try to rework it for cc65 -- we could try vbcc, but.. that has other issues)

So I came across this alternative, which looks reasonably representative of the original:
https://github.com/donnierussellii/zork1c

There were a few compiling issues with cc65, but most were easily resolved. And one thing to note, you have to compile and run compress_data.c in order to auto-generate some of the code that is then used in the actual build. Basically it generates a list of constants for the rooms and objects, but also generates a compressed string version of all the text -- which yes, that means it gets baked into the build and not as an external file (no wonder the mainframe version requires 1MB of memory). But it's also a good excuse to figure out this BANKing stuff for building large C programs on the X16.

cc65 comes with an x16-bank.cfg but, I'm not exactly sure how to use it. OR, this build is still exceeding all the available BANK memory? It looks like we're ~66K short, based on this:

Code: Select all

ld65: Warning: F:\X16\cc65-snapshot-win32\cfg/cx16.cfg:17: Segment 'CODE' overflows memory area 'MAIN' by 66614 bytes
ld65: Error: Cannot generate most of the files due to memory area overflow
I recall being in this situation with cc65 on the PET, where every byte was starting to count!



I've put a discussion about it on the cc65 github, if anyone has ideas on things to try from here:

https://github.com/cc65/cc65/discussions/2164


Obviously with some inline assembly, you could just manage the banking yourself (even within cc65). But eventually "business logic" portions of code will get large enough (like maybe after adding AI logic and such), the executable code would need to get banked as well?
Xiphod
Posts: 568
Joined: Thu Apr 15, 2021 8:05 am

Re: banking in cc65 and large program (and a text adventure)

Post by Xiphod »

Using the "-m" argument of ld65 (part of cc65), I can get some size metrics of each of the compiled units of this Zork.

NOTE: I'm compiling without any optimization, since currently optimization is causing issues with cc65 on this particular set of code -- some branches end up attempted beyond 127 offset when optimization is enabled.

Here is a summary of the memory need per C module:
zork1_memory_summary.png
zork1_memory_summary.png (16.91 KiB) Viewed 986 times
Zork tries to be "self sufficient" by having a lot of the Room and Object string descriptions as part of the build, rather than external files. Maybe this was a performance thing, as any disk access even in 1980 would have been slow (and noisy). There are 111 rooms and 80 objects. I considered just reducing the number of rooms (and objects), since even just being able to move between two rooms would be a nice proof-of-concept. But so far it's not that simple.

The parsing code itself is roughly 47K (to handle verbs and nouns; that's code and data).

Then the supporting code, to transition between rooms (which has special handling of objects and encounters), that's about 60K (which includes handling three "villain" encounters) -- plus about 57K of supporting DATA. The Room and Object data is compressed, and C code uses malloc/free when Uncompressing that data (so at least about 300 bytes of RAM needs to available to hold the uncompressed thing).

Then there is a RNG and TextCompression support routines, which altogether need about another 7K (combined with the C-standard library stuff that is also some byte code that needs to be compiled in).

The good news is this should be do-able even on a 256KB system (CODE+DATA totally to about 180KB). But I'm still not sure how to take advantage of BANKing here.

It seems I need a way to say "I want this specific function compiled for BANK n" (which means anytime I invoke that function, BANK n is activated right before the call -- and maintain a stack of BANK changes in case of nested calls).

The Room Descriptions is probably the largest const data structure, and I think it was right at about 7.5KB -- so a way to designate which BANK that gets stored on would help (and automatically switch to that BANK - and back - when using the data structure).

Still getting oriented on how this code is arranged...





Code: Select all

Modules list:
-------------
compress.o:                                                             contains CompressText and DecompressText
    CODE              Offs=000000  Size=00075E  Align=00001  Fill=0000  1886 bytes
    RODATA            Offs=000000  Size=0002C3  Align=00001  Fill=0000  707  bytes
    DATA              Offs=000000  Size=000006  Align=00001  Fill=0000
game.o:                                                                 handles transition from one room to another
    CODE              Offs=00075E  Size=00B81A  Align=00001  Fill=0000  47,130 bytes
    RODATA            Offs=0002C3  Size=009DAD  Align=00001  Fill=0000  40,365 bytes
    BSS               Offs=000000  Size=000058  Align=00001  Fill=0000
    DATA              Offs=000006  Size=000784  Align=00001  Fill=0000   1,924 bytes
mt.o:                                                                   implements random number generator ("Mersenne Twist")
    CODE              Offs=00BF78  Size=000825  Align=00001  Fill=0000   2,085 bytes
    BSS               Offs=000058  Size=0004E4  Align=00001  Fill=0000   1,252 bytes
    DATA              Offs=00078A  Size=000004  Align=00001  Fill=0000
parser.o:                                                               main() is here, handles the game parsing
                                                                        malloc/free used when room descriptions Decompressed
    CODE              Offs=00C79D  Size=007C13  Align=00001  Fill=0000  31,763 bytes
    RODATA            Offs=00A070  Size=000F53  Align=00001  Fill=0000   3,923 bytes
    BSS               Offs=00053C  Size=000472  Align=00001  Fill=0000   1,138 bytes
    DATA              Offs=00078E  Size=000008  Align=00001  Fill=0000

tables.o:                                                              room "scenery", room passages, object locations and rules, 
                                                                       verb to action, noun tables, 
    RODATA            Offs=00AFC3  Size=001302  Align=00001  Fill=0000   4,865 bytes
    DATA              Offs=000796  Size=001CE3  Align=00001  Fill=0000   7,395 bytes

villains.o:                                                            handles a troll, thief, and cyclopes encounters
    CODE              Offs=0143B0  Size=00336E  Align=00001  Fill=0000  13,166 bytes
    RODATA            Offs=00C2C5  Size=000B8F  Align=00001  Fill=0000   2,959 bytes
    DATA              Offs=002479  Size=000018  Align=00001  Fill=0000   

_data.o:                                                               compressed Room and Object descriptions
    RODATA            Offs=00CE54  Size=002E2F  Align=00001  Fill=0000  11,823 bytes
    DATA              Offs=002491  Size=0001AC  Align=00001  Fill=0000     428 bytes


..\lib\cx16.lib(_directerrno.o):
    CODE              Offs=01771E  Size=000009  Align=00001  Fill=0000
..\lib\cx16.lib(_fdesc.o):
    CODE              Offs=017727  Size=00001D  Align=00001  Fill=0000
..\lib\cx16.lib(_file.o):
    DATA              Offs=00263D  Size=00001E  Align=00001  Fill=0000
..\lib\cx16.lib(_fopen.o):
    CODE              Offs=017744  Size=00007B  Align=00001  Fill=0000
    BSS               Offs=0009AE  Size=000002  Align=00001  Fill=0000
..\lib\cx16.lib(_heap.o):
    DATA              Offs=00265B  Size=00000A  Align=00001  Fill=0000
    ONCE              Offs=000000  Size=000010  Align=00001  Fill=0000
..\lib\cx16.lib(_hextab.o):
    RODATA            Offs=00FC83  Size=000010  Align=00001  Fill=0000
..\lib\cx16.lib(_longminstr.o):
    RODATA            Offs=00FC93  Size=00000C  Align=00001  Fill=0000
..\lib\cx16.lib(_mappederrno.o):
    CODE              Offs=0177BF  Size=00000F  Align=00001  Fill=0000
..\lib\cx16.lib(_oserror.o):
    BSS               Offs=0009B0  Size=000001  Align=00001  Fill=0000
..\lib\cx16.lib(_printf.o):
    CODE              Offs=0177CE  Size=0003A5  Align=00001  Fill=0000      943 bytes
    BSS               Offs=0009B1  Size=00002B  Align=00001  Fill=0000
    DATA              Offs=002665  Size=000003  Align=00001  Fill=0000
..\lib\cx16.lib(_seterrno.o):
    CODE              Offs=017B73  Size=000009  Align=00001  Fill=0000
..\lib\cx16.lib(add.o):
    CODE              Offs=017B7C  Size=000018  Align=00001  Fill=0000
..\lib\cx16.lib(addeqsp.o):
    CODE              Offs=017B94  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(addysp.o):
    CODE              Offs=017BA5  Size=00000E  Align=00001  Fill=0000
..\lib\cx16.lib(aslax1.o):
    CODE              Offs=017BB3  Size=000008  Align=00001  Fill=0000
..\lib\cx16.lib(aslax2.o):
    CODE              Offs=017BBB  Size=00000B  Align=00001  Fill=0000
..\lib\cx16.lib(aslax3.o):
    CODE              Offs=017BC6  Size=00000E  Align=00001  Fill=0000
..\lib\cx16.lib(aslax4.o):
    CODE              Offs=017BD4  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(atexit.o):
    CODE              Offs=017BE5  Size=000037  Align=00001  Fill=0000
    BSS               Offs=0009DC  Size=00000B  Align=00001  Fill=0000
..\lib\cx16.lib(axlong.o):
    CODE              Offs=017C1C  Size=00000D  Align=00001  Fill=0000
..\lib\cx16.lib(bankramaddr.o):
    BRAM01ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM02ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM03ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM04ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM05ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM06ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM07ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM08ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
    BRAM09ADDR        Offs=000000  Size=000002  Align=00001  Fill=0000
..\lib\cx16.lib(bneg.o):
    CODE              Offs=017C29  Size=00000E  Align=00001  Fill=0000
..\lib\cx16.lib(call.o):
    CODE              Offs=017C37  Size=000007  Align=00001  Fill=0000
..\lib\cx16.lib(callmain.o):
    CODE              Offs=017C3E  Size=000017  Align=00001  Fill=0000
    DATA              Offs=002668  Size=000004  Align=00001  Fill=0000
..\lib\cx16.lib(close.o):
    CODE              Offs=017C55  Size=000038  Align=00001  Fill=0000
..\lib\cx16.lib(condes.o):
    CODE              Offs=017C8D  Size=00000C  Align=00001  Fill=0000
    DATA              Offs=00266C  Size=000025  Align=00001  Fill=0000
    ONCE              Offs=000010  Size=00000C  Align=00001  Fill=0000
..\lib\cx16.lib(crt0.o):
    STARTUP           Offs=000000  Size=000021  Align=00001  Fill=0000
    ONCE              Offs=00001C  Size=00001B  Align=00001  Fill=0000
    INIT              Offs=000000  Size=000002  Align=00001  Fill=0000
..\lib\cx16.lib(ctype.o):
    RODATA            Offs=00FC9F  Size=00008B  Align=00001  Fill=0000
..\lib\cx16.lib(ctypemask.o):
    CODE              Offs=017C99  Size=00001E  Align=00001  Fill=0000
..\lib\cx16.lib(decax1.o):
    CODE              Offs=017CB7  Size=000007  Align=00001  Fill=0000
..\lib\cx16.lib(decax4.o):
    CODE              Offs=017CBE  Size=000007  Align=00001  Fill=0000
..\lib\cx16.lib(decaxy.o):
    CODE              Offs=017CC5  Size=000009  Align=00001  Fill=0000
..\lib\cx16.lib(decsp1.o):
    CODE              Offs=017CCE  Size=000009  Align=00001  Fill=0000
..\lib\cx16.lib(decsp2.o):
    CODE              Offs=017CD7  Size=00000D  Align=00001  Fill=0000
..\lib\cx16.lib(decsp4.o):
    CODE              Offs=017CE4  Size=00000D  Align=00001  Fill=0000
..\lib\cx16.lib(decsp6.o):
    CODE              Offs=017CF1  Size=00000D  Align=00001  Fill=0000
..\lib\cx16.lib(decsp8.o):
    CODE              Offs=017CFE  Size=00000D  Align=00001  Fill=0000
..\lib\cx16.lib(diskcmd.o):
    CODE              Offs=017D0B  Size=0000C4  Align=00001  Fill=0000
    BSS               Offs=0009E7  Size=000017  Align=00001  Fill=0000
..\lib\cx16.lib(div.o):
    CODE              Offs=017DCF  Size=000015  Align=00001  Fill=0000
..\lib\cx16.lib(divt.o):
    CODE              Offs=017DE4  Size=000015  Align=00001  Fill=0000
..\lib\cx16.lib(eq.o):
    CODE              Offs=017DF9  Size=00000A  Align=00001  Fill=0000
..\lib\cx16.lib(errno.o):
    BSS               Offs=0009FE  Size=000002  Align=00001  Fill=0000
..\lib\cx16.lib(exehdr.o):
    EXEHDR            Offs=000000  Size=00000C  Align=00001  Fill=0000
..\lib\cx16.lib(fclose.o):
    CODE              Offs=017E03  Size=000022  Align=00001  Fill=0000
..\lib\cx16.lib(fgetc.o):
    CODE              Offs=017E25  Size=000084  Align=00001  Fill=0000
..\lib\cx16.lib(fgets.o):
    CODE              Offs=017EA9  Size=0000A8  Align=00001  Fill=0000
..\lib\cx16.lib(filedes.o):
    CODE              Offs=017F51  Size=00000E  Align=00001  Fill=0000
    DATA              Offs=002691  Size=000010  Align=00001  Fill=0000
..\lib\cx16.lib(filename.o):
    CODE              Offs=017F5F  Size=0000A0  Align=00001  Fill=0000
    BSS               Offs=000A00  Size=000003  Align=00001  Fill=0000
    DATA              Offs=0026A1  Size=000024  Align=00001  Fill=0000
..\lib\cx16.lib(filetype.o):
    DATA              Offs=0026C5  Size=000001  Align=00001  Fill=0000
..\lib\cx16.lib(filevars.o):
    CODE              Offs=017FFF  Size=000007  Align=00001  Fill=0000
    INIT              Offs=000002  Size=000001  Align=00001  Fill=0000
    ONCE              Offs=000037  Size=00000E  Align=00001  Fill=0000
..\lib\cx16.lib(fmisc.o):
    CODE              Offs=018006  Size=000044  Align=00001  Fill=0000
..\lib\cx16.lib(fopen.o):
    CODE              Offs=01804A  Size=000018  Align=00001  Fill=0000
..\lib\cx16.lib(fputc.o):
    CODE              Offs=018062  Size=000054  Align=00001  Fill=0000
    RODATA            Offs=00FD2A  Size=000002  Align=00001  Fill=0000
..\lib\cx16.lib(fputs.o):
    CODE              Offs=0180B6  Size=000041  Align=00001  Fill=0000
..\lib\cx16.lib(fread.o):
    CODE              Offs=0180F7  Size=0000D3  Align=00001  Fill=0000
    BSS               Offs=000A03  Size=000003  Align=00001  Fill=0000
..\lib\cx16.lib(free.o):
    CODE              Offs=0181CA  Size=0001D3  Align=00001  Fill=0000
..\lib\cx16.lib(fwrite.o):
    CODE              Offs=01839D  Size=00007B  Align=00001  Fill=0000
    BSS               Offs=000A06  Size=000002  Align=00001  Fill=0000
..\lib\cx16.lib(ge.o):
    CODE              Offs=018418  Size=00000A  Align=00001  Fill=0000
..\lib\cx16.lib(getchar.o):
    CODE              Offs=018422  Size=000009  Align=00001  Fill=0000
..\lib\cx16.lib(gettime.o):
    CODE              Offs=01842B  Size=00004C  Align=00001  Fill=0000
..\lib\cx16.lib(gt.o):
    CODE              Offs=018477  Size=00000A  Align=00001  Fill=0000
..\lib\cx16.lib(icmp.o):
    CODE              Offs=018481  Size=00002E  Align=00001  Fill=0000
..\lib\cx16.lib(incax2.o):
    CODE              Offs=0184AF  Size=000007  Align=00001  Fill=0000
..\lib\cx16.lib(incax3.o):
    CODE              Offs=0184B6  Size=000005  Align=00001  Fill=0000
..\lib\cx16.lib(incax8.o):
    CODE              Offs=0184BB  Size=000005  Align=00001  Fill=0000
..\lib\cx16.lib(incaxy.o):
    CODE              Offs=0184C0  Size=00000B  Align=00001  Fill=0000
..\lib\cx16.lib(incsp1.o):
    CODE              Offs=0184CB  Size=000007  Align=00001  Fill=0000
..\lib\cx16.lib(incsp2.o):
    CODE              Offs=0184D2  Size=000015  Align=00001  Fill=0000
..\lib\cx16.lib(incsp3.o):
    CODE              Offs=0184E7  Size=000005  Align=00001  Fill=0000
..\lib\cx16.lib(incsp4.o):
    CODE              Offs=0184EC  Size=000005  Align=00001  Fill=0000
..\lib\cx16.lib(incsp6.o):
    CODE              Offs=0184F1  Size=000005  Align=00001  Fill=0000
..\lib\cx16.lib(incsp8.o):
    CODE              Offs=0184F6  Size=000005  Align=00001  Fill=0000
..\lib\cx16.lib(isspace.o):
    CODE              Offs=0184FB  Size=000008  Align=00001  Fill=0000
..\lib\cx16.lib(isupper.o):
    CODE              Offs=018503  Size=000008  Align=00001  Fill=0000
..\lib\cx16.lib(jmpvec.o):
    DATA              Offs=0026C6  Size=000003  Align=00001  Fill=0000
..\lib\cx16.lib(kernal.o):
..\lib\cx16.lib(ladd.o):
    CODE              Offs=01850B  Size=000024  Align=00001  Fill=0000
..\lib\cx16.lib(land.o):
    CODE              Offs=01852F  Size=000021  Align=00001  Fill=0000
..\lib\cx16.lib(ldaui.o):
    CODE              Offs=018550  Size=000009  Align=00001  Fill=0000
..\lib\cx16.lib(ldaxi.o):
    CODE              Offs=018559  Size=00000D  Align=00001  Fill=0000
..\lib\cx16.lib(ldaxsp.o):
    CODE              Offs=018566  Size=000009  Align=00001  Fill=0000
..\lib\cx16.lib(ldeaxi.o):
    CODE              Offs=01856F  Size=000017  Align=00001  Fill=0000
..\lib\cx16.lib(le.o):
    CODE              Offs=018586  Size=00000A  Align=00001  Fill=0000
..\lib\cx16.lib(leaaxsp.o):
    CODE              Offs=018590  Size=00000C  Align=00001  Fill=0000
..\lib\cx16.lib(lmul.o):
    CODE              Offs=01859C  Size=000059  Align=00001  Fill=0000
..\lib\cx16.lib(lneg.o):
    CODE              Offs=0185F5  Size=00001E  Align=00001  Fill=0000
..\lib\cx16.lib(loadaddr.o):
    LOADADDR          Offs=000000  Size=000002  Align=00001  Fill=0000
..\lib\cx16.lib(lor.o):
    CODE              Offs=018613  Size=000021  Align=00001  Fill=0000
..\lib\cx16.lib(lpush.o):
    CODE              Offs=018634  Size=00001E  Align=00001  Fill=0000
..\lib\cx16.lib(lsub.o):
    CODE              Offs=018652  Size=000024  Align=00001  Fill=0000
..\lib\cx16.lib(lt.o):
    CODE              Offs=018676  Size=00000A  Align=00001  Fill=0000
..\lib\cx16.lib(ltoa.o):
    CODE              Offs=018680  Size=000093  Align=00001  Fill=0000
..\lib\cx16.lib(lxor.o):
    CODE              Offs=018713  Size=000021  Align=00001  Fill=0000
..\lib\cx16.lib(mainargs.o):
    DATA              Offs=0026C9  Size=000016  Align=00001  Fill=0000
    ONCE              Offs=000045  Size=00006A  Align=00001  Fill=0000
    INIT              Offs=000003  Size=000012  Align=00001  Fill=0000
..\lib\cx16.lib(makebool.o):
    CODE              Offs=018734  Size=00002C  Align=00001  Fill=0000
..\lib\cx16.lib(malloc.o):
    CODE              Offs=018760  Size=00010E  Align=00001  Fill=0000     270 bytes
..\lib\cx16.lib(memcpy.o):
    CODE              Offs=01886E  Size=00003C  Align=00001  Fill=0000
..\lib\cx16.lib(memset.o):
    CODE              Offs=0188AA  Size=00005D  Align=00001  Fill=0000
..\lib\cx16.lib(mktime.o):
    CODE              Offs=018907  Size=0003D1  Align=00001  Fill=0000     977 bytes
    RODATA            Offs=00FD2C  Size=00002E  Align=00001  Fill=0000
..\lib\cx16.lib(mod.o):
    CODE              Offs=018CD8  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(mul.o):
    CODE              Offs=018CE9  Size=000045  Align=00001  Fill=0000
..\lib\cx16.lib(mul8.o):
    CODE              Offs=018D2E  Size=00003A  Align=00001  Fill=0000
..\lib\cx16.lib(mulax10.o):
    CODE              Offs=018D68  Size=000019  Align=00001  Fill=0000
..\lib\cx16.lib(mulax3.o):
    CODE              Offs=018D81  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(mulax5.o):
    CODE              Offs=018D92  Size=000014  Align=00001  Fill=0000
..\lib\cx16.lib(mulax6.o):
    CODE              Offs=018DA6  Size=000016  Align=00001  Fill=0000
..\lib\cx16.lib(ne.o):
    CODE              Offs=018DBC  Size=00000A  Align=00001  Fill=0000
..\lib\cx16.lib(negabs.o):
    CODE              Offs=018DC6  Size=000012  Align=00001  Fill=0000
..\lib\cx16.lib(open.o):
    CODE              Offs=018DD8  Size=0000BE  Align=00001  Fill=0000
..\lib\cx16.lib(oserror.o):
    CODE              Offs=018E96  Size=000016  Align=00001  Fill=0000
    RODATA            Offs=00FD5A  Size=00005A  Align=00001  Fill=0000
..\lib\cx16.lib(popptr1.o):
    CODE              Offs=018EAC  Size=00000E  Align=00001  Fill=0000
..\lib\cx16.lib(push1.o):
    CODE              Offs=018EBA  Size=000005  Align=00001  Fill=0000
..\lib\cx16.lib(pusha.o):
    CODE              Offs=018EBF  Size=000016  Align=00001  Fill=0000
..\lib\cx16.lib(pushax.o):
    CODE              Offs=018ED5  Size=00001A  Align=00001  Fill=0000
..\lib\cx16.lib(pushwsp.o):
    CODE              Offs=018EEF  Size=00001C  Align=00001  Fill=0000
..\lib\cx16.lib(putchar.o):
    CODE              Offs=018F0B  Size=00000C  Align=00001  Fill=0000
..\lib\cx16.lib(read.o):
    CODE              Offs=018F17  Size=00007C  Align=00001  Fill=0000
    BSS               Offs=000A08  Size=000001  Align=00001  Fill=0000
    ONCE              Offs=0000AF  Size=00000C  Align=00001  Fill=0000
..\lib\cx16.lib(regswap2.o):
    CODE              Offs=018F93  Size=000016  Align=00001  Fill=0000
..\lib\cx16.lib(return0.o):
    CODE              Offs=018FA9  Size=000004  Align=00001  Fill=0000
..\lib\cx16.lib(rwcommon.o):
    CODE              Offs=018FAD  Size=00001A  Align=00001  Fill=0000
..\lib\cx16.lib(scratch.o):
    CODE              Offs=018FC7  Size=000019  Align=00001  Fill=0000
..\lib\cx16.lib(shelp.o):
    CODE              Offs=018FE0  Size=000020  Align=00001  Fill=0000
..\lib\cx16.lib(shrax1.o):
    CODE              Offs=019000  Size=000008  Align=00001  Fill=0000
..\lib\cx16.lib(shrax2.o):
    CODE              Offs=019008  Size=00000B  Align=00001  Fill=0000
..\lib\cx16.lib(shrax3.o):
    CODE              Offs=019013  Size=00000E  Align=00001  Fill=0000
..\lib\cx16.lib(shrax4.o):
    CODE              Offs=019021  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(sprintf.o):
    CODE              Offs=019032  Size=00002B  Align=00001  Fill=0000
    BSS               Offs=000A09  Size=000001  Align=00001  Fill=0000
..\lib\cx16.lib(staspidx.o):
    CODE              Offs=01905D  Size=000016  Align=00001  Fill=0000
..\lib\cx16.lib(staxsp.o):
    CODE              Offs=019073  Size=00000B  Align=00001  Fill=0000
..\lib\cx16.lib(staxspi.o):
    CODE              Offs=01907E  Size=00001A  Align=00001  Fill=0000
..\lib\cx16.lib(steaxspi.o):
    CODE              Offs=019098  Size=000022  Align=00001  Fill=0000
..\lib\cx16.lib(strcat.o):
    CODE              Offs=0190BA  Size=00002F  Align=00001  Fill=0000
..\lib\cx16.lib(strchr.o):
    CODE              Offs=0190E9  Size=000025  Align=00001  Fill=0000
..\lib\cx16.lib(strcmp.o):
    CODE              Offs=01910E  Size=000021  Align=00001  Fill=0000
..\lib\cx16.lib(strcpy.o):
    CODE              Offs=01912F  Size=00001F  Align=00001  Fill=0000
..\lib\cx16.lib(strlen.o):
    CODE              Offs=01914E  Size=000016  Align=00001  Fill=0000
..\lib\cx16.lib(strlower.o):
    CODE              Offs=019164  Size=000027  Align=00001  Fill=0000
..\lib\cx16.lib(sub.o):
    CODE              Offs=01918B  Size=000014  Align=00001  Fill=0000
..\lib\cx16.lib(subeqsp.o):
    CODE              Offs=01919F  Size=000015  Align=00001  Fill=0000
..\lib\cx16.lib(subysp.o):
    CODE              Offs=0191B4  Size=00000D  Align=00001  Fill=0000
..\lib\cx16.lib(time.o):
    CODE              Offs=0191C1  Size=000043  Align=00001  Fill=0000
    BSS               Offs=000A0A  Size=000008  Align=00001  Fill=0000
..\lib\cx16.lib(timezone.o):
    DATA              Offs=0026DF  Size=00000F  Align=00001  Fill=0000
..\lib\cx16.lib(tmcommon.o):
    CODE              Offs=019204  Size=00000D  Align=00001  Fill=0000
    DATA              Offs=0026EE  Size=000012  Align=00001  Fill=0000
..\lib\cx16.lib(tolower.o):
    CODE              Offs=019211  Size=000012  Align=00001  Fill=0000
..\lib\cx16.lib(toslong.o):
    CODE              Offs=019223  Size=000032  Align=00001  Fill=0000
..\lib\cx16.lib(udiv.o):
    CODE              Offs=019255  Size=00004F  Align=00001  Fill=0000
..\lib\cx16.lib(ugt.o):
    CODE              Offs=0192A4  Size=00000A  Align=00001  Fill=0000
..\lib\cx16.lib(ult.o):
    CODE              Offs=0192AE  Size=000008  Align=00001  Fill=0000
..\lib\cx16.lib(umod.o):
    CODE              Offs=0192B6  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(vsnprintf.o):
    CODE              Offs=0192C7  Size=0000DA  Align=00001  Fill=0000
    DATA              Offs=002700  Size=000008  Align=00001  Fill=0000
..\lib\cx16.lib(vsprintf.o):
    CODE              Offs=0193A1  Size=000012  Align=00001  Fill=0000
..\lib\cx16.lib(write.o):
    CODE              Offs=0193B3  Size=000052  Align=00001  Fill=0000
    ONCE              Offs=0000BB  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(xor.o):
    CODE              Offs=019405  Size=000011  Align=00001  Fill=0000
..\lib\cx16.lib(zerobss.o):
    CODE              Offs=019416  Size=000023  Align=00001  Fill=0000
..\lib\cx16.lib(zeropage.o):
    ZEROPAGE          Offs=000000  Size=00001A  Align=00001  Fill=0000


Segment list:
-------------
Name                   Start     End    Size  Align
----------------------------------------------------
ZEROPAGE              000022  00003B  00001A  00001
LOADADDR              0007FF  000800  000002  00001
EXEHDR                000801  00080C  00000C  00001
STARTUP               00080D  00082D  000021  00001
CODE                  00082E  019C66  019439  00001   103,481 bytes  [game ~96K   C-library ~7K]
BRAM01ADDR            009FFE  009FFF  000002  00001
BRAM02ADDR            009FFE  009FFF  000002  00001
BRAM03ADDR            009FFE  009FFF  000002  00001
BRAM04ADDR            009FFE  009FFF  000002  00001
BRAM05ADDR            009FFE  009FFF  000002  00001
BRAM06ADDR            009FFE  009FFF  000002  00001
BRAM07ADDR            009FFE  009FFF  000002  00001
BRAM08ADDR            009FFE  009FFF  000002  00001
BRAM09ADDR            009FFE  009FFF  000002  00001
RODATA                019C67  029A20  00FDBA  00001    64,954 bytes   [game]
DATA                  029A21  02C128  002708  00001     9,992 bytes   [game]
INIT                  02C129  02C13D  000015  00001
BSS                   02C13E  02CB4F  000A12  00001
ONCE                  02C13E  02C213  0000D6  00001
DragWx
Posts: 362
Joined: Tue Mar 07, 2023 9:07 pm

Re: banking in cc65 and large program (and a text adventure)

Post by DragWx »

I looked into it a while back just out of curiosity. I haven't tested any of this, but it seems like it should work.

To summarize, several segments occupying the same address range are defined, and are given a "bank" value that will come in handy later. (Explained here)

Next, write a wrapper function that will receive two things: the address of a function to call, and the "bank" value from before. The wrapper function must set the bank, call the function, then restore the bank. (Explained here)

Finally, surround your high-ram functions with the #pragma wrapped-call directives to tell cc65 to use your trampoline when calling them, as well as using #pragma code-name with the name of a high-ram bank (defined in the cfg file) you want the code to compile to.

When using the default cx16-bank.cfg from cc65, each bank of high-ram will compile to a separate file ("myprogram.01" for bank 1, "myprogram.02" for bank 2, and so on). It's your program's responsibility to load these files into high-ram.
Post Reply