mirror of
https://github.com/StewBC/cc65-Chess.git
synced 2024-06-09 07:29:36 +00:00
c08a759404
Made the old C64 version C64.chr and created a new graphical interface version for the C64 and the Commander X16. Also changed the Oric to be called the atmos since that works better with the build system.
402 lines
8.8 KiB
C
402 lines
8.8 KiB
C
/*
|
|
* platTerm.c
|
|
* cc65 Chess
|
|
*
|
|
* Created by Stefan Wessels, February 2014.
|
|
*
|
|
*/
|
|
|
|
#include <curses.h>
|
|
#include <string.h>
|
|
#include <sys/time.h>
|
|
#include "types.h"
|
|
#include "globals.h"
|
|
#include "undo.h"
|
|
#include "frontend.h"
|
|
#include "plat.h"
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Internal function Prototype
|
|
char plat_TimeExpired(unsigned int aTime);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// These are read from the curses library but I assume at least 24 rows
|
|
// and 55 cols
|
|
int SCREEN_HEIGHT, SCREEN_WIDTH;
|
|
int LOG_WINDOW_HEIGHT;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
#define SCROLL_SPEED 150000
|
|
#define BOARD_PIECE_WIDTH 6
|
|
#define BOARD_PIECE_HEIGHT 3
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Names of the pieces NONE, Rook, knight, Bishop, Queen, King, pawn
|
|
static const char sc_pieces[] = {'\0','R','k','B','Q','K','p'};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_Init()
|
|
{
|
|
// Curses init
|
|
initscr();
|
|
intrflush(stdscr, FALSE);
|
|
keypad(stdscr, TRUE);
|
|
nonl();
|
|
cbreak();
|
|
noecho();
|
|
timeout(0);
|
|
curs_set(0);
|
|
getmaxyx(stdscr, SCREEN_HEIGHT, SCREEN_WIDTH) ;
|
|
LOG_WINDOW_HEIGHT = SCREEN_HEIGHT - 2;
|
|
|
|
if(has_colors() != FALSE)
|
|
{
|
|
start_color();
|
|
assume_default_colors(COLOR_WHITE, COLOR_BLACK);
|
|
init_pair(1, COLOR_BLACK, COLOR_YELLOW);
|
|
init_pair(2, COLOR_WHITE, COLOR_BLACK);
|
|
init_pair(3, COLOR_GREEN, COLOR_BLACK);
|
|
init_pair(4, COLOR_RED, COLOR_BLACK);
|
|
init_pair(5, COLOR_CYAN, COLOR_BLACK);
|
|
init_pair(6, COLOR_BLUE, COLOR_BLACK);
|
|
init_pair(7, COLOR_WHITE, COLOR_WHITE);
|
|
init_pair(8, COLOR_BLACK, COLOR_BLACK);
|
|
}
|
|
|
|
// Setting this to 0 will not show the "Quit" option in the main menu
|
|
gReturnToOS = 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_UpdateScreen()
|
|
{
|
|
refresh();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Very simple menu with a heading and a scrolling banner as a footer
|
|
char plat_Menu(char **menuItems, char height, char *scroller)
|
|
{
|
|
static char *prevScroller, *pScroller;
|
|
char *pEnd;
|
|
int keyMask;
|
|
char i, j, sx, sy, numMenuItems, maxLen = 0;
|
|
|
|
if(prevScroller != scroller)
|
|
{
|
|
prevScroller = scroller;
|
|
pScroller = scroller;
|
|
}
|
|
pEnd = scroller + strlen(scroller);
|
|
|
|
for(numMenuItems=0; menuItems[numMenuItems]; ++numMenuItems)
|
|
{
|
|
char len = strlen(menuItems[numMenuItems]);
|
|
if(len > maxLen)
|
|
maxLen = len;
|
|
}
|
|
sy = MAX_SIZE(0, ((8*BOARD_PIECE_HEIGHT) / 2) - (height / 2) - 1);
|
|
sx = MAX_SIZE(0, ((8*BOARD_PIECE_WIDTH) / 2) - (maxLen / 2) - 1);
|
|
maxLen = MIN_SIZE((8*BOARD_PIECE_WIDTH)-2, maxLen);
|
|
|
|
color_set(3,0);
|
|
move(sy,sx);
|
|
printw(" %.*s ",maxLen, menuItems[0]);
|
|
color_set(1,0);
|
|
move(++sy, sx);
|
|
for(j=0; j<maxLen+2; ++j)
|
|
printw(" ");
|
|
|
|
for(i=1; i<numMenuItems; ++i)
|
|
{
|
|
move(sy+i, sx);
|
|
printw(" %.*s ",maxLen, menuItems[i]);
|
|
}
|
|
|
|
for(;i<height;++i)
|
|
{
|
|
move(sy+i, sx);
|
|
for(j=0; j<maxLen+2; ++j)
|
|
printw(" ");
|
|
}
|
|
|
|
i = 1;
|
|
do
|
|
{
|
|
move(sy+i,sx);
|
|
attron(WA_REVERSE);
|
|
color_set(2,0);
|
|
printw(">%.*s<",maxLen, menuItems[i]);
|
|
attroff(WA_REVERSE);
|
|
color_set(1,0);
|
|
keyMask = plat_ReadKeys(0);
|
|
if(keyMask & INPUT_MOTION)
|
|
{
|
|
move(sy+i,sx);
|
|
printw(" %.*s ",maxLen, menuItems[i]);
|
|
switch(keyMask & INPUT_MOTION)
|
|
{
|
|
case INPUT_UP:
|
|
if(!--i)
|
|
i = numMenuItems-1;
|
|
break;
|
|
|
|
case INPUT_DOWN:
|
|
if(numMenuItems == ++i)
|
|
i = 1;
|
|
break;
|
|
}
|
|
}
|
|
keyMask &= (INPUT_SELECT | INPUT_BACKUP);
|
|
|
|
move(sy+height,sx);
|
|
color_set(5,0);
|
|
printw(" %.*s ",maxLen, pScroller);
|
|
if((pEnd - pScroller) < maxLen-1)
|
|
{
|
|
move(sy+height,sx+(pEnd-pScroller)+1);
|
|
printw(" %.*s ",maxLen-(pEnd - pScroller)-1, scroller);
|
|
}
|
|
|
|
if(plat_TimeExpired(SCROLL_SPEED))
|
|
{
|
|
++pScroller;
|
|
if(!*pScroller)
|
|
pScroller = scroller;
|
|
}
|
|
} while(keyMask != INPUT_SELECT && keyMask != INPUT_BACKUP);
|
|
|
|
if(keyMask & INPUT_BACKUP)
|
|
return 0;
|
|
|
|
return i;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_DrawBoard(char clearLog)
|
|
{
|
|
char i;
|
|
|
|
if(clearLog)
|
|
erase();
|
|
|
|
for(i=0; i<64; ++i)
|
|
plat_DrawSquare(i);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_DrawSquare(char position)
|
|
{
|
|
char piece, color, dx, dy;
|
|
char y = position / 8, x = position & 7;
|
|
char blackWhite = !((x & 1) ^ (y & 1));
|
|
|
|
if(blackWhite)
|
|
color = 7;
|
|
else
|
|
color = 8;
|
|
|
|
for(dy=0; dy<BOARD_PIECE_HEIGHT; ++dy)
|
|
{
|
|
for(dx=0; dx<BOARD_PIECE_WIDTH; ++dx)
|
|
{
|
|
move(dy+y*BOARD_PIECE_HEIGHT,dx+x*BOARD_PIECE_WIDTH);
|
|
color_set(color,0);
|
|
printw(" ");
|
|
}
|
|
}
|
|
|
|
// Show the attack numbers
|
|
if(gShowAttackBoard)
|
|
{
|
|
color_set(1, 0);
|
|
move(y*BOARD_PIECE_HEIGHT+2, x*BOARD_PIECE_WIDTH);
|
|
printw("%d",(gpAttackBoard[giAttackBoardOffset[position][0]]));
|
|
color_set(2,0);
|
|
move(y*BOARD_PIECE_HEIGHT+2, x*BOARD_PIECE_WIDTH+5);
|
|
printw("%d",(gpAttackBoard[giAttackBoardOffset[position][1]]));
|
|
move(y*BOARD_PIECE_HEIGHT, x*BOARD_PIECE_WIDTH);
|
|
printw("%02X",gChessBoard[y][x]);
|
|
move(y*BOARD_PIECE_HEIGHT, x*BOARD_PIECE_WIDTH+5);
|
|
printw("%d",(gChessBoard[y][x]&PIECE_WHITE)>>7);
|
|
}
|
|
|
|
piece = gChessBoard[y][x];
|
|
color = piece & PIECE_WHITE;
|
|
piece &= PIECE_DATA;
|
|
|
|
if(piece)
|
|
{
|
|
move(y*BOARD_PIECE_HEIGHT+(BOARD_PIECE_HEIGHT/2),x*BOARD_PIECE_WIDTH+(BOARD_PIECE_WIDTH/2));
|
|
color_set(color?2:1,0);
|
|
printw("%c",sc_pieces[piece]);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_ShowSideToGoLabel(char side)
|
|
{
|
|
move(0, 2+8*BOARD_PIECE_WIDTH);
|
|
color_set(side?2:1, 0);
|
|
printw("%s",gszSideLabel[side]);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_Highlight(char position, char color, char cursor)
|
|
{
|
|
char y = (BOARD_PIECE_HEIGHT/2)+1+BOARD_PIECE_HEIGHT*((position / 8)), x = (BOARD_PIECE_WIDTH/2)+BOARD_PIECE_WIDTH*((position & 7));
|
|
move(y,x);
|
|
color_set(color,0);
|
|
printw(cursor?"*":"!");
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_ShowMessage(char *str, char color)
|
|
{
|
|
move((8*BOARD_PIECE_HEIGHT)-1, 1+(8*BOARD_PIECE_WIDTH));
|
|
color_set(color,0);
|
|
printw("%.*s",SCREEN_WIDTH-1-(8*BOARD_PIECE_WIDTH),str);
|
|
clrtoeol();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_ClearMessage()
|
|
{
|
|
move((8*BOARD_PIECE_HEIGHT)-1, 1+(8*BOARD_PIECE_WIDTH));
|
|
clrtoeol();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// This function can/will change the gTile and related global variables so
|
|
// caution is needed
|
|
void plat_AddToLogWin()
|
|
{
|
|
char bot = (8*BOARD_PIECE_HEIGHT)-2, y = 1, x = 1+(8*BOARD_PIECE_WIDTH);
|
|
|
|
for(; y<=bot; ++y)
|
|
{
|
|
move(y, x);
|
|
if(undo_FindUndoLine(bot-y))
|
|
{
|
|
frontend_FormatLogString();
|
|
color_set(gColor[0]+1,0);
|
|
printw("%.*s",SCREEN_WIDTH-1-x,gLogStrBuffer);
|
|
}
|
|
clrtoeol();
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_AddToLogWinTop()
|
|
{
|
|
plat_AddToLogWin();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
char plat_TimeExpired(unsigned int aTime)
|
|
{
|
|
static struct timeval sst_store;
|
|
static int si_init = 0;
|
|
struct timeval now;
|
|
gettimeofday(&now, NULL);
|
|
if(!si_init || (MAX_SIZE(now.tv_usec,sst_store.tv_usec) - MIN_SIZE(now.tv_usec,sst_store.tv_usec) > SCROLL_SPEED))
|
|
{
|
|
si_init = 1;
|
|
sst_store = now;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int plat_ReadKeys(char blocking)
|
|
{
|
|
char key = 0;
|
|
int keyMask = 0;
|
|
|
|
if(blocking)
|
|
{
|
|
timeout(-1) ;
|
|
key = getch();
|
|
timeout(0);
|
|
}
|
|
else
|
|
{
|
|
key = getch();
|
|
}
|
|
|
|
switch(key)
|
|
{
|
|
case 3: // Up
|
|
keyMask |= INPUT_UP;
|
|
break;
|
|
|
|
case 5: // Right
|
|
keyMask |= INPUT_RIGHT;
|
|
break;
|
|
|
|
case 2: // Down
|
|
keyMask |= INPUT_DOWN;
|
|
break;
|
|
|
|
case 4: // Left
|
|
keyMask |= INPUT_LEFT;
|
|
break;
|
|
|
|
case 27: // Esc
|
|
keyMask |= INPUT_BACKUP;
|
|
break;
|
|
|
|
case 'a': // 'a' - Show Attackers
|
|
keyMask |= INPUT_TOGGLE_A;
|
|
break;
|
|
|
|
case 'b': // 'b' - Board attacks - Show all attacks
|
|
keyMask |= INPUT_TOGGLE_B;
|
|
break;
|
|
|
|
case 'd': // 'd' - Show Defenders
|
|
keyMask |= INPUT_TOGGLE_D;
|
|
break;
|
|
|
|
case 'm': // 'm' - Menu
|
|
keyMask |= INPUT_MENU;
|
|
break;
|
|
|
|
case 13: // Enter
|
|
keyMask |= INPUT_SELECT;
|
|
break;
|
|
|
|
case 'r':
|
|
keyMask |= INPUT_REDO;
|
|
break;
|
|
|
|
case 'u':
|
|
keyMask |= INPUT_UNDO;
|
|
break;
|
|
|
|
// default: // Debug - show key code
|
|
// {
|
|
// char s[] = "Key:000";
|
|
// if(key != 255)
|
|
// {
|
|
// s[4] = (key/100)+'0';
|
|
// key -= (s[4] - '0') * 100;
|
|
// s[5] = (key/10)+'0';
|
|
// s[6] = (key%10)+'0';
|
|
// plat_ShowMessage(s,COLOR_RED);
|
|
// }
|
|
// refresh();
|
|
// }
|
|
// break;
|
|
}
|
|
|
|
return keyMask;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_Shutdown()
|
|
{
|
|
endwin();
|
|
}
|