initial commit

This commit is contained in:
R-type
2015-12-14 14:00:35 +01:00
commit 5a96c0ca66
377 changed files with 149124 additions and 0 deletions
+868
View File
@@ -0,0 +1,868 @@
/*
* atari_curses.c - Curses based port code
*
* Copyright (c) 1995-1998 David Firth
* Copyright (c) 1998-2014 Atari800 development team (see DOC/CREDITS)
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Atari800 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <string.h>
#ifdef USE_NCURSES
#include <ncurses.h>
#else
#include <curses.h>
#endif
#include "antic.h" /* ypos */
#include "atari.h"
#include "binload.h"
#include "gtia.h" /* GTIA_COLPFx */
#include "input.h"
#include "akey.h"
#include "log.h"
#include "monitor.h"
#include "platform.h"
#include "ui.h" /* UI_alt_function */
#ifdef SOUND
#include "sound.h"
#endif
#define CURSES_LEFT 0
#define CURSES_CENTRAL 1
#define CURSES_RIGHT 2
#define CURSES_WIDE_1 3
#define CURSES_WIDE_2 4
static int curses_mode = CURSES_LEFT;
static int curses_screen[24][40];
int PLATFORM_Initialise(int *argc, char *argv[])
{
int i;
int j;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-left") == 0)
curses_mode = CURSES_LEFT;
else if (strcmp(argv[i], "-central") == 0)
curses_mode = CURSES_CENTRAL;
else if (strcmp(argv[i], "-right") == 0)
curses_mode = CURSES_RIGHT;
else if (strcmp(argv[i], "-wide1") == 0)
curses_mode = CURSES_WIDE_1;
else if (strcmp(argv[i], "-wide2") == 0)
curses_mode = CURSES_WIDE_2;
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-central Center emulated screen\n"
"\t-left Align left\n"
"\t-right Align right (on 80 columns)\n"
"\t-wide1 Use 80 columns\n"
"\t-wide2 Use 80 columns, display twice"
);
}
argv[j++] = argv[i];
}
}
*argc = j;
initscr();
noecho();
cbreak(); /* Don't wait for carriage return */
keypad(stdscr, TRUE);
curs_set(0); /* Disable Cursor */
nodelay(stdscr, 1); /* Don't block for keypress */
#ifdef SOUND
if (!Sound_Initialise(argc, argv))
return FALSE;
#endif
return TRUE;
}
int PLATFORM_Exit(int run_monitor)
{
curs_set(1);
endwin();
Log_flushlog();
if (run_monitor && MONITOR_Run()) {
curs_set(0);
return TRUE;
}
return FALSE;
}
void curses_clear_screen(void)
{
int x;
int y;
for (y = 0; y < 24; y++)
for (x = 0; x < 40; x++)
curses_screen[y][x] = ' ';
}
void curses_clear_rectangle(int x1, int y1, int x2, int y2)
{
int x;
int y;
for (y = y1; y <= y2; y++)
for (x = x1; x <= x2; x++)
curses_screen[y][x] = ' ';
}
void curses_putch(int x, int y, int ascii, UBYTE fg, UBYTE bg)
{
/* handle line drawing chars */
switch (ascii) {
case 18:
ascii = '-';
break;
case 17:
case 3:
ascii = '/';
break;
case 26:
case 5:
ascii = '\\';
break;
case 124:
ascii = '|';
break;
default:
break;
}
if ((bg & 0xf) > (fg & 0xf))
curses_screen[y][x] = ascii + A_REVERSE;
else
curses_screen[y][x] = ascii;
}
void curses_display_line(int anticmode, const UBYTE *screendata)
{
int y;
int *p;
int w;
if (ANTIC_ypos < 32 || ANTIC_ypos >= 224)
return;
y = (ANTIC_ypos >> 3) - 4;
p = &(curses_screen[y][0]);
switch (anticmode) {
case 2:
case 3:
case 4:
case 5:
switch (ANTIC_DMACTL & 3) {
case 1:
p += 4;
w = 32;
break;
case 2:
w = 40;
break;
case 3:
screendata += 4;
w = 40;
break;
default:
return;
}
do {
static const int offset[8] = {
0x20, /* 0x00-0x1f: Numbers + !"$% etc. */
0x20, /* 0x20-0x3f: Upper Case Characters */
A_BOLD, /* 0x40-0x5f: Control Characters */
0, /* 0x60-0x7f: Lower Case Characters */
-0x80 + 0x20 + A_REVERSE, /* 0x80-0x9f: Numbers + !"$% etc. */
-0x80 + 0x20 + A_REVERSE, /* 0xa0-0xbf: Upper Case Characters */
-0x80 + A_BOLD + A_REVERSE, /* 0xc0-0xdf: Control Characters */
-0x80 + A_REVERSE /* 0xe0-0xff: Lower Case Characters */
};
UBYTE c = *screendata++;
/* PDCurses prints '\x7f' as "^?".
This causes problems if this is the last character in line.
Use bold '>' for Atari's Tab symbol (filled right-pointing triangle). */
if (c == 0x7f)
*p = '>' + A_BOLD;
else if (c == 0xff)
*p = '>' + A_BOLD + A_REVERSE;
else
*p = c + offset[c >> 5];
p++;
} while (--w);
break;
case 6:
case 7:
switch (ANTIC_DMACTL & 3) {
case 1:
p += 12;
w = 16;
break;
case 2:
p += 10;
w = 20;
break;
case 3:
p += 8;
w = 24;
break;
default:
return;
}
{
#define LIGHT_THRESHOLD 0x0c
int light[4];
light[0] = (GTIA_COLPF0 & 0x0e) >= LIGHT_THRESHOLD ? 0x20 + A_BOLD : 0x20;
light[1] = (GTIA_COLPF1 & 0x0e) >= LIGHT_THRESHOLD ? -0x40 + 0x20 + A_BOLD : -0x40 + 0x20;
light[2] = (GTIA_COLPF2 & 0x0e) >= LIGHT_THRESHOLD ? -0x80 + 0x20 + A_BOLD : -0x80 + 0x20;
light[3] = (GTIA_COLPF3 & 0x0e) >= LIGHT_THRESHOLD ? -0xc0 + 0x20 + A_BOLD : -0xc0 + 0x20;
do {
*p++ = *screendata + light[*screendata >> 6];
screendata++;
} while (--w);
}
break;
default:
break;
}
}
void PLATFORM_DisplayScreen(void)
{
int x;
int y;
for (y = 0; y < 24; y++) {
for (x = 0; x < 40; x++) {
int ch = curses_screen[y][x];
switch (curses_mode) {
default:
case CURSES_LEFT:
move(y, x);
break;
case CURSES_CENTRAL:
move(y, 20 + x);
break;
case CURSES_RIGHT:
move(y, 40 + x);
break;
case CURSES_WIDE_1:
move(y, x + x);
break;
case CURSES_WIDE_2:
move(y, x + x);
addch(ch);
ch = ' ' + (ch & A_REVERSE);
break;
}
addch(ch);
}
}
refresh();
}
int PLATFORM_Keyboard(void)
{
int keycode = getch();
#if 0
/* for debugging */
if (keycode > 0) {
Atari800_ErrExit();
printf("keycode == %d (0x%x)\n", keycode, keycode);
exit(1);
}
#endif
BINLOAD_pause_loading = FALSE;
INPUT_key_consol = INPUT_CONSOL_NONE;
switch (keycode) {
case 0x01:
keycode = AKEY_CTRL_a;
break;
case 0x02:
keycode = AKEY_CTRL_b;
break;
case 0x03 :
keycode = AKEY_CTRL_c;
break;
case 0x04:
keycode = AKEY_CTRL_d;
break;
case 0x05:
keycode = AKEY_CTRL_e;
break;
case 0x06:
keycode = AKEY_CTRL_f;
break;
case 0x07:
keycode = AKEY_CTRL_g;
break;
/*
case 0x08:
keycode = AKEY_CTRL_h;
break;
*/
case 0x09:
keycode = AKEY_TAB;
break;
/*
case 0x0a:
keycode = AKEY_CTRL_j;
break;
*/
case 0x0b:
keycode = AKEY_CTRL_k;
break;
case 0x0c:
keycode = AKEY_CTRL_l;
break;
/*
case 0x0d:
keycode = AKEY_CTRL_m;
break;
*/
case 0x0e:
keycode = AKEY_CTRL_n;
break;
case 0x0f:
keycode = AKEY_CTRL_o;
break;
case 0x10:
keycode = AKEY_CTRL_p;
break;
case 0x11:
keycode = AKEY_CTRL_q;
break;
case 0x12:
keycode = AKEY_CTRL_r;
break;
case 0x13:
keycode = AKEY_CTRL_s;
break;
case 0x14:
keycode = AKEY_CTRL_t;
break;
case 0x15:
keycode = AKEY_CTRL_u;
break;
case 0x16:
keycode = AKEY_CTRL_v;
break;
case 0x17:
keycode = AKEY_CTRL_w;
break;
case 0x18:
keycode = AKEY_CTRL_x;
break;
case 0x19:
keycode = AKEY_CTRL_y;
break;
case 0x1a:
keycode = AKEY_CTRL_z;
break;
case '`':
keycode = AKEY_CAPSTOGGLE;
break;
case '!':
keycode = AKEY_EXCLAMATION;
break;
case '"':
keycode = AKEY_DBLQUOTE;
break;
case '#':
keycode = AKEY_HASH;
break;
case '$':
keycode = AKEY_DOLLAR;
break;
case '%':
keycode = AKEY_PERCENT;
break;
case '&':
keycode = AKEY_AMPERSAND;
break;
case '\'':
keycode = AKEY_QUOTE;
break;
case '@':
keycode = AKEY_AT;
break;
case '(':
keycode = AKEY_PARENLEFT;
break;
case ')':
keycode = AKEY_PARENRIGHT;
break;
case '[':
keycode = AKEY_BRACKETLEFT;
break;
case ']':
keycode = AKEY_BRACKETRIGHT;
break;
case '<':
keycode = AKEY_LESS;
break;
case '>':
keycode = AKEY_GREATER;
break;
case '=':
keycode = AKEY_EQUAL;
break;
case '?':
keycode = AKEY_QUESTION;
break;
#ifdef PADMINUS
case PADMINUS:
#endif
case '-':
keycode = AKEY_MINUS;
break;
#ifdef PADPLUS
case PADPLUS:
#endif
case '+':
keycode = AKEY_PLUS;
break;
#ifdef PADSTAR
case PADSTAR:
#endif
case '*':
keycode = AKEY_ASTERISK;
break;
#ifdef PADSLASH
case PADSLASH:
#endif
case '/':
keycode = AKEY_SLASH;
break;
case ':':
keycode = AKEY_COLON;
break;
case ';':
keycode = AKEY_SEMICOLON;
break;
case ',':
keycode = AKEY_COMMA;
break;
case '.':
keycode = AKEY_FULLSTOP;
break;
case '_':
keycode = AKEY_UNDERSCORE;
break;
case '^':
keycode = AKEY_CIRCUMFLEX;
break;
case '\\':
keycode = AKEY_BACKSLASH;
break;
case '|':
keycode = AKEY_BAR;
break;
case ' ':
keycode = AKEY_SPACE;
break;
case '0':
keycode = AKEY_0;
break;
case '1':
keycode = AKEY_1;
break;
case '2':
keycode = AKEY_2;
break;
case '3':
keycode = AKEY_3;
break;
case '4':
keycode = AKEY_4;
break;
case '5':
keycode = AKEY_5;
break;
case '6':
keycode = AKEY_6;
break;
case '7':
keycode = AKEY_7;
break;
case '8':
keycode = AKEY_8;
break;
case '9':
keycode = AKEY_9;
break;
case 'a':
keycode = AKEY_a;
break;
case 'b':
keycode = AKEY_b;
break;
case 'c':
keycode = AKEY_c;
break;
case 'd':
keycode = AKEY_d;
break;
case 'e':
keycode = AKEY_e;
break;
case 'f':
keycode = AKEY_f;
break;
case 'g':
keycode = AKEY_g;
break;
case 'h':
keycode = AKEY_h;
break;
case 'i':
keycode = AKEY_i;
break;
case 'j':
keycode = AKEY_j;
break;
case 'k':
keycode = AKEY_k;
break;
case 'l':
keycode = AKEY_l;
break;
case 'm':
keycode = AKEY_m;
break;
case 'n':
keycode = AKEY_n;
break;
case 'o':
keycode = AKEY_o;
break;
case 'p':
keycode = AKEY_p;
break;
case 'q':
keycode = AKEY_q;
break;
case 'r':
keycode = AKEY_r;
break;
case 's':
keycode = AKEY_s;
break;
case 't':
keycode = AKEY_t;
break;
case 'u':
keycode = AKEY_u;
break;
case 'v':
keycode = AKEY_v;
break;
case 'w':
keycode = AKEY_w;
break;
case 'x':
keycode = AKEY_x;
break;
case 'y':
keycode = AKEY_y;
break;
case 'z':
keycode = AKEY_z;
break;
case 'A':
keycode = AKEY_A;
break;
case 'B':
keycode = AKEY_B;
break;
case 'C':
keycode = AKEY_C;
break;
case 'D':
keycode = AKEY_D;
break;
case 'E':
keycode = AKEY_E;
break;
case 'F':
keycode = AKEY_F;
break;
case 'G':
keycode = AKEY_G;
break;
case 'H':
keycode = AKEY_H;
break;
case 'I':
keycode = AKEY_I;
break;
case 'J':
keycode = AKEY_J;
break;
case 'K':
keycode = AKEY_K;
break;
case 'L':
keycode = AKEY_L;
break;
case 'M':
keycode = AKEY_M;
break;
case 'N':
keycode = AKEY_N;
break;
case 'O':
keycode = AKEY_O;
break;
case 'P':
keycode = AKEY_P;
break;
case 'Q':
keycode = AKEY_Q;
break;
case 'R':
keycode = AKEY_R;
break;
case 'S':
keycode = AKEY_S;
break;
case 'T':
keycode = AKEY_T;
break;
case 'U':
keycode = AKEY_U;
break;
case 'V':
keycode = AKEY_V;
break;
case 'W':
keycode = AKEY_W;
break;
case 'X':
keycode = AKEY_X;
break;
case 'Y':
keycode = AKEY_Y;
break;
case 'Z':
keycode = AKEY_Z;
break;
case 0x1b:
keycode = AKEY_ESCAPE;
break;
case KEY_F0 + 1:
keycode = AKEY_UI;
break;
case KEY_F0 + 2:
INPUT_key_consol &= ~INPUT_CONSOL_OPTION;
keycode = AKEY_NONE;
break;
case KEY_F0 + 3:
INPUT_key_consol &= ~INPUT_CONSOL_SELECT;
keycode = AKEY_NONE;
break;
case KEY_F0 + 4:
INPUT_key_consol &= ~INPUT_CONSOL_START;
keycode = AKEY_NONE;
break;
case KEY_F0 + 5:
keycode = AKEY_WARMSTART;
break;
#ifdef KEY_HELP
case KEY_HELP:
#endif
#ifdef KEY_SHELP
case KEY_SHELP:
#endif
#ifdef KEY_LHELP
case KEY_LHELP:
#endif
case KEY_F0 + 6:
keycode = AKEY_HELP;
break;
#ifdef KEY_BREAK
case KEY_BREAK:
#endif
case KEY_F0 + 7:
if (BINLOAD_wait_active) {
BINLOAD_pause_loading = TRUE;
keycode = AKEY_NONE;
}
else
keycode = AKEY_BREAK;
break;
case KEY_F0 + 8:
keycode = PLATFORM_Exit(TRUE) ? AKEY_NONE : AKEY_EXIT;
break;
case KEY_F0 + 9:
keycode = AKEY_EXIT;
break;
case KEY_F0 + 10:
keycode = AKEY_SCREENSHOT;
break;
case KEY_DOWN:
keycode = AKEY_DOWN;
break;
case KEY_LEFT:
keycode = AKEY_LEFT;
break;
case KEY_RIGHT:
keycode = AKEY_RIGHT;
break;
case KEY_UP:
keycode = AKEY_UP;
break;
case 8:
case 127:
#ifdef KEY_BACKSPACE
# if KEY_BACKSPACE != 8 && KEY_BACKSPACE != 127
case KEY_BACKSPACE:
# endif
#endif
keycode = AKEY_BACKSPACE;
break;
#ifdef PADENTER
case PADENTER:
#endif
case KEY_ENTER:
case '\n':
keycode = AKEY_RETURN;
break;
#ifdef KEY_HOME
case KEY_HOME:
keycode = AKEY_CLEAR;
break;
#endif
#ifdef KEY_CLEAR
case KEY_CLEAR:
keycode = AKEY_CLEAR;
break;
#endif
#ifdef KEY_IC
case KEY_IC:
keycode = AKEY_INSERT_CHAR;
break;
#endif
#ifdef KEY_IL
case KEY_IL:
keycode = AKEY_INSERT_LINE;
break;
#endif
#ifdef KEY_DC
case KEY_DC:
keycode = AKEY_DELETE_CHAR;
break;
#endif
#ifdef KEY_DL
case KEY_DL:
keycode = AKEY_DELETE_LINE;
break;
#endif
#ifdef KEY_STAB
case KEY_STAB:
keycode = AKEY_SETTAB;
break;
#endif
#ifdef KEY_CTAB
case KEY_CTAB:
keycode = AKEY_CLRTAB;
break;
#endif
#ifdef ALT_A
/* PDCurses specific */
case ALT_A:
UI_alt_function = UI_MENU_ABOUT;
keycode = AKEY_UI;
break;
case ALT_C:
UI_alt_function = UI_MENU_CARTRIDGE;
keycode = AKEY_UI;
break;
case ALT_D:
UI_alt_function = UI_MENU_DISK;
keycode = AKEY_UI;
break;
case ALT_L:
UI_alt_function = UI_MENU_LOADSTATE;
keycode = AKEY_UI;
break;
case ALT_O:
UI_alt_function = UI_MENU_SOUND;
keycode = AKEY_UI;
break;
case ALT_R:
UI_alt_function = UI_MENU_RUN;
keycode = AKEY_UI;
break;
case ALT_S:
UI_alt_function = UI_MENU_SAVESTATE;
keycode = AKEY_UI;
break;
case ALT_T:
UI_alt_function = UI_MENU_CASSETTE;
keycode = AKEY_UI;
break;
case ALT_W:
UI_alt_function = UI_MENU_SOUND_RECORDING;
keycode = AKEY_UI;
break;
case ALT_Y:
UI_alt_function = UI_MENU_SYSTEM;
keycode = AKEY_UI;
break;
#endif
default:
keycode = AKEY_NONE;
break;
}
return keycode;
}
int PLATFORM_PORT(int num)
{
return 0xff;
}
int PLATFORM_TRIG(int num)
{
return 1;
}
int main(int argc, char **argv)
{
/* initialise Atari800 core */
if (!Atari800_Initialise(&argc, argv))
return 3;
/* main loop */
for (;;) {
INPUT_key_code = PLATFORM_Keyboard();
Atari800_Frame();
if (Atari800_display_screen)
PLATFORM_DisplayScreen();
}
}