1 /*
2 * atari_ps2.c - Sony PlayStation 2 port code
3 *
4 * Copyright (c) 2005 Troy Ayers and Piotr Fusik
5 * Copyright (c) 2005-2014 Atari800 development team (see DOC/CREDITS)
6 *
7 * This file is part of the Atari800 emulator project which emulates
8 * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
9 *
10 * Atari800 is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * Atari800 is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Atari800; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24 //TODO: map the following keys
25 //control <>: (suits)
26 //akey_clear
27 //AKEY_BREAK
28 //all ALT+key shortcut keys
29 //Atari OPTION key (temple of apshai, others?)
30 //keyboard repeat (when shift nor control pressed)
31 //mouse support
32 //autodetect pal vs ntsc
33 //allow user to map own keyboard keys to controller
34 //enable cdfs, hdd, mass, and host support.
35
36 #include "config.h"
37 #include <stdio.h>
38 #include <string.h>
39 #include <tamtypes.h>
40 #include <loadfile.h>
41 #include <fileio.h>
42 #include <sifcmd.h>
43 #include <sifrpc.h>
44 #include <kernel.h>
45 #include <debug.h>
46 #include <libmc.h>
47 #include <libkbd.h>
48 #include <libpad.h>
49 #include <gsKit.h>
50 #include <dmaKit.h>
51
52 #include "atari.h"
53 #include "colours.h"
54 #include "input.h"
55 #include "akey.h"
56 #include "log.h"
57 #include "monitor.h"
58 #include "screen.h"
59 #include "ui.h"
60 #include "util.h"
61
62 //#ifdef SOUND
63 #include <audsrv.h>
64 #include "pokeysnd.h"
65 #include "sound.h"
66 extern unsigned char audsrv[];
67 extern unsigned int size_audsrv;
68 //#endif
69
70 // define to use T0 and T1 timers
71 #define USE_TIMERS
72 extern unsigned char usbd[];
73 extern unsigned int size_usbd;
74
75 extern unsigned char ps2kbd[];
76 extern unsigned int size_ps2kbd;
77
78 static GSGLOBAL *gsGlobal = NULL;
79
80 static int clut[256] __attribute__((aligned(16)));
81
82 //int PS2KbdCAPS = 0;
83 int PS2KbdSHIFT = 0;
84 int PS2KbdCONTROL = 0;
85 int PS2KbdALT = 0;
86
87 #define PAD_PORT 0
88 #define PAD_SLOT 0
89
90 static char padBuf[256] __attribute__((aligned(64)));
91
92 #ifdef USE_TIMERS
93
94 /* We use T0 for PLATFORM_Time() and T1 for PLATFORM_Sleep().
95 Note that both timers are just 16-bit. */
96
97 #define T0_COUNT (*(volatile unsigned long *) 0x10000000)
98 #define T0_MODE (*(volatile unsigned long *) 0x10000010)
99 #define T0_COMP (*(volatile unsigned long *) 0x10000020)
100 #define T1_COUNT (*(volatile unsigned long *) 0x10000800)
101 #define T1_MODE (*(volatile unsigned long *) 0x10000810)
102 #define T1_COMP (*(volatile unsigned long *) 0x10000820)
103
104 #define INTC_TIM0 9
105 #define INTC_TIM1 10
106
107 static int t0_interrupt_id = -1;
108 static int t1_interrupt_id = -1;
109
110 /* The range of int is enough for about 7 years
111 of continuous running. */
112 static volatile int timer_interrupt_ticks = 0;
113
114 static int sleeping_thread_id = 0;
115
t0_interrupt_handler(int ca)116 static int t0_interrupt_handler(int ca)
117 {
118 timer_interrupt_ticks++;
119 T0_MODE |= 0x800; // clear overflow status
120 // __asm__ volatile("sync.l; ei"); // XXX: necessary?
121 return -1; // XXX: or 0? what does it mean?
122 }
123
t1_interrupt_handler(int ca)124 static int t1_interrupt_handler(int ca)
125 {
126 iWakeupThread(sleeping_thread_id);
127 T1_MODE = 0; // disable
128 // __asm__ volatile("sync.l; ei"); // XXX: necessary?
129 return -1; // XXX: or 0? what does it mean?
130 }
131
timer_initialize(void)132 static void timer_initialize(void)
133 {
134 T0_MODE = 0; // disable
135 t0_interrupt_id = AddIntcHandler(INTC_TIM0, t0_interrupt_handler, 0);
136 EnableIntc(INTC_TIM0);
137 T0_COUNT = 0;
138 T0_MODE = 0x002 // 576000 Hz clock
139 + 0x080 // start counting
140 + 0x200; // generate interrupt on overflow
141
142 T1_MODE = 0; // disable
143 t1_interrupt_id = AddIntcHandler(INTC_TIM1, t1_interrupt_handler, 0);
144 EnableIntc(INTC_TIM1);
145 }
146
timer_shutdown(void)147 static void timer_shutdown(void)
148 {
149 T0_MODE = 0;
150 if (t0_interrupt_id >= 0) {
151 DisableIntc(INTC_TIM0);
152 RemoveIntcHandler(INTC_TIM0, t0_interrupt_id);
153 t0_interrupt_id = -1;
154 }
155 T1_MODE = 0;
156 if (t1_interrupt_id >= 0) {
157 DisableIntc(INTC_TIM1);
158 RemoveIntcHandler(INTC_TIM1, t1_interrupt_id);
159 t1_interrupt_id = -1;
160 }
161 }
162
163 #endif /* USE_TIMERS */
164
PLATFORM_Time(void)165 double PLATFORM_Time(void)
166 {
167 #ifdef USE_TIMERS
168 /* AFAIK, multiplication is faster than division,
169 on every CPU architecture */
170 return (timer_interrupt_ticks * 65536.0 + T0_COUNT) * (1.0 / 576000);
171 #else
172 static double fake_timer = 0;
173 return fake_timer++;
174 #endif
175 }
176
177 /* this PLATFORM_Sleep() supports times only up to 0.11 sec,
178 which is enough for Atari800 purposes */
179
180 /* void PLATFORM_Sleep(double s)
181 {
182 #ifdef USE_TIMERS
183 unsigned long count = 65536 - (unsigned long) (s * 576000);
184 // do nothing if s is less than one T1 tick
185 if (count >= 65536)
186 return;
187 sleeping_thread_id = GetThreadId();
188 T1_COUNT = count;
189 T1_MODE = 0x002 // 576000 Hz clock
190 + 0x080 // start counting
191 + 0x200; // generate interrupt on overflow
192 // SleepThread();
193 #endif
194 }
195 */
196 //volatile int locked = 1;
197
198 //void wakeup(s32 id, u16 time, void *arg)
199 //{
200 // locked = 0;
201 //}
202 //
203 //void PLATFORM_Sleep(double s)
204 //{
205 //
206 // /* 15734 is around 1 second on NTSC */
207 // /* is about 1ms? */
208 // SetAlarm(15734 * s, wakeup, 0);
209 // while (locked);
210 // locked = 1;
211 //}
PLATFORM_Sleep(double s)212 void PLATFORM_Sleep(double s)
213 {
214
215 if (UI_is_active){
216 int i,ret;
217 for (i=0;i<s * 100.0;i++){
218
219 ee_sema_t sema;
220 sema.attr = 0;
221 sema.count = 0;
222 sema.init_count = 0;
223 sema.max_count = 1;
224 ret = CreateSema(&sema);
225 if (ret <= 0) {
226 //could not create sema, strange! continue anyway.
227 return;
228 }
229
230 iSignalSema(ret);
231 WaitSema(ret);
232 DeleteSema(ret);
233 }
234 }
235 }
236
237
loadModules(void)238 void loadModules(void)
239 {
240 int ret;
241 //init_scr();
242
243 ret = SifLoadModule("rom0:SIO2MAN", 0, NULL);
244 if (ret < 0) {
245 Log_print("Sio2man loading failed: %d", ret);
246 SleepThread();
247 }
248
249 // Log_print("mcman");
250 SifLoadModule("rom0:MCMAN", 0, NULL);
251
252 // Log_print("mcserv");
253 SifLoadModule("rom0:MCSERV", 0, NULL);
254
255 // Log_print("padman");
256 ret = SifLoadModule("rom0:PADMAN", 0, NULL);
257 if (ret < 0) {
258 Log_print("Padman loading failed: %d", ret);
259 SleepThread();
260 }
261
262 mcInit(MC_TYPE_MC);
263
264 // cdinit(1);
265 SifInitRpc(0);
266
267 SifExecModuleBuffer(usbd, size_usbd, 0, NULL, &ret);
268 SifExecModuleBuffer(ps2kbd, size_ps2kbd, 0, NULL, &ret);
269
270 if (PS2KbdInit() == 0) {
271 Log_print("Failed to Init Keyboard.");
272 }
273 PS2KbdSetReadmode(PS2KBD_READMODE_RAW);
274
275 #ifdef SOUND
276 ret = SifLoadModule("rom0:LIBSD", 0, NULL);
277
278 ret = SifExecModuleBuffer(audsrv, size_audsrv, 0, NULL, &ret);
279 #endif
280
281 }
282
PLATFORM_Initialise(int * argc,char * argv[])283 int PLATFORM_Initialise(int *argc, char *argv[])
284 {
285 // Swap Red and Blue components
286 int i;
287 for (i = 0; i < 256; i++) {
288 int c = Colours_table[i];
289 // clut[i] = (c >> 16) + (c & 0xff00) + ((c & 0xff) << 16);
290 // swap bits 3 and 4 to workaround a bug in gsKit
291 clut[(i ^ i * 2) & 16 ? i ^ 24 : i] = (c >> 16) + (c & 0xff00) + ((c & 0xff) << 16);
292 }
293 // Clear debug from screen
294 init_scr();
295 // Initialize graphics
296 gsGlobal = gsKit_init_global(GS_MODE_NTSC);
297 dmaKit_init(D_CTRL_RELE_ON, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC,
298 D_CTRL_STD_OFF, D_CTRL_RCYC_8);
299 dmaKit_chan_init(DMA_CHANNEL_GIF);
300 gsGlobal->PSM = GS_PSM_CT32;
301 gsGlobal->Test->ZTE = 0;
302 gsKit_init_screen(gsGlobal);
303 // Init joypad
304 padInit(0);
305 padPortOpen(PAD_PORT, PAD_SLOT, padBuf);
306 #ifdef USE_TIMERS
307 timer_initialize();
308 #endif
309 #ifdef SOUND
310 if (!Sound_Initialise(argc, argv))
311 return FALSE;
312 #endif
313
314 return TRUE;
315 }
316
PLATFORM_Exit(int run_monitor)317 int PLATFORM_Exit(int run_monitor)
318 {
319 // TODO: shutdown graphics mode
320 Log_flushlog();
321 #if 0
322 if (run_monitor && MONITOR_Run()) {
323 // TODO: reinitialize graphics mode
324 return TRUE;
325 }
326 #endif
327 #ifdef USE_TIMERS
328 timer_shutdown();
329 #endif
330 /* TODO Sound_Exit should not be called here! It only stays here now because
331 the next step restarts the PS2 without ever returning from this function to
332 Atari800_Exit, so the call to Sound_Exit located in the latter function is
333 never invoked. So, should the LoadExecPS2call below get removed, so should
334 this call to Sound_Exit. */
335 #ifdef SOUND
336 Sound_Exit();
337 #endif
338 //zzz temp exit procedure
339 //Hard coded to go back to ulaunch
340 fioExit();
341 SifExitRpc();
342 LoadExecPS2("mc0:/BOOT/BOOT.ELF", 0, NULL);
343 //zzz end
344 return FALSE;
345 }
346
PLATFORM_DisplayScreen(void)347 void PLATFORM_DisplayScreen(void)
348 {
349 GSTEXTURE tex;
350 tex.Width = Screen_WIDTH;
351 tex.Height = Screen_HEIGHT;
352 tex.PSM = GS_PSM_T8;
353 tex.Mem = (UBYTE *) Screen_atari;
354 tex.Clut = clut;
355 tex.Vram = 0x200000;
356 tex.VramClut = 0x280000;
357 tex.Filter = GS_FILTER_LINEAR;
358 // TODO: upload clut just once
359 gsKit_texture_upload(gsGlobal, &tex);
360 gsKit_prim_sprite_texture(gsGlobal, &tex, 0, 0, 32, 0, 640, 480, 32 + 320, 240, 0, 0x80808080);
361 #if 0
362 gsKit_sync_flip(gsGlobal);
363 #else
364 // flip without vsync
365 // this is a copy of gsKit_sync_flip() code with just gsKit_vsync() call removed
366 GS_SET_DISPFB2(gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192,
367 gsGlobal->Width / 64, gsGlobal->PSM, 0, 0 );
368 gsGlobal->ActiveBuffer ^= 1;
369 gsGlobal->PrimContext ^= 1;
370 gsGlobal->EvenOrOdd = ((GSREG *) GS_CSR)->FIELD;
371 gsKit_setactive(gsGlobal);
372 #endif
373
374 }
375
PadButtons(void)376 static int PadButtons(void)
377 {
378 struct padButtonStatus buttons;
379 for (;;) {
380 int ret = padGetState(PAD_PORT, PAD_SLOT);
381 if (ret == PAD_STATE_STABLE || ret == PAD_STATE_FINDCTP1)
382 break;
383 if (ret == PAD_STATE_DISCONN)
384 return 0;
385 }
386 padRead(PAD_PORT, PAD_SLOT, &buttons);
387 return ~buttons.btns;
388 }
389
PLATFORM_Keyboard(void)390 int PLATFORM_Keyboard(void)
391 {
392 int new_pad = PadButtons();
393 PS2KbdRawKey key;
394 INPUT_key_consol = INPUT_CONSOL_NONE;
395
396 if (UI_is_active) {
397 if (new_pad & PAD_CROSS)
398 return AKEY_RETURN;
399 if (new_pad & PAD_CIRCLE)
400 return AKEY_ESCAPE;
401 if (new_pad & PAD_LEFT)
402 return AKEY_LEFT;
403 if (new_pad & PAD_RIGHT)
404 return AKEY_RIGHT;
405 if (new_pad & PAD_UP)
406 return AKEY_UP;
407 if (new_pad & PAD_DOWN)
408 return AKEY_DOWN;
409 if (new_pad & PAD_L1)
410 return AKEY_COLDSTART;
411 if (new_pad & PAD_R1)
412 return AKEY_WARMSTART;
413 }
414 //PAD_CROSS is used for PLATFORM_TRIG().
415 if (new_pad & PAD_TRIANGLE)
416 return AKEY_UI;
417 if (new_pad & PAD_SQUARE)
418 return AKEY_SPACE;
419 if (new_pad & PAD_CIRCLE)
420 return AKEY_RETURN;
421 if (new_pad & PAD_L1)
422 return AKEY_COLDSTART;
423 if (new_pad & PAD_R1)
424 return AKEY_WARMSTART;
425 if (Atari800_machine_type == Atari800_MACHINE_5200) {
426 if (new_pad & PAD_START)
427 return AKEY_5200_START;
428 }
429 else {
430 if (new_pad & PAD_START)
431 INPUT_key_consol ^= INPUT_CONSOL_START;
432 if (new_pad & PAD_SELECT)
433 INPUT_key_consol ^= INPUT_CONSOL_SELECT;
434 if (new_pad & PAD_CROSS)
435 return AKEY_HELP;
436 }
437 if (Atari800_machine_type != Atari800_MACHINE_5200 || UI_is_active) {
438
439 while (PS2KbdReadRaw(&key) != 0) {
440 if (key.state == PS2KBD_RAWKEY_DOWN) {
441 switch (key.key) {
442 case EOF:
443 Atari800_Exit(FALSE);
444 exit(0);
445 break;
446 case 0x28:
447 return AKEY_RETURN;
448 case 0x29:
449 return AKEY_ESCAPE;
450 case 0x2A:
451 return AKEY_BACKSPACE;
452 case 0x2B:
453 return AKEY_TAB;
454 case 0x2C:
455 return AKEY_SPACE;
456 case 0x46://Print Screen Button
457 return AKEY_SCREENSHOT;
458 case 0x4F:
459 return AKEY_RIGHT;
460 case 0x50:
461 return AKEY_LEFT;
462 case 0x51:
463 return AKEY_DOWN;
464 case 0x52:
465 return AKEY_UP;
466 case 0x58:
467 return AKEY_RETURN;
468
469 case 0xE0:
470 PS2KbdCONTROL = 1;
471 return AKEY_NONE;
472 case 0xE4:
473 PS2KbdCONTROL = 1;
474 return AKEY_NONE;
475 case 0xE1:
476 PS2KbdSHIFT = 1;
477 return AKEY_NONE;
478 case 0xE2:
479 PS2KbdALT = 1;
480 return AKEY_NONE;
481 case 0xE5:
482 PS2KbdSHIFT = 1;
483 return AKEY_NONE;
484 case 0xE6:
485 PS2KbdALT = 1;
486 return AKEY_NONE;
487 default:
488 break;
489 }
490 }
491
492 if ((key.state == PS2KBD_RAWKEY_DOWN) && !PS2KbdSHIFT && !PS2KbdALT) {
493 switch (key.key) {
494 case 0x1E:
495 return AKEY_1;
496 case 0X1F:
497 return AKEY_2;
498 case 0x20:
499 return AKEY_3;
500 case 0x21:
501 return AKEY_4;
502 case 0x22:
503 return AKEY_5;
504 case 0x23:
505 return AKEY_6;
506 case 0x24:
507 return AKEY_7;
508 case 0x25:
509 return AKEY_8;
510 case 0x26:
511 return AKEY_9;
512 case 0x27:
513 return AKEY_0;
514 case 0x2D:
515 return AKEY_MINUS;
516 case 0x2E:
517 return AKEY_EQUAL;
518 case 0x2F:
519 return AKEY_BRACKETLEFT;
520 case 0x30:
521 return AKEY_BRACKETRIGHT;
522 case 0x31:
523 return AKEY_BACKSLASH;
524 case 0x33:
525 return AKEY_SEMICOLON;
526 case 0x34:
527 return AKEY_QUOTE;
528 case 0x35:
529 return AKEY_ATARI;
530 case 0x36:
531 return AKEY_COMMA;
532 case 0x37:
533 return AKEY_FULLSTOP;
534 case 0x38:
535 return AKEY_SLASH;
536 case 0x3A://F1
537 return AKEY_UI;
538 case 0x3E://F5
539 return AKEY_WARMSTART;
540 case 0x42://F9
541 return AKEY_EXIT;
542 case 0x43://F10
543 return AKEY_SCREENSHOT;
544 default:
545 break;
546 }
547 }
548 if ((key.state == PS2KBD_RAWKEY_DOWN) && PS2KbdSHIFT && !PS2KbdCONTROL && !PS2KbdALT) {
549 switch (key.key) {
550 case 0x4:
551 return AKEY_A;
552 case 0x5:
553 return AKEY_B;
554 case 0x6:
555 return AKEY_C;
556 case 0x7:
557 return AKEY_D;
558 case 0x8:
559 return AKEY_E;
560 case 0x9:
561 return AKEY_F;
562 case 0xA:
563 return AKEY_G;
564 case 0xB:
565 return AKEY_H;
566 case 0xC:
567 return AKEY_I;
568 case 0xD:
569 return AKEY_J;
570 case 0xE:
571 return AKEY_K;
572 case 0xF:
573 return AKEY_L;
574 case 0x10:
575 return AKEY_M;
576 case 0x11:
577 return AKEY_N;
578 case 0x12:
579 return AKEY_O;
580 case 0x13:
581 return AKEY_P;
582 case 0x14:
583 return AKEY_Q;
584 case 0x15:
585 return AKEY_R;
586 case 0x16:
587 return AKEY_S;
588 case 0x17:
589 return AKEY_T;
590 case 0x18:
591 return AKEY_U;
592 case 0x19:
593 return AKEY_V;
594 case 0x1A:
595 return AKEY_W;
596 case 0x1B:
597 return AKEY_X;
598 case 0x1C:
599 return AKEY_Y;
600 case 0x1D:
601 return AKEY_Z;
602 case 0x1E:
603 return AKEY_EXCLAMATION;
604 case 0X1F:
605 return AKEY_AT;
606 case 0x20:
607 return AKEY_HASH;
608 case 0x21:
609 return AKEY_DOLLAR;
610 case 0x22:
611 return AKEY_PERCENT;
612 case 0x23:
613 // return AKEY_CIRCUMFLEX;
614 return AKEY_CARET;
615 case 0x24:
616 return AKEY_AMPERSAND;
617 case 0x25:
618 return AKEY_ASTERISK;
619 case 0x26:
620 return AKEY_PARENLEFT;
621 case 0x27:
622 return AKEY_PARENRIGHT;
623 case 0x2B:
624 return AKEY_SETTAB;
625 case 0x2D:
626 return AKEY_UNDERSCORE;
627 case 0x2E:
628 return AKEY_PLUS;
629 case 0x31:
630 return AKEY_BAR;
631 case 0x33:
632 return AKEY_COLON;
633 case 0x34:
634 return AKEY_DBLQUOTE;
635 case 0x36:
636 return AKEY_LESS;
637 case 0x37:
638 return AKEY_GREATER;
639 case 0x38:
640 return AKEY_QUESTION;
641 case 0x3E://Shift+F5
642 return AKEY_COLDSTART;
643 case 0x43://Shift+F10
644 return AKEY_SCREENSHOT_INTERLACE;
645 case 0x49://Shift+Insert key
646 return AKEY_INSERT_LINE;
647 case 0x4C://Shift+Backspace Key
648 return AKEY_DELETE_LINE;
649 default:
650 break;
651 }
652 }
653 if ((key.state == PS2KBD_RAWKEY_DOWN) && !PS2KbdSHIFT && !PS2KbdCONTROL && !PS2KbdALT) {
654 switch (key.key) {
655 case 0x4:
656 return AKEY_a;
657 case 0x5:
658 return AKEY_b;
659 case 0x6:
660 return AKEY_c;
661 case 0x7:
662 return AKEY_d;
663 case 0x8:
664 return AKEY_e;
665 case 0x9:
666 return AKEY_f;
667 case 0xA:
668 return AKEY_g;
669 case 0xB:
670 return AKEY_h;
671 case 0xC:
672 return AKEY_i;
673 case 0xD:
674 return AKEY_j;
675 case 0xE:
676 return AKEY_k;
677 case 0xF:
678 return AKEY_l;
679 case 0x10:
680 return AKEY_m;
681 case 0x11:
682 return AKEY_n;
683 case 0x12:
684 return AKEY_o;
685 case 0x13:
686 return AKEY_p;
687 case 0x14:
688 return AKEY_q;
689 case 0x15:
690 return AKEY_r;
691 case 0x16:
692 return AKEY_s;
693 case 0x17:
694 return AKEY_t;
695 case 0x18:
696 return AKEY_u;
697 case 0x19:
698 return AKEY_v;
699 case 0x1A:
700 return AKEY_w;
701 case 0x1B:
702 return AKEY_x;
703 case 0x1C:
704 return AKEY_y;
705 case 0x1D:
706 return AKEY_z;
707 case 0x49:
708 return AKEY_INSERT_CHAR;
709 case 0x4C:
710 return AKEY_DELETE_CHAR;
711 default:
712 break;
713 }
714 }
715 if ((key.state == PS2KBD_RAWKEY_DOWN) && PS2KbdCONTROL && !PS2KbdALT) {
716 switch(key.key) {
717 case 0x4:
718 return AKEY_CTRL_a;
719 case 0x5:
720 return AKEY_CTRL_b;
721 case 0x6:
722 return AKEY_CTRL_c;
723 case 0x7:
724 return AKEY_CTRL_d;
725 case 0x8:
726 return AKEY_CTRL_e;
727 case 0x9:
728 return AKEY_CTRL_f;
729 case 0xA:
730 return AKEY_CTRL_g;
731 case 0xB:
732 return AKEY_CTRL_h;
733 case 0xC:
734 return AKEY_CTRL_i;
735 case 0xD:
736 return AKEY_CTRL_j;
737 case 0xE:
738 return AKEY_CTRL_k;
739 case 0xF:
740 return AKEY_CTRL_l;
741 case 0x10:
742 return AKEY_CTRL_m;
743 case 0x11:
744 return AKEY_CTRL_n;
745 case 0x12:
746 return AKEY_CTRL_o;
747 case 0x13:
748 return AKEY_CTRL_p;
749 case 0x14:
750 return AKEY_CTRL_q;
751 case 0x15:
752 return AKEY_CTRL_r;
753 case 0x16:
754 return AKEY_CTRL_s;
755 case 0x17:
756 return AKEY_CTRL_t;
757 case 0x18:
758 return AKEY_CTRL_u;
759 case 0x19:
760 return AKEY_CTRL_v;
761 case 0x1A:
762 return AKEY_CTRL_w;
763 case 0x1B:
764 return AKEY_CTRL_x;
765 case 0x1C:
766 return AKEY_CTRL_y;
767 case 0x1D:
768 return AKEY_CTRL_z;
769 case 0x1E:
770 return AKEY_CTRL_1;
771 case 0x1F:
772 return AKEY_CTRL_2;
773 case 0x20:
774 return AKEY_CTRL_3;
775 case 0x21:
776 return AKEY_CTRL_4;
777 case 0x22:
778 return AKEY_CTRL_5;
779 case 0x23:
780 return AKEY_CTRL_6;
781 case 0x24:
782 return AKEY_CTRL_7;
783 case 0x25:
784 return AKEY_CTRL_8;
785 case 0x26:
786 return AKEY_CTRL_9;
787 case 0x27:
788 return AKEY_CTRL_0;
789 case 0x2B:
790 return AKEY_CLRTAB;
791 case 0x33:
792 return AKEY_SEMICOLON | AKEY_CTRL;
793 case 0x36:
794 return AKEY_LESS | AKEY_CTRL;
795 case 0x37:
796 return AKEY_GREATER | AKEY_CTRL;
797 default:
798 break;
799 }
800 }
801 if ((key.state == PS2KBD_RAWKEY_DOWN) && PS2KbdALT) {
802 switch(key.key) {
803 //case dcr ylsa
804 case 0x7:
805 UI_alt_function = UI_MENU_DISK;
806 return AKEY_UI;
807 case 0x6:
808 UI_alt_function = UI_MENU_CARTRIDGE;
809 return AKEY_UI;
810 case 0x15:
811 UI_alt_function = UI_MENU_RUN;
812 return AKEY_UI;
813 case 0x1C:
814 UI_alt_function = UI_MENU_SYSTEM;
815 return AKEY_UI;
816 case 0xF:
817 UI_alt_function = UI_MENU_LOADSTATE;
818 return AKEY_UI;
819 case 0x16:
820 UI_alt_function = UI_MENU_SAVESTATE;
821 return AKEY_UI;
822 case 0x17:
823 UI_alt_function = UI_MENU_CASSETTE;
824 return AKEY_UI;
825 case 0x4:
826 UI_alt_function = UI_MENU_ABOUT;
827 return AKEY_UI;
828 default:
829 break;
830 }
831 }
832
833
834 if (key.state == PS2KBD_RAWKEY_UP) {
835 switch (key.key) {
836 case 0x39:
837
838 return AKEY_CAPSTOGGLE;
839 case 0xE0:
840 PS2KbdCONTROL = 0;
841 return AKEY_NONE;
842 case 0xE4:
843 PS2KbdCONTROL = 0;
844 return AKEY_NONE;
845 case 0xE1:
846 PS2KbdSHIFT = 0;
847 return AKEY_NONE;
848 case 0xE2:
849 PS2KbdALT = 0;
850 return AKEY_NONE;
851 case 0xE5:
852 PS2KbdSHIFT = 0;
853 return AKEY_NONE;
854 case 0xE6:
855 PS2KbdALT = 0;
856 return AKEY_NONE;
857 default:
858 break;
859 }
860 }
861 }
862 }
863 return AKEY_NONE;
864 }
865
PLATFORM_PORT(int num)866 int PLATFORM_PORT(int num)
867 {
868 int ret = 0xff;
869 if (num == 0) {
870 int pad = PadButtons();
871 if (pad & PAD_LEFT)
872 ret &= 0xf0 | INPUT_STICK_LEFT;
873 if (pad & PAD_RIGHT)
874 ret &= 0xf0 | INPUT_STICK_RIGHT;
875 if (pad & PAD_UP)
876 ret &= 0xf0 | INPUT_STICK_FORWARD;
877 if (pad & PAD_DOWN)
878 ret &= 0xf0 | INPUT_STICK_BACK;
879 }
880 return ret;
881 }
882
PLATFORM_TRIG(int num)883 int PLATFORM_TRIG(int num)
884 {
885 if (num == 0 && PadButtons() & PAD_CROSS)
886 return 0;
887 return 1;
888 }
889
890 char dir_path[FILENAME_MAX];
891
892 static int dir_n;
893 static int dir_i;
894
895 // XXX: use followup calls to get directory entries one-by-one?
896
897 #define MAX_FILES_PER_DIR 1000
898
899 static mcTable mcDir[MAX_FILES_PER_DIR];
900
Atari_OpenDir(const char * filename)901 int Atari_OpenDir(const char *filename)
902 {
903 // TODO: support other devices
904 if (strncmp(filename, "mc0:/", 5) != 0)
905 return FALSE;
906 dir_n = mcGetDir(0, 0, filename + 4, 0 /* followup flag */, MAX_FILES_PER_DIR, mcDir);
907 mcSync(0,NULL,&dir_n);
908 if (dir_n < 0)
909 return FALSE;
910 dir_i = 0;
911 // XXX: does it know (and needs to know) that "mc0:/" is a root directory?
912 Util_splitpath(filename, dir_path, NULL);
913 return TRUE;
914 }
915
Atari_ReadDir(char * fullpath,char * filename,int * isdir,int * readonly,int * size,char * timetext)916 int Atari_ReadDir(char *fullpath, char *filename, int *isdir,
917 int *readonly, int *size, char *timetext)
918 {
919 const mcTable *p;
920 if (dir_i >= dir_n)
921 return FALSE;
922 p = mcDir + dir_i;
923 if (fullpath != NULL)
924 Util_catpath(fullpath, dir_path, p->name);
925 if (filename != NULL)
926 strcpy(filename, p->name);
927 if (isdir != NULL)
928 *isdir = (p->attrFile & MC_ATTR_SUBDIR) ? TRUE : FALSE;
929 if (readonly != NULL)
930 *readonly = (p->attrFile & MC_ATTR_WRITEABLE) ? FALSE : TRUE; // XXX: MC_ATTR_PROTECTED ?
931 if (size != NULL)
932 *size = (int) (p->fileSizeByte);
933 if (timetext != NULL) {
934 // FIXME: adjust from GMT to local time
935 int hour = p->_modify.hour;
936 char ampm = 'a';
937 if (hour >= 12) {
938 hour -= 12;
939 ampm = 'p';
940 }
941 if (hour == 0)
942 hour = 12;
943 sprintf(timetext, "%2d-%02d-%02d %2d:%02d%c",
944 p->_modify.month, p->_modify.day, p->_modify.year % 100, hour, p->_modify.sec, ampm);
945 }
946 dir_i++;
947 return TRUE;
948 }
949
950 #ifdef SOUND
951
Sound_Initialise(int * argc,char * argv[])952 int Sound_Initialise(int *argc, char *argv[])
953 {
954 if (audsrv_init() != 0)
955 Log_print("failed to initialize audsrv: %s", audsrv_get_error_string());
956 else {
957 struct audsrv_fmt_t format;
958 format.bits = 8;
959 format.freq = 44100;
960 format.channels = 1;
961 audsrv_set_format(&format);
962 audsrv_set_volume(MAX_VOLUME);
963 POKEYSND_Init(POKEYSND_FREQ_17_EXACT, 44100, 1, 0);
964 }
965 return TRUE;
966 }
967
Sound_Exit(void)968 void Sound_Exit(void)
969 {
970 audsrv_quit();
971 }
972
Sound_Update(void)973 void Sound_Update(void)
974 {
975 static char buffer[44100 / 50];
976 unsigned int nsamples = (Atari800_tv_mode == Atari800_TV_NTSC) ? (44100 / 60) : (44100 / 50);
977 POKEYSND_Process(buffer, nsamples);
978 audsrv_wait_audio(nsamples);
979 audsrv_play_audio(buffer, nsamples);
980 }
981
Sound_Pause(void)982 void Sound_Pause(void)
983 {
984 audsrv_stop_audio();
985 }
986
Sound_Continue(void)987 void Sound_Continue(void)
988 {
989 if (audsrv_init() != 0)
990 Log_print("failed to initialize audsrv: %s", audsrv_get_error_string());
991 else {
992 struct audsrv_fmt_t format;
993 format.bits = 8;
994 format.freq = 44100;
995 format.channels = 1;
996 audsrv_set_format(&format);
997 audsrv_set_volume(MAX_VOLUME);
998 }
999 }
1000
1001 #endif /* SOUND */
1002
main(int argc,char ** argv)1003 int main(int argc, char **argv)
1004 {
1005 loadModules();
1006 /* initialise Atari800 core */
1007 if (!Atari800_Initialise(&argc, argv))
1008 return 3;
1009
1010 /* main loop */
1011 for (;;) {
1012 INPUT_key_code = PLATFORM_Keyboard();
1013 Atari800_Frame();
1014 if (Atari800_display_screen){
1015 PLATFORM_DisplayScreen();}
1016 }
1017 }
1018