Atari Version added

Added the Atari platform (tested on 48K Atari 800 - NTSC artifacting used for color)
This commit is contained in:
StewBC 2020-07-09 15:46:25 -07:00
parent 5233ed008b
commit 3766cbc902
9 changed files with 1478 additions and 18 deletions

View File

@ -9,7 +9,7 @@
# Space or comma separated list of cc65 supported target platforms to build for.
# Default: c64 (lowercase!)
TARGETS := apple2 atmos c64 c64.chr cx16
TARGETS := apple2 atari atmos c64 c64.chr cx16
# Name of the final, single-file executable.
# Default: name of the current dir with target name appended
@ -67,6 +67,7 @@ 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
@ -157,7 +158,7 @@ plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload
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
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

44
Makefile-atr.mk Normal file
View File

@ -0,0 +1,44 @@
# If ATARIDOS is commented out, the disk will be MyPicodos 4.05
# if ATARIDOS is not commented out, set ATARIDOSTYPE to the
# desired type (say Dos25 for Dos 2.5) and put the
# sys files for the correct version in the ataridos folder
# (i.e. dos.sys and dup.sys). Only tested with Dos25 and MyPicodos
ATR = cc65-Chess.atr
# ATARIDOS = ataridos
ATARIDOSTYPE = Dos25
ATARIDSK = atari.atr
DIR2ATR ?= dir2atr.exe
# Unix or Windows
ifeq ($(shell echo),)
CP = cp $1
else
CP = copy $(subst /,\,$1)
endif
# Just the files, not the atari.atr folder. Don't know how to extend the zap: in the Makefile
REMOVES += $(ATR) $(ATARIDSK)/cc65-Chess $(ATRDOSOBJS)
.PHONY: ATR
atr: $(ATR)
$(ATARIDSK):
$(call MKDIR,$@)
$(ATARIDSK)/%.sys:
$(call CP,$(ATARIDOS)/$(notdir $(@)) $@)
# Different based on ATARIDOS or MyPicoDos
ifeq ($(ATARIDOS),)
ATARIDOSTYPE = MyPicoDOS405
ATRDOSOBJS :=
else
# I don't know of a better way to "copy if needed" the .sys files from one folder to another
ATRDOSSRCS += $(wildcard $(ATARIDOS)/*.sys)
ATRDOSOBJS := $(addsuffix .sys,$(basename $(addprefix $(ATARIDSK)/,$(notdir $(ATRDOSSRCS)))))
endif
$(ATR): cc65-Chess.atari $(ATARIDSK) $(ATRDOSOBJS)
$(call CP,$< $(ATARIDSK)/cc65-Chess)
$(DIR2ATR) -b $(ATARIDOSTYPE) cc65-Chess.atr $(ATARIDSK)

View File

@ -1,5 +1,6 @@
0. Updates
* Jul 2020 - Added a version for the Atari.
* 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.
@ -257,9 +258,11 @@ XI. Build Instructions
All of the 8-Bit versions of cc65 Chess can be built using make.
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.
I recommend the game be built for speed on almost all targets, which also
results in smaller file and is essential for all targets. This is done by
using the OPTIONS=optspeed command line to make. For the Atari, it is
essential to use OPTIONS=optsize as the 48K Atari really needs the extra
1K of memory.
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):
@ -269,50 +272,54 @@ versions. Currently, that means the following (cc65 target name in brackets):
* Apple 2 (apple2)
* Oric-1/Atmos/Telestrat (atmos)
* Commander X16 (cx16)
* Atari (atari - Needs at least 48K, tested on Atari 800 48K)
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.
program (prg), disk (dsk, atr) or tape (tap) file. Do make again, but with dsk
(Apple 2 dsk), atr (Atari disk), tap (Oric tape), prg (C64 prg), cprg (c64.chr
prg) or cxprg (cX16 prg) on the command line.
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
make OPTIONS=optsize all dsk atr tap prg cprg cxprg
Makeing a terminal version (using curses) - See IV (b) above.
Making a terminal version (using curses) - See IV (b) above.
Examples:
1) Make everything, and then make the dsk and tap files for the Apple and Oric.
1) Make everything, and then make the images for all platforms.
make OPTIONS=optspeed
make OPTIONS=optsize
This will make the following files:
cc65-Chess.apple2
cc65-Chess.atari
cc65-Chess.atmos
cc65-Chess.c64
cc65-Chess.c64.chr
cc65-Chess.cx16
make dsk tap prg cprg cxprg
make dsk atr tap prg cprg cxprg
This will make the following files:
cc65-Chess.tap
cc65-Chess.atr
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.
Once you have used the OPTIONS=optsize (or 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
make OPTIONS=optsize 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
make OPTIONS=optsize 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.
@ -325,6 +332,6 @@ 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
Lastly - the Atari, 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.

62
src/atari/chessAtari.cfg Normal file
View File

@ -0,0 +1,62 @@
FEATURES {
STARTADDRESS: default = $2000;
}
SYMBOLS {
__EXEHDR__: type = import;
__SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
__AUTOSTART__: type = import; # force inclusion of autostart "trailer"
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTADDRESS__: type = export, value = %S;
__RESERVED_MEMORY__: type = weak, value = $0000;
}
MEMORY {
ZP: file = "", define = yes, start = $0082, size = $007E;
# file header, just $FFFF
HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
SYSCHKHDR: file = %O, start = $0000, size = $0004;
SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
MAINHDR: file = %O, start = $0000, size = $0004;
MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
TRAILER: file = %O, start = $0000, size = $0006;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes;
MAINHDR: load = MAINHDR, type = ro;
STARTUP: load = MAIN, type = ro, define = yes;
LOWBSS: load = MAIN, type = rw, optional = yes; # not zero initialized
LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
ONCE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro, define = yes;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
DLIST: load = MAIN, type = rw, define = yes, optional = yes, align = $0100;
INIT: load = MAIN, type = rw, optional = yes;
BSS: load = MAIN, type = bss, define = yes;
AUTOSTRT: load = TRAILER, type = ro;
}
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__;
}

318
src/atari/dataAtari.c Normal file
View File

@ -0,0 +1,318 @@
/*
* dataAtari.c
* cc65 Chess
*
* Created by Stefan Wessels, July 2020.
*
*/
#include "../types.h"
#include "dataAtari.h"
/*-----------------------------------------------------------------------*/
// Atari specific graphics for the chess pieces
// 66 = 3 cols * 22 rows, 2 per side, PAWN # pieces
const char gfxTiles[PAWN][2][66] =
{
{
{
0x00, 0x00, 0x00,
0x3C, 0x7C, 0x78,
0x24, 0x44, 0x48,
0x24, 0x44, 0x48,
0x27, 0xC7, 0xC8,
0x20, 0x00, 0x08,
0x10, 0x00, 0x10,
0x08, 0x00, 0x20,
0x05, 0xFF, 0x40,
0x06, 0x00, 0xC0,
0x02, 0x00, 0x80,
0x02, 0x00, 0x80,
0x02, 0x00, 0x80,
0x02, 0x00, 0x80,
0x02, 0x00, 0x80,
0x04, 0x00, 0x40,
0x08, 0x00, 0x20,
0x0B, 0xFF, 0xA0,
0x10, 0x00, 0x10,
0x3F, 0xFF, 0xF8,
0x3F, 0xFF, 0xF8,
0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00,
0x3C, 0x7C, 0x78,
0x3C, 0x7C, 0x78,
0x3C, 0x7C, 0x78,
0x3F, 0xFF, 0xF8,
0x3F, 0xFF, 0xF8,
0x1F, 0xFF, 0xF0,
0x0F, 0xFF, 0xE0,
0x07, 0xFF, 0xC0,
0x04, 0x00, 0x40,
0x03, 0xFF, 0x80,
0x03, 0xFF, 0x80,
0x03, 0xFF, 0x80,
0x03, 0xFF, 0x80,
0x03, 0xFF, 0x80,
0x07, 0xFF, 0xC0,
0x0F, 0xFF, 0xE0,
0x0F, 0xFF, 0xE0,
0x10, 0x00, 0x10,
0x3F, 0xFF, 0xF8,
0x3F, 0xFF, 0xF8,
0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00,
0x00, 0x88, 0x00,
0x01, 0x54, 0x00,
0x02, 0x12, 0x00,
0x02, 0x01, 0x00,
0x04, 0x00, 0x80,
0x04, 0x42, 0x80,
0x04, 0x02, 0x80,
0x08, 0x03, 0x40,
0x10, 0x01, 0x40,
0x20, 0x00, 0x40,
0x21, 0xE0, 0x40,
0x12, 0x11, 0x60,
0x0C, 0x21, 0xA0,
0x00, 0x40, 0x90,
0x00, 0x80, 0x50,
0x01, 0x00, 0x18,
0x02, 0x00, 0x08,
0x05, 0xFF, 0xE8,
0x04, 0x00, 0x08,
0x07, 0xFF, 0xF8,
0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00,
0x00, 0x88, 0x00,
0x01, 0x54, 0x00,
0x03, 0xEE, 0x00,
0x03, 0xFF, 0x00,
0x07, 0xFF, 0x80,
0x07, 0xBD, 0x80,
0x07, 0xFD, 0x80,
0x0F, 0xFC, 0xC0,
0x1F, 0xFE, 0xC0,
0x3F, 0xFF, 0xC0,
0x3F, 0xFF, 0xC0,
0x1E, 0x1E, 0xE0,
0x0C, 0x3E, 0x60,
0x00, 0x7F, 0x70,
0x00, 0xFF, 0xB0,
0x01, 0xFF, 0xF8,
0x03, 0xFF, 0xF8,
0x04, 0x00, 0x08,
0x07, 0xFF, 0xF8,
0x07, 0xFF, 0xF8,
0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x44, 0x00,
0x00, 0x82, 0x00,
0x01, 0x11, 0x00,
0x02, 0x10, 0x80,
0x02, 0xFE, 0x80,
0x04, 0x10, 0x40,
0x04, 0x10, 0x40,
0x04, 0x10, 0x40,
0x02, 0x10, 0x80,
0x02, 0x00, 0x80,
0x01, 0x01, 0x00,
0x00, 0xFE, 0x00,
0x00, 0x82, 0x00,
0x00, 0x82, 0x00,
0x00, 0x7C, 0x00,
0x02, 0x00, 0x80,
0x0F, 0xFF, 0xE0,
0x1F, 0xFF, 0xF0,
0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x7C, 0x00,
0x00, 0xFE, 0x00,
0x01, 0xEF, 0x00,
0x03, 0xEF, 0x80,
0x03, 0x01, 0x80,
0x07, 0xEF, 0xC0,
0x07, 0xEF, 0xC0,
0x07, 0xEF, 0xC0,
0x03, 0xEF, 0x80,
0x03, 0xFF, 0x80,
0x01, 0xFF, 0x00,
0x00, 0x82, 0x00,
0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00,
0x00, 0x7C, 0x00,
0x03, 0xFF, 0x80,
0x08, 0x00, 0x20,
0x1F, 0xFF, 0xF0,
0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x44, 0x00,
0x0E, 0x44, 0xE0,
0x11, 0x29, 0x10,
0x21, 0x45, 0x08,
0x22, 0x82, 0x88,
0x20, 0x00, 0x08,
0x22, 0x10, 0x88,
0x23, 0x39, 0x88,
0x11, 0xFF, 0x10,
0x10, 0xFE, 0x10,
0x08, 0x00, 0x20,
0x08, 0x00, 0x20,
0x0B, 0xFF, 0xA0,
0x04, 0x00, 0x40,
0x04, 0x00, 0x40,
0x04, 0x00, 0x40,
0x06, 0x00, 0xC0,
0x03, 0xFF, 0x80,
0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x7C, 0x00,
0x0E, 0x7C, 0xE0,
0x1F, 0x39, 0xF0,
0x3F, 0x7D, 0xF8,
0x3E, 0xFE, 0xF8,
0x3F, 0xFF, 0xF8,
0x3D, 0xEF, 0x78,
0x3C, 0xC6, 0x78,
0x1E, 0x00, 0xF0,
0x1F, 0x01, 0xF0,
0x0F, 0xFF, 0xE0,
0x0F, 0xFF, 0xE0,
0x0C, 0x00, 0x60,
0x07, 0xFF, 0xC0,
0x07, 0xFF, 0xC0,
0x07, 0xFF, 0xC0,
0x07, 0xFF, 0xC0,
0x03, 0xFF, 0x80,
0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x28, 0x00,
0x00, 0xEE, 0x00,
0x00, 0xC6, 0x00,
0x03, 0x29, 0x80,
0x04, 0xAA, 0x40,
0x08, 0x6C, 0x20,
0x10, 0x28, 0x10,
0x12, 0x44, 0x90,
0x24, 0x28, 0x48,
0x24, 0x10, 0x48,
0x22, 0x10, 0x88,
0x11, 0x01, 0x10,
0x10, 0x82, 0x10,
0x08, 0x00, 0x20,
0x09, 0xFF, 0x20,
0x04, 0x00, 0x40,
0x04, 0x00, 0x40,
0x06, 0x00, 0xC0,
0x03, 0xFF, 0x80,
0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x28, 0x00,
0x00, 0xEE, 0x00,
0x00, 0xC6, 0x00,
0x03, 0x29, 0x80,
0x07, 0xAB, 0xC0,
0x0F, 0xEF, 0xE0,
0x1F, 0xC7, 0xF0,
0x1D, 0xAB, 0x70,
0x3B, 0xC7, 0xB8,
0x3B, 0xEF, 0xB8,
0x3D, 0xFF, 0x78,
0x1E, 0xFE, 0xF0,
0x1F, 0x7D, 0xF0,
0x0F, 0xFF, 0xE0,
0x0C, 0x00, 0x60,
0x07, 0xFF, 0xC0,
0x07, 0xFF, 0xC0,
0x07, 0xFF, 0xC0,
0x03, 0xFF, 0x80,
0x00, 0x00, 0x00,
},
},
{
{
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x44, 0x00,
0x00, 0x82, 0x00,
0x00, 0x82, 0x00,
0x00, 0x82, 0x00,
0x00, 0x44, 0x00,
0x00, 0x38, 0x00,
0x00, 0x44, 0x00,
0x00, 0x44, 0x00,
0x00, 0xC6, 0x00,
0x00, 0x44, 0x00,
0x00, 0x44, 0x00,
0x00, 0xFE, 0x00,
0x01, 0x01, 0x00,
0x03, 0xFF, 0x80,
0x03, 0xFF, 0x80,
0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x38, 0x00,
0x00, 0x7C, 0x00,
0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00,
0x00, 0x7C, 0x00,
0x00, 0x38, 0x00,
0x00, 0x7C, 0x00,
0x00, 0x7C, 0x00,
0x00, 0xFE, 0x00,
0x00, 0x7C, 0x00,
0x00, 0x7C, 0x00,
0x00, 0xFE, 0x00,
0x01, 0x01, 0x00,
0x03, 0xFF, 0x80,
0x03, 0xFF, 0x80,
0x00, 0x00, 0x00,
},
},
};

14
src/atari/dataAtari.h Normal file
View File

@ -0,0 +1,14 @@
/*
* dataAtari.h
* cc65 Chess
*
* Created by Stefan Wessels, July 2020.
*
*/
#ifndef _DATA_H_
#define _DATA_H_
extern const char gfxTiles[PAWN][2][66];
#endif //_DATA_H_

319
src/atari/genpieces.cpp Normal file
View File

@ -0,0 +1,319 @@
/*
* genPieces.cpp
* cc65 Chess
*
* Created by Oliver Schmidt, January 2020.
* Pieces designed by Frank Gebhart, 1980s.
* Modified for Atari by S. Wessels, Jul 2020.
*
*/
#include <stdio.h>
char pieces[]=
" "
" **** ***** **** "
" * * * * * * "
" * * * * * * "
" * ***** ***** * "
" * * "
" * * "
" * * "
" * ********* * "
" ** ** "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * * "
" * *********** * "
" * * "
" ******************* "
" ******************* "
" "
" "
" **** ***** **** "
" **** ***** **** "
" **** ***** **** "
" ******************* "
" ******************* "
" ***************** "
" *************** "
" ************* "
" * * "
" *********** "
" *********** "
" *********** "
" *********** "
" *********** "
" ************* "
" *************** "
" *************** "
" * * "
" ******************* "
" ******************* "
" "
" "
" * * "
" * * * * "
" * * * "
" * * "
" * * "
" * * * * "
" * * * "
" * ** * "
" * * * "
" * * "
" * **** * "
" * * * * ** "
" ** * ** * "
" * * * "
" * * * "
" * ** "
" * * "
" * ************ * "
" * * "
" **************** "
" "
" "
" * * "
" * * * * "
" ***** *** "
" ********** "
" ************ "
" **** **** ** "
" ********* ** "
" ********** ** "
" ************ ** "
" **************** "
" **************** "
" **** **** *** "
" ** ***** ** "
" ******* *** "
" ********* ** "
" ************** "
" *************** "
" * * "
" **************** "
" **************** "
" "
" "
" "
" *** "
" * * "
" * * "
" * * * "
" * * * "
" * ******* * "
" * * * "
" * * * "
" * * * "
" * * * "
" * * "
" * * "
" ******* "
" * * "
" * * "
" ***** "
" * * "
" *************** "
" ***************** "
" "
" "
" "
" *** "
" ***** "
" ******* "
" **** **** "
" ***** ***** "
" ** ** "
" ****** ****** "
" ****** ****** "
" ****** ****** "
" ***** ***** "
" *********** "
" ********* "
" * * "
" ******* "
" ******* "
" ***** "
" *********** "
" * * "
" ***************** "
" "
" "
" "
" *** "
" * * "
" *** * * *** "
" * * * * * * "
" * * * * * * "
" * * * * * * "
" * * "
" * * * * * "
" * ** *** ** * "
" * ********* * "
" * ******* * "
" * * "
" * * "
" * *********** * "
" * * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" "
" *** "
" ***** "
" *** ***** *** "
" ***** *** ***** "
" ****** ***** ****** "
" ***** ******* ***** "
" ******************* "
" **** **** **** **** "
" **** ** ** **** "
" **** **** "
" ***** ***** "
" *************** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" * * * * * * "
" * ** ** * "
" * * * * "
" * * * * * * "
" * * * * * * "
" * * * * * "
" * * * * * "
" * * * * "
" * * * * "
" * * "
" * ********* * "
" * * "
" * * "
" ** ** "
" *********** "
" "
" "
" *** "
" * * "
" *** *** "
" ** ** "
" ** * * ** "
" **** * * **** "
" ******* ******* "
" ******* ******* "
" *** ** * * ** *** "
" *** **** **** *** "
" *** ***** ***** *** "
" **** ********* **** "
" **** ******* **** "
" ***** ***** ***** "
" *************** "
" ** ** "
" ************* "
" ************* "
" ************* "
" *********** "
" "
" "
" "
" "
" "
" "
" *** "
" * * "
" * * "
" * * "
" * * "
" * * "
" *** "
" * * "
" * * "
" ** ** "
" * * "
" * * "
" ******* "
" * * "
" *********** "
" *********** "
" "
" "
" "
" "
" "
" "
" *** "
" ***** "
" ******* "
" ******* "
" ******* "
" ***** "
" *** "
" ***** "
" ***** "
" ******* "
" ***** "
" ***** "
" ******* "
" * * "
" *********** "
" *********** "
" "
;
int main(void)
{
int i, j, k;
unsigned char c = 0;
printf("const char gfxTiles[PAWN][2][66] = \n{\n\t{\n\t\t{\n\t\t\t");
for(i=0, j=7, k=0; i<sizeof(pieces); ++i)
{
c |= (pieces[i] == '*') << j--;
if (j<0)
{
printf("0x%02X, ", c);
k++;
if(!(k%3))
printf("\n\t\t");
c = 0;
j = 7;
if(!(k % 66))
{
printf("},\n");
if(!(k % 132))
{
printf("\t},\n");
if(k != 66 * 12)
printf("\t{\n");
}
if(k != 66 * 12)
printf("\t\t{\n\t\t\t");
}
else
{
printf("\t");
}
}
}
printf("};\n");
return 0;
}

228
src/atari/hiresAtari.s Normal file
View File

@ -0,0 +1,228 @@
; hiresAtari.s
; cc65 Chess
;
; Created by Stefan Wessels, July 2020.
;
;-----------------------------------------------------------------------
.include "atari.inc"
.include "zeropage.inc"
;-----------------------------------------------------------------------
; Display-list related defenitions
scrn = $9100 ; screen starts here
scnd = $a000 ; lower part of screen here
top = ((scnd - scrn) / $28) ; display list entries before scnd
bot = ($c0-top) ; display list entries after scnd
mode = $0f ; mode to run the screen at
;-----------------------------------------------------------------------
; Display list - mode 0x0f (320x192, 2 color).
; Goes in its own segment so it won't cross a boundry
.segment "DLIST"
displayList:
.byte $70,$70,$70 ; 24 blank lines
.byte $40 + mode,<scrn,>scrn ; Mode $0x + LMS, setting screen memory to $9000
.repeat top-1 ; 102 lines of mode $0x (incl LMS row above)
.byte mode
.endrep
.byte $40 +mode, <(scnd), >(scnd) ; clear the 4k boundry and start another row of mode $0x
.repeat bot-1 ; another 90 lines of mode $0x (incl. LMS row above)
.byte mode
.endrep
.byte $41,<displayList,>displayList ; Vertical Blank jump to start of displayList
;-----------------------------------------------------------------------
; lookup to the start of a graphics row
rowL:
.repeat top, I ; $66 rows at $9000
.byte <(scrn + I *40)
.endrep
.repeat bot, I ; $5a rows at $a000
.byte <(scnd + I *40)
.endrep
rowH:
.repeat top, I
.byte >(scrn + I *40)
.endrep
.repeat bot, I
.byte >(scnd + I *40)
.endrep
;-----------------------------------------------------------------------
; The code to draw in hires
.code
;-----------------------------------------------------------------------
.import popa
;-----------------------------------------------------------------------
; the functions exported to "C"
.export _plat_atariInit
.export _plat_gfxFill
.export _plat_showPiece
.export _plat_showStrXY
;-----------------------------------------------------------------------
; Init the hires screen with teh display list
.proc _plat_atariInit
lda #0 ; stop the dma
sta DMACTL
lda #<displayList ; install the new display list
sta SDLSTL
lda #>displayList
sta SDLSTH
lda #$22 ; resume the DMA
sta DMACTL
rts
.endproc
;-----------------------------------------------------------------------
; void plat_gfxFill(char fill, char x, char y, char w, char h)
.proc _plat_gfxFill
sta ptr2 + 1 ; h was in acc
jsr popa ; w
sta ptr2
jsr popa ; y
sta tmp1
jsr popa ; x
sta tmp2
jsr popa ; fill
sta tmp3
rowStart:
ldy tmp1 ; get the row top
lda rowL, y ; get the address where the row starts
sta ptr1
lda rowH, y
sta ptr1 + 1
lda tmp3 ; get the fill byte
ldx ptr2 ; width in x
ldy tmp2 ; and col x in y register
:
sta (ptr1), y ; write the fill byte
iny ; memory is linear
dex ; one less column to do
bne :- ; do for all columns
inc tmp1 ; go down one row
dec ptr2 + 1 ; one less row to do in height
bne rowStart ; repeat till all height rows done
rts
.endproc
;-----------------------------------------------------------------------
; void plat_showPiece(char x, char Y, const char *src)
.proc _plat_showPiece
sta read + 1 ; store the pointer to the piece
stx read + 2
jsr popa ; y
sta tmp1
jsr popa ; x
sta tmp2
lda #22 ; pieces are 22 heigh
sta tmp4
ldx #0 ; start at the 1st byte of the piece
loop:
ldy tmp1 ; get the current piece row
lda rowL, y ; look up teh row start address in memory
sta ptr1
lda rowH, y
sta ptr1 + 1
lda #3 ; a piece is 3 bytes wide
sta tmp3 ; col counter
ldy tmp2 ; the col x goes into y register
read:
lda $ffff, x ; read a byte from the piece
eor (ptr1), y ; eor with teh screen
sta (ptr1), y ; and save back to the screen
inx ; next byte in piece
iny ; next byte on screen
dec tmp3 ; one less col byte to do
bne read ; if not all done, do the rest of the cols on this row
inc tmp1 ; next row
dec tmp4 ; one less row to do of the 22
bne loop ; if not all done, do the next row
rts
.endproc
;-----------------------------------------------------------------------
; void plat_showStrXY(char x, char Y, char *str)
.proc _plat_showStrXY
sta strRead + 1 ; pointer to the strin comes in as a, x regsiters
stx strRead + 2
jsr popa ; get the y
asl ; mult it by 8
asl
asl
sta tmp1 ; y * 8
jsr popa
sta tmp2 ; x
loop:
lda #0
sta fontRead + 2 ; prep the hi byte
strRead:
lda $ffff ; get the character
bne :+ ; if not 0, not at end of string
rts ; end of string, all done
:
cmp #96 ; if lowercase
bcs :+ ; then all is well
sec ; uppercase and numbers need to shift
sbc #32 ; down by 32 to be aligned with the ROM font
:
inc strRead + 1 ; next char in string
bne :+
inc strRead + 2
:
asl ; ROM char is 8 wide so mult string char * 8
rol fontRead + 2
asl
rol fontRead + 2
asl
rol fontRead + 2
sta fontRead + 1
clc
lda CHBAS ; add the character rom hi
adc fontRead + 2 ; to the character pointer
sta fontRead + 2
ldx #0 ; start at first row of 8 rows in a char
ldy tmp1 ; y reg is the piwel row to draw at
charPlot:
sty tmp3 ; copy the pixel row
lda rowL, y ; look up the screen address of the row
sta ptr1
lda rowH, y
sta ptr1 + 1
ldy tmp2 ; put the col into the y reg
fontRead:
lda $ffff, x ; read the font defenition for this char row (char row in x)
sta (ptr1), y ; store to the screen
ldy tmp3 ; get the screen pixel row in y
iny ; go down a row
inx ; one more of the 8 character rows done
cpx #8 ; all 8 done
bne charPlot ; if not, keep going
inc tmp2 ; next column on screeen
jmp loop ; do the next character in the string
.endproc

467
src/atari/platAtari.c Normal file
View File

@ -0,0 +1,467 @@
/*
* platAtari.c
* cc65 Chess
*
* Created by Stefan Wessels, July 2020.
*
*/
#include <atari.h>
#include <stdio.h>
#include <string.h>
#include "../types.h"
#include "../globals.h"
#include "../undo.h"
#include "../frontend.h"
#include "../plat.h"
#include "dataAtari.h"
/*-----------------------------------------------------------------------*/
#define SCROLL_SPEED 10
#define BOARD_PIECE_WIDTH 3
#define BOARD_PIECE_HEIGHT 22
#define SCREEN_WIDTH 40
#define SCREEN_HEIGHT 24
#define LOG_WINDOW_HEIGHT (SCREEN_HEIGHT - 2)
/*-----------------------------------------------------------------------*/
// Internal function Prototype
char plat_TimeExpired(unsigned char aTime);
/*-----------------------------------------------------------------------*/
// Function Prototype for functions in hiresAtari.s
extern void plat_atariInit(void);
extern void plat_gfxFill(char fill, char x, char y, char w, char h);
extern void plat_showPiece(char x, char Y, const char *src);
extern void plat_showStrXY(char x, char y, char *str);
/*-----------------------------------------------------------------------*/
// Local storage
char textStr[41];
static char subMenu;
/*-----------------------------------------------------------------------*/
void plat_Init()
{
// Setting this to 0 will not show the "Quit" option in the main menu
gReturnToOS = 1;
plat_gfxFill(0,0,0,40,191);
plat_atariInit();
_setcolor(1,0xc,0xf); // Pixel %1 color
_setcolor(2,0xc,0x7); // Pixel %0 color
_setcolor(4,0xC,0x7); // border color
// Show the welcome text
strcpy(textStr, "Atari graphics version, July 2020.");
plat_showStrXY(2,SCREEN_HEIGHT/2-1, gszAbout);
plat_showStrXY(3,SCREEN_HEIGHT/2+1,textStr);
// Show the welcome kings (black and white, solid versions)
plat_showPiece(SCREEN_WIDTH/2 - 1, 8*(SCREEN_HEIGHT/2 - 6), gfxTiles[KING-1][1]);
plat_showPiece(SCREEN_WIDTH/2 - 1, 8*(SCREEN_HEIGHT/2 + 4), gfxTiles[KING-1][0]);
// Hold the welcome screen
plat_ReadKeys(1);
// Set game colors
_setcolor(2,0x0,0x0); // Pixel %0 color
plat_gfxFill(0,0,0,40,191);
// Not in a menu
subMenu = 0;
}
/*-----------------------------------------------------------------------*/
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;
subMenu++;
// 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 , 8*(sy-1 ), maxLen+4 , 8*(1 ));
plat_gfxFill(0xAA , sx-1 , 8*(sy ), 1 , 8*(height+3));
plat_gfxFill(0xAA , sx+maxLen+2, 8*(sy ), 1 , 8*(height+3));
plat_gfxFill(0xAA , sx , 8*(sy+height+2), maxLen+2 , 8*(1 ));
// Show the title
sprintf(textStr, " %.*s ",38, menuItems[0]);
plat_showStrXY(sx, sy, textStr);
// Leave a blank line
sprintf(textStr, "%-*s", maxLen+2," ");
plat_showStrXY(sx, ++sy, textStr);
// Show all the menu items
for(i=1; i<numMenuItems; ++i)
{
sprintf(textStr, " %.*s ",maxLen, menuItems[i]);
plat_showStrXY(sx, sy+i, textStr);
}
// Pad with blank lines to menu height
for(;i<height;++i)
{
sprintf(textStr, "%-*s", maxLen+2," ");
plat_showStrXY(sx, sy+i, textStr);
}
// Select the first item
i = 1;
do
{
// Highlight the selected item
sprintf(textStr, ">%.*s<",maxLen, menuItems[i]);
plat_showStrXY(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);
// 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))
{
++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;
}
/*-----------------------------------------------------------------------*/
void plat_DrawBoard(char clearLog)
{
char i;
// Not in a menu when drawBoard is called
if(subMenu)
{
clearLog = 1;
subMenu = 0;
}
if(clearLog)
{
// Clear the log area pixels and color to green
plat_gfxFill(0, 25, 0, 15, 24*8);
}
// 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);
sprintf(textStr, "%d",8-i);
plat_showStrXY(0, 1+i*3, textStr);
}
}
/*-----------------------------------------------------------------------*/
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 board square
plat_gfxFill(blackWhite ? 0xff : 0x0, 1 + x * BOARD_PIECE_WIDTH, 8 + 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, 8 + y * BOARD_PIECE_HEIGHT, 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)*3, textStr);
// Defenders (bottom right)
sprintf(textStr, "%d",(gpAttackBoard[giAttackBoardOffset[position][1]]));
plat_showStrXY(1+x*BOARD_PIECE_WIDTH+3,(y+1)*3, 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*3, textStr);
// Color
sprintf(textStr, "%d",piece_color);
plat_showStrXY(1+x*BOARD_PIECE_WIDTH+3,1+y*3, textStr);
}
}
/*-----------------------------------------------------------------------*/
void plat_ShowSideToGoLabel(char side)
{
// Show Black or White
sprintf(textStr, "%s",gszSideLabel[side]);
plat_showStrXY(2+8*BOARD_PIECE_WIDTH, 0, textStr);
}
/*-----------------------------------------------------------------------*/
void plat_Highlight(char position, char color, char cursor)
{
char colSelect[6] = {0x55, 0xaa, 0x55, 0xaa, 0x55};
char y = position / 8, x = position & 7;
// get a pattern for the cursor
color = colSelect[color-2];
// If an attacker/defender cursor, swap the colors
if(!cursor)
color ^= 0xff;
// for my real Atari 800 on a Commodore 1802 monitor, this is
// what I want. On Altirra 3.20 with an NTSC 800 and NTSC
// artifacting, the colors are inverted from what I want.
// A little odd, but I am going with the real hardware.
color ^= 0xff;
// 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 += 8;
// Draw the two vertical bars - the "cursor"
plat_gfxFill(color, x + 1 , y, 1, BOARD_PIECE_HEIGHT);
plat_gfxFill(color, x + BOARD_PIECE_WIDTH, y, 1, BOARD_PIECE_HEIGHT);
}
/*-----------------------------------------------------------------------*/
void plat_ShowMessage(char *str, char )
{
sprintf(textStr, "%.*s",SCREEN_WIDTH-1-(8*BOARD_PIECE_WIDTH),str);
plat_showStrXY(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(1+(8*BOARD_PIECE_WIDTH), (SCREEN_HEIGHT-1), textStr);
}
/*-----------------------------------------------------------------------*/
// This function can/will change the gTile and related global variables so
// caution is needed
void plat_AddToLogWin()
{
char bot = SCREEN_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);
}
else
{
sprintf(textStr, "%-*s",SCREEN_WIDTH-x," ");
plat_showStrXY(x, y, textStr);
}
}
}
/*-----------------------------------------------------------------------*/
void plat_AddToLogWinTop()
{
plat_AddToLogWin();
}
/*-----------------------------------------------------------------------*/
char plat_TimeExpired(unsigned char aTime)
{
if(OS.rtclok[2] > aTime)
{
OS.rtclok[2] = 0;
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------*/
int plat_ReadKeys(char blocking)
{
char key = 0;
int keyMask = 0;
if(blocking)
{
while(KEY_NONE == (key = OS.ch));
}
else
{
if(KEY_NONE == (key = OS.ch))
return 0;
}
switch(key)
{
case KEY_DASH | KEY_CTRL: //KEY_UP: // Up
keyMask |= INPUT_UP;
break;
case KEY_RIGHT: // Right
keyMask |= INPUT_RIGHT;
break;
case KEY_DOWN: // Down
keyMask |= INPUT_DOWN;
break;
case KEY_LEFT: // Left
keyMask |= INPUT_LEFT;
break;
case KEY_ESC: // Esc
keyMask |= INPUT_BACKUP;
break;
case KEY_A: // 'a' - Show Attackers
keyMask |= INPUT_TOGGLE_A;
break;
case KEY_B: // 'b' - Board attacks - Show all attacks
keyMask |= INPUT_TOGGLE_B;
break;
case KEY_D: // 'd' - Show Defenders
keyMask |= INPUT_TOGGLE_D;
break;
case KEY_M: // 'm' - Menu
keyMask |= INPUT_MENU;
break;
case KEY_RETURN: // Enter
keyMask |= INPUT_SELECT;
break;
case KEY_R:
keyMask |= INPUT_REDO;
break;
case KEY_U:
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;
}
OS.ch = KEY_NONE;
return keyMask;
}
/*-----------------------------------------------------------------------*/
void plat_Shutdown()
{
}