]> git.sur5r.net Git - cc65/blob - samples/overlaydemo.c
Make use of doesclrscrafterexit().
[cc65] / samples / overlaydemo.c
1 /*
2 ** Minimalistic overlay demo program.
3 **
4 ** Shows how to load overlay files from disk.
5 **
6 ** 2009-10-02, Oliver Schmidt (ol.sc@web.de)
7 **
8 */
9
10
11
12 #include <stdio.h>
13 #include <cc65.h>
14 #ifndef __CBM__
15 #include <fcntl.h>
16 #include <unistd.h>
17 #else
18 #include <device.h>
19 #endif
20
21
22 extern void _OVERLAY1_LOAD__[], _OVERLAY1_SIZE__[];
23 extern void _OVERLAY2_LOAD__[], _OVERLAY2_SIZE__[];
24 extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[];
25
26
27 /* Functions resident in an overlay can call back functions resident in the
28 ** main program at any time without any precautions. The function log() is
29 ** an example for such a function resident in the main program.
30 */
31 void log (char *msg)
32 {
33     printf ("Log: %s\n", msg);
34 }
35
36
37 /* In a real-world overlay program one would probably not use a #pragma but
38 ** rather place all the code of certain source files into the overlay by
39 ** compiling them with --code-name OVERLAY1.
40 */
41 #pragma code-name (push, "OVERLAY1");
42
43 void foo (void)
44 {
45     /* Functions resident in an overlay can access all program variables and
46     ** constants at any time without any precautions because those are never
47     ** placed in overlays. The string constant below is an example for such
48     ** a constant resident in the main program.
49     */
50     log ("Calling main from overlay 1");
51 }
52
53 #pragma code-name (pop);
54
55
56 #pragma code-name (push, "OVERLAY2");
57
58 void bar (void)
59 {
60     log ("Calling main from overlay 2");
61 }
62
63 #pragma code-name (pop);
64
65
66 #pragma code-name (push, "OVERLAY3");
67
68 void foobar (void)
69 {
70     log ("Calling main from overlay 3");
71 }
72
73 #pragma code-name(pop);
74
75
76 unsigned char loadfile (char *name, void *addr, void *size)
77 {
78 #ifndef __CBM__
79
80     int file = open (name, O_RDONLY);
81     if (file == -1) {
82         log ("Opening overlay file failed");
83         return 0;
84     }
85     read (file, addr, (unsigned) size);
86     close (file);
87
88 #else
89
90     /* Avoid compiler warnings about unused parameters. */
91     (void) addr; (void) size;
92     if (cbm_load (name, getcurrentdevice (), NULL) == 0) {
93         log ("Loading overlay file failed");
94         return 0;
95     }
96
97 #endif
98     return 1;
99 }
100
101
102 void main (void)
103 {
104     log ("Calling overlay 1 from main");
105
106     /* The symbols _OVERLAY1_LOAD__ and _OVERLAY1_SIZE__ were generated by the
107     ** linker. They contain the overlay area address and size specific to a
108     ** certain program.
109     */
110     if (loadfile ("ovrldemo.1", _OVERLAY1_LOAD__, _OVERLAY1_SIZE__)) {
111
112         /* The linker makes sure that the call to foo() ends up at the right mem
113         ** addr. However it's up to user to make sure that the - right - overlay
114         ** is actually loaded before making the the call.
115         */
116         foo ();
117     }
118
119     log ("Calling overlay 2 from main");
120
121     /* Replacing one overlay with another one can only happen from the main
122     ** program. This implies that an overlay can never load another overlay.
123     */
124     if (loadfile ("ovrldemo.2", _OVERLAY2_LOAD__, _OVERLAY2_SIZE__)) {
125         bar ();
126     }
127
128     log ("Calling overlay 3 from main");
129     if (loadfile ("ovrldemo.3", _OVERLAY3_LOAD__, _OVERLAY3_SIZE__)) {
130         foobar ();
131     }
132
133     if (doesclrscrafterexit ()) {
134         getchar ();
135     }
136 }