C64 Graphics and CX16 versions

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.
This commit is contained in:
StewBC 2020-05-25 18:20:37 -07:00
parent 78187953ff
commit c08a759404
26 changed files with 3041 additions and 70 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/.vscode/
/obj/
/Makefile.options
/cc65-chess.*

View File

@ -9,7 +9,7 @@
# Space or comma separated list of cc65 supported target platforms to build for.
# Default: c64 (lowercase!)
TARGETS := c64 apple2 oric
TARGETS := apple2 atmos c64 c64.chr cx16
# Name of the final, single-file executable.
# Default: name of the current dir with target name appended
@ -52,18 +52,21 @@ EMUCMD :=
# Optional commands used before starting the emulation process, and after finishing it.
# Default: none
#PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate"
#PREEMUCMD := osascript -e "tell application \"X11\" to activate"
#POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false"
#POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate"
#PREEMUCMD := osascript -e "tell application /"System Events/" to set isRunning to (name of processes) contains /"X11.bin/"" -e "if isRunning is true then tell application /"X11/" to activate"
#PREEMUCMD := osascript -e "tell application /"X11/" to activate"
#POSTEMUCMD := osascript -e "tell application /"System Events/" to tell process /"X11/" to set visible to false"
#POSTEMUCMD := osascript -e "tell application /"Terminal/" to activate"
PREEMUCMD :=
POSTEMUCMD :=
# On Windows machines VICE emulators may not be available in the PATH by default.
# In such case, please set the variable below to point to directory containing
# VICE emulators.
#VICE_HOME := "C:\Program Files\WinVICE-2.2-x86\"
VICE_HOME :=
#VICE_HOME := "C:/Program Files/WinVICE-2.2-x86/"
VICE_HOME :=
CX16_HOME :=
AWIN_HOME :=
ORIC_HOME :=
# Options state file name. You should not need to change this, but for those
# rare cases when you feel you really need to name it differently - here you are
@ -143,17 +146,9 @@ ifeq ($(OBJDIR),)
endif
TARGETOBJDIR := $(OBJDIR)/$(TARGETS)
# On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily
# rely on cl65 being added to the PATH in this scenario.
ifdef CC65_HOME
CC := $(CC65_HOME)/bin/cl65
else
CC := cl65
endif
# Default emulator commands and options for particular targets.
# Set EMUCMD to override.
c64_EMUCMD := $(VICE_HOME)x64 -kernal kernal -VICIIdsize -autoload
c64_EMUCMD := $(VICE_HOME)x64 -kernal kernal -VICIIdsize -autostart
c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload
vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload
pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload
@ -163,7 +158,9 @@ c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload
cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload
cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload
atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run
apple2_EMUCMD :=
cx16_EMUCMD := $(CX16_HOME)x16emu -run -prg
apple2_EMUCMD := $(AWIN_HOME)AppleWin.exe -d1
atmos_EMUCMD := $(ORIC_HOME)Oricutron.exe -t
ifeq ($(EMUCMD),)
EMUCMD = $($(CC65TARGET)_EMUCMD)
@ -175,10 +172,10 @@ endif
# The "Native Win32" GNU Make contains quite some workarounds to get along with
# cmd.exe as shell. However it does not provide means to determine that it does
# actually activate those workarounds. Especially does $(SHELL) NOT contain the
# actually activate those workarounds. Especially $(SHELL) does NOT contain the
# value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to
# execute the command 'echo' without any parameters. Only cmd.exe will return a
# non-empy string - saying 'ECHO is on/off'.
# non-empty string - saying 'ECHO is on/off'.
#
# Many "Native Win32" programs accept '/' as directory delimiter just fine. How-
# ever the internal commands of cmd.exe generally require '\' to be used.
@ -291,25 +288,25 @@ $(TARGETOBJDIR):
vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
$(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS)
$(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
cl65 -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
test: $(PROGRAM)
$(PREEMUCMD)

16
Makefile-cprg.mk Normal file
View File

@ -0,0 +1,16 @@
CPRG = cc65-Chess-chr.prg
# Unix or Windows
ifeq ($(shell echo),)
CP = cp $1
else
CP = copy $(subst /,\,$1)
endif
REMOVES += $(CPRG)
.PHONY: cprg
cprg: $(CPRG)
$(CPRG): cc65-chess.c64.chr
$(call CP, $< $@)

16
Makefile-cxprg.mk Normal file
View File

@ -0,0 +1,16 @@
CXPRG = cc65-Chess-cx16.prg
# Unix or Windows
ifeq ($(shell echo),)
CP = cp $1
else
CP = copy $(subst /,\,$1)
endif
REMOVES += $(CXPRG)
.PHONY: cxprg
cxprg: $(CXPRG)
$(CXPRG): cc65-chess.cx16
$(call CP, $< $@)

16
Makefile-prg.mk Normal file
View File

@ -0,0 +1,16 @@
PRG = cc65-Chess-c64.prg
# Unix or Windows
ifeq ($(shell echo),)
CP = cp $1
else
CP = copy $(subst /,\,$1)
endif
REMOVES += $(PRG)
.PHONY: prg
prg: $(PRG)
$(PRG): cc65-chess.c64
$(call CP, $< $@)

View File

@ -12,5 +12,5 @@ REMOVES += $(TAP)
.PHONY: tap
tap: $(TAP)
$(TAP): cc65-chess.oric
$(TAP): cc65-chess.atmos
$(call CP, $< $@)

View File

@ -1,10 +1,11 @@
0. Updates
May 2020 - [raxiss] created a nice Oric-1/Atmos/Telestrat port. See X below.
Jan 2020 - Oliver Schmidt created a beautiful Apple II port. See IX below.
There is a Commodore 64 .PRG and an Apple II .DSK file in the release tab.
* May 2020 - Advanced Build instructions at XI.
* May 2020 - I created a version for the Commander X16 (R37).
* May 2020 - I created a graphics version for the C64.
* May 2020 - [raxiss] created a nice Oric-1/Atmos/Telestrat port.
* Jan 2020 - Oliver Schmidt created a beautiful Apple II port. See IX below.
* There are images for all platforms in the releases tab.
I. Introduction (Feb 14, 2014)
@ -252,45 +253,78 @@ Oliver Schmidt
Jan 19, 2020
X. Apple II Build Instructions
XI. Build Instructions
To build the Apple II version use the make command line:
make TARGETS=apple2 OPTIONS=optspeed
The OPTIONS=optspeed will be remembered and need only be given once.
All of the 8-Bit versions of cc65 Chess can be built using make.
To make the disc image, set an environment variable to point at apple commander
(see notes) and then use the command:
make TARGETS=apple2 dsk
I recommend the game be built for speed, which also results in smaller file and
is essential for all targets. This is done by using the OPTIONS=optspeed
command line to make. See examples below.
If you want to edit the code and get into some iterative development/testing,
you can edit the Makefile and fill in the commands commands neccesary to launch
an emulator as well. Look for apple2_EMUCMD and set that as neccesary. The
simplest is to call test.sh or test.bat and fill in a complete command in the
batch file or shell script. However you choose to do this, once done, you can
do everything with the command:
make TARGETS=apple2 dsk test
When you type make (using GNU Make) the default behaviour is to make all of the
versions. Currently, that means the following (cc65 target name in brackets):
You could also edit the Makefile and change the line TARGETS := c64 apple2 to
include only the apple2 in which case you can omit the TARGETS=apple2 part form
all make commands.
* Commodore 64 HiRes (c64)
* Commodore 64 Multicolor Text (c64.chr)
* Apple 2 (apple2)
* Oric-1/Atmos/Telestrat (atmos)
* Commander X16 (cx16)
NOTES:
1) Find AppleCommander here (I used Version 1.5.0):
https://github.com/AppleCommander/AppleCommander/releases
2) Set the environment variable (or change the Makefile-dsk.md) to point at the
apple commander jar file. Here's how it's done for different shell's:
Powershell:
$env:AC = "path to apple commander.jar"
cmd.exe
set AC="path to apple commander.jar"
bash (Unix or macOS terminal):
export AC="path to apple commander.jar"
Most platforms have an additional step that can be performed, which is to make a
program (prg), disk (dsk) or tape (tap) file. Do make again, but with dsk
(Apple 2 dsk), tap (Oric tape), prg (C64 prg), cprg (c64.chr prg) or cxprg (cX16
prg) on the command line.
XI. Oric Build Instructions
To build the Oric-1/Atmos/Telestrat version set the environment variable CC65_HOME
with the path to the base cc65 directory i.e: export CC65_HOME=${HOME}/cc65
The two steps can be combined into a single make command, by using "all" as the
first target, i.e:
make OPTIONS=optspeed all dsk tap prg cprg cxprg
and use the make command line:
make TARGETS=oric CC65TARGET=atmos OPTIONS=optspeed tap
Makeing a terminal version (using curses) - See IV (b) above.
This will create a ready to run TAP file: cc65-Chess.tap
Examples:
1) Make everything, and then make the dsk and tap files for the Apple and Oric.
make OPTIONS=optspeed
This will make the following files:
cc65-Chess.apple2
cc65-Chess.atmos
cc65-Chess.c64
cc65-Chess.c64.chr
cc65-Chess.cx16
make dsk tap prg cprg cxprg
This will make the following files:
cc65-Chess.tap
cc65-Chess.dsk
cc65-Chess-c64.prg
cc65-Chess-chr.prg
cc65-Chess-cx16.prg
Once you have used the OPTIONS=optspeed on the command-line, you do not have to
use it again since the options are saved in a file called Makefile.options.
2) Build just one version (let's say the Oric)
make OPTIONS=optspeed TARGETS=atmos tap
This will create a ready to run TAP file named cc65-Chess.tap
3) You can also start an emulator directly from make with the test command-line.
make OPTIONS=optspeed atmos test
This last command example is a good way of callimg make to build and test any of
the targets by itself, provided you have configured an emulator in the Makefile.
In this case, it will call the emulator with cc65-Chess.atmos but Oricutron
doesn't mind that the exytension isn't .tap.
Look for _EMUCMD in the Makefile. You may have to specify a full path to the
emulator, and in some cases you may need to change the test: command itself. For
example, to run AppleWin I removed the $< from $(EMUCMD) $< in the test:
section, because AppleWin did not like the extra (cc64-Chess.apple2) file being
passed, and I had to give it the full path to cc64-Chess.dsk as part of apple2_EMUCMD.
Lastly - the CX16 and C64 versions use the same piece defenitions that Oliver
Schmidt added for the Apple II, and kindly agreed to let me use for these
versions as well. See genPieces.cpp in the specific src folder for more details.

View File

@ -1,5 +1,5 @@
/*
* data.c
* dataC64CHR.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
@ -7,7 +7,7 @@
*/
#include "../types.h"
#include "data.h"
#include "dataC64CHR.h"
/*-----------------------------------------------------------------------*/
// C64 specific graphics for the chess pieces

View File

@ -1,5 +1,5 @@
/*
* data.h
* dataC64CHR.h
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.

View File

@ -1,5 +1,5 @@
/*
* plat64.c
* platC64CHR.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
@ -14,7 +14,7 @@
#include "../undo.h"
#include "../frontend.h"
#include "../plat.h"
#include "data.h"
#include "dataC64CHR.h"
/*-----------------------------------------------------------------------*/
// System locations

44
src/c64/chessC64.cfg Normal file
View File

@ -0,0 +1,44 @@
FEATURES {
STARTADDRESS: default = $0801;
}
SYMBOLS {
__LOADADDR__: type = import;
__EXEHDR__: type = import;
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $C000;
}
MEMORY {
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = %S - 2, size = $0002;
HEADER: file = %O, define = yes, start = %S, size = $000D;
MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __HEADER_LAST__;
BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
INIT: load = MAIN, type = rw;
ONCE: load = MAIN, type = ro, define = yes;
BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

202
src/c64/dataC64.c Normal file
View File

@ -0,0 +1,202 @@
/*
* dataC64.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#include "../types.h"
#include "dataC64.h"
/*-----------------------------------------------------------------------*/
// C64 specific graphics for the chess pieces
// The comment shows an icon 16x24
// The data is 24 chars & 24 chars (2 * 8x24). The second set of 24
// is the right-hand side 8-bits of the icon
// 96 = 4 cols * 3 rows * 8 byte / col
const char gfxTiles[PAWN][2][96] =
{
{
{
0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0xC7, 0x44, 0x44, 0x7C, 0x00,
0x00, 0x00, 0x00, 0xC7, 0x44, 0x44, 0x7C, 0x00,
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x5F, 0x60, 0x20, 0x20, 0x20, 0x20,
0x01, 0x02, 0xF4, 0x0C, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00,
0x20, 0x40, 0x80, 0xBF, 0x00, 0xFF, 0xFF, 0x00,
0x08, 0x04, 0x02, 0xFA, 0x01, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
},
{
0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00, 0x00, 0xC7, 0xC7, 0xC7, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0xC7, 0xC7, 0xC7, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x7F, 0x40, 0x3F, 0x3F, 0x3F, 0x3F,
0xFF, 0xFE, 0xFC, 0x04, 0xF8, 0xF8, 0xF8, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00,
0x3F, 0x7F, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
0xF8, 0xFC, 0xFE, 0xFE, 0x01, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x15, 0x21, 0x20, 0x40,
0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,
0x44, 0x40, 0x80, 0x00, 0x00, 0x1E, 0x21, 0xC2,
0x28, 0x28, 0x34, 0x14, 0x04, 0x04, 0x16, 0x1A,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x08, 0x10, 0x20, 0x5F, 0x40, 0x7F, 0x00,
0x09, 0x05, 0x01, 0x00, 0xFE, 0x00, 0xFF, 0x00,
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x15, 0x3E, 0x3F, 0x7F,
0x00, 0x00, 0x00, 0x80, 0x40, 0xE0, 0xF0, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00,
0x7B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0xC3,
0xD8, 0xD8, 0xCC, 0xEC, 0xFC, 0xFC, 0xEE, 0xE6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x0F, 0x1F, 0x3F, 0x40, 0x7F, 0x7F, 0x00,
0xF7, 0xFB, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x11,
0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x2F, 0x41, 0x41, 0x41, 0x21, 0x20, 0x10,
0x08, 0xE8, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x0F, 0x08, 0x08, 0x07, 0x20, 0xFF, 0xFF, 0x00,
0xE0, 0x20, 0x20, 0xC0, 0x08, 0xFE, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x1E,
0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x30, 0x7E, 0x7E, 0x7E, 0x3E, 0x3F, 0x1F,
0xF8, 0x18, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x08, 0x0F, 0x0F, 0x07, 0x3F, 0x80, 0xFF, 0x00,
0x20, 0xE0, 0xE0, 0xC0, 0xF8, 0x02, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0xE4, 0x12,
0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x4E, 0x91,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00,
0x14, 0x28, 0x00, 0x21, 0x33, 0x1F, 0x0F, 0x80,
0x50, 0x28, 0x00, 0x08, 0x98, 0xF1, 0xE1, 0x02,
0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xBF, 0x40, 0x40, 0x40, 0x60, 0x3F, 0x00,
0x02, 0xFA, 0x04, 0x04, 0x04, 0x0C, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0xE7, 0xF3,
0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xCE, 0x9F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00,
0xF7, 0xEF, 0xFF, 0xDE, 0xCC, 0xE0, 0xF0, 0xFF,
0xDF, 0xEF, 0xFF, 0xF7, 0x67, 0x0F, 0x1F, 0xFE,
0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xC0, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x00,
0xFE, 0x06, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x02, 0x0E, 0x0C, 0x32,
0x00, 0x00, 0x00, 0x80, 0x80, 0xE0, 0x60, 0x98,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01,
0x4A, 0x86, 0x02, 0x24, 0x42, 0x41, 0x21, 0x10,
0xA4, 0xC2, 0x81, 0x49, 0x84, 0x04, 0x08, 0x11,
0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x80, 0x9F, 0x40, 0x40, 0x60, 0x3F, 0x00,
0x21, 0x02, 0xF2, 0x04, 0x04, 0x0C, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x02, 0x0E, 0x0C, 0x32,
0x00, 0x00, 0x00, 0x80, 0x80, 0xE0, 0x60, 0x98,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01,
0x7A, 0xFE, 0xFC, 0xDA, 0xBC, 0xBE, 0xDF, 0xEF,
0xBC, 0xFE, 0x7F, 0xB7, 0x7B, 0xFB, 0xF7, 0xEF,
0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF7, 0xFF, 0xC0, 0x7F, 0x7F, 0x7F, 0x3F, 0x00,
0xDF, 0xFE, 0x06, 0xFC, 0xFC, 0xFC, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x08, 0x08, 0x08, 0x04, 0x03, 0x04, 0x04,
0x40, 0x20, 0x20, 0x20, 0x40, 0x80, 0x40, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x04, 0x04, 0x0F, 0x10, 0x3F, 0x3F, 0x00,
0x60, 0x40, 0x40, 0xE0, 0x10, 0xF8, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x07, 0x07,
0xC0, 0xE0, 0xE0, 0xE0, 0xC0, 0x80, 0xC0, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x07, 0x07, 0x0F, 0x10, 0x3F, 0x3F, 0x00,
0xE0, 0xC0, 0xC0, 0xE0, 0x10, 0xF8, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
};

14
src/c64/dataC64.h Normal file
View File

@ -0,0 +1,14 @@
/*
* dataC64.h
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#ifndef _DATA_H_
#define _DATA_H_
extern const char gfxTiles[PAWN][2][96];
#endif //_DATA_H_

360
src/c64/genpieces.cpp Normal file
View File

@ -0,0 +1,360 @@
/*
* genPieces.cpp
* cc65 Chess
*
* Created by Oliver Schmidt, January 2020.
* Pieces designed by Frank Gebhart, 1980s.
* Modified for C64 by S. Wessels, May 2020.
*
*/
#include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <memory.h>
char pieces[]=
" "
" "
" **** ***** **** "
" * * * * * * "
" * * * * * * "
" * ***** ***** * "
" * * "
" * * "
" * * "
" * ********* * "
" ** ** "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * *********** * "
" * * "
" ******************* "
" ******************* "
" "
" "
" "
" "
" **** ***** **** "
" **** ***** **** "
" **** ***** **** "
" ******************* "
" ******************* "
" ***************** "
" *************** "
" ************* "
" * * "
" *********** "
" *********** "
" *********** "
" *********** "
" *********** "
" ************* "
" *************** "
" *************** "
" * * "
" ******************* "
" ******************* "
" "
" "
" "
" "
" * * "
" * * * * "
" * * * "
" * * "
" * * "
" * * * * "
" * * * "
" * ** * "
" * * * "
" * * "
" * **** * "
" * * * * ** "
" ** * ** * "
" * * * "
" * * * "
" * ** "
" * * "
" * ************ * "
" * * "
" **************** "
" "
" "
" "
" "
" * * "
" * * * * "
" ***** *** "
" ********** "
" ************ "
" **** **** ** "
" ********* ** "
" ********** ** "
" ************ ** "
" **************** "
" **************** "
" **** **** *** "
" ** ***** ** "
" ******* *** "
" ********* ** "
" ************** "
" *************** "
" * * "
" **************** "
" **************** "
" "
" "
" "
" "
" "
" *** "
" * * "
" * * "
" * * * "
" * * * "
" * ******* * "
" * * * "
" * * * "
" * * * "
" * * * "
" * * "
" * * "
" ******* "
" * * "
" * * "
" ***** "
" * * "
" *************** "
" ***************** "
" "
" "
" "
" "
" "
" *** "
" ***** "
" ******* "
" **** **** "
" ***** ***** "
" ** ** "
" ****** ****** "
" ****** ****** "
" ****** ****** "
" ***** ***** "
" *********** "
" ********* "
" * * "
" ******* "
" ******* "
" ***** "
" *********** "
" * * "
" ***************** "
" "
" "
" "
" "
" "
" *** "
" * * "
" *** * * *** "
" * * * * * * "
" * * * * * * "
" * * * * * * "
" * * "
" * * * * * "
" * ** *** ** * "
" * ********* * "
" * ******* * "
" * * "
" * * "
" * *********** * "
" * * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" "
" "
" "
" *** "
" ***** "
" *** ***** *** "
" ***** *** ***** "
" ****** ***** ****** "
" ***** ******* ***** "
" ******************* "
" **** **** **** **** "
" **** ** ** **** "
" **** **** "
" ***** ***** "
" *************** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" * * * * * * "
" * ** ** * "
" * * * * "
" * * * * * * "
" * * * * * * "
" * * * * * "
" * * * * * "
" * * * * "
" * * * * "
" * * "
" * ********* * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" **** * * **** "
" ******* ******* "
" ******* ******* "
" *** ** * * ** *** "
" *** **** **** *** "
" *** ***** ***** *** "
" **** ********* **** "
" **** ******* **** "
" ***** ***** ***** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" "
" "
" "
" "
" "
" "
" *** "
" * * "
" * * "
" * * "
" * * "
" * * "
" *** "
" * * "
" * * "
" ** ** "
" * * "
" * * "
" ******* "
" * * "
" *********** "
" *********** "
" "
" "
" "
" "
" "
" "
" "
" "
" *** "
" ***** "
" ******* "
" ******* "
" ******* "
" ***** "
" *** "
" ***** "
" ***** "
" ******* "
" ***** "
" ***** "
" ******* "
" * * "
" *********** "
" *********** "
" "
" "
;
int main(void)
{
int i, j, k;
unsigned int c[8] ;
memset(c,0,sizeof(c));
j = k = 0;
printf("const char gfxTiles[PAWN][2][96] = \n{\n");
for(i=0; i<sizeof(pieces); ++i)
{
c[j] |= (pieces[i] == '*') << (26-(i%21));
if (!(i%21))
{
++j;
if(!(j%8))
{
if(!k)
printf("\t{\n");
k++;
printf("\t\t{");
int x, y;
for(x=0;x<4;x++)
{
printf("\n\t\t\t");
unsigned char v;
for(y=0;y<8;y++)
{
v = (c[y] >> (8*(3-x))) & 0xff;
printf("0x%02X, ", v);
}
}
printf("\n\t\t},\n");
if(2==k)
{
printf("\t},\n");
k = 0;
}
j = 0;
for(y=0;y<8;y++)
{
c[y] = 0;
}
}
}
}
printf("};\n");
return 0;
}

394
src/c64/hiresC64.s Normal file
View File

@ -0,0 +1,394 @@
; hiresC64.s
; cc65 Chess
;
; Created by Stefan Wessels, May 2020.
;
;-----------------------------------------------------------------------
.include "zeropage.inc"
;-----------------------------------------------------------------------
.export _plat_gfxFill, _plat_showStrXY, _plat_showPiece, _plat_colorStringXY, _plat_colorFill
.import popa
;-----------------------------------------------------------------------
.define VIC_BASE_RAM $C000
.define SCREEN_RAM VIC_BASE_RAM + $2000
.define CHARMAP_RAM VIC_BASE_RAM + $2800
;-----------------------------------------------------------------------
.code
;-----------------------------------------------------------------------
; Utility - Turn tmp2 (y) and tmp3 (x) into a pointer in ptr2 that points
; in VIC_BASE_RAM with x, y being col and row with col and row being
; 8 pixels
.proc plat_ptr2AtHgrXY
lda tmp2 ; load y
asl ; ptr2 points at start with 320 = 256 + 64 so
asl ; y in hi + 64 * y in lo/hi + SCREEN_RAM hi = address
asl
asl
rol ptr2 + 1
asl
rol ptr2 + 1
asl
rol ptr2 + 1
sta ptr2
lda tmp2 ; add y in hi
adc ptr2 + 1
adc #>(VIC_BASE_RAM) ; and vic ram in hi (vic ram aligned, lo = 0)
sta ptr2 + 1 ; ptr2 now points at the correct row
stx tmp2 ; re-use tmp2, clear for possible carry
lda tmp3 ; x * 8 is offset into row where this col starts
asl
asl
asl
rol tmp2
adc ptr2
sta ptr2
lda tmp2
adc ptr2 + 1
sta ptr2 + 1 ; ptr2 now points at the start address on-screen, incl. x
rts
.endproc
;-----------------------------------------------------------------------
; Utility - Turn tmp2 (y) and ptr1 (x) into a pointer in ptr1 that points
; at SCREEN_RAM[x+y*40]
.proc plat_ptr2AtScrXY
lda tmp2 ; load y
asl ; * 32
asl
asl
asl
rol ptr1 + 1
asl
rol ptr1 + 1
adc ptr1 ; add x in
sta ptr1
bcc :+
inc ptr1 + 1
:
lda tmp2 ; start with y
asl ; 8 * + 32 * = 40 *
asl
asl
adc ptr1
sta ptr1
lda ptr1 + 1
adc #>(SCREEN_RAM) ; add screen ram hi as lo is $0 (aligned)
sta ptr1 + 1
rts
.endproc
;-----------------------------------------------------------------------
; void plat_gfxFill(char fill, char x, char y, char w, char h)
; where y & h are multiples of 8 and x and w are in columns (i.e.
; bytes not pixels). Fill the 8x8 aligned rectangle with fill.
.proc _plat_gfxFill
sta tmp1 ; h
ldx #0
stx ptr1 + 1 ; prep ptr1 hi for possible carry
stx ptr2 + 1 ; prep ptr2 hi for possible carry
jsr popa ; w
asl ; w * 8 - w in cols and 8 bytes per col till next col
asl
asl
rol ptr1 + 1 ; ptr1 now contains number of bytes to fill per row
sta ptr1
jsr popa
sta tmp2 ; y in tmp2
jsr popa
sta tmp3 ; x in tmp3
jsr plat_ptr2AtHgrXY
sec ; calculate (320 - width) as the "stride"
lda #$40
sbc ptr1
sta tmp2
lda #1
sbc ptr1 + 1
sta tmp3
jsr popa ; fill
sta tmp4
sei ; stop interrupts
lda 1 ; kernel out
and #$FD
sta 1
loop:
lda tmp4
ldy ptr1 + 1 ; check hi byte of width to fill
beq low ; width totals less than 256 bytes, no hi copy
ldy #0 ; fill 256 bytes
:
sta (ptr2), y
dey
bne :-
inc ptr2 + 1 ; adjust the write pointer by 256 bytes
low:
ldy ptr1 ; get the low bytes top copy
beq rowdone ; if none left to copy then row is done
:
dey
sta (ptr2), y ; write the block of bytes < 256
bne :-
rowdone:
dec tmp1 ; one more row done
beq done ; when wrap all rows are done
clc
lda ptr1
adc ptr2
bcc :+
inc ptr2 + 1
clc
:
adc tmp2 ; add stride to get to next row
sta ptr2
lda tmp3
adc ptr2 + 1
sta ptr2 + 1
bne loop ; bra
done:
lda 1 ; kernel in
ora #$02
sta 1
cli ; resume interrupts
rts
.endproc
;-----------------------------------------------------------------------
; void plat_colorFill(char color, char x, char y, char w, char h)
; Fills a rectangle in SCREEN_RAM with color.
.proc _plat_colorFill
sta tmp1 ; h
lda #0
sta ptr1 + 1 ; prep ptr2 hi for possible carry
jsr popa ; w
sta tmp3
jsr popa
sta tmp2 ; y in tmp2
jsr popa
sta ptr1 ; x in tmp3
jsr plat_ptr2AtScrXY
jsr popa ; color
sta tmp2
loop:
lda tmp2
ldy tmp3 ; get the low bytes top copy
beq rowdone ; if none left to copy then row is done
:
dey
sta (ptr1), y ; write the color
bne :-
rowdone:
dec tmp1 ; one more row done
beq done ; when wrap all rows are done
lda ptr1
adc #$28
sta ptr1
bcc loop
inc ptr1 + 1
clc
bne loop ; bra
done:
rts
.endproc
;-----------------------------------------------------------------------
; void plat_showStrXY(char x, char Y, char *str)
; Display the string pointed at by str in hires using the character set
; which must be located at CHARACTER_RAM. This must be Set 2 which
; includes lower case characters
.proc _plat_showStrXY
sta ptr1
stx ptr1 + 1
ldx #0
stx ptr2 + 1 ; init hi value for possibly shifting carry into
jsr popa
sta tmp2 ; y in tmp2
jsr popa
sta tmp3 ; x in tmp3
jsr plat_ptr2AtHgrXY
sei ; stop interrupts
lda 1 ; kernel out
and #$FD
sta 1
ldy #0
sty tmp2
loop:
ldy tmp2
lda (ptr1), y ; character
beq done
cmp #'z'
bpl :+
and #63
:
and #127
ldy #7
ldx #0
stx read + 2
asl ; *8 for bytes
rol read + 2
asl
rol read + 2
asl
rol read + 2
sta read + 1
lda #>(CHARMAP_RAM)
adc read + 2
sta read + 2
read:
lda $ffff, y
sta (ptr2), y
dey
bpl read
lda ptr2
adc #8
sta ptr2
bcc :+
inc ptr2 + 1
clc
:
inc tmp2
bne loop
done:
lda 1 ; kernel in
ora #$02
sta 1
cli ; resume interrupts
rts
.endproc
;-----------------------------------------------------------------------
; void plat_colorStringXY(char color, char x, char y, char *str)
; Uses str only for length. Writes color into SCREEN_RAM at
; SCREEN_RAM[i+x+y*40] where i iterates the string [while(str[i]) i++].
.proc _plat_colorStringXY
sta ptr2 ; store the str pointer in ptr2
stx ptr2 + 1
lda #0 ; clear ptr1 hi for carry
sta ptr1 + 1
jsr popa ; y
sta tmp2 ; save y in tmp 2
jsr popa ; x
sta ptr1 ; save x in ptr1 lo
jsr plat_ptr2AtScrXY
jsr popa ; get the color
tax ; save it in x
ldy #0 ; start at 0
:
lda (ptr2), y
beq done ; as long as string has a valid character
txa ; put color in a
sta (ptr1), y ; and write to SCREEN_RAM
iny
bne :-
done:
rts
.endproc
;-----------------------------------------------------------------------
; void plat_showPiece(char x, char Y, const char *src)
; copies 3 * 32 consecutive bytes from src to a rectangle in VIC RAM at x, y
; The rect is 4 bytes by 24 bytes (rows) so 96 bytes total
.proc _plat_showPiece
sta ptr1 ; store the pointer to the piece
stx ptr1 + 1
ldx #0 ; plat_ptr2AtHgrXY assumes x = 0
stx ptr2 + 1 ; init hi value for possibly shifting carry into
jsr popa
sta tmp2 ; y in tmp2
jsr popa
sta tmp3 ; x in tmp3
jsr plat_ptr2AtHgrXY ; calculate offset into ptr2
sei ; stop interrupts
lda 1 ; kernel out
and #$FD
sta 1
lda #3 ; need to do 3 loops for a whole piece
sta tmp1
loop:
ldy #31 ; 32 bytes to copy
:
lda (ptr1), y ; load src
eor (ptr2), y ; merge with dest
sta (ptr2), y ; save at dest
dey
bpl :- ; do all 32
dec tmp1 ; another 3rd done
beq done ; all done?
lda ptr1 ; more to do - move src data ptr along by 32
adc #32
sta ptr1
bcc :+
clc
inc ptr1 + 1
:
lda ptr2 ; move graphics pointer along by 320 (row down)
adc #<320
sta ptr2
lda ptr2 + 1
adc #>320
sta ptr2 + 1
bne loop ; bra
done:
lda 1 ; kernel in
ora #$02
sta 1
cli ; resume interrupts
rts
.endproc

550
src/c64/platC64.c Normal file
View File

@ -0,0 +1,550 @@
/*
* platC64.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#include <c64.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 "dataC64.h"
/*-----------------------------------------------------------------------*/
// System locations
#define VIC_BASE_RAM (0xC000)
#define BITMAP_OFFSET (0x0000)
#define CHARMAP_ROM (0xD000)
#define SCREEN_RAM ((char*)VIC_BASE_RAM + 0x2000)
#define CHARMAP_RAM ((char*)VIC_BASE_RAM + 0x2800)
/*-----------------------------------------------------------------------*/
#define BOARD_PIECE_WIDTH 4
#define BOARD_PIECE_HEIGHT 3
#define SCREEN_WIDTH 40
#define SCREEN_HEIGHT 25
#define COLOR_OFFSET 0
#define SCROLL_SPEED 0xf5
/*-----------------------------------------------------------------------*/
// Internal function Prototype
char plat_TimeExpired(unsigned int aTime, char *timerInit);
/*-----------------------------------------------------------------------*/
// Function Prototype for functions in hires.s
void plat_gfxFill(char fill, char x, char y, char w, char h);
void plat_colorFill(char color, char x, char y, char w, char h);
void plat_showStrXY(char x, char y, char *str);
void plat_colorStringXY(char color, char x, char y, char *str);
void plat_showPiece(char x, char Y, const char *src);
/*-----------------------------------------------------------------------*/
// Local storage
static char sc_pra, sc_vad, sc_ct1, sc_ct2, sc_vbc;
char textStr[41];
static char subMenu;
/*-----------------------------------------------------------------------*/
// 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;
if(gReturnToOS)
{
// Save these values so they can be restored
sc_pra = CIA2.pra;
sc_vad = VIC.addr;
sc_ct1 = VIC.ctrl1;
sc_ct2 = VIC.ctrl2;
sc_vbc = VIC.bordercolor;
}
// set the border and blank the screen for setup
VIC.bordercolor = COLOR_GREEN;
VIC.ctrl1 &= 239;
// Select the bank
CIA2.pra = (CIA2.pra & 0xFC) | (3 - (VIC_BASE_RAM >> 14));
// Set the location of the Screen (color) and bitmap (0 or 8192 only)
VIC.addr = ((((int)(SCREEN_RAM - VIC_BASE_RAM) / 0x0400) << 4) | (BITMAP_OFFSET / 0X400));
// Turn on HiRes mode
VIC.ctrl1 = (VIC.ctrl1 & 0xBF) | 0x20;
VIC.ctrl2 = (VIC.ctrl2 & 0xEF);
// Turn off the timer
CIA1.cra &= 0xfe;
// CHAREN - Map characters into CPU
*(char*)0x01 &= 0xfb;
// Copy the standard font to where the char font will live
memcpy((char*)CHARMAP_RAM, (char*)CHARMAP_ROM+256*8,256*8);
// Unmap character rom from CPU
*(char*)0x01 |= 0x04;
// Turn timer back on
CIA1.cra |= 0x01;
// Clear all pixels on the screen
plat_gfxFill(0,0,0,40,25);
// set the base screen color on green
memset(SCREEN_RAM, COLOR_WHITE<<4|COLOR_GREEN, 0x400);
// Show the welcome text
strcpy(textStr, "Commodore 64 graphics version, 2020.");
plat_showStrXY(2,SCREEN_HEIGHT/2-1, gszAbout);
plat_showStrXY(2,SCREEN_HEIGHT/2+1,textStr);
plat_colorStringXY(COLOR_BLACK<<4|COLOR_GREEN,2,SCREEN_HEIGHT/2+1,textStr);
// Set the color for the black king
plat_colorFill(COLOR_BLACK<<4|COLOR_GREEN ,SCREEN_WIDTH/2 - 1, SCREEN_HEIGHT/2 - 6, 4, 3);
// Show the welcome kings (black and white, solid versions)
plat_showPiece(SCREEN_WIDTH/2 - 1, SCREEN_HEIGHT/2 - 6, gfxTiles[KING-1][1]);
plat_showPiece(SCREEN_WIDTH/2 - 1, SCREEN_HEIGHT/2 + 4, gfxTiles[KING-1][1]);
// hack to make the menu not flash (no when dimming into sub-menus)
subMenu = 0;
// Un-blank the screen
VIC.ctrl1 |= 16;
plat_ReadKeys(1);
}
/*-----------------------------------------------------------------------*/
// This is not needed on the C64
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;
// Darken the chessboard so the menu "pops"
if(!subMenu++)
plat_colorFill(COLOR_GRAY1<<4,1,1,32,24);
// 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 and color a frame
plat_gfxFill(0xAA , sx-1 , sy-1 , maxLen+4 , 1 );
plat_gfxFill(0xAA , sx-1 , sy , 1 , height+3 );
plat_gfxFill(0xAA , sx+maxLen+2, sy , 1 , height+3 );
plat_gfxFill(0xAA , sx , sy+height+2, maxLen+2 , 1 );
plat_colorFill(COLOR_YELLOW<<4, sx-1 , sy-1 , maxLen+4 , 1 );
plat_colorFill(COLOR_YELLOW<<4, sx-1 , sy , 1 , height+3 );
plat_colorFill(COLOR_YELLOW<<4, sx+maxLen+2, sy , 1 , height+3 );
plat_colorFill(COLOR_YELLOW<<4, sx , sy+height+2, maxLen+2 , 1 );
// Show the title
sprintf(textStr, " %.*s ",38, menuItems[0]);
plat_showStrXY(sx, sy, textStr);
plat_colorStringXY(COLOR_YELLOW<<4|COLOR_BLUE, sx, sy, textStr);
// Leave a blank line
sprintf(textStr, "%-*s", maxLen+2," ");
plat_showStrXY(sx, ++sy, textStr);
plat_colorStringXY(COLOR_BLUE, sx, sy, textStr);
// Show all the menu items
for(i=1; i<numMenuItems; ++i)
{
sprintf(textStr, " %.*s ",maxLen, menuItems[i]);
plat_showStrXY(sx, sy+i, textStr);
plat_colorStringXY(COLOR_GRAY2<<4|COLOR_BLUE, sx, sy+i, textStr);
}
// Pad with blank lines to menu height
for(;i<height;++i)
{
sprintf(textStr, "%-*s", maxLen+2," ");
plat_showStrXY(sx, sy+i, textStr);
plat_colorStringXY(COLOR_BLUE, sx, sy+i, textStr);
}
// Color the scroller area once
plat_colorStringXY(COLOR_CYAN<<4|COLOR_BLUE, sx, sy+height, textStr);
// Select the first item
i = 1;
do
{
// Highlight the selected item
sprintf(textStr, ">%.*s<",maxLen, menuItems[i]);
plat_showStrXY(sx, sy+i, textStr);
plat_colorStringXY(COLOR_WHITE<<4|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(sx, sy+i, textStr);
plat_colorStringXY(COLOR_GRAY2<<4|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(sx, sy+height, textStr);
// Wrap the message if needed
if((pEnd - pScroller) < maxLen-1)
{
sprintf(textStr, " %.*s ",maxLen-(pEnd - pScroller)-1, scroller);
plat_showStrXY(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;
// Not in a menu when drawBoard is called
subMenu = 0;
if(clearLog)
{
// Clear the log area pixels and color to green
plat_gfxFill(0,33,0,7,25);
plat_colorFill(COLOR_GREEN,33,0,7,25);
}
// set the left and top margin row/col to clear & green
plat_colorFill(COLOR_GREEN,0,0,33,1);
plat_colorFill(COLOR_GREEN,0,0,1,25);
// redraw all tiles
for(i=0; i<64; ++i)
{
plat_DrawSquare(i);
}
// Add the A..H and 1..8 tile-keys
for(i=0; i<8; ++i)
{
// Print the letters and numbers in Black on Green
sprintf(textStr, "%c",'A'+i);
plat_showStrXY(2+i*BOARD_PIECE_WIDTH, 0, textStr);
plat_colorStringXY(COLOR_BLACK<<4|COLOR_GREEN,2+i*BOARD_PIECE_WIDTH, 0, textStr);
sprintf(textStr, "%d",8-i);
plat_showStrXY(0, 2+i*BOARD_PIECE_HEIGHT, textStr);
plat_colorStringXY(COLOR_BLACK<<4|COLOR_GREEN,0, 2+i*BOARD_PIECE_HEIGHT, textStr);
}
}
/*-----------------------------------------------------------------------*/
// 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 ? 0xff : 0x0, 1 + x * BOARD_PIECE_WIDTH, 1 + y * BOARD_PIECE_HEIGHT, BOARD_PIECE_WIDTH, BOARD_PIECE_HEIGHT);
plat_colorFill(COLOR_WHITE<<4 , 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(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(1+x*BOARD_PIECE_WIDTH,(y+1)*BOARD_PIECE_HEIGHT, textStr);
plat_colorStringXY((piece_color ? COLOR_RED : COLOR_GREEN)<<4,1+x*BOARD_PIECE_WIDTH,(y+1)*BOARD_PIECE_HEIGHT, textStr);
// Defenders (bottom right)
sprintf(textStr, "%d",(gpAttackBoard[giAttackBoardOffset[position][1]]));
plat_showStrXY(1+x*BOARD_PIECE_WIDTH+3,(y+1)*BOARD_PIECE_HEIGHT, textStr);
plat_colorStringXY((!piece_color ? COLOR_RED : COLOR_GREEN)<<4,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(1+x*BOARD_PIECE_WIDTH,1+y*BOARD_PIECE_HEIGHT, textStr);
plat_colorStringXY(COLOR_PURPLE<<4,1+x*BOARD_PIECE_WIDTH,1+y*BOARD_PIECE_HEIGHT, textStr);
// Color
sprintf(textStr, "%d",piece_color);
plat_showStrXY(1+x*BOARD_PIECE_WIDTH+3,1+y*BOARD_PIECE_HEIGHT, textStr);
plat_colorStringXY((piece_color ? COLOR_WHITE : COLOR_GRAY1)<<4,1+x*BOARD_PIECE_WIDTH+3,1+y*BOARD_PIECE_HEIGHT, textStr);
}
}
/*-----------------------------------------------------------------------*/
void plat_ShowSideToGoLabel(char side)
{
// Show Black or White
sprintf(textStr, "%s",gszSideLabel[side]);
plat_showStrXY(2+8*BOARD_PIECE_WIDTH, 0, textStr);
plat_colorStringXY((side ? COLOR_WHITE : COLOR_BLACK)<<4|COLOR_GREEN, 2+8*BOARD_PIECE_WIDTH, 0, textStr);
}
/*-----------------------------------------------------------------------*/
void plat_Highlight(char position, char color, char)
{
char y = position / 8, x = position & 7;
char white = !((x & 1) ^ (y & 1));
// White pieces need the foreground color set, black the background color
if(white)
color <<= 4;
// turn position into a board based offset
x *= BOARD_PIECE_WIDTH;
y *= BOARD_PIECE_HEIGHT;
// The board is 1 line down from the top
y++;
// Draw the two vertical bars - the "cursor"
plat_colorFill(color, x + 1 , y, 1, BOARD_PIECE_HEIGHT);
plat_colorFill(color, x + BOARD_PIECE_WIDTH, y, 1, BOARD_PIECE_HEIGHT);
}
/*-----------------------------------------------------------------------*/
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(1+(8*BOARD_PIECE_WIDTH), SCREEN_HEIGHT-1, textStr);
plat_colorStringXY(COLOR_RED<<4|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((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(x, y, textStr);
plat_colorStringXY((gColor[0] ? COLOR_WHITE : COLOR_BLACK)<<4|COLOR_GREEN, x, y, textStr);
}
else
{
sprintf(textStr, "%-*s",SCREEN_WIDTH-x," ");
plat_showStrXY(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)
{
// return 0;
if(!*timerInit || (CIA1.tb_lo < aTime))
{
*timerInit = 1;
CIA1.crb &= 0xfe;
CIA1.tb_lo = 0xff;
CIA1.tb_hi = 0xff;
CIA1.crb |= 0x41;
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()
{
VIC.bordercolor = sc_vbc;
VIC.ctrl2 = sc_ct2;
VIC.ctrl1 = sc_ct1;
VIC.addr = sc_vad;
CIA2.pra = sc_pra;
CIA1.crb &= 0xfe;
CIA1.tb_lo = 0xff;
CIA1.tb_hi = 0xff;
CIA1.crb = 0x8;
printf("Sadly, you cannot re-run the game...\n");
}

345
src/cx16/dataCX16.c Normal file
View File

@ -0,0 +1,345 @@
/*
* dataCX16.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#include "../types.h"
#include "dataCX16.h"
/*-----------------------------------------------------------------------*/
// C64 specific graphics for the chess pieces
// The comment shows an icon 16x24
// The data is 24 chars & 24 chars (2 * 8x24). The second set of 24
// is the right-hand side 8-bits of the icon
const char gfxTiles[PAWN][2][96] =
{
{
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x03, 0xC7, 0xC7, 0x80,
0x02, 0x44, 0x44, 0x80,
0x02, 0x44, 0x44, 0x80,
0x02, 0x7C, 0x7C, 0x80,
0x02, 0x00, 0x00, 0x80,
0x01, 0x00, 0x01, 0x00,
0x00, 0x80, 0x02, 0x00,
0x00, 0x5F, 0xF4, 0x00,
0x00, 0x60, 0x0C, 0x00,
0x00, 0x20, 0x08, 0x00,
0x00, 0x20, 0x08, 0x00,
0x00, 0x20, 0x08, 0x00,
0x00, 0x20, 0x08, 0x00,
0x00, 0x20, 0x08, 0x00,
0x00, 0x40, 0x04, 0x00,
0x00, 0x80, 0x02, 0x00,
0x00, 0xBF, 0xFA, 0x00,
0x01, 0x00, 0x01, 0x00,
0x03, 0xFF, 0xFF, 0x80,
0x03, 0xFF, 0xFF, 0x80,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x03, 0xC7, 0xC7, 0x80,
0x03, 0xC7, 0xC7, 0x80,
0x03, 0xC7, 0xC7, 0x80,
0x03, 0xFF, 0xFF, 0x80,
0x03, 0xFF, 0xFF, 0x80,
0x01, 0xFF, 0xFF, 0x00,
0x00, 0xFF, 0xFE, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x40, 0x04, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0xFF, 0xFE, 0x00,
0x00, 0xFF, 0xFE, 0x00,
0x01, 0x00, 0x01, 0x00,
0x03, 0xFF, 0xFF, 0x80,
0x03, 0xFF, 0xFF, 0x80,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x80, 0x00,
0x00, 0x15, 0x40, 0x00,
0x00, 0x21, 0x20, 0x00,
0x00, 0x20, 0x10, 0x00,
0x00, 0x40, 0x08, 0x00,
0x00, 0x44, 0x28, 0x00,
0x00, 0x40, 0x28, 0x00,
0x00, 0x80, 0x34, 0x00,
0x01, 0x00, 0x14, 0x00,
0x02, 0x00, 0x04, 0x00,
0x02, 0x1E, 0x04, 0x00,
0x01, 0x21, 0x16, 0x00,
0x00, 0xC2, 0x1A, 0x00,
0x00, 0x04, 0x09, 0x00,
0x00, 0x08, 0x05, 0x00,
0x00, 0x10, 0x01, 0x80,
0x00, 0x20, 0x00, 0x80,
0x00, 0x5F, 0xFE, 0x80,
0x00, 0x40, 0x00, 0x80,
0x00, 0x7F, 0xFF, 0x80,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x80, 0x00,
0x00, 0x15, 0x40, 0x00,
0x00, 0x3E, 0xE0, 0x00,
0x00, 0x3F, 0xF0, 0x00,
0x00, 0x7F, 0xF8, 0x00,
0x00, 0x7B, 0xD8, 0x00,
0x00, 0x7F, 0xD8, 0x00,
0x00, 0xFF, 0xCC, 0x00,
0x01, 0xFF, 0xEC, 0x00,
0x03, 0xFF, 0xFC, 0x00,
0x03, 0xFF, 0xFC, 0x00,
0x01, 0xE1, 0xEE, 0x00,
0x00, 0xC3, 0xE6, 0x00,
0x00, 0x07, 0xF7, 0x00,
0x00, 0x0F, 0xFB, 0x00,
0x00, 0x1F, 0xFF, 0x80,
0x00, 0x3F, 0xFF, 0x80,
0x00, 0x40, 0x00, 0x80,
0x00, 0x7F, 0xFF, 0x80,
0x00, 0x7F, 0xFF, 0x80,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0x08, 0x20, 0x00,
0x00, 0x11, 0x10, 0x00,
0x00, 0x21, 0x08, 0x00,
0x00, 0x2F, 0xE8, 0x00,
0x00, 0x41, 0x04, 0x00,
0x00, 0x41, 0x04, 0x00,
0x00, 0x41, 0x04, 0x00,
0x00, 0x21, 0x08, 0x00,
0x00, 0x20, 0x08, 0x00,
0x00, 0x10, 0x10, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x08, 0x20, 0x00,
0x00, 0x08, 0x20, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x20, 0x08, 0x00,
0x00, 0xFF, 0xFE, 0x00,
0x01, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x1E, 0xF0, 0x00,
0x00, 0x3E, 0xF8, 0x00,
0x00, 0x30, 0x18, 0x00,
0x00, 0x7E, 0xFC, 0x00,
0x00, 0x7E, 0xFC, 0x00,
0x00, 0x7E, 0xFC, 0x00,
0x00, 0x3E, 0xF8, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x1F, 0xF0, 0x00,
0x00, 0x08, 0x20, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x80, 0x02, 0x00,
0x01, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0xE4, 0x4E, 0x00,
0x01, 0x12, 0x91, 0x00,
0x02, 0x14, 0x50, 0x80,
0x02, 0x28, 0x28, 0x80,
0x02, 0x00, 0x00, 0x80,
0x02, 0x21, 0x08, 0x80,
0x02, 0x33, 0x98, 0x80,
0x01, 0x1F, 0xF1, 0x00,
0x01, 0x0F, 0xE1, 0x00,
0x00, 0x80, 0x02, 0x00,
0x00, 0x80, 0x02, 0x00,
0x00, 0xBF, 0xFA, 0x00,
0x00, 0x40, 0x04, 0x00,
0x00, 0x40, 0x04, 0x00,
0x00, 0x40, 0x04, 0x00,
0x00, 0x60, 0x0C, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0xE7, 0xCE, 0x00,
0x01, 0xF3, 0x9F, 0x00,
0x03, 0xF7, 0xDF, 0x80,
0x03, 0xEF, 0xEF, 0x80,
0x03, 0xFF, 0xFF, 0x80,
0x03, 0xDE, 0xF7, 0x80,
0x03, 0xCC, 0x67, 0x80,
0x01, 0xE0, 0x0F, 0x00,
0x01, 0xF0, 0x1F, 0x00,
0x00, 0xFF, 0xFE, 0x00,
0x00, 0xFF, 0xFE, 0x00,
0x00, 0xC0, 0x06, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x02, 0x80, 0x00,
0x00, 0x0E, 0xE0, 0x00,
0x00, 0x0C, 0x60, 0x00,
0x00, 0x32, 0x98, 0x00,
0x00, 0x4A, 0xA4, 0x00,
0x00, 0x86, 0xC2, 0x00,
0x01, 0x02, 0x81, 0x00,
0x01, 0x24, 0x49, 0x00,
0x02, 0x42, 0x84, 0x80,
0x02, 0x41, 0x04, 0x80,
0x02, 0x21, 0x08, 0x80,
0x01, 0x10, 0x11, 0x00,
0x01, 0x08, 0x21, 0x00,
0x00, 0x80, 0x02, 0x00,
0x00, 0x9F, 0xF2, 0x00,
0x00, 0x40, 0x04, 0x00,
0x00, 0x40, 0x04, 0x00,
0x00, 0x60, 0x0C, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x02, 0x80, 0x00,
0x00, 0x0E, 0xE0, 0x00,
0x00, 0x0C, 0x60, 0x00,
0x00, 0x32, 0x98, 0x00,
0x00, 0x7A, 0xBC, 0x00,
0x00, 0xFE, 0xFE, 0x00,
0x01, 0xFC, 0x7F, 0x00,
0x01, 0xDA, 0xB7, 0x00,
0x03, 0xBC, 0x7B, 0x80,
0x03, 0xBE, 0xFB, 0x80,
0x03, 0xDF, 0xF7, 0x80,
0x01, 0xEF, 0xEF, 0x00,
0x01, 0xF7, 0xDF, 0x00,
0x00, 0xFF, 0xFE, 0x00,
0x00, 0xC0, 0x06, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x7F, 0xFC, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0x08, 0x20, 0x00,
0x00, 0x08, 0x20, 0x00,
0x00, 0x08, 0x20, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0x0C, 0x60, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0x04, 0x40, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x10, 0x10, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x03, 0x80, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x07, 0xC0, 0x00,
0x00, 0x0F, 0xE0, 0x00,
0x00, 0x10, 0x10, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x3F, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
},
};

14
src/cx16/dataCX16.h Normal file
View File

@ -0,0 +1,14 @@
/*
* dataCX16.h
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#ifndef _DATA_H_
#define _DATA_H_
extern const char gfxTiles[PAWN][2][96];
#endif //_DATA_H_

342
src/cx16/genpieces.cpp Normal file
View File

@ -0,0 +1,342 @@
/*
* genPieces.cpp
* cc65 Chess
*
* Created by Oliver Schmidt, January 2020.
* Pieces designed by Frank Gebhart, 1980s.
* Modified for CX16 by S. Wessels, May 2020.
*
*/
#include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <memory.h>
char pieces[]=
" "
" "
" **** ***** **** "
" * * * * * * "
" * * * * * * "
" * ***** ***** * "
" * * "
" * * "
" * * "
" * ********* * "
" ** ** "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * *********** * "
" * * "
" ******************* "
" ******************* "
" "
" "
" "
" "
" **** ***** **** "
" **** ***** **** "
" **** ***** **** "
" ******************* "
" ******************* "
" ***************** "
" *************** "
" ************* "
" * * "
" *********** "
" *********** "
" *********** "
" *********** "
" *********** "
" ************* "
" *************** "
" *************** "
" * * "
" ******************* "
" ******************* "
" "
" "
" "
" "
" * * "
" * * * * "
" * * * "
" * * "
" * * "
" * * * * "
" * * * "
" * ** * "
" * * * "
" * * "
" * **** * "
" * * * * ** "
" ** * ** * "
" * * * "
" * * * "
" * ** "
" * * "
" * ************ * "
" * * "
" **************** "
" "
" "
" "
" "
" * * "
" * * * * "
" ***** *** "
" ********** "
" ************ "
" **** **** ** "
" ********* ** "
" ********** ** "
" ************ ** "
" **************** "
" **************** "
" **** **** *** "
" ** ***** ** "
" ******* *** "
" ********* ** "
" ************** "
" *************** "
" * * "
" **************** "
" **************** "
" "
" "
" "
" "
" "
" *** "
" * * "
" * * "
" * * * "
" * * * "
" * ******* * "
" * * * "
" * * * "
" * * * "
" * * * "
" * * "
" * * "
" ******* "
" * * "
" * * "
" ***** "
" * * "
" *************** "
" ***************** "
" "
" "
" "
" "
" "
" *** "
" ***** "
" ******* "
" **** **** "
" ***** ***** "
" ** ** "
" ****** ****** "
" ****** ****** "
" ****** ****** "
" ***** ***** "
" *********** "
" ********* "
" * * "
" ******* "
" ******* "
" ***** "
" *********** "
" * * "
" ***************** "
" "
" "
" "
" "
" "
" *** "
" * * "
" *** * * *** "
" * * * * * * "
" * * * * * * "
" * * * * * * "
" * * "
" * * * * * "
" * ** *** ** * "
" * ********* * "
" * ******* * "
" * * "
" * * "
" * *********** * "
" * * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" "
" "
" "
" *** "
" ***** "
" *** ***** *** "
" ***** *** ***** "
" ****** ***** ****** "
" ***** ******* ***** "
" ******************* "
" **** **** **** **** "
" **** ** ** **** "
" **** **** "
" ***** ***** "
" *************** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" * * * * * * "
" * ** ** * "
" * * * * "
" * * * * * * "
" * * * * * * "
" * * * * * "
" * * * * * "
" * * * * "
" * * * * "
" * * "
" * ********* * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" **** * * **** "
" ******* ******* "
" ******* ******* "
" *** ** * * ** *** "
" *** **** **** *** "
" *** ***** ***** *** "
" **** ********* **** "
" **** ******* **** "
" ***** ***** ***** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" "
" "
" "
" "
" "
" "
" *** "
" * * "
" * * "
" * * "
" * * "
" * * "
" *** "
" * * "
" * * "
" ** ** "
" * * "
" * * "
" ******* "
" * * "
" *********** "
" *********** "
" "
" "
" "
" "
" "
" "
" "
" "
" *** "
" ***** "
" ******* "
" ******* "
" ******* "
" ***** "
" *** "
" ***** "
" ***** "
" ******* "
" ***** "
" ***** "
" ******* "
" * * "
" *********** "
" *********** "
" "
" "
;
int main(void)
{
int i;
unsigned char c = 0;
printf("const char gfxTiles[PAWN][2][384] = \n{\n");
for(i=0; i<sizeof(pieces); i++)
{
if(!(i%(32*24*2)))
printf("\t{\n");
if(!(i%(32*24)))
printf("\t\t{\n");
if(!(i % 32))
printf("\t\t\t");
c |= (pieces[i] == '*') << (7-(i%8));
if ((i%8) == 7)
{
printf("0x%02X, ", c);
c = 0;
}
if(31 == (i%32))
printf("\n");
if((32*24) -1 == (i%(32*24)))
printf("\t\t},\n");
if((32*24*2) - 1 == (i%(32*24*2)))
printf("\t},\n");
}
printf("};\n");
return 0;
}

626
src/cx16/platCX16.c Normal file
View File

@ -0,0 +1,626 @@
/*
* 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 int offset = 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;
}
}
/*-----------------------------------------------------------------------*/
// 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_320x200) ;
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");
}

View File

@ -267,7 +267,7 @@ void plat_ClearMessage()
}
/*-----------------------------------------------------------------------*/
// This function can/will gange the gTile and related global variables so
// This function can/will change the gTile and related global variables so
// caution is needed
void plat_AddToLogWin()
{