]> git.sur5r.net Git - cc65/blob - samples/mousetest.c
Merge pull request #125 from groessler/something_to_pull2
[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-09-05, 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 #endif
34
35
36
37 #if defined(__C64__) || defined(__C128__) || defined(__CBM510__)
38
39 /* Addresses of data for sprite 0 */
40 #if defined(__C64__)
41 #  define SPRITE0_DATA  ((unsigned char[64])0x0340)
42 #  define SPRITE0_PTR   ((unsigned char *)0x07F8)
43 #elif defined(__C128__)
44 #  define SPRITE0_DATA  ((unsigned char[64])0x0E00)
45 #  define SPRITE0_PTR   ((unsigned char *)0x07F8)
46 #elif defined(__CBM510__)
47 #  define SPRITE0_DATA  ((unsigned char[64])0xF400)
48 #  define SPRITE0_PTR   ((unsigned char *)0xF3F8)
49 #endif
50
51 /* The mouse sprite (an arrow) */
52 static const unsigned char MouseSprite[64] = {
53     0xFE, 0x00, 0x00,
54     0xFC, 0x00, 0x00,
55     0xF8, 0x00, 0x00,
56     0xFC, 0x00, 0x00,
57     0xDE, 0x00, 0x00,
58     0x8F, 0x00, 0x00,
59     0x07, 0x80, 0x00,
60     0x03, 0xC0, 0x00,
61     0x01, 0xE0, 0x00,
62     0x00, 0xF0, 0x00,
63     0x00, 0x78, 0x00,
64     0x00, 0x38, 0x00,
65     0x00, 0x00, 0x00,
66     0x00, 0x00, 0x00,
67     0x00, 0x00, 0x00,
68     0x00, 0x00, 0x00,
69     0x00, 0x00, 0x00,
70     0x00, 0x00, 0x00,
71     0x00, 0x00, 0x00,
72     0x00, 0x00, 0x00,
73     0x00, 0x00, 0x00
74 };
75 #endif
76
77
78
79 static void __fastcall__ CheckError (const char* S, unsigned char Error)
80 {
81     if (Error != MOUSE_ERR_OK) {
82         cprintf ("\n%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error);
83
84         /* Wait for a key-press, so that some platforms can show the error
85         ** message before they remove the current screen.
86         */
87         cgetc();
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 should be 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 #if defined(__C64__) || defined(__C128__) || defined(__CBM510__)
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 #if defined(__CBM__)
225     cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4,
226              width / 2, "");
227 #else
228     cprintf ("%3u,%3u\r\n%*s+", width / 2 * 8 + 4, height / 2 * 8 + 4,
229              width / 2, "");
230 #endif
231
232     /* Test loop */
233     ShowState (Jailed, Invisible);
234     do {
235         /* Get the current co-ordinates and button states; and, print them. */
236         mouse_info (&info);
237         gotoxy (0, 2);
238         cprintf (" X  = %3d\r\n", info.pos.x);
239         cprintf (" Y  = %3d\r\n", info.pos.y);
240         cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ?
241 #ifdef __CBM__
242                  0x5F
243 #else
244                  'v'
245 #endif
246                  : '^');
247         cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ?
248 #ifdef __CBM__
249                  0x5F
250 #else
251                  'v'
252 #endif
253                  : '^');
254
255         /* Handle user input */
256         if (kbhit ()) {
257             cclearxy (1, 9, 23);
258             switch (tolower (C = cgetc ())) {
259                 case 'd':
260                     BREAK();
261
262                     /* The debugger might have changed the colors.
263                     ** Restore them.
264                     */
265 #ifdef __CBM__
266                     (void) bordercolor (COLOR_GRAY2);
267                     (void) bgcolor (COLOR_WHITE);
268                     (void) textcolor (COLOR_GRAY1);
269 #else
270                     (void) bordercolor (COLOR_BLUE);
271                     (void) bgcolor (COLOR_WHITE);
272                     (void) textcolor (COLOR_BLACK);
273 #endif
274
275                     /* The debugger changed the screen; restore it. */
276                     goto top;
277
278                 case 'h':
279                     mouse_hide ();
280                     ShowState (Jailed, ++Invisible);
281                     break;
282
283                 case 'j':
284                     if (Jailed) {
285                         mouse_setbox (&full_box);
286                         Jailed = false;
287                     } else {
288                         small_box.minx = max (info.pos.x - 10, full_box.minx);
289                         small_box.miny = max (info.pos.y - 10, full_box.miny);
290                         small_box.maxx = min (info.pos.x + 10, full_box.maxx);
291                         small_box.maxy = min (info.pos.y + 10, full_box.maxy);
292                         mouse_setbox (&small_box);
293                         Jailed = true;
294                     }
295                     ShowState (Jailed, Invisible);
296                     break;
297
298                 case 's':
299                     mouse_show ();
300                     if (Invisible) {
301                         ShowState (Jailed, --Invisible);
302                     }
303                     break;
304
305                 case 'q':
306                     Done = true;
307                     break;
308
309                 default:
310                     gotoxy (1, 9);
311                     cprintf ("Spurious character: $%02X", C);
312             }
313         }
314     } while (!Done);
315
316 #if DYN_DRV
317     /* Uninstall and unload the driver. */
318     CheckError ("mouse_unload", mouse_unload ());
319 #else
320     /* Uninstall the static driver. */
321     CheckError ("mouse_uninstall", mouse_uninstall ());
322 #endif
323
324     /* Say goodbye */
325     cputsxy (0, height / 2 + 3, "Goodbye!");
326     return EXIT_SUCCESS;
327 }