]> git.sur5r.net Git - cc65/blobdiff - samples/multidemo.c
Removed a "cc65_" prefix.
[cc65] / samples / multidemo.c
index bdf669cb049d3fa71215abb6514f80c410933406..396d7344a1b6dfacd9348e3052a5b6314006aeb4 100644 (file)
@@ -1,29 +1,37 @@
 /*
- * Extended memory overlay demo program.
- *
- * 2012-17-07, Oliver Schmidt (ol.sc@web.de)
- *
- */
+** Extended memory overlay demo program.
+**
+** Shows how to combine multiple cc65 features
+** incl. overlays and extended memory drivers.
+**
+** 2012-17-07, Oliver Schmidt (ol.sc@web.de)
+**
+*/
 
 
 
 #include <string.h>
 #include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
+#include <stdlib.h>
 #include <dirent.h>
 #include <em.h>
-#include <conio.h>
+#include <cc65.h>
+#ifndef __CBM__
+#include <fcntl.h>
+#include <unistd.h>
+#else
+#include <cbm.h>
+#include <device.h>
+#endif
 
 
 /* The symbols _OVERLAY?_LOAD__ and _OVERLAY?_SIZE__ were generated by the
- * linker. They contain the overlay area address and size specific to a
- * certain program.
- */
-extern void _OVERLAY1_LOAD__, _OVERLAY1_SIZE__;
-extern void _OVERLAY2_LOAD__, _OVERLAY2_SIZE__;
-extern void _OVERLAY3_LOAD__, _OVERLAY3_SIZE__;
-extern void _OVERLAY4_LOAD__, _OVERLAY4_SIZE__;
+** linker. They contain the overlay area address and size specific to a
+** certain program.
+*/
+extern void _OVERLAY1_LOAD__[], _OVERLAY1_SIZE__[];
+extern void _OVERLAY2_LOAD__[], _OVERLAY2_SIZE__[];
+extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[];
 
 struct {
     char     *name;
@@ -31,42 +39,31 @@ struct {
     void     *addr;
     unsigned size;
 } overlay[] =
-    {{"multdemo.1", -1, &_OVERLAY1_LOAD__, (unsigned)&_OVERLAY1_SIZE__},
-     {"multdemo.2", -1, &_OVERLAY2_LOAD__, (unsigned)&_OVERLAY2_SIZE__},
-     {"multdemo.3", -1, &_OVERLAY3_LOAD__, (unsigned)&_OVERLAY3_SIZE__},
-     {"multdemo.4", -1, &_OVERLAY4_LOAD__, (unsigned)&_OVERLAY4_SIZE__}};
-
-/* Copy overlays into extended memory up to overlay 3. Overlay 4 is known to
- * to be loaded only once for onetime initialization purposes so there's no
- * use in allocating extended memory for it.
- */
-#define MAX_EM_OVERLAY 3
-
-/* Search for up to 10 extended memory drivers.
- */
-#define MAX_EM_DRIVER 10
+    {{"multdemo.1", -1, _OVERLAY1_LOAD__, (unsigned)_OVERLAY1_SIZE__},
+     {"multdemo.2", -1, _OVERLAY2_LOAD__, (unsigned)_OVERLAY2_SIZE__},
+     {"multdemo.3", -1, _OVERLAY3_LOAD__, (unsigned)_OVERLAY3_SIZE__}};
 
 
 
 /* Functions resident in an overlay can call back functions resident in the
- * main program at any time without any precautions. The function log() is
- * an example for such a function resident in the main program.
- */
+** main program at any time without any precautions. The function log() is
+** an example for such a function resident in the main program.
+*/
 void log (char *msg)
 {
     /* Functions resident in an overlay can access all program variables and
-     * constants at any time without any precautions because those are never
-     * placed in overlays. The string constant below is an example for such 
-     * a constant resident in the main program.
-     */
+    ** constants at any time without any precautions because those are never
+    ** placed in overlays. The string constant below is an example for such
+    ** a constant resident in the main program.
+    */
     printf ("Log: %s\n", msg);
 }
 
 
 /* In a real-world overlay program one would probably not use a #pragma but
- * rather place the all the code of certain source files into the overlay by
- * compiling them with --code-name OVERLAY1.
- */
+** rather place all the code of certain source files into the overlay by
+** compiling them with --code-name OVERLAY1.
+*/
 #pragma code-name (push, "OVERLAY1");
 
 void foo (void)
@@ -97,13 +94,11 @@ void foobar (void)
 #pragma code-name(pop);
 
 
-#pragma code-name (push, "OVERLAY4");
-
 unsigned char loademdriver (void)
 {
-    static char emd[MAX_EM_DRIVER][FILENAME_MAX];
-    DIR* dir;
-    struct dirent* ent;
+    DIR *dir;
+    struct dirent *ent;
+    char *emd = NULL;
     unsigned char max = 0;
     unsigned char num;
 
@@ -128,78 +123,35 @@ unsigned char loademdriver (void)
         }
 
         printf ("Dbg: Memorizing file %s\n", ent->d_name);
-        strcpy (emd[max], ent->d_name);
-        if (++max == MAX_EM_DRIVER) {
-            break;
-        }
+        emd = realloc (emd, FILENAME_MAX * (max + 1));
+        strcpy (emd + FILENAME_MAX * max++, ent->d_name);
     }
     closedir (dir);
 
     for (num = 0; num < max; ++num) {
-        printf ("Dbg: Trying emdriver %s\n", emd[num]);
-        if (em_load_driver (emd[num]) == EM_ERR_OK) {
-            printf ("Dbg: Loaded emdriver %s\n", emd[num]);
-            return 1;
-        }
-        printf ("Dbg: Emdriver %s failed\n", emd[num]);
-    }
-    return 0;
-}
+        char *drv;
 
-void copyoverlays (void)
-{
-    unsigned page = 0;
-    unsigned char num;
-
-    for (num = 0; num < MAX_EM_OVERLAY; ++num) {
-        int file;
-        int size;
-
-        if ((overlay[num].size + EM_PAGE_SIZE - 1) / EM_PAGE_SIZE >
-             em_pagecount () - page) {
-            printf ("Dbg: Not enough memory for overlay %u\n", num + 1);
-            continue;
-        }
-
-        printf ("Dbg: Reading overlay file %s\n", overlay[num].name);
-        file = open (overlay[num].name, O_RDONLY);
-        if (file == -1) {
-            log ("Opening overlay file failed");
-            continue;
-        }
-
-        overlay[num].page = page;
-        size = overlay[num].size;
-        while (size) {
-            void *buf;
-
-            /* In general one could as well use em_copyto() to copy a fully
-             * loaded overlay into extended memory in one step. However the
-             * "streaming" of an overlay from disk to extended memory shown
-             * here has two advantages:
-             * - It can be done from another overlay (like done here).
-             * - It avoids unnecessary double buffering with emdrivers that
-             *   provide a hardware memory window.
-             */
-            buf = em_use (page++);
-            size -= read (file, buf, EM_PAGE_SIZE);
-            em_commit ();
+        drv = emd + FILENAME_MAX * num;
+        printf ("Dbg: Trying emdriver %s\n", drv);
+        if (em_load_driver (drv) == EM_ERR_OK) {
+            printf ("Dbg: Loaded emdriver %s\n", drv);
+            free (emd);
+            return 1;
         }
 
-        printf ("Dbg: Stored overlay %u in pages %u-%u\n",
-                num + 1, overlay[num].page, page - 1);
-
-        close (file);
+        printf ("Dbg: Emdriver %s failed\n", drv);
     }
-}
 
-#pragma code-name(pop);
+    free (emd);
+    return 0;
+}
 
 
 unsigned char loadoverlay (unsigned char num)
 {
     if (overlay[num - 1].page < 0) {
+#ifndef __CBM__
+
         int file;
 
         printf ("Dbg: Loading overlay %u from file\n", num);
@@ -211,6 +163,15 @@ unsigned char loadoverlay (unsigned char num)
         read (file, overlay[num - 1].addr,
                     overlay[num - 1].size);
         close (file);
+
+#else
+
+        if (cbm_load (overlay[num - 1].name, getcurrentdevice (), NULL) == 0) {
+            log ("Loading overlay file failed");
+            return 0;
+        }
+
+#endif
         return 1;
     } else {
         struct em_copy copyinfo;
@@ -225,34 +186,65 @@ unsigned char loadoverlay (unsigned char num)
     }
 }
 
-void main (void)
+
+void copyoverlays (void)
 {
-    if (loadoverlay (4)) {
-        log ("Loading extended memory driver");
-        if (loademdriver ()) {
-            log ("Copying overlays into ext. memory");
-            copyoverlays ();
-        } else {
-            log ("No extended memory driver found");
+    unsigned page = 0;
+    unsigned char num;
+
+    for (num = 0; num < sizeof (overlay) / sizeof (overlay[0]); ++num) {
+        struct em_copy copyinfo;
+        unsigned size = (overlay[num].size + EM_PAGE_SIZE - 1) / EM_PAGE_SIZE;
+
+        if (size > em_pagecount () - page) {
+            printf ("Dbg: Not enough memory for overlay %u\n", num + 1);
+            continue;
         }
+
+        if (loadoverlay (num + 1) == 0)
+            continue;
+
+        copyinfo.offs  = 0;
+        copyinfo.page  = page;
+        copyinfo.buf   = overlay[num].addr;
+        copyinfo.count = overlay[num].size;
+        em_copyto (&copyinfo);
+
+        overlay[num].page = page;
+        page += size;
+
+        printf ("Dbg: Stored overlay %u in pages %u-%u\n",
+                num + 1, overlay[num].page, page - 1);
+    }
+}
+
+
+void main (void)
+{
+    log ("Loading extended memory driver");
+    if (loademdriver ()) {
+        log ("Copying overlays into ext. memory");
+        copyoverlays ();
+    } else {
+        log ("No extended memory driver found");
     }
 
     log ("Press any key...");
-    cgetc ();
+    getchar ();
 
     if (loadoverlay (1)) {
         log ("Calling overlay 1 from main");
 
         /* The linker makes sure that the call to foo() ends up at the right mem
-         * addr. However it's up to user to make sure that the - right - overlay
-         * is actually loaded before making the the call.
-         */
+        ** addr. However it's up to user to make sure that the - right - overlay
+        ** is actually loaded before making the the call.
+        */
         foo ();
     }
 
     /* Replacing one overlay with another one can only happen from the main
-     * program. This implies that an overlay can never load another overlay.
-     */
+    ** program. This implies that an overlay can never load another overlay.
+    */
     if (loadoverlay (2)) {
         log ("Calling overlay 2 from main");
         bar ();
@@ -263,6 +255,8 @@ void main (void)
         foobar ();
     }
 
-    log ("Press any key...");
-    cgetc ();
+    if (doesclrscrafterexit ()) {
+        log ("Press any key...");
+        getchar ();
+    }
 }