632 lines
16 KiB
C
632 lines
16 KiB
C
/*
|
|
* plat64.c
|
|
* cc65 Chess
|
|
*
|
|
* Created by Stefan Wessels, February 2014.
|
|
*
|
|
*/
|
|
|
|
/*-----------------------------------------------------------------------*\
|
|
* I really wanted to use the Commander X16 built-in APIs (GRAPH in
|
|
* particular) and for the most part I did. I did end up using conio
|
|
* for text though, as the menu system is set up for monospace fonts and
|
|
* I wasn't getting what I wanted from the CONSOLE api, although I
|
|
* probably could have, had I tried a bit harder. Conio has curso issues
|
|
* which I think will go away with revisions. Also, clrscr() in conio
|
|
* doesn't play nice with the GRAPH api. The FRAMEBUFFER api was a
|
|
* better fit for drawing the pieces, so I used that. I tried to do as
|
|
* much as possible in "C" but this does mean I rely on the generated "C"
|
|
* code ending with a result in .a, for example, in places which may
|
|
* change. All in all, I am still quite pleased with how easy it is to
|
|
* mix assembly code and "C" code in cc65.
|
|
\*-----------------------------------------------------------------------*/
|
|
|
|
#include <cx16.h>
|
|
#include <stdio.h>
|
|
#include <conio.h>
|
|
#include <string.h>
|
|
#include "../types.h"
|
|
#include "../globals.h"
|
|
#include "../undo.h"
|
|
#include "../frontend.h"
|
|
#include "../plat.h"
|
|
#include "dataCX16.h"
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// System locations
|
|
struct __cx16regs
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
char r0l;
|
|
char r0h;
|
|
char r1l;
|
|
char r1h;
|
|
char r2l;
|
|
char r2h;
|
|
char r3l;
|
|
char r3h;
|
|
char r4l;
|
|
char r4h;
|
|
char r5l;
|
|
char r5h;
|
|
char r6l;
|
|
char r6h;
|
|
char r7l;
|
|
char r7h;
|
|
char r8l;
|
|
char r8h;
|
|
char r9l;
|
|
char r9h;
|
|
char r10l;
|
|
char r10h;
|
|
char r11l;
|
|
char r11h;
|
|
char r12l;
|
|
char r12h;
|
|
char r13l;
|
|
char r13h;
|
|
char r14l;
|
|
char r14h;
|
|
char r15l;
|
|
char r15h;
|
|
} ;
|
|
unsigned int r[16];
|
|
};
|
|
};
|
|
|
|
#define REG16 (*(struct __cx16regs*)0x02)
|
|
#define jiffyTime ((char*)0xA039)
|
|
#define CURS_FLAG ((char*)0x037B)
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
#define BOARD_PIECE_WIDTH 4
|
|
#define BOARD_PIECE_HEIGHT 3
|
|
#define SCREEN_WIDTH 40
|
|
#define SCREEN_HEIGHT 25
|
|
#define SCROLL_SPEED 0x0A
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Internal function Prototype
|
|
char plat_TimeExpired(unsigned int aTime, char *timerInit);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Can't use clrscr as it clears both layers
|
|
void clearTextLayer(int x, int y, int w, int h)
|
|
{
|
|
int sx, sw;
|
|
unsigned long offset = 0x1B000 + y * 256; // lines have a stride of 256
|
|
|
|
// Double width for characters - character then color
|
|
x *= 2;
|
|
offset += x;
|
|
sx = x;
|
|
w = w * 2;
|
|
sw = x + w;
|
|
h += y;
|
|
|
|
for(; y < h; y++)
|
|
{
|
|
x = sx;
|
|
for(; x < sw; x+=2)
|
|
{
|
|
vpoke(32, offset++);
|
|
vpoke(0, offset++);
|
|
}
|
|
// Skip to the start of the next area to fill
|
|
offset += 256 - w;
|
|
}
|
|
// long i;
|
|
// for(i=0x1B000; i < 0x1EBFF; i+=2) {
|
|
// vpoke(32,i);
|
|
// vpoke(0,i+1);
|
|
// }
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Get the colors into .a .x & .y for the GRAPH function
|
|
void plat_setColors(char stroke, char fill, char)
|
|
{
|
|
__asm__("sta tmp1");
|
|
__asm__("ldy #%o", fill);
|
|
__asm__("lda (sp), y");
|
|
__asm__("tax");
|
|
__asm__("ldy #%o", stroke);
|
|
__asm__("lda (sp), y");
|
|
__asm__("ldy tmp1");
|
|
__asm__("jsr GRAPH_SET_COLORS");
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Draw a rectangle using the GRAPH api
|
|
void plat_gfxFill(char stroke, char back, char x, char y, char w, char h)
|
|
{
|
|
plat_setColors(stroke, stroke, back);
|
|
|
|
REG16.r[0] = x * 8;
|
|
REG16.r[1] = y * 8;
|
|
REG16.r[2] = w * 8;
|
|
REG16.r[3] = h * 8;
|
|
REG16.r[4] = 0;
|
|
|
|
__asm__("sec");
|
|
__asm__("jsr GRAPH_DRAW_RECT");
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Use conio for text - the GRAPH text is non-proportional and the CONSOLE
|
|
// font is also taler than 8. This is just easier
|
|
void plat_showStrXY(char fore, char back, char x, char y, char* str)
|
|
{
|
|
textcolor(fore);
|
|
bgcolor(back);
|
|
gotoxy(x,y);
|
|
cputs(str);
|
|
// Something messes up the cursor but this seems to work to
|
|
// keep it hidden
|
|
*CURS_FLAG = 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Use the frameBuffer API to draw the pieces. The GRAPH api
|
|
// uses bytes/pixel and this is bits/pixel
|
|
void plat_showPiece(char color, char x, char y, const char *src)
|
|
{
|
|
static unsigned char xColor;
|
|
char row, col, i, c;
|
|
|
|
// put the color somewhere safe
|
|
__asm__("ldy #%o", color);
|
|
__asm__("lda (sp), y");
|
|
__asm__("sta %v", xColor);
|
|
|
|
// do the 24 rows
|
|
for(row = i = 0; row < 24; row++)
|
|
{
|
|
REG16.r[0] = x * 8;
|
|
REG16.r[1] = row + y * 8;
|
|
__asm__("jsr FB_CURSOR_POSITION");
|
|
|
|
// and a width of 4 bytes (32 bits / piece)
|
|
for(col = 0; col < 4; i++, col++)
|
|
{
|
|
c = src[i];
|
|
__asm__("ldx %v", xColor);
|
|
__asm__("jsr FB_SET_8_PIXELS");
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Local storage
|
|
static char sc_vm; // the existing video mode for quitting
|
|
char textStr[41]; // All visible text goes through here
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Called one-time to set up the platform (or computer or whatever)
|
|
void plat_Init()
|
|
{
|
|
// Setting this to 0 will not show the "Quit" option in the main menu
|
|
gReturnToOS = 1;
|
|
|
|
// Map bank 0 in
|
|
VIA1.pra = 0;
|
|
|
|
// Video mode and graphics init
|
|
sc_vm = videomode(VIDEOMODE_320x240) ;
|
|
clearTextLayer(0, 0, 40, 25);
|
|
plat_setColors(COLOR_WHITE, COLOR_WHITE, COLOR_GREEN);
|
|
__asm__("jsr GRAPH_CLEAR");
|
|
|
|
// Force full-screen. Scale is a bit whacky but I really don't like the balck bar at the bottom
|
|
VERA.control = 2;
|
|
VERA.display.hstart = 0;
|
|
VERA.display.hstop = 640 / 4;
|
|
VERA.display.vstart = 0;
|
|
VERA.display.vstop = 480/2;
|
|
VERA.control = 0;
|
|
VERA.display.vscale = 53;
|
|
|
|
// Show the welcome text
|
|
strcpy(textStr, "Commander X16 version, May 2020.");
|
|
plat_showStrXY(COLOR_YELLOW, COLOR_GREEN, 2,SCREEN_HEIGHT/2-1, gszAbout);
|
|
plat_showStrXY(COLOR_YELLOW, COLOR_GREEN, 4,SCREEN_HEIGHT/2+1,textStr);
|
|
|
|
// Show the welcome kings (black and white, solid versions)
|
|
plat_showPiece(COLOR_BLACK, SCREEN_WIDTH/2 - 1, SCREEN_HEIGHT/2 - 6, gfxTiles[KING-1][1]);
|
|
plat_showPiece(COLOR_WHITE, SCREEN_WIDTH/2 - 1, SCREEN_HEIGHT/2 + 4, gfxTiles[KING-1][1]);
|
|
|
|
plat_ReadKeys(1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// This is not needed on the CX16
|
|
void plat_UpdateScreen()
|
|
{
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// 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, *pEnd;
|
|
int keyMask;
|
|
char i, sx, sy, numMenuItems, timerInit = 0, maxLen = 0;
|
|
|
|
// If the scroller message chages, cache the new one
|
|
if(prevScroller != scroller)
|
|
{
|
|
prevScroller = scroller;
|
|
pScroller = scroller;
|
|
pEnd = scroller + strlen(scroller);
|
|
}
|
|
|
|
// Find the longest entry
|
|
for(numMenuItems=0; menuItems[numMenuItems]; ++numMenuItems)
|
|
{
|
|
char len = strlen(menuItems[numMenuItems]);
|
|
if(len > maxLen)
|
|
maxLen = len;
|
|
}
|
|
|
|
// Centre on the screen
|
|
sy = MAX_SIZE(0, (SCREEN_HEIGHT / 2) - (height / 2) - 1);
|
|
sx = MAX_SIZE(0, (SCREEN_WIDTH / 2) - (maxLen / 2) - 1);
|
|
maxLen = MIN_SIZE(SCREEN_WIDTH-2, maxLen);
|
|
|
|
// Draw a frame for the menu
|
|
sprintf(textStr, "%-*s", maxLen+4," ");
|
|
plat_showStrXY(COLOR_YELLOW, COLOR_YELLOW, sx-1, sy-1, textStr);
|
|
plat_showStrXY(COLOR_YELLOW, COLOR_YELLOW, sx-1, sy+height+2, textStr);
|
|
*(textStr + 1) = '\0';
|
|
for(i = 0; i < height + 2; i++)
|
|
{
|
|
plat_showStrXY(COLOR_YELLOW, COLOR_YELLOW, sx-1, sy+i, textStr);
|
|
plat_showStrXY(COLOR_YELLOW, COLOR_YELLOW, sx+maxLen+2, sy+i, textStr);
|
|
}
|
|
|
|
// Show the title
|
|
sprintf(textStr, " %.*s ",38, menuItems[0]);
|
|
plat_showStrXY(COLOR_YELLOW, COLOR_BLUE, sx, sy, textStr);
|
|
|
|
// Leave a blank line
|
|
sprintf(textStr, "%-*s", maxLen+2," ");
|
|
plat_showStrXY(COLOR_WHITE, COLOR_BLUE, sx, ++sy, textStr);
|
|
|
|
// Show all the menu items
|
|
for(i=1; i<numMenuItems; ++i)
|
|
{
|
|
sprintf(textStr, " %.*s ",maxLen, menuItems[i]);
|
|
plat_showStrXY(COLOR_GRAY2, COLOR_BLUE, sx, sy+i, textStr);
|
|
}
|
|
|
|
// Pad with blank lines to menu height
|
|
for(;i<height;++i)
|
|
{
|
|
sprintf(textStr, "%-*s", maxLen+2," ");
|
|
plat_showStrXY(COLOR_WHITE, COLOR_BLUE, sx, sy+i, textStr);
|
|
}
|
|
|
|
// Select the first item
|
|
i = 1;
|
|
do
|
|
{
|
|
// Highlight the selected item
|
|
sprintf(textStr, ">%.*s<",maxLen, menuItems[i]);
|
|
plat_showStrXY(COLOR_WHITE, COLOR_BLUE, sx, sy+i, textStr);
|
|
|
|
// Look for user input
|
|
keyMask = plat_ReadKeys(0);
|
|
|
|
if(keyMask & INPUT_MOTION)
|
|
{
|
|
// selection changes so de-highlight the selected item
|
|
sprintf(textStr, " %.*s ",maxLen, menuItems[i]);
|
|
plat_showStrXY(COLOR_GRAY2, COLOR_BLUE, sx, sy+i, textStr);
|
|
|
|
// see if the selection goes up or down
|
|
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);
|
|
|
|
// Show the scroller
|
|
sprintf(textStr, " %.*s ",maxLen, pScroller);
|
|
plat_showStrXY(COLOR_WHITE, COLOR_GREEN, sx, sy+height, textStr);
|
|
|
|
// Wrap the message if needed
|
|
if((pEnd - pScroller) < maxLen-1)
|
|
{
|
|
sprintf(textStr, " %.*s ",maxLen-(pEnd - pScroller)-1, scroller);
|
|
plat_showStrXY(COLOR_WHITE, COLOR_GREEN, sx+(pEnd-pScroller)+1, sy+height, textStr);
|
|
}
|
|
|
|
// Only update the scrolling when needed
|
|
if(plat_TimeExpired(SCROLL_SPEED, &timerInit))
|
|
{
|
|
++pScroller;
|
|
if(!*pScroller)
|
|
pScroller = scroller;
|
|
}
|
|
} while(keyMask != INPUT_SELECT && keyMask != INPUT_BACKUP);
|
|
|
|
// if backing out of the menu, return 0
|
|
if(keyMask & INPUT_BACKUP)
|
|
return 0;
|
|
|
|
// return the selection
|
|
return i;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Draw the chess board and possibly clear the log section
|
|
void plat_DrawBoard(char clearLog)
|
|
{
|
|
char i, c;
|
|
|
|
clearTextLayer(0, 0, 40, 25);
|
|
|
|
if(clearLog)
|
|
{
|
|
// Clear the log area pixels and color to green
|
|
plat_gfxFill(COLOR_GREEN,COLOR_GREEN,33,0,7,25);
|
|
}
|
|
|
|
plat_setColors(COLOR_WHITE, COLOR_GREEN, COLOR_GREEN);
|
|
// $12: ATTRIBUTES: REVERSE so white text shows up on green
|
|
__asm__("lda #$12");
|
|
__asm__("jsr GRAPH_PUT_CHAR");
|
|
|
|
// Add the A..H and 1..8 tile-keys before the board since the font draws taller than 8 pixels
|
|
for(i=0; i<8; ++i)
|
|
{
|
|
// Put this into the graphics layer as it's part of the board
|
|
REG16.r[0] = 20 + (i * 32);
|
|
REG16.r[1] = 6;
|
|
c = 'A'+i;
|
|
__asm__("jsr GRAPH_PUT_CHAR");
|
|
|
|
REG16.r[0] = 0;
|
|
REG16.r[1] = 24 + (i * 24);
|
|
c = '0'+(8-i);
|
|
__asm__("jsr GRAPH_PUT_CHAR");
|
|
}
|
|
|
|
// redraw all tiles
|
|
for(i=0; i<64; ++i)
|
|
{
|
|
plat_DrawSquare(i);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Draw a tile with background and piece on it for positions 0..63
|
|
void plat_DrawSquare(char position)
|
|
{
|
|
char index;
|
|
char piece, color;
|
|
char y = position / 8, x = position & 7;
|
|
char blackWhite = !((x & 1) ^ (y & 1));
|
|
|
|
// Draw the boatrd square
|
|
plat_gfxFill(blackWhite, !blackWhite, 1 + x * BOARD_PIECE_WIDTH, 1 + y * BOARD_PIECE_HEIGHT, BOARD_PIECE_WIDTH, BOARD_PIECE_HEIGHT);
|
|
|
|
|
|
// Get the piece data to draw the piece over the tile
|
|
piece = gChessBoard[y][x];
|
|
color = piece & PIECE_WHITE;
|
|
piece &= PIECE_DATA;
|
|
|
|
if(piece)
|
|
{
|
|
index = 1;
|
|
if((color && blackWhite) || (!color && !blackWhite))
|
|
index = 0;
|
|
plat_showPiece(!blackWhite, 1 + x * BOARD_PIECE_WIDTH, y * BOARD_PIECE_HEIGHT + 1, gfxTiles[piece-1][index]);
|
|
}
|
|
|
|
// Show the attack numbers
|
|
if(gShowAttackBoard)
|
|
{
|
|
char piece_value = (gChessBoard[y][x] & 0x0f);
|
|
char piece_color = (gChessBoard[y][x] & PIECE_WHITE) >> 7;
|
|
|
|
// Attackers (bottom left)
|
|
sprintf(textStr, "%d",(gpAttackBoard[giAttackBoardOffset[position][0]]));
|
|
plat_showStrXY(COLOR_WHITE, COLOR_GREEN, 1+x*BOARD_PIECE_WIDTH,(y+1)*BOARD_PIECE_HEIGHT, textStr);
|
|
|
|
// Defenders (bottom right)
|
|
sprintf(textStr, "%d",(gpAttackBoard[giAttackBoardOffset[position][1]]));
|
|
plat_showStrXY(COLOR_WHITE, COLOR_GREEN, 1+x*BOARD_PIECE_WIDTH+3,(y+1)*BOARD_PIECE_HEIGHT, textStr);
|
|
|
|
// Color (0 is black, 128 is white) and piece value (1=ROOK, 2=KNIGHT, 3=BISHOP, 4=QUEEN, 5=KING, 6=PAWN)
|
|
sprintf(textStr, "%0d",piece_value);
|
|
plat_showStrXY(COLOR_WHITE, COLOR_GREEN, 1+x*BOARD_PIECE_WIDTH,1+y*BOARD_PIECE_HEIGHT, textStr);
|
|
|
|
// Color
|
|
sprintf(textStr, "%d",piece_color);
|
|
plat_showStrXY(COLOR_WHITE, COLOR_GREEN, 1+x*BOARD_PIECE_WIDTH+3,1+y*BOARD_PIECE_HEIGHT, textStr);
|
|
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_ShowSideToGoLabel(char side)
|
|
{
|
|
// Show Black or White (can't print in black?)
|
|
sprintf(textStr, "%s",gszSideLabel[side]);
|
|
plat_showStrXY(side ? COLOR_WHITE : COLOR_GRAY1, COLOR_GREEN, 2+8*BOARD_PIECE_WIDTH, 0, textStr);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_Highlight(char position, char color, char)
|
|
{
|
|
char y = position / 8, x = position & 7;
|
|
|
|
// Draw the two vertical bars - the "cursor"
|
|
plat_gfxFill(color, color, x * 4 + 1, y * 3 + 1, 1, 3);
|
|
plat_gfxFill(color, color, x * 4 + 4, y * 3 + 1, 1, 3);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_ShowMessage(char *str, char)
|
|
{
|
|
// Always an error message - illegal move or no more undo/redo
|
|
sprintf(textStr, "%.*s",SCREEN_WIDTH-1-(8*BOARD_PIECE_WIDTH),str);
|
|
plat_showStrXY(COLOR_RED, COLOR_GREEN, 1+(8*BOARD_PIECE_WIDTH), SCREEN_HEIGHT-1, textStr);
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_ClearMessage()
|
|
{
|
|
// Erase the message from ShowMessage
|
|
sprintf(textStr, "%-*s",SCREEN_WIDTH-1-8*BOARD_PIECE_WIDTH," ");
|
|
plat_showStrXY(COLOR_GREEN, COLOR_GREEN, (8*BOARD_PIECE_WIDTH)+1, (8*BOARD_PIECE_HEIGHT), textStr);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void plat_AddToLogWin()
|
|
{
|
|
char bot = (8*BOARD_PIECE_HEIGHT)-2, y = 1, x = 2+(8*BOARD_PIECE_WIDTH);
|
|
char i = 0;
|
|
|
|
// Show a log of the moves that have been played
|
|
for(; y<=bot; ++y)
|
|
{
|
|
if(undo_FindUndoLine(bot-y))
|
|
{
|
|
frontend_FormatLogString();
|
|
sprintf(textStr, "%-6s",gLogStrBuffer);
|
|
plat_showStrXY((gColor[0] ? COLOR_WHITE : COLOR_GRAY1), COLOR_GREEN, x, y, textStr);
|
|
|
|
}
|
|
else
|
|
{
|
|
sprintf(textStr, "%-*s",SCREEN_WIDTH-x," ");
|
|
plat_showStrXY(COLOR_GREEN, COLOR_GREEN, x, y, textStr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Important note about this function is that it alters the gTile...
|
|
// global data trackers so beware when calling it
|
|
void plat_AddToLogWinTop()
|
|
{
|
|
// This redraws the whole log window so just call it
|
|
plat_AddToLogWin();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Use timer B to time a duration
|
|
char plat_TimeExpired(unsigned int aTime, char *timerInit)
|
|
{
|
|
VIA1.pra = 0;
|
|
if(!*timerInit || aTime < *jiffyTime )
|
|
{
|
|
*timerInit = 1;
|
|
*jiffyTime = 0;
|
|
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int plat_ReadKeys(char blocking)
|
|
{
|
|
char key = 0;
|
|
int keyMask = 0;
|
|
|
|
if(blocking || kbhit())
|
|
key = cgetc();
|
|
else
|
|
return 0;
|
|
|
|
switch(key)
|
|
{
|
|
case 145: // Up
|
|
keyMask |= INPUT_UP;
|
|
break;
|
|
|
|
case 29: // Right
|
|
keyMask |= INPUT_RIGHT;
|
|
break;
|
|
|
|
case 17: // Down
|
|
keyMask |= INPUT_DOWN;
|
|
break;
|
|
|
|
case 157: // Left
|
|
keyMask |= INPUT_LEFT;
|
|
break;
|
|
|
|
case 3: // Esc
|
|
keyMask |= INPUT_BACKUP;
|
|
break;
|
|
|
|
case 65: // 'a' - Show Attackers
|
|
keyMask |= INPUT_TOGGLE_A;
|
|
break;
|
|
|
|
case 66: // 'b' - Board attacks - Show all attacks
|
|
keyMask |= INPUT_TOGGLE_B;
|
|
break;
|
|
|
|
case 68: // 'd' - Show Defenders
|
|
keyMask |= INPUT_TOGGLE_D;
|
|
break;
|
|
|
|
case 77: // 'm' - Menu
|
|
keyMask |= INPUT_MENU;
|
|
break;
|
|
|
|
case 13: // Enter
|
|
keyMask |= INPUT_SELECT;
|
|
break;
|
|
|
|
case 82:
|
|
keyMask |= INPUT_REDO;
|
|
break;
|
|
|
|
case 85:
|
|
keyMask |= INPUT_UNDO;
|
|
break;
|
|
|
|
// default: // Debug - show key code
|
|
// {
|
|
// char s[] = "Key:000";
|
|
// 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);
|
|
// }
|
|
break;
|
|
}
|
|
|
|
return keyMask;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Only gets called if gReturnToOS is true, which it isn't
|
|
void plat_Shutdown()
|
|
{
|
|
videomode(sc_vm);
|
|
clrscr();
|
|
printf("Sadly, you cannot re-run the game...\n");
|
|
}
|