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