]> git.sur5r.net Git - cc65/blob - samples/fire.c
7d2c4e9db494ac020bfb441b8b832195fec85ba1
[cc65] / samples / fire.c
1 /*****************************************************************************
2  * fire test program for cc65.                                               *
3  *                                                                           *
4  * (w)2002 by groepaz/hitmen                                                 *
5  *                                                                           *
6  * Cleanup and porting by Ullrich von Bassewitz.                             *
7  *                                                                           *
8  *****************************************************************************/
9
10
11
12 /* sync page-flipping to vertical blank */
13 //#define DOVSYNC
14
15 #include <stdlib.h>
16 #include <string.h> /* for memset */
17 #include <time.h>
18 #include <conio.h>
19
20
21
22 #if defined(__C64__)
23 #  define BUFFER                0x0400
24 #  define SCREEN1               0xE000
25 #  define SCREEN2               0xE400
26 #  define CHARSET               0xE800
27 #  define COLORRAM              0xD800
28 #  define outb(addr,val)        (*(addr)) = (val)
29 #  define inb(addr)             (*(addr))
30 #elif defined(__C128__)
31 #  define SCREEN1               0xE000
32 #  define SCREEN2               0xE400
33 #  define CHARSET               0xE800
34 #  define COLORRAM              0xD800
35 #  define outb(addr,val)        (*(addr)) = (val)
36 #  define inb(addr)             (*(addr))
37 #elif defined(__CBM510__)
38 #  define BUFFER                0xF800
39 #  define SCREEN1               0xF000
40 #  define SCREEN2               0xF400
41 #  define CHARSET               0xE000
42 #  define COLORRAM              0xD400
43 #  define outb(addr,val)        pokebsys ((unsigned)(addr), val)
44 #  define inb(addr)             peekbsys ((unsigned)(addr))
45 #endif
46
47
48
49 /* Values for the VIC address register to switch between the two pages */
50 #define PAGE1                   ((SCREEN1 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E)
51 #define PAGE2                   ((SCREEN2 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E)
52
53
54
55 /* Use static local variables for speed */
56 #pragma staticlocals (1);
57
58
59
60 #ifdef DOVSYNC
61 #  define waitvsync() while(VIC.ctrl1 < 0x80) {}
62 #else
63 #  define waitvsync()
64 #endif
65
66
67
68 static void makechar (void)
69 {
70     static const unsigned char bittab[8] = {
71         0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
72     };
73     register char *font;
74     register unsigned char i, ii, b, bc;
75     unsigned char c;
76
77     gotoxy (0, 1);
78
79     for (font = (char*)CHARSET; font != (char*)(CHARSET+(1*8)); ++font) {
80         *font = 0x00;
81     }
82     for (font = (char*)(CHARSET+(64*8)); font != (char*)(CHARSET+(256*8)); ++font) {
83         *font = 0xff;
84     }
85
86
87     for (c = 0; c < 0x40; ++c) {
88         bc = 0;
89         for (i = 0; i < 8; i++){
90             b = 0;
91             for (ii = 0; ii < 8; ii++) {
92                 bc += c;
93                 if (bc > 0x3f) {
94                     bc = bc - 0x40;
95                     b += bittab[(ii + (i & 1)) & 0x7];
96                 }
97             }
98             ((unsigned char*)CHARSET + (1 * 8)) [(c * 8) + i] = b;
99         }
100         if ((c & 0x07) == 0) {
101             cputc ('.');
102         }
103     }
104 }
105
106
107
108 static void fire (unsigned screenbase)
109 {
110     register char* screen;
111     register char* buffer;
112     register char c;
113
114     screen = (char*) screenbase;
115     buffer = (char*) BUFFER;
116
117     while (buffer != (char*) (BUFFER + (24 * 40))) {
118         c = (buffer[40-1] + buffer[40-1] + buffer[40] + buffer[41]) / 4;
119         if (c > 2) {
120             c -= 3;
121         }
122         *screen = *buffer = c;
123         ++screen;
124         ++buffer;
125     }
126
127     screen = (char*) (screenbase + (23 * 40));
128     buffer = (char*) (BUFFER + (23 * 40));
129
130     for(; buffer != (char*)(BUFFER+(25*40)); ++screen, ++buffer) {
131         *screen = *buffer = 0x30 + (inb (&SID.noise) >> 4);
132     }
133 }
134
135
136
137 int main (void)
138 {
139     unsigned char border;
140     unsigned char background;
141     unsigned char text;
142     unsigned char v;
143     clock_t       t;
144     unsigned long f = 0;
145     unsigned long sec;
146     unsigned      sec10;
147     unsigned long fps;
148     unsigned      fps10;
149     int           i;
150
151 #if defined(__C64__)
152     unsigned char block;
153 #endif
154 #if defined(__C128__)
155     unsigned char block;
156     unsigned char initflag;
157     unsigned char graphflag;
158 #endif
159
160     /* Noise on channel 3 for random numbers  */
161     outb (&SID.v3.freq, 0xffff);
162     outb (&SID.v3.ctrl, 0x80);
163
164     clrscr ();
165     cprintf ("Making charset, mompls");
166     makechar ();
167
168     /* Set the border and background colors */
169     border     = bordercolor (COLOR_BLACK);
170     background = bgcolor (COLOR_BLACK);
171     text       = textcolor (COLOR_BLACK);
172     clrscr ();
173
174     for(i = 0; i != 0x400; i++) {
175         *((char *)(i + BUFFER))  = 0;
176         *((char *)(i + SCREEN1)) = 0;
177         *((char *)(i + SCREEN2)) = 0;
178         outb ((char*)(i + COLORRAM), COLOR_YELLOW);
179     }
180
181 #if defined(__C64__) || defined(__C128__)
182     /* Move the VIC 16K block */
183     block = inb (&CIA2.pra);
184     outb (&CIA2.pra, (block & 0xFC) | ((SCREEN1 >> 14) ^ 0x03));
185 #endif
186 #if defined(__C128__)
187     /* Save and change some flags, so that kernal/basic interupt handler will
188      * not interfere with our routine.
189      */
190     initflag = *(unsigned char*) 0xA04;
191     *(unsigned char*) 0xA04 &= 0xFE;
192     graphflag = *(unsigned char*) 0xD8;
193     *(unsigned char*) 0xD8 = 0xFF;
194 #endif
195
196     /* Remember the VIC address register */
197     v = inb (&VIC.addr);
198
199     /* Run the demo until a key was hit */
200     t = clock ();
201     while (!kbhit()) {
202         /* Build page 1, then make it visible */
203         fire (SCREEN1);
204         waitvsync ();
205         outb (&VIC.addr, PAGE1);
206
207         /* Build page 2, then make it visible */
208         fire (SCREEN2);
209         waitvsync ();
210         outb (&VIC.addr, PAGE2);
211
212         /* Count frames */
213         f += 2;
214     }
215     t = clock() - t;
216
217     /* Switch back the VIC screen */
218     outb (&VIC.addr, v);
219
220 #if defined(__C64__) || defined(__C128__)
221     /* Move back the VIC 16K block */
222     outb (&CIA2.pra, block);
223 #endif
224 #if defined(__C128__)
225     /* Restore the flags */
226     *(unsigned char*) 0xA04 = initflag;
227     *(unsigned char*) 0xD8  = graphflag;
228 #endif
229
230     /* Fetch the character from the keyboard buffer and discard it */
231     (void) cgetc();
232
233     /* Reset screen colors */
234     bordercolor (border);
235     bgcolor (background);
236     textcolor (text);
237     clrscr ();
238
239     /* Calculate stats */
240     sec   = (t * 10) / CLK_TCK;
241     sec10 = sec % 10;
242     sec  /= 10;
243     fps   = (f * (CLK_TCK * 10)) / t;
244     fps10 = fps % 10;
245     fps  /= 10;
246
247     /* Output stats */
248     gotoxy (0, 0); cprintf ("time  : %lu.%us", sec, sec10);
249     gotoxy (0, 1); cprintf ("frames: %lu", f);
250     gotoxy (0, 2); cprintf ("fps   : %lu.%u", fps, fps10);
251
252     /* Wait for a key, then end */
253     cputsxy (0, 4, "Press any key when done...");
254     (void) cgetc ();
255
256     /* Done */
257     return EXIT_SUCCESS;
258 }
259
260
261