Apple II chess gui work

This commit is contained in:
equant 2021-10-05 16:54:29 -07:00
parent b7da06f6f9
commit 3eaae61950
28 changed files with 361 additions and 151 deletions

3
.gitignore vendored
View File

@ -1,6 +1,9 @@
*.swp
*.swo
.gitattributes
*Output.txt
_FileInformation.txt
history
credentials.h
tags
*.o

View File

@ -6,9 +6,9 @@
// Address offsets
#define RAM_A2I 0
#define RAM_APPLE 1
#define SHARED_RAM_START_ADDRESS 2
//#define RAM_A2I 0
//#define RAM_APPLE 1
//#define SHARED_RAM_START_ADDRESS 2
#define MAIN_LOOP_INTERVAL 3 // Unimplemented

52
cc65-lib/apple2idiot.c Normal file
View File

@ -0,0 +1,52 @@
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <peekpoke.h>
#include "globals.h"
#include "apple2idiot.h"
#define MAX_STR_LEN 250
unsigned char read_byte(unsigned int address) {
gotoxy(0,2);
//printf("read_data(%u)", address);
}
unsigned char write_byte(unsigned int address, unsigned char byte_to_write) {
//printf("%u <- %d, [%c]\n", address, byte_to_write, byte_to_write);
POKE(address, byte_to_write);
}
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send) {
unsigned char i;
unsigned char size = strlen(string_to_send);
gotoxy(0,2);
if (string_to_send[size-1] == '\n') {
string_to_send[size-1] = '\0';
}
//printf("%u (%s)\n", address, string_to_send);
for (i=0; i<size; i++) {
write_byte(address+i, string_to_send[i]);
}
if (string_to_send[size-1] != '\0') {
write_byte(address+i, '\0');
}
}
// HOW DO I PASS THE ADDRESS TO read_string_from_ram ???
void read_string_from_ram(unsigned int address, char *data, char length) {
unsigned char c, i;
gotoxy(0,2);
//printf("A: %u, L: %c\n", address, length);
//cgetc();
for (i=0; i<length; i++) {
c = PEEK(address + i);
data[i] = c;
if (c == 0) {
break;
}
}
}

9
cc65-lib/apple2idiot.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _A2I_H
#define _A2I_H
unsigned char read_byte(unsigned int address);
unsigned char write_byte(unsigned int address, unsigned char byte_to_write);
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send);
void read_string_from_ram(unsigned int address, char *data, char length);
#endif

View File

@ -11,19 +11,20 @@
void Chess::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
a2i = a2ip;
http = httpp;
strcpy(game_string, "a2a3e7e5e2e4");
//strcpy(game_string, "a2a3e7e5e2e4");
}
byte Chess::handleCommand(byte command) {
switch(command) {
case CHESS_MAKE_MOVE: {
Serial.println("CHESS() MAKE_MOVE");
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
Serial.println("CHESS() MAKE_MOVE");
String move_string;
move_string = a2i->read_string_from_ram(SHARED_RAM_START_ADDRESS);
Serial.println("Received move: ["+move_string+"]");
byte result = makeMove(move_string);
int address_counter = a2i->write_data(result, SHARED_RAM_START_ADDRESS);
a2i->write_data(result, ESP_COMMAND_ADDRESS);
int address_counter = a2i->write_string_to_shared_ram(last_ai_move, SHARED_RAM_START_ADDRESS);
getBoard();
for (int i=0; i<9; i++) {
address_counter = a2i->write_string_to_shared_ram(game_board[i], address_counter + 1);
@ -69,9 +70,12 @@ byte Chess::makeMove(String move_string) {
Serial.print("after player move game_status:"); Serial.println(game_status);
if (strcmp(game_status, "in_progress") == 0) {
char* ai_move;
ai_move = getAIMove();
strcat(game_string, ai_move);
//char* ai_move;
//ai_move = getAIMove();
//strcat(game_string, ai_move);
//last_ai_move = getAIMove();
strcpy(last_ai_move, getAIMove());
strcat(game_string, last_ai_move);
game_status = getGameStatus(game_string);
Serial.print("after AI move game_status:"); Serial.println(game_status);
if (strcmp(game_status, "in_progress") == 0) { return STATUS_IN_PROGRESS; }

View File

@ -24,6 +24,8 @@ class Chess {
char game_string[MAX_GAME_SIZE]; // This is probably not enough, but it's fine for development.
char game_status[25];
char last_player_move[5]; // "a2a4"
char last_ai_move[5]; // "8g76"
//char game_board[9][20];
char game_board[9][22] = {

View File

@ -9,16 +9,17 @@
# Space or comma separated list of cc65 supported target platforms to build for.
# Default: c64 (lowercase!)
TARGETS := apple2
TARGETS := apple2enh
#TARGETS := apple2
# Name of the final, single-file executable.
# Default: name of the current dir with target name appended
PROGRAM := weather
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 :=
LIBS :=
# Custom linker configuration file
# Use only if you don't want to place it in SRCDIR

View File

@ -1,9 +1,3 @@
# Apple2 Internet Weather Client Example
This is the C code to compile the software that runs on an Apple2 and makes use
of the Apple2idiot card to display the weather for a given city.
## How I use this
This is how I compile, make a disk and then stage the disk for transfer to my //c using ADTPro.

View File

@ -1,3 +0,0 @@
java -jar ~/bin/AppleCommander.jar -d ~/bin/ADTPro-2.1.0/disks/dev.dsk weather
java -jar ~/bin/AppleCommander.jar -as ~/bin/ADTPro-2.1.0/disks/dev.dsk weather bin < weather.apple2
java -jar ~/bin/AppleCommander.jar -l ~/bin/ADTPro-2.1.0/disks/dev.dsk

Binary file not shown.

View File

@ -1,2 +0,0 @@
cl65 -t apple2 weather.c -o weather
cp weather.dsk ~/bin/ADTPro-2.1.0/disks/

View File

@ -1,16 +0,0 @@
cc65 -g -Oi -t apple2 weather.c
cc65 -g -Oi -t apple2 inputline.c
cc65 -g -Oi -t apple2 menu.c
cc65 -g -Oi -t apple2 screen.c
ca65 -g weather.s
ca65 -g inputline.s
ca65 -g menu.s
ca65 -g screen.s
ld65 -o weather -t apple2 weather.o inputline.o menu.o screen.o apple2.lib
#cl65 -t apple2 weather.c -o weather
#cl65 -c -Oirs -t apple2 weather.c -o weather
java -jar ~/bin/AppleCommander.jar -d hello.dsk weather
java -jar ~/bin/AppleCommander.jar -as hello.dsk weather bin < weather
java -jar ~/bin/AppleCommander.jar -l hello.dsk
java -jar ~/bin/AppleCommander.jar -as ~/bin/ADTPro-2.1.0/disks/dev.dsk weather bin < weather.apple2

View File

@ -1,2 +1,2 @@
# -uimodekey DEL -ui_active
mame apple2e -skip_gameinfo -window -nomax -uimodekey DEL -flop1 weather.dsk
mame apple2e -skip_gameinfo -window -nomax -uimodekey DEL -flop1 chess.dsk

View File

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

View File

@ -1,52 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <peekpoke.h>
#include "globals.h"
#include "apple2idiot.h"
#define MAX_STR_LEN 250
unsigned char read_byte(unsigned int address) {
gotoxy(0,2);
//printf("read_data(%u)", address);
}
unsigned char write_byte(unsigned int address, unsigned char byte_to_write) {
//printf("%u <- %d, [%c]\n", address, byte_to_write, byte_to_write);
POKE(address, byte_to_write);
}
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send) {
unsigned char i;
unsigned char size = strlen(string_to_send);
gotoxy(0,2);
if (string_to_send[size-1] == '\n') {
string_to_send[size-1] = '\0';
}
//printf("%u (%s)\n", address, string_to_send);
for (i=0; i<size; i++) {
write_byte(address+i, string_to_send[i]);
}
if (string_to_send[size-1] != '\0') {
write_byte(address+i, '\0');
}
}
// HOW DO I PASS THE ADDRESS TO read_string_from_ram ???
void read_string_from_ram(unsigned int address, char *data, char length) {
unsigned char c, i;
gotoxy(0,2);
//printf("A: %u, L: %c\n", address, length);
//cgetc();
for (i=0; i<length; i++) {
c = PEEK(address + i);
data[i] = c;
if (c == 0) {
break;
}
}
}

View File

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

View File

@ -1,9 +0,0 @@
#ifndef _A2I_H
#define _A2I_H
unsigned char read_byte(unsigned int address);
unsigned char write_byte(unsigned int address, unsigned char byte_to_write);
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send);
void read_string_from_ram(unsigned int address, char *data, char length);
#endif

View File

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

Binary file not shown.

View File

@ -1,22 +1,28 @@
#ifndef _GLOBALS_H
#define _GLOBALS_H
#define ASCII_0 48
#define ASCII_1 49
#define ASCII_2 50
#define ASCII_3 51
#define ASCII_4 52
#define ASCII_5 53
#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 COMMAND_SET_COUNTRY 200
#define COMMAND_SET_CITY 201
#define COMMAND_FETCH_WEATHER 205
#define ESP_TIMEOUT 5555
//#define COMMAND_SET_COUNTRY 200
//#define COMMAND_SET_CITY 201
//#define COMMAND_FETCH_WEATHER 205
#endif

View File

@ -8,32 +8,263 @@
#include "globals.h"
#include "menu.h"
#include "apple2idiot.h"
#include "../../chess_commands.h"
#include "../../../../arduino-lib/Apple2Idiot/A2I_commands.h"
unsigned char i = 0;
char pause_char;
char city[33];
char country_code[3];
char temperature[7];
char humidity[7];
char wind_speed[7];
char wind_direction[5];
char weather1[250];
char weather2[250];
char player_move[5];
char ai_move[5];
char state = STATE_NONE;
unsigned int address_offset = 0;
void main(void)
{
unsigned char key;
clrscr();
char game_board[10][24] = {
"8: r n b q k b n r",
"7: p p p p p p p p",
"6: . . . . . . . .",
"5: . . . . . . . .",
"4: . . . . . . . .",
"3: . . . . . . . .",
"2: P P P P P P P P",
"1: R N B Q K B N R",
" ---------------",
" a b c d e f g h"
};
void displayCurrentBoard(void);
void createNewBoard(void); // deprecated
void spinner(void);
void awaitMoveResponse(void);
void popup(unsigned char* message);
void popup(unsigned char* message) {
//cclearxy(x, y, SIZE_X);
//gotoxy(x,y);
cclearxy(0, 7, SIZE_X);
cclearxy(0, 8, SIZE_X);
cclearxy(0, 9, SIZE_X);
cclearxy(0, 10, SIZE_X);
gotoxy(0,7);
printf("+-------------------------------------+\n");
printf("! %s \n", message);
printf("+-------------------------------------+\n");
printf("(Press a key)\n");
if (kbhit()) {
cgetc();
}
pause_char = cgetc();
}
void main(void) {
unsigned char key;
while (state != STATE_QUIT) {
switch(state) {
case STATE_LOCAL_GAME:
displayCurrentBoard();
cclearxy(0, 23, SIZE_X);
gotoxy(0,23);
printf("Your Move:");
fgets(player_move, sizeof player_move, stdin);
player_move[strcspn(player_move, "\n")] = 0;
write_string_to_ram(RAM_DATA_START_ADDRESS, player_move);
write_byte(APPLE_COMMAND_ADDRESS, CHESS_MAKE_MOVE);
awaitMoveResponse();
break;
case STATE_NONE:
clrscr();
drawMenuBar();
gotoxy(0,23);
printf("Menu Selection:");
cursor(1);
key = toupper(cgetc());
switch(key) {
case ASCII_W:
cclearxy(0, 11, SIZE_X);
gotoxy(0,11);
printf("+--------------------------------------+\n");
printf("! Not implemented yet. !\n");
printf("+--------------------------------------+\n");
printf("(Press a key)\n");
pause_char = cgetc();
break;
case ASCII_L:
//createNewBoard();
state = STATE_LOCAL_GAME;
break;
case ASCII_Q:
state = STATE_QUIT;
break;
default:
popup("Not implemented yet.");
//cclearxy(0, 11, SIZE_X);
//gotoxy(0,11);
//printf("+--------------------------------------+\n");
//printf("! Not implemented yet. !\n");
//printf("+--------------------------------------+\n");
//printf("(Press a key)\n");
//pause_char = cgetc();
}
break;
default:
break;
}
}
}
void spinner(void) {
// From https://github.com/bobbimanners/emailler
static char chars[] = "|/-\\";
//static uint8_t i = 0;
static char i = 0;
//putchar(BACKSPACE);
//putchar(chars[(i++) % 4]);
gotoxy(10+4+2,23);
cputc(chars[(i++) % 4]);
}
void awaitMoveResponse(void) {
int delay_count = 0;
int timeout_count = 0;
unsigned char read_char;
int received_esp_response = 0;
gotoxy(10+4+2,23);
spinner();
while (received_esp_response==0 && timeout_count < ESP_TIMEOUT) {
timeout_count++;
read_char = read_byte(ESP_COMMAND_ADDRESS);
switch(read_char) {
case STATUS_IN_PROGRESS:
received_esp_response = 1;
break;
case STATUS_BLACK_WON:
received_esp_response = 1;
break;
case STATUS_WHITE_WON:
received_esp_response = 1;
break;
case STATUS_STALEMATE:
received_esp_response = 1;
break;
case STATUS_FIFTY_RULE_MOVE:
received_esp_response = 1;
break;
case STATUS_UNKNOWN:
received_esp_response = 1;
break;
case STATUS_UNHANDLED:
received_esp_response = 1;
break;
case STATUS_ERROR:
received_esp_response = 1;
break;
case CHESS_INVALID_MOVE:
received_esp_response = 1;
break;
default:
break;
}
// delay
for (i=0; delay_count < 5555; ++delay_count) {
spinner();
}
}
if (timeout_count == ESP_TIMEOUT) {
popup("ESP TIMEOUT");
return;
}
//getBoard();
switch(read_char) {
case STATUS_IN_PROGRESS:
popup("STATUS_IN_PROGRESS");
read_string_from_ram(RAM_DATA_START_ADDRESS, ai_move, sizeof ai_move-1);
popup(sprintf("AI Move: %s", ai_move));
address_offset = 5;
for (i=0; i<9; i++) {
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, game_board[0], sizeof game_board[0]-1);
address_offset += strlen(game_board[0]) + 1;
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, game_board[1], sizeof game_board[1]-1);
address_offset += strlen(game_board[1]) + 1;
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, game_board[2], sizeof game_board[2]-1);
address_offset += strlen(game_board[2]) + 1;
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, game_board[3], sizeof game_board[3]-1);
address_offset += strlen(game_board[3]) + 1;
}
break;
case STATUS_BLACK_WON:
popup("You lose.");
break;
case STATUS_WHITE_WON:
popup("You win.");
break;
case STATUS_STALEMATE:
popup("Stalemate");
break;
case STATUS_FIFTY_RULE_MOVE:
popup("Fifty move rule.");
break;
case STATUS_UNKNOWN:
popup("STATUS_UNKNOWN");
break;
case STATUS_UNHANDLED:
popup("STATUS_UNHANDLED");
break;
case STATUS_ERROR:
popup("STATUS_ERROR");
break;
case CHESS_INVALID_MOVE:
popup("CHESS_INVALID_MOVE");
break;
default:
popup("Unrecognised response from ESP.");
break;
}
}
void displayCurrentBoard(void) {
unsigned char i;
for (i=0; i<10; i++) {
cclearxy(0, i+7, SIZE_X);
gotoxy(10,i+7);
printf("%s", game_board[i]);
}
}
void createNewBoard(void) {
cclearxy(0, 7, SIZE_X);
gotoxy(10,7);
printf("8: r n b q k b n r");
cclearxy(0, 8, SIZE_X);
gotoxy(10,8);
printf("7: p p p p p p p p");
gotoxy(10,9);
printf("6: . . . . . . . .");
gotoxy(10,10);
printf("5: . . . . . . . .");
gotoxy(10,11);
printf("4: . . . . . . . .");
gotoxy(10,12);
printf("3: . . . . . . . .");
gotoxy(10,13);
printf("2: P P P P P P P P");
gotoxy(10,14);
printf("1: R N B Q K B N R");
gotoxy(10,15);
printf(" ---------------");
gotoxy(10,16);
printf(" a b c d e f g h");
}
/*
while (key != ASCII_5) { // Last menu item should be Quit
drawMenuBar();
gotoxy(0,2);
printf("Country: %s City:%s", country_code, city);
gotoxy(0,SIZE_Y-1);
printf("Menu Selection:");
cursor(1);
key = toupper(cgetc());
gotoxy(0,SIZE_Y-3);
//printf("cgetc() -> \"%c\"", key);
@ -101,4 +332,4 @@ void main(void)
}
}
}
*/

View File

@ -6,27 +6,17 @@
#include "globals.h"
#include "menu.h"
#define MENU_LENGTH 5
#define MENU_WORD_LENGTH 8
unsigned char menuEntries[MENU_LENGTH][MENU_WORD_LENGTH] = {"Country", "City", "Fetch", "Display", "Quit"};
void drawMenuBar() {
static unsigned char i;
static unsigned char x_offset;
x_offset = 0;
cclearxy(0, 0, SIZE_X);
gotoxy(0,0);
for(i = 0; i < MENU_LENGTH; i++){
//printf("%d, %d, %d\n", i, strlen(menuEntries[i]), x_offset);
revers(1);
gotoxy(x_offset, 0); cputc('1' + i);
revers(0);
cputsxy(x_offset + 1, 0, menuEntries[i]);
x_offset += strlen(menuEntries[i]) + 1;
}
revers(0);
revers(1); printf("W");
revers(0); printf("ifi Game | ");
revers(1); printf("L");
revers(0); printf("ocal Game | ");
revers(1); printf("S");
revers(0); printf("ettings | ");
revers(1); printf("Q");
revers(0); printf("uit");
}
void fancy_hline(unsigned char x, unsigned char y) {

View File

@ -116,8 +116,6 @@ void loop() {
chess_app.handleCommand(command_byte);
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
//a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
//a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
//a2i.write_data(ESP_COMMAND_ADDRESS, result); // notify Apple IIe we are done processing command byte
}
}
lastMainLoopTime = millis();