2 ** Extended memory overlay demo program.
4 ** Shows how to combine multiple cc65 features
5 ** incl. overlays and extended memory drivers.
7 ** 2012-17-07, Oliver Schmidt (ol.sc@web.de)
27 /* The symbols _OVERLAY?_LOAD__ and _OVERLAY?_SIZE__ were generated by the
28 ** linker. They contain the overlay area address and size specific to a
31 extern void _OVERLAY1_LOAD__[], _OVERLAY1_SIZE__[];
32 extern void _OVERLAY2_LOAD__[], _OVERLAY2_SIZE__[];
33 extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[];
41 {{"multdemo.1", -1, _OVERLAY1_LOAD__, (unsigned)_OVERLAY1_SIZE__},
42 {"multdemo.2", -1, _OVERLAY2_LOAD__, (unsigned)_OVERLAY2_SIZE__},
43 {"multdemo.3", -1, _OVERLAY3_LOAD__, (unsigned)_OVERLAY3_SIZE__}};
47 /* Functions resident in an overlay can call back functions resident in the
48 ** main program at any time without any precautions. The function log() is
49 ** an example for such a function resident in the main program.
53 /* Functions resident in an overlay can access all program variables and
54 ** constants at any time without any precautions because those are never
55 ** placed in overlays. The string constant below is an example for such
56 ** a constant resident in the main program.
58 printf ("Log: %s\n", msg);
62 /* In a real-world overlay program one would probably not use a #pragma but
63 ** rather place all the code of certain source files into the overlay by
64 ** compiling them with --code-name OVERLAY1.
66 #pragma code-name (push, "OVERLAY1");
70 log ("Calling main from overlay 1");
73 #pragma code-name (pop);
76 #pragma code-name (push, "OVERLAY2");
80 log ("Calling main from overlay 2");
83 #pragma code-name (pop);
86 #pragma code-name (push, "OVERLAY3");
90 log ("Calling main from overlay 3");
93 #pragma code-name(pop);
96 unsigned char loademdriver (void)
101 unsigned char max = 0;
104 printf ("Dbg: Searching for emdrivers\n");
107 log ("Opening directory failed");
111 while (ent = readdir (dir)) {
114 if (!_DE_ISREG (ent->d_type)) {
118 ext = strrchr (ent->d_name, '.');
119 if (!ext || strcasecmp (ext, ".emd")) {
120 printf ("Dbg: Skipping file %s\n", ent->d_name);
124 printf ("Dbg: Memorizing file %s\n", ent->d_name);
125 emd = realloc (emd, FILENAME_MAX * (max + 1));
126 strcpy (emd + FILENAME_MAX * max++, ent->d_name);
130 for (num = 0; num < max; ++num) {
133 drv = emd + FILENAME_MAX * num;
134 printf ("Dbg: Trying emdriver %s\n", drv);
135 if (em_load_driver (drv) == EM_ERR_OK) {
136 printf ("Dbg: Loaded emdriver %s\n", drv);
141 printf ("Dbg: Emdriver %s failed\n", drv);
149 unsigned char loadoverlay (unsigned char num)
151 if (overlay[num - 1].page < 0) {
156 printf ("Dbg: Loading overlay %u from file\n", num);
157 file = open (overlay[num - 1].name, O_RDONLY);
159 log ("Opening overlay file failed");
162 read (file, overlay[num - 1].addr,
163 overlay[num - 1].size);
168 if (cbm_load (overlay[num - 1].name, getcurrentdevice (), NULL) == 0) {
169 log ("Loading overlay file failed");
176 struct em_copy copyinfo;
178 printf ("Dbg: Loading overlay %u from memory\n", num);
180 copyinfo.page = overlay[num - 1].page;
181 copyinfo.buf = overlay[num - 1].addr;
182 copyinfo.count = overlay[num - 1].size;
183 em_copyfrom (©info);
189 void copyoverlays (void)
194 for (num = 0; num < sizeof (overlay) / sizeof (overlay[0]); ++num) {
195 struct em_copy copyinfo;
196 unsigned size = (overlay[num].size + EM_PAGE_SIZE - 1) / EM_PAGE_SIZE;
198 if (size > em_pagecount () - page) {
199 printf ("Dbg: Not enough memory for overlay %u\n", num + 1);
203 if (loadoverlay (num + 1) == 0)
207 copyinfo.page = page;
208 copyinfo.buf = overlay[num].addr;
209 copyinfo.count = overlay[num].size;
210 em_copyto (©info);
212 overlay[num].page = page;
215 printf ("Dbg: Stored overlay %u in pages %u-%u\n",
216 num + 1, overlay[num].page, page - 1);
223 log ("Loading extended memory driver");
224 if (loademdriver ()) {
225 log ("Copying overlays into ext. memory");
228 log ("No extended memory driver found");
231 log ("Press any key...");
234 if (loadoverlay (1)) {
235 log ("Calling overlay 1 from main");
237 /* The linker makes sure that the call to foo() ends up at the right mem
238 ** addr. However it's up to user to make sure that the - right - overlay
239 ** is actually loaded before making the the call.
244 /* Replacing one overlay with another one can only happen from the main
245 ** program. This implies that an overlay can never load another overlay.
247 if (loadoverlay (2)) {
248 log ("Calling overlay 2 from main");
252 if (loadoverlay (3)) {
253 log ("Calling overlay 3 from main");
257 log ("Press any key...");