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