]> git.sur5r.net Git - cc65/blob - samples/mousetest.c
Merge remote-tracking branch 'upstream/master'
[cc65] / samples / mousetest.c
1 /*
2 ** Test/demo program for mouse usage.
3 ** Will work for the C64/C128/CBM510/Atari/Apple2.
4 **
5 ** 2001-09-13, Ullrich von Bassewitz
6 ** 2013-07-25, Greg King
7 **
8 */
9
10
11
12 #include <stdbool.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <mouse.h>
16 #include <pen.h>
17 #include <conio.h>
18 #include <ctype.h>
19 #include <dbg.h>
20
21 #define max(a,b)  (((a) > (b)) ? (a) : (b))
22 #define min(a,b)  (((a) < (b)) ? (a) : (b))
23
24
25
26 #ifdef MOUSE_DRIVER
27
28 /* A statically linked driver was named on the compiler's command line.
29 ** Make sure that it is used instead of a dynamic one.
30 */
31 #  undef DYN_DRV
32 #  define DYN_DRV       0
33 #else
34
35 /* Use a dynamically loaded driver, by default. */
36 #  ifndef DYN_DRV
37 #    define DYN_DRV     1
38 #  endif
39 #endif
40
41
42
43 #if defined(__C64__) || defined(__C128__) || defined(__CBM510__)
44
45 /* Addresses of data for sprite 0 */
46 #if defined(__C64__)
47 #  define SPRITE0_DATA  ((unsigned char[64])0x0340)
48 #  define SPRITE0_PTR   ((unsigned char *)0x07F8)
49 #elif defined(__C128__)
50 #  define SPRITE0_DATA  ((unsigned char[64])0x0E00)
51 #  define SPRITE0_PTR   ((unsigned char *)0x07F8)
52 #elif defined(__CBM510__)
53 #  define SPRITE0_DATA  ((unsigned char[64])0xF400)
54 #  define SPRITE0_PTR   ((unsigned char *)0xF3F8)
55 #endif
56
57 /* The mouse sprite (an arrow) */
58 static const unsigned char MouseSprite[64] = {
59     0xFE, 0x00, 0x00,
60     0xFC, 0x00, 0x00,
61     0xF8, 0x00, 0x00,
62     0xFC, 0x00, 0x00,
63     0xDE, 0x00, 0x00,
64     0x8F, 0x00, 0x00,
65     0x07, 0x80, 0x00,
66     0x03, 0xC0, 0x00,
67     0x01, 0xE0, 0x00,
68     0x00, 0xF0, 0x00,
69     0x00, 0x78, 0x00,
70     0x00, 0x38, 0x00,
71     0x00, 0x00, 0x00,
72     0x00, 0x00, 0x00,
73     0x00, 0x00, 0x00,
74     0x00, 0x00, 0x00,
75     0x00, 0x00, 0x00,
76     0x00, 0x00, 0x00,
77     0x00, 0x00, 0x00,
78     0x00, 0x00, 0x00,
79     0x00, 0x00, 0x00
80 };
81 #endif
82
83
84
85 static void __fastcall__ CheckError (const char* S, unsigned char Error)
86 {
87     if (Error != MOUSE_ERR_OK) {
88         cprintf ("%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error);
89         exit (EXIT_FAILURE);
90     }
91 }
92
93
94
95 #if DYN_DRV
96
97 /* Points to the dynamic driver's name. */
98 static const char *mouse_name;
99
100
101
102 static void DoWarning (void)
103 /* Warn the user that a driver is needed for this program. */
104 {
105     cprintf ("Warning: This program needs\r\n"
106              "the driver with the name\r\n"
107              "    %s\r\n"
108              "on a disk! Press 'y' if you have it;\r\n"
109              "or, any other key to exit.\r\n", mouse_stddrv);
110     if (tolower (cgetc ()) != 'y') {
111         exit (EXIT_SUCCESS);
112     }
113     cprintf ("OK. Please wait patiently...\r\n");
114 }
115 #endif
116
117
118
119 static void __fastcall__ ShowState (unsigned char Jailed, unsigned char Invisible)
120 /* Display jail and cursor states. */
121 {
122     cclearxy (0, 7, 32);
123     gotoxy (0, 7);
124     cprintf ("Pointer is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : "");
125 }
126
127
128
129 #if DYN_DRV
130 int main (int argc, char *argv[])
131 #else
132 int main (void)
133 #endif
134 {
135     struct mouse_info info;
136     struct mouse_box full_box, small_box;
137     unsigned char width, height;
138     char C;
139     bool Invisible = true, Done = false, Jailed = false;
140
141     /* Initialize the debugger */
142     DbgInit (0);
143
144     /* Set dark-on-light colors.  Clear the screen. */
145 #ifdef __CBM__
146     (void) bordercolor (COLOR_GRAY2);
147     (void) bgcolor (COLOR_WHITE);
148     (void) textcolor (COLOR_GRAY1);
149 #else
150     (void) bordercolor (COLOR_BLUE);
151     (void) bgcolor (COLOR_WHITE);
152     (void) textcolor (COLOR_BLACK);
153 #endif
154     cursor (0);
155     clrscr ();
156
157     /* The pointer is created before the driver is installed,
158     ** in case a lightpen driver needs it during calibration.
159     */
160
161 #if defined(__C64__) || defined(__C128__) || defined(__CBM510__)
162     /* Copy the sprite data */
163     memcpy ((void*) SPRITE0_DATA, MouseSprite, sizeof (MouseSprite));
164
165     /* Set the VIC-II sprite pointer. */
166     *SPRITE0_PTR = ((unsigned) SPRITE0_DATA & 0x3FFF) / sizeof SPRITE0_DATA;
167
168     /* Set the color of sprite 0 */
169 #  ifdef __CBM510__
170     pokebsys ((unsigned) &VIC.spr0_color, COLOR_BLACK);
171 #  else
172     VIC.spr0_color = COLOR_BLACK;
173 #  endif
174 #endif
175
176     /* If a lightpen driver is installed, then it can get a calibration value
177     ** from this file (if it exists).  Or, the user can adjust the pen; and,
178     ** the value will be put into this file, for the next time.
179     ** (Other drivers will ignore this.)
180     */
181 #ifdef __CBM__
182     pen_adjust ("pen.dat");
183 #endif
184
185 #if DYN_DRV
186     /* If a dynamically loadable driver is named on the command line,
187     ** then use that driver instead of the standard one.
188     */
189     if (argc > 1) {
190         mouse_name = argv[1];
191     } else {
192         /* Output a warning about the standard driver that is needed. */
193         DoWarning ();
194         mouse_name = mouse_stddrv;
195     }
196
197     /* Load and install the driver. */
198     CheckError ("mouse_load_driver",
199                 mouse_load_driver (&mouse_def_callbacks, mouse_name));
200 #else
201     /* Install the driver. */
202     CheckError ("mouse_install",
203                 mouse_install (&mouse_def_callbacks,
204 #  ifdef MOUSE_DRIVER
205                                MOUSE_DRIVER
206 #  else
207                                mouse_static_stddrv
208 #  endif
209                                ));
210 #endif
211
212     /* Get the initial bounding box. */
213     mouse_getbox (&full_box);
214
215     screensize (&width, &height);
216
217 top:
218     clrscr ();
219
220     /* Print a help line */
221     cputs (" d)ebug  h)ide   q)uit   s)how   j)ail");
222
223     /* Put a cross at the center of the screen. */
224     gotoxy (width / 2 - 3, height / 2 - 1);
225     cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4,
226              width / 2, "");
227
228     /* Test loop */
229     ShowState (Jailed, Invisible);
230     do {
231         /* Get the current co-ordinates and button states; and, print them. */
232         mouse_info (&info);
233         gotoxy (0, 2);
234         cprintf (" X  = %3d\r\n", info.pos.x);
235         cprintf (" Y  = %3d\r\n", info.pos.y);
236         cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ?
237 #ifdef __CBM__
238                  0x5F
239 #else
240                  'v'
241 #endif
242                  : '^');
243         cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ?
244 #ifdef __CBM__
245                  0x5F
246 #else
247                  'v'
248 #endif
249                  : '^');
250
251         /* Handle user input */
252         if (kbhit ()) {
253             cclearxy (1, 9, 23);
254             switch (tolower (C = cgetc ())) {
255                 case 'd':
256                     BREAK();
257
258                     /* The debugger might have changed the colors.
259                     ** Restore them.
260                     */
261 #ifdef __CBM__
262                     (void) bordercolor (COLOR_GRAY2);
263                     (void) bgcolor (COLOR_WHITE);
264                     (void) textcolor (COLOR_GRAY1);
265 #else
266                     (void) bordercolor (COLOR_BLUE);
267                     (void) bgcolor (COLOR_WHITE);
268                     (void) textcolor (COLOR_BLACK);
269 #endif
270
271                     /* The debugger changed the screen; restore it. */
272                     goto top;
273
274                 case 'h':
275                     mouse_hide ();
276                     ShowState (Jailed, ++Invisible);
277                     break;
278
279                 case 'j':
280                     if (Jailed) {
281                         mouse_setbox (&full_box);
282                         Jailed = false;
283                     } else {
284                         small_box.minx = max (info.pos.x - 10, full_box.minx);
285                         small_box.miny = max (info.pos.y - 10, full_box.miny);
286                         small_box.maxx = min (info.pos.x + 10, full_box.maxx);
287                         small_box.maxy = min (info.pos.y + 10, full_box.maxy);
288                         mouse_setbox (&small_box);
289                         Jailed = true;
290                     }
291                     ShowState (Jailed, Invisible);
292                     break;
293
294                 case 's':
295                     mouse_show ();
296                     if (Invisible) {
297                         ShowState (Jailed, --Invisible);
298                     }
299                     break;
300
301                 case 'q':
302                     Done = true;
303                     break;
304
305                 default:
306                     gotoxy (1, 9);
307                     cprintf ("Spurious character: $%02X", C);
308             }
309         }
310     } while (!Done);
311
312 #if DYN_DRV
313     /* Uninstall and unload the driver. */
314     CheckError ("mouse_unload", mouse_unload ());
315 #else
316     /* Uninstall the static driver. */
317     CheckError ("mouse_uninstall", mouse_uninstall ());
318 #endif
319
320     /* Say goodbye */
321     cputsxy (0, height / 2 + 3, "Goodbye!");
322     return EXIT_SUCCESS;
323 }