This commit is contained in:
equant 2022-02-19 15:45:59 -07:00
commit d2e4ee41ea
106 changed files with 2429 additions and 87 deletions

View File

@ -0,0 +1,21 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.18362.0",
"compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/cl.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64"
}
],
"version": 4
}

View File

@ -0,0 +1,5 @@
{
"files.associations": {
"plat.h": "c"
}
}

View File

@ -0,0 +1,59 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build and Run",
"type": "shell",
"command": "make dsk test",
"args": [],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"clear": true
},
"problemMatcher": [
"$ca65",
"$ld65",
"$ld65-config",
"$ld65-unresolved"
]
},
{
"label": "Clean",
"type": "shell",
"command": "make clean",
"args": [],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"clear": true
},
"problemMatcher": []
},
{
"label": "Build",
"type": "shell",
"command": "make",
"args": [],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"clear": true
},
"problemMatcher": [
"$ca65",
"$ld65",
"$ld65-config",
"$ld65-unresolved"
]
}
]
}

View File

@ -0,0 +1,345 @@
###############################################################################
### Generic Makefile for cc65 projects - full version with abstract options ###
### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" Łogiewa ###
###############################################################################
###############################################################################
### In order to override defaults - values can be assigned to the variables ###
###############################################################################
# Space or comma separated list of cc65 supported target platforms to build for.
# Default: c64 (lowercase!)
TARGETS := apple2
# Name of the final, single-file executable.
# Default: name of the current dir with target name appended
PROGRAM := chess
# Path(s) to additional libraries required for linking the program
# Use only if you don't want to place copies of the libraries in SRCDIR
# Default: none
LIBS :=
# Custom linker configuration file
# Use only if you don't want to place it in SRCDIR
# Default: none
CONFIG :=
# Additional C compiler flags and options.
# Default: none
CFLAGS =
# Additional assembler flags and options.
# Default: none
ASFLAGS =
# Additional linker flags and options.
# Default: none
LDFLAGS =
cc65-Chess.apple2: LDFLAGS += --start-addr 0x4000 -Wl -D -Wl __HIMEM__=0xBF00
# Path to the directory containing C and ASM sources.
# Default: src
SRCDIR :=
# Path to the directory where object files are to be stored (inside respective target subdirectories).
# Default: obj
OBJDIR :=
# Command used to run the emulator.
# Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload
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 :=
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 :=
CX16_HOME :=
AWIN_HOME :=
ORIC_HOME :=
ATARI_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
STATEFILE := Makefile.options
###################################################################################
#### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! ####
###################################################################################
###################################################################################
### Mapping abstract options to the actual compiler, assembler and linker flags ###
### Predefined compiler, assembler and linker flags, used with abstract options ###
### valid for 2.14.x. Consult the documentation of your cc65 version before use ###
###################################################################################
# Compiler flags used to tell the compiler to optimise for SPEED
define _optspeed_
CFLAGS += -Oris
endef
# Compiler flags used to tell the compiler to optimise for SIZE
define _optsize_
CFLAGS += -Or
endef
# Compiler and assembler flags for generating listings
define _listing_
CFLAGS += --listing $$(@:.o=.lst)
ASFLAGS += --listing $$(@:.o=.lst)
REMOVES += $(addsuffix .lst,$(basename $(OBJECTS)))
endef
# Linker flags for generating map file
define _mapfile_
LDFLAGS += --mapfile $$@.map
REMOVES += $(PROGRAM).map
endef
# Linker flags for generating VICE label file
define _labelfile_
LDFLAGS += -Ln $$@.lbl
REMOVES += $(PROGRAM).lbl
endef
# Linker flags for generating a debug file
define _debugfile_
LDFLAGS += -Wl --dbgfile,$$@.dbg
REMOVES += $(PROGRAM).dbg
endef
###############################################################################
### Defaults to be used if nothing defined in the editable sections above ###
###############################################################################
# Presume the C64 target like the cl65 compile & link utility does.
# Set TARGETS to override.
ifeq ($(TARGETS),)
TARGETS := c64
endif
# Presume we're in a project directory so name the program like the current
# directory. Set PROGRAM to override.
ifeq ($(PROGRAM),)
PROGRAM := $(notdir $(CURDIR))
endif
# Presume the C and asm source files to be located in the subdirectory 'src'.
# Set SRCDIR to override.
ifeq ($(SRCDIR),)
SRCDIR := src
endif
# Presume the object and dependency files to be located in the subdirectory
# 'obj' (which will be created). Set OBJDIR to override.
ifeq ($(OBJDIR),)
OBJDIR := obj
endif
TARGETOBJDIR := $(OBJDIR)/$(TARGETS)
# Default emulator commands and options for particular targets.
# Set EMUCMD to override.
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
plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload
# So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option
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 := $(ATARI_HOME)Altirra64 /defprofile:800 /disk cc65-Chess.atr
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)
endif
###############################################################################
### The magic begins ###
###############################################################################
# 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 $(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-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.
#
# cmd.exe has an internal command 'mkdir' that doesn't understand nor require a
# '-p' to create parent directories as needed.
#
# cmd.exe has an internal command 'del' that reports a syntax error if executed
# without any file so make sure to call it only if there's an actual argument.
ifeq ($(shell echo),)
MKDIR = mkdir -p $1
RMDIR = rmdir $1
RMFILES = $(RM) $1
else
MKDIR = mkdir $(subst /,\,$1)
RMDIR = rmdir $(subst /,\,$1)
RMFILES = $(if $1,del /f $(subst /,\,$1))
endif
COMMA := ,
SPACE := $(N/A) $(N/A)
define NEWLINE
endef
# Note: Do not remove any of the two empty lines above !
TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS))
ifeq ($(words $(TARGETLIST)),1)
# Set PROGRAM to something like 'myprog.c64'.
override PROGRAM := $(PROGRAM).$(TARGETLIST)
# Set SOURCES to something like 'src/foo.c src/bar.s'.
# Use of assembler files with names ending differently than .s is deprecated!
SOURCES := $(wildcard $(SRCDIR)/*.c)
SOURCES += $(wildcard $(SRCDIR)/*.s)
SOURCES += $(wildcard $(SRCDIR)/*.asm)
SOURCES += $(wildcard $(SRCDIR)/*.a65)
# Add to SOURCES something like 'src/c64/me.c src/c64/too.s'.
# Use of assembler files with names ending differently than .s is deprecated!
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c)
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s)
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm)
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65)
# Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'.
OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES)))))
# Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'.
DEPENDS := $(OBJECTS:.o=.d)
# Add to LIBS something like 'src/foo.lib src/c64/bar.lib'.
LIBS += $(wildcard $(SRCDIR)/*.lib)
LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib)
# Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'.
CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg)
CONFIG += $(wildcard $(SRCDIR)/*.cfg)
# Select CONFIG file to use. Target specific configs have higher priority.
ifneq ($(word 2,$(CONFIG)),)
CONFIG := $(firstword $(CONFIG))
$(info Using config file $(CONFIG) for linking)
endif
.SUFFIXES:
.PHONY: all test clean zap love
all: $(PROGRAM)
-include $(DEPENDS)
-include $(STATEFILE)
# If OPTIONS are given on the command line then save them to STATEFILE
# if (and only if) they have actually changed. But if OPTIONS are not
# given on the command line then load them from STATEFILE. Have object
# files depend on STATEFILE only if it actually exists.
ifeq ($(origin OPTIONS),command line)
ifneq ($(OPTIONS),$(_OPTIONS_))
ifeq ($(OPTIONS),)
$(info Removing OPTIONS)
$(shell $(RM) $(STATEFILE))
$(eval $(STATEFILE):)
else
$(info Saving OPTIONS=$(OPTIONS))
$(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE))
endif
$(eval $(OBJECTS): $(STATEFILE))
endif
else
ifeq ($(origin _OPTIONS_),file)
$(info Using saved OPTIONS=$(_OPTIONS_))
OPTIONS = $(_OPTIONS_)
$(eval $(OBJECTS): $(STATEFILE))
endif
endif
# Transform the abstract OPTIONS to the actual cc65 options.
$(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_)))
# Strip potential variant suffix from the actual cc65 target.
CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST)))
# The remaining targets.
$(TARGETOBJDIR):
$(call MKDIR,$@)
vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR)
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR)
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR)
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR)
cl65 -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
$(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS)
cl65 -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
test: $(PROGRAM)
$(PREEMUCMD)
$(EMUCMD) $<
$(POSTEMUCMD)
clean:
$(call RMFILES,$(OBJECTS))
$(call RMFILES,$(DEPENDS))
$(call RMFILES,$(REMOVES))
$(call RMFILES,$(PROGRAM))
else # $(words $(TARGETLIST)),1
all test clean:
$(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE))
endif # $(words $(TARGETLIST)),1
OBJDIRLIST := $(wildcard $(OBJDIR)/*)
zap:
$(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE))
$(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE))
-$(call RMDIR,$(OBJDIR))
-$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE))
love:
@echo "Not war, eh?"
###################################################################
### Place your additional targets in the additional Makefiles ###
### in the same directory - their names have to end with ".mk"! ###
###################################################################
-include *.mk

View File

@ -0,0 +1,22 @@
DSK = cc65-Chess.dsk
# For this one, see https://applecommander.github.io/
#AC ?= ac.jar
AC ?= ~/bin/AppleCommander.jar
# Unix or Windows
ifeq ($(shell echo),)
CP = cp $1
else
CP = copy $(subst /,\,$1)
endif
REMOVES += $(DSK)
.PHONY: dsk
dsk: $(DSK)
$(DSK): cc65-Chess.apple2
$(call CP, apple2/template.dsk $@)
java -jar $(AC) -p $@ chess.system sys < $(shell cl65 --print-target-path)/apple2/util/loader.system
java -jar $(AC) -as $@ chess bin < cc65-Chess.apple2

View File

@ -0,0 +1 @@
_OPTIONS_=optspeed

View File

@ -0,0 +1,4 @@
obj/apple2/globals.o: src/globals.c src/types.h src/globals.h
src/globals.c src/types.h src/globals.h:

View File

@ -0,0 +1,4 @@
obj/apple2/hires.o: src/apple2/hires.s /usr/share/cc65/asminc/apple2.inc /usr/share/cc65/asminc/zeropage.inc src/apple2/charset.bin src/apple2/pieces.bin
src/apple2/hires.s /usr/share/cc65/asminc/apple2.inc /usr/share/cc65/asminc/zeropage.inc src/apple2/charset.bin src/apple2/pieces.bin:

View File

@ -0,0 +1,4 @@
obj/apple2/human.o: src/human.c src/types.h src/globals.h src/human.h src/plat.h
src/human.c src/types.h src/globals.h src/human.h src/plat.h:

View File

@ -0,0 +1,4 @@
obj/apple2/main.o: src/main.c src/types.h src/globals.h src/human.h src/plat.h src/apple2idiot.h src/../../../chess/chess_commands.h src/../../../../arduino-lib/Apple2Idiot/A2I_commands.h
src/main.c src/types.h src/globals.h src/human.h src/plat.h src/apple2idiot.h src/../../../chess/chess_commands.h src/../../../../arduino-lib/Apple2Idiot/A2I_commands.h:

View File

@ -0,0 +1,4 @@
obj/apple2/platA2.o: src/apple2/platA2.c src/apple2/../types.h src/apple2/../globals.h src/apple2/../plat.h
src/apple2/platA2.c src/apple2/../types.h src/apple2/../globals.h src/apple2/../plat.h:

View File

@ -0,0 +1,302 @@
/*
* genPieces.cpp
* cc65 Chess
*
* Created by Oliver Schmidt, January 2020.
* Pieces designed by Frank Gebhart, 1980s.
*
*/
#include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
char pieces[]=
" "
" **** ***** **** "
" * * * * * * "
" * * * * * * "
" * ***** ***** * "
" * * "
" * * "
" * * "
" * ********* * "
" ** ** "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * *********** * "
" * * "
" ******************* "
" ******************* "
" "
" "
" **** ***** **** "
" **** ***** **** "
" **** ***** **** "
" ******************* "
" ******************* "
" ***************** "
" *************** "
" ************* "
" * * "
" *********** "
" *********** "
" *********** "
" *********** "
" *********** "
" ************* "
" *************** "
" *************** "
" * * "
" ******************* "
" ******************* "
" "
" "
" * * "
" * * * * "
" * * * "
" * * "
" * * "
" * * * * "
" * * * "
" * ** * "
" * * * "
" * * "
" * **** * "
" * * * * ** "
" ** * ** * "
" * * * "
" * * * "
" * ** "
" * * "
" * ************ * "
" * * "
" **************** "
" "
" "
" * * "
" * * * * "
" ***** *** "
" ********** "
" ************ "
" **** **** ** "
" ********* ** "
" ********** ** "
" ************ ** "
" **************** "
" **************** "
" **** **** *** "
" ** ***** ** "
" ******* *** "
" ********* ** "
" ************** "
" *************** "
" * * "
" **************** "
" **************** "
" "
" "
" "
" *** "
" * * "
" * * "
" * * * "
" * * * "
" * ******* * "
" * * * "
" * * * "
" * * * "
" * * * "
" * * "
" * * "
" ******* "
" * * "
" * * "
" ***** "
" * * "
" *************** "
" ***************** "
" "
" "
" "
" *** "
" ***** "
" ******* "
" **** **** "
" ***** ***** "
" ** ** "
" ****** ****** "
" ****** ****** "
" ****** ****** "
" ***** ***** "
" *********** "
" ********* "
" * * "
" ******* "
" ******* "
" ***** "
" *********** "
" * * "
" ***************** "
" "
" "
" "
" *** "
" * * "
" *** * * *** "
" * * * * * * "
" * * * * * * "
" * * * * * * "
" * * "
" * * * * * "
" * ** *** ** * "
" * ********* * "
" * ******* * "
" * * "
" * * "
" * *********** * "
" * * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" "
" *** "
" ***** "
" *** ***** *** "
" ***** *** ***** "
" ****** ***** ****** "
" ***** ******* ***** "
" ******************* "
" **** **** **** **** "
" **** ** ** **** "
" **** **** "
" ***** ***** "
" *************** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" * * * * * * "
" * ** ** * "
" * * * * "
" * * * * * * "
" * * * * * * "
" * * * * * "
" * * * * * "
" * * * * "
" * * * * "
" * * "
" * ********* * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" **** * * **** "
" ******* ******* "
" ******* ******* "
" *** ** * * ** *** "
" *** **** **** *** "
" *** ***** ***** *** "
" **** ********* **** "
" **** ******* **** "
" ***** ***** ***** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" "
" "
" "
" "
" *** "
" * * "
" * * "
" * * "
" * * "
" * * "
" *** "
" * * "
" * * "
" ** ** "
" * * "
" * * "
" ******* "
" * * "
" *********** "
" *********** "
" "
" "
" "
" "
" "
" "
" *** "
" ***** "
" ******* "
" ******* "
" ******* "
" ***** "
" *** "
" ***** "
" ***** "
" ******* "
" ***** "
" ***** "
" ******* "
" * * "
" *********** "
" *********** "
" "
;
int main(void)
{
int i;
int f = open("pieces.bin",O_CREAT|O_TRUNC|O_WRONLY);
char c = 0;
for(i=0; i<sizeof(pieces); ++i)
{
c |= (pieces[i] == '*') << i%7;
if (i%7 == 6)
{
write(f,&c,1);
c = 0;
}
}
close(f);
return 0;
}

View File

@ -0,0 +1,192 @@
;
; hires.s
; cc65 Chess
;
; Created by Oliver Schmidt, January 2020.
;
;
.export _hires_CharSet, _hires_Pieces
.export _hires_Init, _hires_Done, _hires_Text, _hires_Draw, _hires_Mask
.include "apple2.inc"
.include "zeropage.inc"
.import popa, popax
VERSION := $FBB3
.rodata
BASELO:
.repeat $C0, I
.byte I & $08 << 4 | I & $C0 >> 1 | I & $C0 >> 3
.endrep
BASEHI:
.repeat $C0, I
.byte >$2000 | I & $07 << 2 | I & $30 >> 4
.endrep
_hires_CharSet:
.incbin "charset.bin"
_hires_Pieces:
.incbin "pieces.bin"
.code
.proc _hires_Init
bit $C082 ; Switch in ROM
lda VERSION ; Needs ROM
cmp #$06 ; Apple //e ?
bne :+
lda #$15 ; Turn off 80-column firmware
jsr $C300 ; Needs ROM (see $CEF4)
: bit $C080 ; Back to LC bank 2 for R/O
bit TXTCLR
bit MIXCLR
bit HIRES
lda #20
sta WNDTOP ; Prepare hires_text()
rts
.endproc
.proc _hires_Done
bit TXTSET
lda #00
sta WNDTOP ; Back to full screen text
rts
.endproc
.proc _hires_Text
tax ; 'flag'
lda MIXCLR,x
rts
.endproc
.data
.proc _hires_Draw
sta src+1 ; 'src' lo
stx src+2 ; 'src' hi
jsr popax ; 'rop'
stx rop
sta rop+1
jsr popa ; 'ysize'
sta ymax+1
jsr popa ; 'xsize'
sta xmax+1
jsr popa ; 'ypos'
sta ypos+1
tax
clc
adc ymax+1
sta ymax+1
jsr popa ; 'xpos'
sta xpos+1
clc
adc xmax+1
sta xmax+1
yloop:
lda BASELO,x
sta dst+1
lda BASEHI,x
sta dst+2
xpos: ldx #$FF ; Patched
xloop:
src: lda $FFFF,y ; Patched
iny
rop: nop ; Patched
nop ; Patched
dst: sta $FFFF,x ; Patched
inx
xmax: cpx #$FF ; Patched
bne xloop
inc ypos+1
ypos: ldx #$FF ; Patched
ymax: cpx #$FF ; Patched
bne yloop
rts
.endproc
.proc _hires_Mask
stx rop ; 'rop' hi
sta rop+1 ; 'rop' lo
jsr popa ; 'ysize'
sta ymax+1
jsr popa ; 'xsize'
sta xmax+1
jsr popa ; 'ypos'
tax
clc
adc ymax+1
sta ymax+1
jsr popa ; 'xpos'
sta xpos+1
clc
adc xmax+1
sta xmax+1
yloop:
lda BASELO,x
sta src+1
sta dst+1
lda BASEHI,x
sta src+2
sta dst+2
xpos: ldy #$FF ; Patched
xloop:
src: lda $FFFF,y ; Patched
rop: nop ; Patched
nop ; Patched
dst: sta $FFFF,y ; Patched
iny
xmax: cpy #$FF ; Patched
bne xloop
inx
ymax: cpx #$FF ; Patched
bne yloop
rts
.endproc

View File

@ -0,0 +1,337 @@
/*
* platA2.c
* cc65 Chess
*
* Created by Oliver Schmidt, January 2020.
*
*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include "../types.h"
#include "../globals.h"
#include "../plat.h"
/*-----------------------------------------------------------------------*/
#define BOARD_PIECE_WIDTH 3
#define BOARD_PIECE_HEIGHT 22
#define CHAR_HEIGHT 8
#define LOG_WINDOW_HEIGHT 23
#define SCREEN_WIDTH 40
#define SCREEN_HEIGHT 192
#define ROP_CONST(val) 0xA980|(val)
#define ROP_BLACK 0xA980
#define ROP_WHITE 0xA9FF
#define ROP_XOR(val) 0x4900|(val)
#define ROP_CPY 0x4980
#define ROP_INV 0x49FF
#define ROP_AND(val) 0x2900|(val)
char rop_Line[2][7] = {{0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F},
{0x00, 0x40, 0x60, 0x70, 0x78, 0x7C, 0x7E}};
char rop_Color[2][2] = {{0x55, 0x2A}, {0xD5, 0xAA}};
extern char hires_CharSet[96][CHAR_HEIGHT];
extern char hires_Pieces[6][2][BOARD_PIECE_WIDTH*BOARD_PIECE_HEIGHT];
void hires_Init(void);
void hires_Done(void);
void hires_Text(char flag);
void hires_Draw(char xpos, char ypos,
char xsize, char ysize,
unsigned rop, char *src);
void hires_Mask(char xpos, char ypos,
char xsize, char ysize,
unsigned rop);
/*-----------------------------------------------------------------------*/
void plat_Drawchar(char x, char y, unsigned rop, char c)
{
hires_Draw(x,y,1,CHAR_HEIGHT,rop,hires_CharSet[c-' ']);
}
/*-----------------------------------------------------------------------*/
void plat_Drawstring(char x, char y, unsigned rop, char *s)
{
while(*s)
plat_Drawchar(x++,y,rop,*s++);
}
/*-----------------------------------------------------------------------*/
void plat_Init()
{
char i;
// Clear the hires screen
hires_Mask(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ROP_BLACK);
// Show the hires screen
hires_Init();
// Draw the board border
hires_Mask( 1, 12,1,8*BOARD_PIECE_HEIGHT+2*2,ROP_CONST(rop_Line[1][2]));
hires_Mask(26, 12,1,8*BOARD_PIECE_HEIGHT+2*2,ROP_CONST(rop_Line[0][2]));
hires_Mask( 2, 12,8*BOARD_PIECE_WIDTH,2, ROP_WHITE);
hires_Mask( 2,190,8*BOARD_PIECE_WIDTH,2, ROP_WHITE);
// Add the A..H and 1..8 tile-keys
for(i=0; i<8; ++i)
{
plat_Drawchar(3+i*BOARD_PIECE_WIDTH,0, ROP_CPY,i+'A');
plat_Drawchar(0,SCREEN_HEIGHT-17-i*BOARD_PIECE_HEIGHT,ROP_CPY,i+'1');
}
}
/*-----------------------------------------------------------------------*/
char plat_Menu(char **menuItems, char height, char *scroller)
{
int keyMask;
char i, j;
clrscr();
hires_Text(1);
// Show the title or the scroller if that is more relevant.
// cputs(scroller == gszAbout ? menuItems[0] : scroller);
// Select the first item
i = 1;
do
{
// Show all the menu items
for(j=1; j<height; ++j)
{
if(!menuItems[j])
break;
gotoxy(((j-1)%2)*SCREEN_WIDTH/2,((j-1)/2)+1);
// Highlight the selected item
if(j==i)
revers(1);
cprintf(" %s ",menuItems[j]);
if(j==i)
revers(0);
}
// Look for user input
keyMask = plat_ReadKeys(1);
if(keyMask & INPUT_MOTION)
{
switch(keyMask & INPUT_MOTION)
{
case INPUT_LEFT:
if(!--i)
i = j-1;
break;
case INPUT_RIGHT:
if(j == ++i)
i = 1;
break;
case INPUT_UP:
if(i > 2)
i -= 2;
else
i = j-1-(i-1)%2;
break;
case INPUT_DOWN:
if(i < j-2)
i += 2;
else
i = 1+(i-1)%2;
break;
}
}
keyMask &= (INPUT_SELECT | INPUT_BACKUP);
} while(keyMask != INPUT_SELECT && keyMask != INPUT_BACKUP);
hires_Text(0);
// 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;
if(clearLog)
hires_Mask(27,0,SCREEN_WIDTH-27,SCREEN_HEIGHT,ROP_BLACK);
// 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)
{
unsigned rop;
char inv;
char y = position / 8, x = position & 7;
char piece = gChessBoard[y][x];
char blackWhite = !((x & 1) ^ (y & 1));
if(piece)
{
rop = blackWhite ? ROP_INV : ROP_CPY;
inv = blackWhite ^ (piece & PIECE_WHITE) != 0;
}
else
rop = blackWhite ? ROP_WHITE : ROP_BLACK;
hires_Draw(2+x*BOARD_PIECE_WIDTH,14+y*BOARD_PIECE_HEIGHT,
BOARD_PIECE_WIDTH,BOARD_PIECE_HEIGHT,rop,
hires_Pieces[(piece&PIECE_DATA)-1][inv]);
}
/*-----------------------------------------------------------------------*/
void plat_ShowSideToGoLabel(char side)
{
// plat_Drawstring(28,SCREEN_HEIGHT-CHAR_HEIGHT,
// side?ROP_CPY:ROP_INV,gszSideLabel[side]);
}
/*-----------------------------------------------------------------------*/
void plat_Highlight(char position, char color, char cursor)
{
char y = position / 8, x = position & 7;
if (cursor && color != HCOLOR_SELECTED)
{
char size = color == HCOLOR_EMPTY ? 6 : color == HCOLOR_INVALID ? 4 : 2;
hires_Mask(2+x*BOARD_PIECE_WIDTH,14+y*BOARD_PIECE_HEIGHT+size,
1,BOARD_PIECE_HEIGHT-2*size,ROP_XOR(rop_Line[0][size]));
hires_Mask(2+x*BOARD_PIECE_WIDTH+BOARD_PIECE_WIDTH-1,14+y*BOARD_PIECE_HEIGHT+size,
1,BOARD_PIECE_HEIGHT-2*size,ROP_XOR(rop_Line[1][size]));
hires_Mask(2+x*BOARD_PIECE_WIDTH,14+y*BOARD_PIECE_HEIGHT,
BOARD_PIECE_WIDTH,size,ROP_XOR(0x7F));
hires_Mask(2+x*BOARD_PIECE_WIDTH,14+y*BOARD_PIECE_HEIGHT+BOARD_PIECE_HEIGHT-size,
BOARD_PIECE_WIDTH,size,ROP_XOR(0x7F));
}
else
{
char set = color == HCOLOR_ATTACK;
char val = cursor ^ x * BOARD_PIECE_WIDTH & 1;
hires_Mask(2+x*BOARD_PIECE_WIDTH,14+y*BOARD_PIECE_HEIGHT,
1,BOARD_PIECE_HEIGHT,ROP_AND(rop_Color[set][!val]));
hires_Mask(2+x*BOARD_PIECE_WIDTH+1,14+y*BOARD_PIECE_HEIGHT,
1,BOARD_PIECE_HEIGHT,ROP_AND(rop_Color[set][val]));
hires_Mask(2+x*BOARD_PIECE_WIDTH+2,14+y*BOARD_PIECE_HEIGHT,
1,BOARD_PIECE_HEIGHT,ROP_AND(rop_Color[set][!val]));
}
}
/*-----------------------------------------------------------------------*/
void plat_ShowMessage(char *str, char)
{
plat_Drawstring(26,0,ROP_CPY,str);
}
/*-----------------------------------------------------------------------*/
void plat_ClearMessage()
{
hires_Mask(26,0,7,CHAR_HEIGHT,ROP_BLACK);
}
/*-----------------------------------------------------------------------*/
int plat_ReadKeys(char blocking)
{
char key = 0;
int keyMask = 0;
if(blocking || kbhit())
key = cgetc();
else
return 0;
switch(key)
{
case CH_CURS_LEFT:
keyMask |= INPUT_LEFT;
break;
case CH_CURS_RIGHT:
keyMask |= INPUT_RIGHT;
break;
case 'O':
case 'o': // Reasonably located on the ][ keyboard
case 0x0B: // No CH_CURS_UP in apple2.h, only in apple2enh.h
keyMask |= INPUT_UP;
break;
case 'L':
case 'l': // Reasonably located on the ][ keyboard
case 0x0A: // No CH_CURS_DOWN in apple2.h, only in apple2enh.h
keyMask |= INPUT_DOWN;
break;
case CH_ESC:
keyMask |= INPUT_BACKUP;
break;
case CH_ENTER:
keyMask |= INPUT_SELECT;
break;
case 'A':
case 'a': // Show Attackers
keyMask |= INPUT_TOGGLE_A;
break;
case 'B':
case 'b': // Board attacks - Show all attacks
keyMask |= INPUT_TOGGLE_B;
break;
case 'D':
case 'd': // Show Defenders
keyMask |= INPUT_TOGGLE_D;
break;
case 'M':
case 'm':
keyMask |= INPUT_MENU;
break;
case 'R':
case 'r':
keyMask |= INPUT_REDO;
break;
case 'U':
case 'u':
keyMask |= INPUT_UNDO;
break;
}
return keyMask;
}
/*-----------------------------------------------------------------------*/
// Only ever gets called if gReturnToOS is true
void plat_Shutdown()
{
hires_Done();
}

View File

@ -0,0 +1,17 @@
/*
* globals.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#include "types.h"
#include "globals.h"
/*-----------------------------------------------------------------------*/
char gChessBoard[8][8]; // The chess board itself - row, col
char gCursorPos[2][2]; // Remember last cursor pos for human players
char gTile[2]; // Tiles on board that user selected - linear 0..63 ; 0 = src, 1 = dest
char state = STATE_NONE;

View File

@ -0,0 +1,18 @@
/*
* globals.h
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#ifndef _GLOBALS_H_
#define _GLOBALS_H_
extern char gChessBoard[8][8];
extern char gCursorPos[2][2];
extern char gTile[2];
extern char state;
#endif //_GLOBALS_H_

View File

@ -0,0 +1,161 @@
/*
* human.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#include "types.h"
#include "globals.h"
#include "human.h"
#include "plat.h"
#include "apple2idiot.h"
#include "../../../chess/chess_commands.h"
#include "../../../../arduino-lib/Apple2Idiot/A2I_commands.h"
/*-----------------------------------------------------------------------*/
// Internal function Prototype
void human_ProcessInput(int keyMask);
void human_ProcessToggle(int keyMask, char side, char tile);
/*-----------------------------------------------------------------------*/
// Track the user controlled curson on the board
static char sc_cursorX, sc_cursorY;
/*-----------------------------------------------------------------------*/
// Handle the cursor movement
void human_ProcessInput(int keyMask)
{
switch(keyMask)
{
case INPUT_UP:
if(!sc_cursorY)
sc_cursorY = 7;
else
--sc_cursorY;
break;
case INPUT_RIGHT:
if(7==sc_cursorX)
sc_cursorX = 0;
else
++sc_cursorX;
break;
case INPUT_DOWN:
if(7==sc_cursorY)
sc_cursorY = 0;
else
++sc_cursorY;
break;
case INPUT_LEFT:
if(!sc_cursorX)
sc_cursorX = 7;
else
--sc_cursorX;
break;
}
}
/*-----------------------------------------------------------------------*/
// Main routine when it's a human player's turn.
// The routine is sort-of in 2 parts. The bit before the user key is read
// and the bit after the key is read.
char human_Play(char side)
{
int keyMask = INPUT_MOTION;
char selector = 0;
// get this sides' cursor
sc_cursorY = gCursorPos[side][0];
sc_cursorX = gCursorPos[side][1];
gTile[0] = sc_cursorY * 8 + sc_cursorX;
do
{
if(keyMask & INPUT_MOTION)
{
// Show the cursor
plat_Highlight(gTile[0], selector ? HCOLOR_SELECTED : gChessBoard[sc_cursorY][sc_cursorX] == NONE ? HCOLOR_EMPTY : HCOLOR_VALID, 1);
if(selector)
{
plat_Highlight(gTile[1], HCOLOR_ATTACK, 1);
}
}
// Get input
keyMask = plat_ReadKeys(1);
if(keyMask & INPUT_MOTION)
{
// Erase the cursor and move it
plat_DrawSquare(gTile[selector]);
human_ProcessInput(keyMask & INPUT_MOTION);
gTile[selector] = sc_cursorY * 8 + sc_cursorX;
plat_DrawSquare(gTile[selector]);
}
else if(keyMask & INPUT_MENU)
{
// Drop out so the menu can be displayed
return OUTCOME_MENU;
}
else if(keyMask & INPUT_BACKUP)
{
// If a piece was selected, deselct the piece
if(selector)
{
plat_DrawSquare(gTile[selector]);
selector = 0;
sc_cursorY = gTile[0] / 8;
sc_cursorX = gTile[0] & 7;
keyMask = INPUT_MOTION;
}
// Otherwise bring up the menu
else
return OUTCOME_MENU;
}
else if(keyMask & INPUT_SELECT)
{
// Check that the piece selected is on the side of the player playing
if(!selector && (gChessBoard[sc_cursorY][sc_cursorX] >> 7) == side)
{
// If the cursor is on a piece of this turn, that has moved and no other piece
// has yet been selected, then select this piece
++selector;
gTile[1] = gTile[0];
keyMask = INPUT_MOTION; // Force a cursor re-draw
}
else if(gTile[0] == gTile[1])
{
// If the selected tile is re-selected, deselect it
--selector;
// Since plat_Highlight doesn't undraw selected, just draw this tile
plat_DrawSquare(gTile[0]);
keyMask = INPUT_MOTION; // force a redraw (which should have made the plat_Drawsquae above unnecessary)
}
else if(selector)
{
// Doesn't consider if this is a valid move, just does it
//write_string_to_ram(RAM_DATA_START_ADDRESS, player_move);
write_byte(APPLE_COMMAND_ADDRESS, CHESS_MAKE_MOVE);
gChessBoard[sc_cursorY][sc_cursorX] = gChessBoard[gTile[0]/8][gTile[0]&7];
gChessBoard[gTile[0]/8][gTile[0]&7] = NONE;
plat_DrawSquare(gTile[0]);
plat_DrawSquare(gTile[1]);
++selector;
}
}
} while(selector < 2);
// Save the cursor positions for next time
gCursorPos[side][0] = sc_cursorY;
gCursorPos[side][1] = sc_cursorX;
return OUTCOME_OK;
}

View File

@ -0,0 +1,14 @@
/*
* human.h
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#ifndef _HUMAN_H_
#define _HUMAN_H_
char human_Play(char side);
#endif //_HUMAN_H_

View File

@ -0,0 +1,97 @@
/*
* main.c
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#include "types.h"
#include "globals.h"
#include "human.h"
#include "plat.h"
#include "apple2idiot.h"
#include "../../../chess/chess_commands.h"
#include "../../../../arduino-lib/Apple2Idiot/A2I_commands.h"
/*-----------------------------------------------------------------------*/
void board_Init()
{
char x,y,i;
for(x=0; x < 8; x++)
{
for(y=0; y < 8; y++)
{
gChessBoard[x][y] = NONE;
}
}
gChessBoard[0][0] = gChessBoard[7][0] = ROOK;
gChessBoard[0][1] = gChessBoard[7][1] = KNIGHT;
gChessBoard[0][2] = gChessBoard[7][2] = BISHOP;
gChessBoard[0][3] = gChessBoard[7][3] = QUEEN;
gChessBoard[0][4] = gChessBoard[7][4] = KING;
gChessBoard[0][5] = gChessBoard[7][5] = BISHOP;
gChessBoard[0][6] = gChessBoard[7][6] = KNIGHT;
gChessBoard[0][7] = gChessBoard[7][7] = ROOK;
for(i=0; i < 8; ++i)
{
gChessBoard[1][i] = PAWN;
gChessBoard[6][i] = PAWN | PIECE_WHITE;
gChessBoard[7][i] |= PIECE_WHITE;
}
// Not part of the board but does need resetting for every game
gCursorPos[SIDE_BLACK][1] = gCursorPos[SIDE_WHITE][1] = 4;
gCursorPos[SIDE_BLACK][0] = 1;
gCursorPos[SIDE_WHITE][0] = 6;
}
/*-----------------------------------------------------------------------*/
// Internal function Prototype
void gameLoop(void);
void init(void);
/*-----------------------------------------------------------------------*/
int main()
{
init();
while (state != STATE_QUIT) {
switch(state) {
case STATE_AI_GAME:
break;
//case STATE_NONE:
//break;
default:
gameLoop();
break;
}
}
plat_Shutdown();
return 0;
}
/*-----------------------------------------------------------------------*/
void init()
{
board_Init();
plat_Init();
}
/*-----------------------------------------------------------------------*/
void gameLoop()
{
char side = SIDE_WHITE, outcome = OUTCOME_OK;
plat_DrawBoard(1);
while(outcome != OUTCOME_QUIT)
{
outcome = human_Play(side);
side = 1 - side;
}
}

View File

@ -0,0 +1,24 @@
/*
* plat.h
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#ifndef _PLAT_H_
#define _PLAT_H_
void plat_Init(void);
void plat_UpdateScreen(void);
char plat_Menu(char **menuItems, char height, char *scroller);
void plat_DrawBoard(char clearLog);
void plat_DrawSquare(char position);
void plat_ShowSideToGoLabel(char side);
void plat_Highlight(char position, char color, char cursor);
void plat_ShowMessage(char *str, char color);
void plat_ClearMessage(void);
int plat_ReadKeys(char blocking);
void plat_Shutdown(void);
#endif //_PLAT_H_

View File

@ -0,0 +1,99 @@
/*
* types.h
* cc65 Chess
*
* Created by Stefan Wessels, February 2014.
*
*/
#ifndef _TYPES_H_
#define _TYPES_H_
/**********************************************************/
// Stuff from my old chess code (NPH)
#define ASCII_L 76
#define ASCII_Q 81
#define ASCII_S 83
#define ASCII_W 87
#define BACKSPACE 8
#define SIZE_X 40
#define SIZE_Y 24
#define STATE_NONE 0
#define STATE_LOCAL_GAME 1
#define STATE_QUIT 27
#define CARD_ADDRESS 0xC200
#define ESP_COMMAND_ADDRESS 0xC200
#define APPLE_COMMAND_ADDRESS 0xC201
#define RAM_DATA_START_ADDRESS 0xC202
#define ESP_TIMEOUT 5555
/**********************************************************/
#define SET_BIT(x) (1<<(x))
#define SIDE_BLACK 0
#define SIDE_WHITE 1
#define NUM_PIECES_SIDE 16
#define HCOLOR_WHITE 1
#define HCOLOR_BLACK 2
#define HCOLOR_EMPTY 4
#define HCOLOR_VALID 5
#define HCOLOR_INVALID 2
#define HCOLOR_SELECTED 6
#define HCOLOR_ATTACK 3
#define PIECE_WHITE SET_BIT(7)
#define PIECE_DATA (SET_BIT(0) | SET_BIT(1) | SET_BIT(2))
#define INPUT_UP SET_BIT(0)
#define INPUT_RIGHT SET_BIT(1)
#define INPUT_DOWN SET_BIT(2)
#define INPUT_LEFT SET_BIT(3)
#define INPUT_BACKUP SET_BIT(4)
#define INPUT_TOGGLE_A SET_BIT(5)
#define INPUT_TOGGLE_B SET_BIT(6)
#define INPUT_TOGGLE_D SET_BIT(7)
#define INPUT_SELECT SET_BIT(8)
#define INPUT_MENU SET_BIT(9)
#define INPUT_UNDO SET_BIT(10)
#define INPUT_REDO SET_BIT(11)
#define INPUT_UNDOREDO (INPUT_UNDO | INPUT_REDO)
#define INPUT_MOTION (INPUT_UP | INPUT_RIGHT | INPUT_DOWN | INPUT_LEFT)
#define INPUT_TOGGLE (INPUT_TOGGLE_A | INPUT_TOGGLE_B | INPUT_TOGGLE_D)
enum
{
NONE,
ROOK,
KNIGHT,
BISHOP,
QUEEN,
KING,
PAWN,
};
enum
{
OUTCOME_INVALID,
OUTCOME_OK,
OUTCOME_CHECK,
OUTCOME_CHECKMATE,
OUTCOME_DRAW,
OUTCOME_STALEMATE,
OUTCOME_MENU,
OUTCOME_ABANDON,
OUTCOME_QUIT,
};
#define STATE_NONE 0
#define STATE_LOCAL_GAME 1
#define STATE_AI_GAME 1
#define STATE_QUIT 27
#endif //_TYPES_H_

View File

@ -0,0 +1,4 @@
obj/apple2/apple2idiot.o: src/apple2idiot.c src/globals.h src/apple2idiot.h src/../../../../arduino-lib/Apple2Idiot/A2I_commands.h
src/apple2idiot.c src/globals.h src/apple2idiot.h src/../../../../arduino-lib/Apple2Idiot/A2I_commands.h:

View File

@ -0,0 +1 @@
../../../../cc65-lib/apple2idiot.c

View File

@ -0,0 +1 @@
../../../../cc65-lib/apple2idiot.h

Some files were not shown because too many files have changed in this diff Show More