]> git.sur5r.net Git - cc65/blob - samples/mousetest.c
Merge pull request #27 from greg-king5/cbm2
[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-08-23, 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 ("\n%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error);
89
90         /* Wait for a key-press, so that some platforms can show the error
91         ** message before they remove the current screen.
92         */
93         cgetc();
94         exit (EXIT_FAILURE);
95     }
96 }
97
98
99
100 #if DYN_DRV
101
102 /* Points to the dynamic driver's name. */
103 static const char *mouse_name;
104
105
106
107 static void DoWarning (void)
108 /* Warn the user that a driver is needed for this program. */
109 {
110     cprintf ("Warning: This program needs\r\n"
111              "the driver with the name\r\n"
112              "    %s\r\n"
113              "on a disk! Press 'y' if you have it;\r\n"
114              "or, any other key to exit.\r\n", mouse_stddrv);
115     if (tolower (cgetc ()) != 'y') {
116         exit (EXIT_SUCCESS);
117     }
118     cprintf ("OK. Please wait patiently...\r\n");
119 }
120 #endif
121
122
123
124 static void __fastcall__ ShowState (unsigned char Jailed, unsigned char Invisible)
125 /* Display jail and cursor states. */
126 {
127     cclearxy (0, 7, 32);
128     gotoxy (0, 7);
129     cprintf ("Pointer is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : "");
130 }
131
132
133
134 #if DYN_DRV
135 int main (int argc, char *argv[])
136 #else
137 int main (void)
138 #endif
139 {
140     struct mouse_info info;
141     struct mouse_box full_box, small_box;
142     unsigned char width, height;
143     char C;
144     bool Invisible = true, Done = false, Jailed = false;
145
146     /* Initialize the debugger */
147     DbgInit (0);
148
149     /* Set dark-on-light colors.  Clear the screen. */
150 #ifdef __CBM__
151     (void) bordercolor (COLOR_GRAY2);
152     (void) bgcolor (COLOR_WHITE);
153     (void) textcolor (COLOR_GRAY1);
154 #else
155     (void) bordercolor (COLOR_BLUE);
156     (void) bgcolor (COLOR_WHITE);
157     (void) textcolor (COLOR_BLACK);
158 #endif
159     cursor (0);
160     clrscr ();
161
162     /* The pointer should be created before the driver is installed,
163     ** in case a lightpen driver needs it during calibration.
164     */
165
166 #if defined(__C64__) || defined(__C128__) || defined(__CBM510__)
167     /* Copy the sprite data */
168     memcpy ((void*) SPRITE0_DATA, MouseSprite, sizeof (MouseSprite));
169
170     /* Set the VIC-II sprite pointer. */
171     *SPRITE0_PTR = ((unsigned) SPRITE0_DATA & 0x3FFF) / sizeof SPRITE0_DATA;
172
173     /* Set the color of sprite 0 */
174 #  ifdef __CBM510__
175     pokebsys ((unsigned) &VIC.spr0_color, COLOR_BLACK);
176 #  else
177     VIC.spr0_color = COLOR_BLACK;
178 #  endif
179 #endif
180
181     /* If a lightpen driver is installed, then it can get a calibration value
182     ** from this file (if it exists).  Or, the user can adjust the pen; and,
183     ** the value will be put into this file, for the next time.
184     ** (Other drivers will ignore this.)
185     */
186 #if defined(__C64__) || defined(__C128__)
187     pen_adjust ("pen.dat");
188 #endif
189
190 #if DYN_DRV
191     /* If a dynamically loadable driver is named on the command line,
192     ** then use that driver instead of the standard one.
193     */
194     if (argc > 1) {
195         mouse_name = argv[1];
196     } else {
197         /* Output a warning about the standard driver that is needed. */
198         DoWarning ();
199         mouse_name = mouse_stddrv;
200     }
201
202     /* Load and install the driver. */
203     CheckError ("mouse_load_driver",
204                 mouse_load_driver (&mouse_def_callbacks, mouse_name));
205 #else
206     /* Install the driver. */
207     CheckError ("mouse_install",
208                 mouse_install (&mouse_def_callbacks,
209 #  ifdef MOUSE_DRIVER
210                                MOUSE_DRIVER
211 #  else
212                                mouse_static_stddrv
213 #  endif
214                                ));
215 #endif
216
217     /* Get the initial bounding box. */
218     mouse_getbox (&full_box);
219
220     screensize (&width, &height);
221
222 top:
223     clrscr ();
224
225     /* Print a help line */
226     cputs (" d)ebug  h)ide   q)uit   s)how   j)ail");
227
228     /* Put a cross at the center of the screen. */
229     gotoxy (width / 2 - 3, height / 2 - 1);
230 #if defined(__CBM__)
231     cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4,
232              width / 2, "");
233 #else
234     cprintf ("%3u,%3u\r\n%*s+", width / 2 * 8 + 4, height / 2 * 8 + 4,
235              width / 2, "");
236 #endif
237
238     /* Test loop */
239     ShowState (Jailed, Invisible);
240     do {
241         /* Get the current co-ordinates and button states; and, print them. */
242         mouse_info (&info);
243         gotoxy (0, 2);
244         cprintf (" X  = %3d\r\n", info.pos.x);
245         cprintf (" Y  = %3d\r\n", info.pos.y);
246         cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ?
247 #ifdef __CBM__
248                  0x5F
249 #else
250                  'v'
251 #endif
252                  : '^');
253         cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ?
254 #ifdef __CBM__
255                  0x5F
256 #else
257                  'v'
258 #endif
259                  : '^');
260
261         /* Handle user input */
262         if (kbhit ()) {
263             cclearxy (1, 9, 23);
264             switch (tolower (C = cgetc ())) {
265                 case 'd':
266                     BREAK();
267
268                     /* The debugger might have changed the colors.
269                     ** Restore them.
270                     */
271 #ifdef __CBM__
272                     (void) bordercolor (COLOR_GRAY2);
273                     (void) bgcolor (COLOR_WHITE);
274                     (void) textcolor (COLOR_GRAY1);
275 #else
276                     (void) bordercolor (COLOR_BLUE);
277                     (void) bgcolor (COLOR_WHITE);
278                     (void) textcolor (COLOR_BLACK);
279 #endif
280
281                     /* The debugger changed the screen; restore it. */
282                     goto top;
283
284                 case 'h':
285                     mouse_hide ();
286                     ShowState (Jailed, ++Invisible);
287                     break;
288
289                 case 'j':
290                     if (Jailed) {
291                         mouse_setbox (&full_box);
292                         Jailed = false;
293                     } else {
294                         small_box.minx = max (info.pos.x - 10, full_box.minx);
295                         small_box.miny = max (info.pos.y - 10, full_box.miny);
296                         small_box.maxx = min (info.pos.x + 10, full_box.maxx);
297                         small_box.maxy = min (info.pos.y + 10, full_box.maxy);
298                         mouse_setbox (&small_box);
299                         Jailed = true;
300                     }
301                     ShowState (Jailed, Invisible);
302                     break;
303
304                 case 's':
305                     mouse_show ();
306                     if (Invisible) {
307                         ShowState (Jailed, --Invisible);
308                     }
309                     break;
310
311                 case 'q':
312                     Done = true;
313                     break;
314
315                 default:
316                     gotoxy (1, 9);
317                     cprintf ("Spurious character: $%02X", C);
318             }
319         }
320     } while (!Done);
321
322 #if DYN_DRV
323     /* Uninstall and unload the driver. */
324     CheckError ("mouse_unload", mouse_unload ());
325 #else
326     /* Uninstall the static driver. */
327     CheckError ("mouse_uninstall", mouse_uninstall ());
328 #endif
329
330     /* Say goodbye */
331     cputsxy (0, height / 2 + 3, "Goodbye!");
332     return EXIT_SUCCESS;
333 }