1 /*
2  *  Display_svga.i - C64 graphics display, emulator window handling,
3  *                   SVGAlib specific stuff
4  *
5  *  Frodo (C) 1994-1997,2002 Christian Bauer
6  *  SVGAlib stuff by Bernd Schmidt
7  */
8 
9 #include <vga.h>
10 #include <vgamouse.h>
11 #include <vgakeyboard.h>
12 
13 #include "C64.h"
14 
15 
16 #define SCODE_CURSORBLOCKUP 103		/* Cursor key block. */
17 #define SCODE_CURSORBLOCKLEFT 105
18 #define SCODE_CURSORBLOCKRIGHT 106
19 #define SCODE_CURSORBLOCKDOWN 108
20 
21 #define SCODE_INSERT 110
22 #define SCODE_HOME 102
23 #define SCODE_PGUP 104
24 #define SCODE_DELETE 111
25 #define SCODE_END 107
26 #define SCODE_PGDN 109
27 
28 #define SCODE_NUMLOCK 69
29 
30 #define SCODE_KEYPAD0  82
31 #define SCODE_KEYPAD1  79
32 #define SCODE_KEYPAD2  80
33 #define SCODE_KEYPAD3  81
34 #define SCODE_KEYPAD4  75
35 #define SCODE_KEYPAD5  76
36 #define SCODE_KEYPAD6  77
37 #define SCODE_KEYPAD7  71
38 #define SCODE_KEYPAD8  72
39 #define SCODE_KEYPAD9  73
40 #define SCODE_KEYPADENTER      96
41 #define SCODE_KEYPADPLUS       78
42 #define SCODE_KEYPADMINUS      74
43 #define SCODE_KEYPADMULTIPLY   55
44 #define SCODE_KEYPADDIVIDE     98
45 
46 #define SCODE_Q                16
47 #define SCODE_W                17
48 #define SCODE_E                18
49 #define SCODE_R                19
50 #define SCODE_T                20
51 #define SCODE_Y                21
52 #define SCODE_U                22
53 #define SCODE_I                23
54 #define SCODE_O                24
55 #define SCODE_P                25
56 
57 #define SCODE_A                30
58 #define SCODE_S                31
59 #define SCODE_D                32
60 #define SCODE_F                33
61 #define SCODE_G                34
62 #define SCODE_H                35
63 #define SCODE_J                36
64 #define SCODE_K                37
65 #define SCODE_L                38
66 
67 #define SCODE_Z                44
68 #define SCODE_X                45
69 #define SCODE_C                46
70 #define SCODE_V                47
71 #define SCODE_B                48
72 #define SCODE_N                49
73 #define SCODE_M                50
74 
75 #define SCODE_ESCAPE           1
76 #define SCODE_ENTER            28
77 #define SCODE_RIGHTCONTROL     97
78 #define SCODE_CONTROL  97
79 #define SCODE_RIGHTALT 100
80 #define SCODE_LEFTCONTROL      29
81 #define SCODE_LEFTALT  56
82 #define SCODE_SPACE            57
83 
84 #define SCODE_F1               59
85 #define SCODE_F2               60
86 #define SCODE_F3               61
87 #define SCODE_F4               62
88 #define SCODE_F5               63
89 #define SCODE_F6               64
90 #define SCODE_F7               65
91 #define SCODE_F8               66
92 #define SCODE_F9               67
93 #define SCODE_F10              68
94 
95 #define SCODE_0 11
96 #define SCODE_1 2
97 #define SCODE_2 3
98 #define SCODE_3 4
99 #define SCODE_4 5
100 #define SCODE_5 6
101 #define SCODE_6 7
102 #define SCODE_7 8
103 #define SCODE_8 9
104 #define SCODE_9 10
105 
106 #define SCODE_LEFTSHIFT 42
107 #define SCODE_RIGHTSHIFT 54
108 #define SCODE_TAB 15
109 
110 #define SCODE_F11 87
111 #define SCODE_F12 88
112 #define SCODE_NEXT 81
113 #define SCODE_PRIOR 73
114 #define SCODE_BS 14
115 
116 #define SCODE_asciicircum 41
117 #define SCODE_bracketleft 26
118 #define SCODE_bracketright 27
119 #define SCODE_comma 51
120 #define SCODE_period 52
121 #define SCODE_slash 53
122 #define SCODE_semicolon 39
123 #define SCODE_grave 40
124 #define SCODE_minus 12
125 #define SCODE_equal 13
126 #define SCODE_numbersign 43
127 #define SCODE_ltgt 86
128 #define SCODE_scrolllock 70
129 
130 static int bitdepth;
131 static char *bufmem;
132 static int hsize;
133 static vga_modeinfo modeinfo;
134 static char *linear_mem;
135 
136 static int keystate[256];
137 static int f11pressed = 0, f12pressed = 0, quit = 0;
138 static int joystate = 0xFF;
139 static int numlock = 0;
140 static UBYTE rev_matrix[8], key_matrix[8];
141 
142 /*
143   C64 keyboard matrix:
144 
145     Bit 7   6   5   4   3   2   1   0
146   0    CUD  F5  F3  F1  F7 CLR RET DEL
147   1    SHL  E   S   Z   4   A   W   3
148   2     X   T   F   C   6   D   R   5
149   3     V   U   H   B   8   G   Y   7
150   4     N   O   K   M   0   J   I   9
151   5     ,   @   :   .   -   L   P   +
152   6     /   ^   =  SHR HOM  ;   *   �
153   7    R/S  Q   C= SPC  2  CTL  <-  1
154 */
155 #define MATRIX(a,b) (((a) << 3) | (b))
156 #define KEY_F10 512
157 #define KEY_F11 513
158 #define KEY_F12 514
159 
160 #define KEY_FIRE 515
161 #define KEY_JUP 516
162 #define KEY_JDN 517
163 #define KEY_JLF 518
164 #define KEY_JRT 519
165 
166 #define KEY_NUMLOCK 520
167 
168 #define KEY_KPPLUS 521
169 #define KEY_KPMINUS 522
170 #define KEY_KPMULT 523
171 #define KEY_KPDIV 524
172 
scode2c64(int scancode)173 static int scode2c64(int scancode)
174 {
175 	switch (scancode) {
176 	case SCODE_asciicircum: return MATRIX(7,1);
177 	case SCODE_KEYPAD0: return KEY_FIRE;
178 	case SCODE_KEYPAD1: return -1;
179 	case SCODE_KEYPAD2: return KEY_JDN;
180 	case SCODE_KEYPAD3: return -1;
181 	case SCODE_KEYPAD4: return KEY_JLF;
182 	case SCODE_KEYPAD5: return -1;
183 	case SCODE_KEYPAD6: return KEY_JRT;
184 	case SCODE_KEYPAD7: return -1;
185 	case SCODE_KEYPAD8: return KEY_JUP;
186 	case SCODE_KEYPAD9: return -1;
187 
188 	case SCODE_NUMLOCK: return KEY_NUMLOCK;
189 	case SCODE_KEYPADMULTIPLY: return KEY_KPMULT;
190 	case SCODE_KEYPADDIVIDE: return KEY_KPDIV;
191 	case SCODE_KEYPADMINUS: return KEY_KPMINUS;
192 	case SCODE_KEYPADPLUS: return KEY_KPPLUS;
193 	case SCODE_KEYPADENTER: return MATRIX(0,1);
194 
195 	case SCODE_F10: return KEY_F10;
196 	case SCODE_F11: return KEY_F11;
197 	case SCODE_F12: return KEY_F12;
198 
199 	case SCODE_comma: return MATRIX(5,7);
200 	case SCODE_period: return MATRIX(5,4);
201 
202 	case SCODE_A: return MATRIX(1,2);
203 	case SCODE_B: return MATRIX(3,4);
204 	case SCODE_C: return MATRIX(2,4);
205 	case SCODE_D: return MATRIX(2,2);
206 	case SCODE_E: return MATRIX(1,6);
207 	case SCODE_F: return MATRIX(2,5);
208 	case SCODE_G: return MATRIX(3,2);
209 	case SCODE_H: return MATRIX(3,5);
210 	case SCODE_I: return MATRIX(4,1);
211 	case SCODE_J: return MATRIX(4,2);
212 	case SCODE_K: return MATRIX(4,5);
213 	case SCODE_L: return MATRIX(5,2);
214 	case SCODE_M: return MATRIX(4,4);
215 	case SCODE_N: return MATRIX(4,7);
216 	case SCODE_O: return MATRIX(4,6);
217 	case SCODE_P: return MATRIX(5,1);
218 	case SCODE_Q: return MATRIX(7,6);
219 	case SCODE_R: return MATRIX(2,1);
220 	case SCODE_S: return MATRIX(1,5);
221 	case SCODE_T: return MATRIX(2,6);
222 	case SCODE_U: return MATRIX(3,6);
223 	case SCODE_V: return MATRIX(3,7);
224 	case SCODE_W: return MATRIX(1,1);
225 	case SCODE_X: return MATRIX(2,7);
226 	case SCODE_Y: return MATRIX(3,1);
227 	case SCODE_Z: return MATRIX(1,4);
228 
229 	case SCODE_BS: return MATRIX(0,0);
230 	case SCODE_DELETE: return MATRIX(0,0);
231 	case SCODE_LEFTCONTROL: return MATRIX(7,2);
232 	case SCODE_TAB: return MATRIX(7,1);
233 	case SCODE_ENTER: return MATRIX(0,1);
234 	case SCODE_SPACE: return MATRIX(7,4);
235 	case SCODE_LEFTSHIFT: return MATRIX(1,7);
236 	case SCODE_RIGHTSHIFT: return MATRIX(6,4);
237 	case SCODE_ESCAPE: return MATRIX(7,7);
238 	case SCODE_RIGHTCONTROL:
239 	case SCODE_LEFTALT:
240 	case SCODE_RIGHTALT: return MATRIX(7,5);
241 
242 	case SCODE_INSERT: return MATRIX(0,0) | 0x80;
243 	case SCODE_HOME: return MATRIX(6,3);
244 	case SCODE_END: return MATRIX(6,0);
245 	case SCODE_PGUP: return MATRIX(6,6);
246 	case SCODE_PGDN: return MATRIX(6,5);
247 
248 	case SCODE_CURSORBLOCKUP: return MATRIX(0,7)| 0x80;
249 	case SCODE_CURSORBLOCKDOWN: return MATRIX(0,7);
250 	case SCODE_CURSORBLOCKLEFT: return MATRIX(0,2) | 0x80;
251 	case SCODE_CURSORBLOCKRIGHT: return MATRIX(0,2);
252 
253 	case SCODE_F1: return MATRIX(0,4);
254 	case SCODE_F2: return MATRIX(0,4) | 0x80;
255 	case SCODE_F3: return MATRIX(0,5);
256 	case SCODE_F4: return MATRIX(0,5) | 0x80;
257 	case SCODE_F5: return MATRIX(0,6);
258 	case SCODE_F6: return MATRIX(0,6) | 0x80;
259 	case SCODE_F7: return MATRIX(0,3);
260 	case SCODE_F8: return MATRIX(0,3) | 0x80;
261 
262 	case SCODE_0: return MATRIX(4,3);
263 	case SCODE_1: return MATRIX(7,0);
264 	case SCODE_2: return MATRIX(7,3);
265 	case SCODE_3: return MATRIX(1,0);
266 	case SCODE_4: return MATRIX(1,3);
267 	case SCODE_5: return MATRIX(2,0);
268 	case SCODE_6: return MATRIX(2,3);
269 	case SCODE_7: return MATRIX(3,0);
270 	case SCODE_8: return MATRIX(3,3);
271 	case SCODE_9: return MATRIX(4,0);
272 
273 	case SCODE_bracketleft: return MATRIX(5,6);
274 	case SCODE_bracketright: return MATRIX(6,1);
275 	case SCODE_slash: return MATRIX(6,7);
276 	case SCODE_semicolon: return MATRIX(5,5);
277 	case SCODE_grave: return MATRIX(6,2);
278 	case SCODE_numbersign: return MATRIX(6,5);
279 	case SCODE_ltgt: return MATRIX(6,6);
280 	case SCODE_minus: return MATRIX(5,0);
281 	case SCODE_equal: return MATRIX(5,3);
282 	}
283 }
284 
my_kbd_handler(int scancode,int newstate)285 static void my_kbd_handler(int scancode, int newstate)
286 {
287 	int kc = scode2c64(scancode);
288 #if 0
289 	if (kc == -1) {
290 		printf("%d\n",kc);
291 		return;
292 	}
293 #endif
294 	if (newstate == KEY_EVENTPRESS) {
295 		switch (kc) {
296 		case KEY_KPPLUS:
297 			if (ThePrefs.SkipFrames < 10)
298 				ThePrefs.SkipFrames++;
299 			break;
300 
301 		case KEY_KPMINUS:
302 			if (ThePrefs.SkipFrames > 1)
303 				ThePrefs.SkipFrames--;
304 			break;
305 
306 		case KEY_KPMULT:
307 			ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed;
308 			break;
309 
310 		case KEY_KPDIV:
311 			ThePrefs.JoystickSwap = !ThePrefs.JoystickSwap;
312 			break;
313 
314 		case KEY_NUMLOCK:
315 			numlock = !numlock;
316 			break;
317 
318 		case KEY_F10:
319 			quit = 1;
320 			break;
321 
322 		case KEY_F11:
323 			f11pressed = 1;
324 			break;
325 
326 		case KEY_F12:
327 			f12pressed = 1;
328 			break;
329 
330 		case KEY_FIRE:
331 			joystate &= ~0x10;
332 			break;
333 
334 		case KEY_JDN:
335 			joystate &= ~0x2;
336 			break;
337 
338 		case KEY_JUP:
339 			joystate &= ~0x1;
340 			break;
341 
342 		case KEY_JLF:
343 			joystate &= ~0x4;
344 			break;
345 
346 		case KEY_JRT:
347 			joystate &= ~0x8;
348 			break;
349 
350 		default:
351 			if (keystate[kc])
352 				break;
353 			keystate[kc] = 1;
354 			int c64_byte, c64_bit, shifted;
355 			c64_byte = kc >> 3;
356 			c64_bit = kc & 7;
357 			shifted = kc & 128;
358 			c64_byte &= 7;
359 			if (shifted) {
360 				key_matrix[6] &= 0xef;
361 				rev_matrix[4] &= 0xbf;
362 			}
363 			key_matrix[c64_byte] &= ~(1 << c64_bit);
364 			rev_matrix[c64_bit] &= ~(1 << c64_byte);
365 			break;
366 		}
367 	} else {
368 		switch (kc) {
369 		case KEY_FIRE:
370 			joystate |= 0x10;
371 			break;
372 
373 		case KEY_JDN:
374 			joystate |= 0x2;
375 			break;
376 
377 		case KEY_JUP:
378 			joystate |= 0x1;
379 			break;
380 
381 		case KEY_JLF:
382 			joystate |= 0x4;
383 			break;
384 
385 		case KEY_JRT:
386 			joystate |= 0x8;
387 			break;
388 
389 		default:
390 			if (!keystate[kc])
391 				break;
392 			keystate[kc] = 0;
393 			int c64_byte, c64_bit, shifted;
394 			c64_byte = kc >> 3;
395 			c64_bit = kc & 7;
396 			shifted = kc & 128;
397 			c64_byte &= 7;
398 			if (shifted) {
399 				key_matrix[6] |= 0x10;
400 				rev_matrix[4] |= 0x40;
401 			}
402 			key_matrix[c64_byte] |= (1 << c64_bit);
403 			rev_matrix[c64_bit] |= (1 << c64_byte);
404 			break;
405 		}
406 
407 	}
408 }
409 
410 
C64Display(C64 * the_c64)411 C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
412 {
413     quit_requested = false;
414 }
415 
416 
~C64Display()417 C64Display::~C64Display()
418 {
419     sleep(1);
420     vga_setmode(TEXT);
421 }
422 
423 
424 /*
425  *  Prefs may have changed
426  */
427 
NewPrefs(Prefs * prefs)428 void C64Display::NewPrefs(Prefs *prefs)
429 {
430 }
431 
432 
Speedometer(int speed)433 void C64Display::Speedometer(int speed)
434 {
435 }
436 
437 
init_graphics(void)438 int init_graphics(void)
439 {
440     int vgamode = G640x480x256;
441     modeinfo = *vga_getmodeinfo (vgamode);
442 
443     if (vga_setmode(vgamode) < 0) {
444 	sleep(1);
445 	vga_setmode(TEXT);
446 	fprintf(stderr, "SVGAlib doesn't like my video mode. Giving up.\n");
447 	return 0;
448     }
449 
450     hsize = modeinfo.linewidth;
451     if (hsize < DISPLAY_X)
452 	hsize = DISPLAY_X;
453 
454 	bufmem = NULL;
455     if ((modeinfo.flags & CAPABLE_LINEAR) && modeinfo.linewidth >= DISPLAY_X) {
456 	if (vga_setlinearaddressing() != -1) {
457 	    linear_mem = (char *)vga_getgraphmem();
458 	    printf("Using linear addressing: %p.\n", linear_mem);
459 	    bufmem = linear_mem;
460 	}
461     }
462     if (bufmem == NULL)
463 	bufmem = (char *)malloc(hsize * DISPLAY_Y);
464 
465     if (keyboard_init() != 0)
466 	abort();
467     keyboard_seteventhandler(my_kbd_handler);
468     /*     keyboard_translatekeys(DONT_CATCH_CTRLC);*/
469 
470     memset(keystate, 0, sizeof(keystate));
471     memset(key_matrix, 0xFF, 8);
472     memset(rev_matrix, 0xFF, 8);
473     return 1;
474 }
475 
476 
Update(void)477 void C64Display::Update(void)
478 {
479     int y;
480 
481     if (linear_mem)
482 	return;
483 
484     for (y = 0; y < DISPLAY_Y; y++) {
485 	vga_drawscanline(y, bufmem + hsize * y);
486     }
487 }
488 
489 
BitmapBase(void)490 UBYTE *C64Display::BitmapBase(void)
491 {
492        return (UBYTE *)bufmem;
493 }
494 
495 
BitmapXMod(void)496 int C64Display::BitmapXMod(void)
497 {
498        return hsize;
499 }
500 
501 
PollKeyboard(UBYTE * CIA_key_matrix,UBYTE * CIA_rev_matrix,UBYTE * joystick)502 void C64Display::PollKeyboard(UBYTE *CIA_key_matrix, UBYTE *CIA_rev_matrix, UBYTE *joystick)
503 {
504     keyboard_update();
505     *joystick = joystate;
506     memcpy(CIA_key_matrix, key_matrix, 8);
507     memcpy(CIA_rev_matrix, rev_matrix, 8);
508     if (f11pressed)
509 	TheC64->NMI();
510     if (f12pressed)
511 	TheC64->Reset();
512     if (quit)
513 	quit_requested = true;
514     f11pressed = f12pressed = 0;
515 }
516 
517 
518 /*
519  *  Check if NumLock is down (for switching the joystick keyboard emulation)
520  */
521 
NumLock(void)522 bool C64Display::NumLock(void)
523 {
524        return numlock;
525 }
526 
527 
528 /*
529  *  Allocate C64 colors
530  */
531 
colorval(int v)532 static int colorval(int v)
533 {
534        return ((v & 255)*0x01010101) >> 26;
535 }
536 
InitColors(UBYTE * colors)537 void C64Display::InitColors(UBYTE *colors)
538 {
539        int i;
540 
541        for (i=0; i< 256; i++) {
542                vga_setpalette(i, colorval(palette_red[i & 0x0f]), colorval(palette_green[i & 0x0f]), colorval(palette_blue[i & 0x0f]));
543                colors[i] = i;
544        }
545 }
546 
547 
548 /*
549  *  Show a requester (error message)
550  */
551 
ShowRequester(char * a,char * b,char *)552 long int ShowRequester(char *a,char *b,char *)
553 {
554        printf("%s: %s\n", a, b);
555        return 1;
556 }
557