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