From c08a7594046dd9c5145f4c8ff67e9be20e1ac85c Mon Sep 17 00:00:00 2001 From: StewBC Date: Mon, 25 May 2020 18:20:37 -0700 Subject: [PATCH] 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. --- .gitignore | 1 + Makefile | 45 +- Makefile-cprg.mk | 16 + Makefile-cxprg.mk | 16 + Makefile-prg.mk | 16 + Makefile-tap.mk | 2 +- readme.txt | 112 ++-- src/{oric => atmos}/oric.cfg | 0 src/{oric => atmos}/platOric.c | 0 src/{oric => atmos}/platOric.h | 0 src/{oric => atmos}/platOrica.s | 0 .../chess.cfg => c64.chr/chessC64CHR.cfg} | 0 src/{c64/data.c => c64.chr/dataC64CHR.c} | 4 +- src/{c64/data.h => c64.chr/dataC64CHR.h} | 2 +- src/{c64/plat64.c => c64.chr/platC64CHR.c} | 4 +- src/c64/chessC64.cfg | 44 ++ src/c64/dataC64.c | 202 ++++++ src/c64/dataC64.h | 14 + src/c64/genpieces.cpp | 360 ++++++++++ src/c64/hiresC64.s | 394 +++++++++++ src/c64/platC64.c | 550 +++++++++++++++ src/cx16/dataCX16.c | 345 ++++++++++ src/cx16/dataCX16.h | 14 + src/cx16/genpieces.cpp | 342 ++++++++++ src/cx16/platCX16.c | 626 ++++++++++++++++++ src/term/platTerm.c | 2 +- 26 files changed, 3041 insertions(+), 70 deletions(-) create mode 100644 Makefile-cprg.mk create mode 100644 Makefile-cxprg.mk create mode 100644 Makefile-prg.mk rename src/{oric => atmos}/oric.cfg (100%) rename src/{oric => atmos}/platOric.c (100%) rename src/{oric => atmos}/platOric.h (100%) rename src/{oric => atmos}/platOrica.s (100%) rename src/{c64/chess.cfg => c64.chr/chessC64CHR.cfg} (100%) rename src/{c64/data.c => c64.chr/dataC64CHR.c} (99%) rename src/{c64/data.h => c64.chr/dataC64CHR.h} (92%) rename src/{c64/plat64.c => c64.chr/platC64CHR.c} (99%) create mode 100644 src/c64/chessC64.cfg create mode 100644 src/c64/dataC64.c create mode 100644 src/c64/dataC64.h create mode 100644 src/c64/genpieces.cpp create mode 100644 src/c64/hiresC64.s create mode 100644 src/c64/platC64.c create mode 100644 src/cx16/dataCX16.c create mode 100644 src/cx16/dataCX16.h create mode 100644 src/cx16/genpieces.cpp create mode 100644 src/cx16/platCX16.c diff --git a/.gitignore b/.gitignore index dd1b936..450bfc5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.vscode/ /obj/ /Makefile.options /cc65-chess.* diff --git a/Makefile b/Makefile index 7ae5203..7b9bc0a 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/Makefile-cprg.mk b/Makefile-cprg.mk new file mode 100644 index 0000000..e8e546c --- /dev/null +++ b/Makefile-cprg.mk @@ -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, $< $@) diff --git a/Makefile-cxprg.mk b/Makefile-cxprg.mk new file mode 100644 index 0000000..222770a --- /dev/null +++ b/Makefile-cxprg.mk @@ -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, $< $@) diff --git a/Makefile-prg.mk b/Makefile-prg.mk new file mode 100644 index 0000000..372550b --- /dev/null +++ b/Makefile-prg.mk @@ -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, $< $@) diff --git a/Makefile-tap.mk b/Makefile-tap.mk index df48854..0fd9e2c 100644 --- a/Makefile-tap.mk +++ b/Makefile-tap.mk @@ -12,5 +12,5 @@ REMOVES += $(TAP) .PHONY: tap tap: $(TAP) -$(TAP): cc65-chess.oric +$(TAP): cc65-chess.atmos $(call CP, $< $@) diff --git a/readme.txt b/readme.txt index 1edbf16..b61efe8 100644 --- a/readme.txt +++ b/readme.txt @@ -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. diff --git a/src/oric/oric.cfg b/src/atmos/oric.cfg similarity index 100% rename from src/oric/oric.cfg rename to src/atmos/oric.cfg diff --git a/src/oric/platOric.c b/src/atmos/platOric.c similarity index 100% rename from src/oric/platOric.c rename to src/atmos/platOric.c diff --git a/src/oric/platOric.h b/src/atmos/platOric.h similarity index 100% rename from src/oric/platOric.h rename to src/atmos/platOric.h diff --git a/src/oric/platOrica.s b/src/atmos/platOrica.s similarity index 100% rename from src/oric/platOrica.s rename to src/atmos/platOrica.s diff --git a/src/c64/chess.cfg b/src/c64.chr/chessC64CHR.cfg similarity index 100% rename from src/c64/chess.cfg rename to src/c64.chr/chessC64CHR.cfg diff --git a/src/c64/data.c b/src/c64.chr/dataC64CHR.c similarity index 99% rename from src/c64/data.c rename to src/c64.chr/dataC64CHR.c index 992eae7..9f0e2f3 100644 --- a/src/c64/data.c +++ b/src/c64.chr/dataC64CHR.c @@ -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 diff --git a/src/c64/data.h b/src/c64.chr/dataC64CHR.h similarity index 92% rename from src/c64/data.h rename to src/c64.chr/dataC64CHR.h index a98fddf..5154722 100644 --- a/src/c64/data.h +++ b/src/c64.chr/dataC64CHR.h @@ -1,5 +1,5 @@ /* - * data.h + * dataC64CHR.h * cc65 Chess * * Created by Stefan Wessels, February 2014. diff --git a/src/c64/plat64.c b/src/c64.chr/platC64CHR.c similarity index 99% rename from src/c64/plat64.c rename to src/c64.chr/platC64CHR.c index 142d1bd..cc9a1e7 100644 --- a/src/c64/plat64.c +++ b/src/c64.chr/platC64CHR.c @@ -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 diff --git a/src/c64/chessC64.cfg b/src/c64/chessC64.cfg new file mode 100644 index 0000000..ec791a5 --- /dev/null +++ b/src/c64/chessC64.cfg @@ -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__; +} diff --git a/src/c64/dataC64.c b/src/c64/dataC64.c new file mode 100644 index 0000000..06aa2de --- /dev/null +++ b/src/c64/dataC64.c @@ -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, + }, + }, +}; diff --git a/src/c64/dataC64.h b/src/c64/dataC64.h new file mode 100644 index 0000000..986d4a8 --- /dev/null +++ b/src/c64/dataC64.h @@ -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_ \ No newline at end of file diff --git a/src/c64/genpieces.cpp b/src/c64/genpieces.cpp new file mode 100644 index 0000000..d731a15 --- /dev/null +++ b/src/c64/genpieces.cpp @@ -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 +#ifdef _WIN32 +#include +#else +#include +#endif + +#include +#include + +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> (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; +} diff --git a/src/c64/hiresC64.s b/src/c64/hiresC64.s new file mode 100644 index 0000000..9edbab1 --- /dev/null +++ b/src/c64/hiresC64.s @@ -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 + diff --git a/src/c64/platC64.c b/src/c64/platC64.c new file mode 100644 index 0000000..557b4c6 --- /dev/null +++ b/src/c64/platC64.c @@ -0,0 +1,550 @@ +/* + * platC64.c + * cc65 Chess + * + * Created by Stefan Wessels, February 2014. + * + */ + +#include +#include +#include +#include +#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%.*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"); +} diff --git a/src/cx16/dataCX16.c b/src/cx16/dataCX16.c new file mode 100644 index 0000000..7f4254d --- /dev/null +++ b/src/cx16/dataCX16.c @@ -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, + }, + }, +}; \ No newline at end of file diff --git a/src/cx16/dataCX16.h b/src/cx16/dataCX16.h new file mode 100644 index 0000000..b55b788 --- /dev/null +++ b/src/cx16/dataCX16.h @@ -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_ \ No newline at end of file diff --git a/src/cx16/genpieces.cpp b/src/cx16/genpieces.cpp new file mode 100644 index 0000000..b9e7a0b --- /dev/null +++ b/src/cx16/genpieces.cpp @@ -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 +#ifdef _WIN32 +#include +#else +#include +#endif + +#include +#include + +char pieces[]= +" " +" " +" **** ***** **** " +" * * * * * * " +" * * * * * * " +" * ***** ***** * " +" * * " +" * * " +" * * " +" * ********* * " +" ** ** " +" * * " +" * * " +" * * " +" * * " +" * * " +" * * " +" * * " +" * *********** * " +" * * " +" ******************* " +" ******************* " +" " +" " +" " +" " +" **** ***** **** " +" **** ***** **** " +" **** ***** **** " +" ******************* " +" ******************* " +" ***************** " +" *************** " +" ************* " +" * * " +" *********** " +" *********** " +" *********** " +" *********** " +" *********** " +" ************* " +" *************** " +" *************** " +" * * " +" ******************* " +" ******************* " +" " +" " +" " +" " +" * * " +" * * * * " +" * * * " +" * * " +" * * " +" * * * * " +" * * * " +" * ** * " +" * * * " +" * * " +" * **** * " +" * * * * ** " +" ** * ** * " +" * * * " +" * * * " +" * ** " +" * * " +" * ************ * " +" * * " +" **************** " +" " +" " +" " +" " +" * * " +" * * * * " +" ***** *** " +" ********** " +" ************ " +" **** **** ** " +" ********* ** " +" ********** ** " +" ************ ** " +" **************** " +" **************** " +" **** **** *** " +" ** ***** ** " +" ******* *** " +" ********* ** " +" ************** " +" *************** " +" * * " +" **************** " +" **************** " +" " +" " +" " +" " +" " +" *** " +" * * " +" * * " +" * * * " +" * * * " +" * ******* * " +" * * * " +" * * * " +" * * * " +" * * * " +" * * " +" * * " +" ******* " +" * * " +" * * " +" ***** " +" * * " +" *************** " +" ***************** " +" " +" " +" " +" " +" " +" *** " +" ***** " +" ******* " +" **** **** " +" ***** ***** " +" ** ** " +" ****** ****** " +" ****** ****** " +" ****** ****** " +" ***** ***** " +" *********** " +" ********* " +" * * " +" ******* " +" ******* " +" ***** " +" *********** " +" * * " +" ***************** " +" " +" " +" " +" " +" " +" *** " +" * * " +" *** * * *** " +" * * * * * * " +" * * * * * * " +" * * * * * * " +" * * " +" * * * * * " +" * ** *** ** * " +" * ********* * " +" * ******* * " +" * * " +" * * " +" * *********** * " +" * * " +" * * " +" * * " +" ** ** " +" *********** " +" " +" " +" " +" " +" " +" *** " +" ***** " +" *** ***** *** " +" ***** *** ***** " +" ****** ***** ****** " +" ***** ******* ***** " +" ******************* " +" **** **** **** **** " +" **** ** ** **** " +" **** **** " +" ***** ***** " +" *************** " +" *************** " +" ** ** " +" ************* " +" ************* " +" ************* " +" ************* " +" *********** " +" " +" " +" " +" " +" *** " +" * * " +" *** *** " +" ** ** " +" ** * * ** " +" * * * * * * " +" * ** ** * " +" * * * * " +" * * * * * * " +" * * * * * * " +" * * * * * " +" * * * * * " +" * * * * " +" * * * * " +" * * " +" * ********* * " +" * * " +" * * " +" ** ** " +" *********** " +" " +" " +" " +" " +" *** " +" * * " +" *** *** " +" ** ** " +" ** * * ** " +" **** * * **** " +" ******* ******* " +" ******* ******* " +" *** ** * * ** *** " +" *** **** **** *** " +" *** ***** ***** *** " +" **** ********* **** " +" **** ******* **** " +" ***** ***** ***** " +" *************** " +" ** ** " +" ************* " +" ************* " +" ************* " +" *********** " +" " +" " +" " +" " +" " +" " +" " +" " +" *** " +" * * " +" * * " +" * * " +" * * " +" * * " +" *** " +" * * " +" * * " +" ** ** " +" * * " +" * * " +" ******* " +" * * " +" *********** " +" *********** " +" " +" " +" " +" " +" " +" " +" " +" " +" *** " +" ***** " +" ******* " +" ******* " +" ******* " +" ***** " +" *** " +" ***** " +" ***** " +" ******* " +" ***** " +" ***** " +" ******* " +" * * " +" *********** " +" *********** " +" " +" " +; + +int main(void) +{ + int i; + unsigned char c = 0; + + printf("const char gfxTiles[PAWN][2][384] = \n{\n"); + for(i=0; i +#include +#include +#include +#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%.*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"); +} diff --git a/src/term/platTerm.c b/src/term/platTerm.c index 980fbf6..f5d0e2c 100644 --- a/src/term/platTerm.c +++ b/src/term/platTerm.c @@ -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() {