Release 01-19-2023-131

This commit is contained in:
David Kuder 2023-01-29 10:50:12 -05:00
parent d9be2ed9cd
commit 564ebb545a
39 changed files with 3179 additions and 741 deletions

View File

@ -34,11 +34,10 @@ else
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_apple2 = \
uploadfont
EXELIST_apple2 = uploadfont/uploadfont uploadfont/flashfont configtool/configtool
ifneq ($(EXELIST_$(SYS)),)
all: $(EXELIST_$(SYS))
all: disk $(EXELIST_$(SYS))
else
all: notavailable
endif
@ -52,15 +51,17 @@ else
@echo > $(NULLDEV)
endif
disk: font.dsk
disk: v2a525.po v2a35.po
font.dsk: uploadfont
cp prodos/prodos.dsk $@
java -jar $(AC) -n $@ FONTDISK
java -jar $(AC) -p $@ BASIC.SYSTEM SYS 0x2000 <prodos/basic.system
java -jar $(AC) -p $@ BITSY.BOOT SYS 0x2000 <prodos/bitsy.boot
java -jar $(AC) -p $@ QUIT.SYSTEM SYS 0x2000 <prodos/quit.system
java -jar $(AC) -as $@ UPLOADFONT <uploadfont
v2a525.po: uploadfont/uploadfont uploadfont/uploadfonte uploadfont/flashfont uploadfont/flashfonte configtool/v2acfg configtool/v2acfge
cp prodos/pd525.po $@
java -jar $(AC) -n $@ V2ANALOG
java -jar $(AC) -as $@ UPLOADFONT <uploadfont/uploadfont
java -jar $(AC) -as $@ UPLOADFONTE <uploadfont/uploadfonte
java -jar $(AC) -as $@ FLASHFONT <uploadfont/flashfont
java -jar $(AC) -as $@ FLASHFONTE <uploadfont/flashfonte
java -jar $(AC) -as $@ V2ACFG <configtool/v2acfg
java -jar $(AC) -as $@ V2ACFGE <configtool/v2acfge
java -jar $(AC) -p $@ IIC.FONT BIN 0x2000 <fonts/iicfont.bin
java -jar $(AC) -p $@ IIPLUS.FONT BIN 0x2000 <fonts/iiplus.bin
java -jar $(AC) -p $@ LOWERCASE.FONT BIN 0x2000 <fonts/lcase.bin
@ -74,9 +75,45 @@ font.dsk: uploadfont
java -jar $(AC) -bas $@ MOUSETEXT.BAS <prodos/mousetext.bas
java -jar $(AC) -bas $@ REACTIVE.BAS <prodos/reactive.bas
uploadfont: uploadfont.c
$(CL) -Oirs -t apple2 --start-addr 0x4000 -m uploadfont.map $^
v2a35.po: uploadfont/uploadfont uploadfont/uploadfonte uploadfont/flashfont uploadfont/flashfonte configtool/v2acfg configtool/v2acfge
cp prodos/pd35.po $@
java -jar $(AC) -n $@ V2ANALOG
java -jar $(AC) -as $@ UPLOADFONT <uploadfont/uploadfont
java -jar $(AC) -as $@ UPLOADFONTE <uploadfont/uploadfonte
java -jar $(AC) -as $@ FLASHFONT <uploadfont/flashfont
java -jar $(AC) -as $@ FLASHFONTE <uploadfont/flashfonte
java -jar $(AC) -as $@ V2ACFG <configtool/v2acfg
java -jar $(AC) -as $@ V2ACFGE <configtool/v2acfge
java -jar $(AC) -p $@ IIC.FONT BIN 0x2000 <fonts/iicfont.bin
java -jar $(AC) -p $@ IIPLUS.FONT BIN 0x2000 <fonts/iiplus.bin
java -jar $(AC) -p $@ LOWERCASE.FONT BIN 0x2000 <fonts/lcase.bin
java -jar $(AC) -p $@ PIG.FONT BIN 0x2000 <fonts/pigfont.bin
java -jar $(AC) -p $@ MOUSETEXT.FONT BIN 0x2000 <fonts/iiemouse.bin
java -jar $(AC) -p $@ REACTIVE.FONT BIN 0x2000 <fonts/reactive.bin
java -jar $(AC) -bas $@ IICFONT.BAS <prodos/iicfont.bas
java -jar $(AC) -bas $@ IIPLUS.BAS <prodos/iiplus.bas
java -jar $(AC) -bas $@ LOWERCASE.BAS <prodos/lowercase.bas
java -jar $(AC) -bas $@ PIGFONT.BAS <prodos/pigfont.bas
java -jar $(AC) -bas $@ MOUSETEXT.BAS <prodos/mousetext.bas
java -jar $(AC) -bas $@ REACTIVE.BAS <prodos/reactive.bas
uploadfont/uploadfont: uploadfont/uploadfont.c
$(MAKE) -C uploadfont uploadfont
uploadfont/uploadfonte: uploadfont/uploadfont.c
$(MAKE) -C uploadfont uploadfonte
uploadfont/flashfont: uploadfont/flashfont.c
$(MAKE) -C uploadfont flashfont
uploadfont/flashfonte: uploadfont/flashfont.c
$(MAKE) -C uploadfont flashfonte
configtool/v2acfg: configtool/configtool.c
$(MAKE) -C configtool v2acfg
configtool/v2acfge: configtool/configtool.c
$(MAKE) -C configtool v2acfge
clean:
@$(DEL) font.dsk 2>$(NULLDEV)
@$(DEL) uploadfont uploadfont.map 2>$(NULLDEV)

View File

@ -1,8 +1,11 @@
#ifndef PICOPAL_SLOT
#define PICOPAL_SLOT 3
#endif
#define PICOPAL_REGISTER(n) (*(volatile unsigned char *)(0xc080 | (n) | (PICOPAL_SLOT << 4)))
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef signed char int8_t;
typedef signed short int16_t;
#define PICOPAL_REGISTER(n) (*(volatile unsigned char *)(0xC080 | (n) | (cardslot << 4)))
#define PICOPAL_WRDATA PICOPAL_REGISTER(0x0)
#define PICOPAL_ALSB PICOPAL_REGISTER(0x1)
@ -13,3 +16,98 @@
#define PICOPAL_RDDATA PICOPAL_REGISTER(0x7)
#define PICOPAL_WRFONT PICOPAL_REGISTER(0x8)
#define PICOPAL_RDFONT PICOPAL_REGISTER(0xf)
#define CFG_BUFFER ((volatile unsigned char *)(0xC0E0 | (cardslot << 8)))
typedef enum {
MODE_REBOOT = 0,
MODE_DIAG,
MODE_FS,
MODE_VGACARD,
MODE_APPLICARD,
MODE_SERIAL,
MODE_PARALLEL,
MODE_MIDI,
MODE_SNESMAX,
MODE_ETHERNET
} v2mode_t;
typedef enum {
SERIAL_LOOP = 0,
SERIAL_USB,
SERIAL_WIFI,
SERIAL_PRINTER,
} serialmux_t;
typedef enum {
USB_HOST_CDC,
USB_GUEST_CDC,
USB_GUEST_MIDI,
} usbmux_t;
typedef enum {
WIFI_CLIENT = 0,
WIFI_AP,
} wifimode_t;
#define FS_BUFFER ((volatile unsigned char *)(0xC800))
#define FS_COMMAND PICOPAL_REGISTER(0x0)
#define FS_FILE PICOPAL_REGISTER(0x1)
#define FS_FLAGS PICOPAL_REGISTER(0x1)
#define FS_SIZELSB PICOPAL_REGISTER(0x2)
#define FS_SIZEMSB PICOPAL_REGISTER(0x3)
#define FS_OFFLSB PICOPAL_REGISTER(0x2)
#define FS_OFFMSB PICOPAL_REGISTER(0x3)
#define FS_WHENCE PICOPAL_REGISTER(0x4)
#define FS_BUSY PICOPAL_REGISTER(0xD)
#define FS_STATUS PICOPAL_REGISTER(0xE)
#define FS_EXECUTE PICOPAL_REGISTER(0xF)
#define FS_O_RD 1
#define FS_O_WR 2
#define FS_O_APPEND 4
#define FS_O_EXISTING 8
#define FS_O_CREATE 16
#define FS_O_TRUNC 32
#define FS_SEEK_SET 0
#define FS_SEEK_CUR 1
#define FS_SEEK_END 2
typedef enum {
FS_OPEN = 0x10,
FS_CLOSE = 0x11,
FS_READ = 0x12,
FS_WRITE = 0x13,
FS_SEEK = 0x14,
FS_TELL = 0x15,
} fscommand_t;
typedef enum {
FS_ERR_OK = 0, // No error
FS_ERR_IO = -1, // Error during device operation
FS_ERR_CORRUPT = -2, // Corrupted
FS_ERR_NOENT = -3, // No directory entry
FS_ERR_EXIST = -4, // Entry already exists
FS_ERR_NOTDIR = -5, // Entry is not a dir
FS_ERR_ISDIR = -5, // Entry is a dir
FS_ERR_NOTEMPTY = -7, // Dir is not empty
FS_ERR_BADF = -8, // Bad file number
FS_ERR_FBIG = -9, // File too large
FS_ERR_INVAL = -10, // Invalid parameter
FS_ERR_NOSPC = -11, // No space left on device
FS_ERR_NOMEM = -12, // No more memory available
FS_ERR_NOATTR = -13, // No data/attr available
FS_ERR_NAMETOOLONG = -14 // File name too long
} fserror_t;
typedef enum {
MACHINE_AUTO = 0,
MACHINE_APPLE_II = 1,
MACHINE_APPLE_IIE = 2,
MACHINE_APPLE_IIGS = 3,
MACHINE_MAXVALUE = 4
} compat_t;

File diff suppressed because it is too large Load Diff

56
utilities/modes/Makefile Normal file
View File

@ -0,0 +1,56 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= apple2
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_apple2 = modeswitch
ifneq ($(EXELIST_$(SYS)),)
all: $(EXELIST_$(SYS))
else
all: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: modeswitch not available for" $(SYS)
else
# suppress the "nothing to be done for 'all' message
@echo > $(NULLDEV)
endif
modeswitch: modeswitch.c
$(CL) -Oirs -t apple2 --start-addr 0x2000 -m $@.map -o $@ $^
~/applesingle/applesingle -r < $@ > $@"#062000"
clean:
@$(DEL) modeswitch modeswitch.map 2>$(NULLDEV)

View File

@ -0,0 +1,299 @@
// cl65 -t apple2 --start-addr 0x4000 uploadfont.c
#include <stdio.h>
#include <conio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "../common/picopal.h"
uint16_t cardslot = 3;
uint8_t *cfgbuf;
void paint_backdrop(char *str) {
int w, i;
w = strlen(str);
if(w > 20) {
w = 20;
}
clrscr();
gotoy(0); gotox(1);
cputs("V2 Analog");
gotoy(0); gotox(39 - w);
if((w == 19) && str[19])
w = 16;
for(i = 0; i < w; i++) {
cputc(str[i]);
}
if((i == 17) && str[i])
cputs("...");
gotoy(1); gotox(0);
cputs("----------------------------------------");
gotoy(22); gotox(0);
cputs("----------------------------------------");
gotoy(23); gotox(4);
cputs("https://www.v2retrocomputing.com");
}
void message(char *str) {
int w, x, i, c;
if(strlen(str) > 34) {
w = 34;
} else {
w = strlen(str);
}
x = 20 - ((w+6)/2);
gotoy(9); gotox(x);
cputs(" +-");
for(i = 0; i < (w); i++) {
cputc('-');
}
cputs("-+ ");
gotoy(10); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(11); gotox(x);
cputs(" ! ");
for(c = 0; c < w; c++) {
cputc(str[c]);
}
cputs(" ! ");
gotoy(12); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(13); gotox(x);
cputs(" ! ");
for(i = 0; i < ((w-4)/2); i++) {
cputc(' ');
}
cputs("[OK]");
i += 4;
for(; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(14); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(15); gotox(x);
cputs(" +-");
for(i = 0; i < w; i++) {
cputc('-');
}
cputs("-+ ");
for(;;) {
switch(cgetc()) {
case 0x0A:
case 0x0D:
case 0x1B:
case 'O':
case 'o':
return;
}
}
}
int confirm(char *str) {
int w, x, i, c;
if(strlen(str) > 34) {
w = 34;
} else {
w = strlen(str);
}
x = 20 - ((w+6)/2);
gotoy(9); gotox(x);
cputs(" +-");
for(i = 0; i < (w); i++) {
cputc('-');
}
cputs("-+ ");
gotoy(10); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(11); gotox(x);
cputs(" ! ");
for(c = 0; c < w; c++) {
cputc(str[c]);
}
cputs(" ! ");
gotoy(12); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(13); gotox(x);
cputs(" ! ");
for(i = 0; i < ((w-12)/2); i++) {
cputc(' ');
}
cputs("[YES] / [NO]");
i += 12;
for(; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(14); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(15); gotox(x);
cputs(" +-");
for(i = 0; i < w; i++) {
cputc('-');
}
cputs("-+ ");
for(;;) {
switch(cgetc()) {
case 0x0A:
case 0x0D:
case 'Y':
case 'y':
return 1;
case 0x1B:
case 'N':
case 'n':
return 0;
}
}
}
void cfg_cmd(char *cmd) {
int i = 0;
uint16_t delay;
while(i < 31) {
if(*cmd) {
cfgbuf[i++] = *cmd++;
} else {
cfgbuf[i++] = 0x00;
}
}
cfgbuf[31] = 0x00;
delay = 0x1fff;
while(delay > 0) delay--;
}
int prompt_slot(void) {
int c;
paint_backdrop("Mode Switch");
gotoy(11); gotox(2);
cputs("Which slot is the card installed in?");
gotoy(13); gotox(14);
printf("Default = %i", cardslot);
for(;;) {
c = cgetc();
if((c >= '1') && (c <= '7')) {
cardslot = c - '0';
return 1;
} else if((c == 0x0A) || (c == 0x0D)) {
return 1;
} else if(c == 0x1B) {
return 0;
}
}
}
void main (void) {
int paint_menu = 1;
int c;
if(!prompt_slot()) {
return;
}
cfgbuf = (uint8_t *)(0xC0E0 | (cardslot << 8));
paint_backdrop("Mode Switch");
gotoy(11); gotox(4);
cputs("1. VGA Card");
gotoy(12); gotox(4);
cputs("2. PCPI Applicard");
gotoy(13); gotox(4);
cputs("3. Serial");
gotoy(14); gotox(4);
cputs("4. Parallel");
gotoy(15); gotox(4);
cputs("5. Card Diagnostic");
gotoy(18); gotox(4);
cputs("8. Save Default");
gotoy(19); gotox(4);
cputs("9. Quit");
for(;;) {
c = cgetc();
switch(c) {
case '1':
cfg_cmd("MODE=VGA");
break;
case '2':
cfg_cmd("MODE=Z80");
break;
case '3':
cfg_cmd("MODE=SERIAL");
break;
case '4':
cfg_cmd("MODE=PARALLEL");
break;
case '5':
cfg_cmd("MODE=DIAG");
break;
case '8':
cfg_cmd("WRITE_CONFIG");
break;
case '9':
clrscr();
puts("Done.\n");
return;
}
}
}

View File

@ -31,8 +31,7 @@ else
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_apple2 = \
uploadfont
EXELIST_apple2 = uploadfont uploadfonte flashfont flashfonte
ifneq ($(EXELIST_$(SYS)),)
all: $(EXELIST_$(SYS))
@ -50,7 +49,20 @@ else
endif
uploadfont: uploadfont.c
$(CL) -Oirs -t apple2 --start-addr 0x4000 -m uploadfont.map $^
$(CL) -Oirs -t apple2 --start-addr 0x2800 -m $@.map -o $@ $^
~/applesingle/applesingle -r < $@ > $@"#062800"
uploadfonte: uploadfont.c
$(CL) -Oirs -t apple2enh --start-addr 0x2800 -m $@.map -o $@ $^
~/applesingle/applesingle -r < $@ > $@"#062800"
flashfont: flashfont.c
$(CL) -Oirs -t apple2 --start-addr 0x2800 -m $@.map -o $@ $^
~/applesingle/applesingle -r < $@ > $@"#062800"
flashfonte: flashfont.c
$(CL) -Oirs -t apple2enh --start-addr 0x2800 -m $@.map -o $@ $^
~/applesingle/applesingle -r < $@ > $@"#062800"
clean:
@$(DEL) uploadfont uploadfont.map 2>$(NULLDEV)
@$(DEL) uploadfont uploadfont.map uploadfonte uploadfonte.map flashfont flashfont.map flashfonte flashfonte.map 2>$(NULLDEV)

View File

@ -0,0 +1,449 @@
// cl65 -t apple2 --start-addr 0x4000 uploadfont.c
#include <stdio.h>
#include <conio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "../common/picopal.h"
uint16_t cardslot = 3;
uint8_t *cfgbuf;
uint8_t *fsbuf;
uint8_t *font = (uint8_t *)0x2000;
#define CARD_TIMEOUT 0xfff
uint16_t timeout = CARD_TIMEOUT;
void paint_backdrop(char *str) {
int w, i;
w = strlen(str);
if(w > 20) {
w = 20;
}
clrscr();
gotoy(0); gotox(1);
cputs("V2 Analog");
gotoy(0); gotox(39 - w);
if((w == 19) && str[19])
w = 16;
for(i = 0; i < w; i++) {
cputc(str[i]);
}
if((i == 17) && str[i])
cputs("...");
gotoy(1); gotox(0);
cputs("----------------------------------------");
gotoy(22); gotox(0);
cputs("----------------------------------------");
gotoy(23); gotox(4);
cputs("https://www.v2retrocomputing.com");
}
void message(char *str) {
int w, x, i, c;
if(strlen(str) > 34) {
w = 34;
} else {
w = strlen(str);
}
x = 20 - ((w+6)/2);
gotoy(9); gotox(x);
cputs(" +-");
for(i = 0; i < (w); i++) {
cputc('-');
}
cputs("-+ ");
gotoy(10); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(11); gotox(x);
cputs(" ! ");
for(c = 0; c < w; c++) {
cputc(str[c]);
}
cputs(" ! ");
gotoy(12); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(13); gotox(x);
cputs(" ! ");
for(i = 0; i < ((w-4)/2); i++) {
cputc(' ');
}
cputs("[OK]");
i += 4;
for(; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(14); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(15); gotox(x);
cputs(" +-");
for(i = 0; i < w; i++) {
cputc('-');
}
cputs("-+ ");
for(;;) {
switch(cgetc()) {
case 0x0A:
case 0x0D:
case 0x1B:
case 'O':
case 'o':
return;
}
}
}
int confirm(char *str) {
int w, x, i, c;
if(strlen(str) > 34) {
w = 34;
} else {
w = strlen(str);
}
x = 20 - ((w+6)/2);
gotoy(9); gotox(x);
cputs(" +-");
for(i = 0; i < (w); i++) {
cputc('-');
}
cputs("-+ ");
gotoy(10); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(11); gotox(x);
cputs(" ! ");
for(c = 0; c < w; c++) {
cputc(str[c]);
}
cputs(" ! ");
gotoy(12); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(13); gotox(x);
cputs(" ! ");
for(i = 0; i < ((w-12)/2); i++) {
cputc(' ');
}
cputs("[YES] / [NO]");
i += 12;
for(; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(14); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(15); gotox(x);
cputs(" +-");
for(i = 0; i < w; i++) {
cputc('-');
}
cputs("-+ ");
for(;;) {
switch(cgetc()) {
case 0x0A:
case 0x0D:
case 'Y':
case 'y':
return 1;
case 0x1B:
case 'N':
case 'n':
return 0;
}
}
}
void cfg_cmd(char *cmd) {
int i = 0;
uint16_t delay;
while(i < 31) {
if(*cmd) {
cfgbuf[i++] = *cmd++;
} else {
cfgbuf[i++] = 0x00;
}
}
cfgbuf[31] = 0x00;
delay = 0x1fff;
while(delay > 0) delay--;
}
int prompt_slot(void) {
int c;
paint_backdrop("Font Upload");
gotoy(11); gotox(2);
cputs("Which slot is the card installed in?");
gotoy(13); gotox(14);
printf("Default = %i", cardslot);
for(;;) {
c = cgetc();
if((c >= '1') && (c <= '7')) {
cardslot = c - '0';
return 1;
} else if((c == 0x0A) || (c == 0x0D)) {
return 1;
} else if(c == 0x1B) {
return 0;
}
}
}
int file_open(char *path, uint8_t flags) {
timeout = CARD_TIMEOUT;
strcpy((char *)fsbuf, path);
FS_FLAGS = flags;
FS_COMMAND = FS_OPEN;
FS_BUSY = 0xFF;
FS_EXECUTE = 0x00;
while(FS_BUSY && (timeout > 0)) {
timeout--;
}
if(FS_BUSY) {
message("I/O Error");
return FS_ERR_IO;
}
if(FS_STATUS != FS_ERR_OK) {
return FS_STATUS;
}
return FS_FILE;
}
int file_close(int file) {
timeout = CARD_TIMEOUT;
FS_FILE = file;
FS_COMMAND = FS_CLOSE;
FS_BUSY = 0xFF;
FS_EXECUTE = 0x00;
while(FS_BUSY && (timeout > 0)) {
timeout--;
}
if(FS_BUSY) {
message("I/O Error");
return FS_ERR_IO;
}
return FS_STATUS;
}
int file_read(int file, char *buffer, uint16_t size) {
timeout = CARD_TIMEOUT;
FS_FILE = file;
FS_COMMAND = FS_READ;
FS_SIZELSB = size & 0xFF;
FS_SIZEMSB = size >> 8;
FS_BUSY = 0xFF;
FS_EXECUTE = 0x00;
while(FS_BUSY && (timeout > 0)) {
timeout--;
}
if(FS_BUSY) {
message("I/O Error");
return FS_ERR_IO;
}
if(FS_STATUS != FS_ERR_OK) {
return FS_STATUS;
}
size = (((uint16_t)FS_SIZEMSB) << 8) | (uint16_t)FS_SIZELSB;
memcpy(buffer, fsbuf, size);
return size;
}
int file_write(int file, char *buffer, uint16_t size) {
timeout = CARD_TIMEOUT;
memcpy(fsbuf, buffer, size);
FS_FILE = file;
FS_COMMAND = FS_WRITE;
FS_SIZELSB = size & 0xFF;
FS_SIZEMSB = size >> 8;
FS_BUSY = 0xFF;
FS_EXECUTE = 0x00;
while(FS_BUSY && (timeout > 0)) {
timeout--;
}
if(FS_BUSY) {
message("I/O Error");
return FS_ERR_IO;
}
if(FS_STATUS != FS_ERR_OK) {
return FS_STATUS;
}
size = (((uint16_t)FS_SIZEMSB) << 8) | (uint16_t)FS_SIZELSB;
return size;
}
int file_seek(int file, int16_t off, uint8_t whence) {
timeout = CARD_TIMEOUT;
FS_FILE = file;
FS_COMMAND = FS_SEEK;
FS_OFFLSB = ((uint16_t)off) & 0xFF;
FS_OFFMSB = ((uint16_t)off) >> 8;
FS_WHENCE = whence;
FS_BUSY = 0xFF;
FS_EXECUTE = 0x00;
while(FS_BUSY && (timeout > 0)) {
timeout--;
}
if(FS_BUSY) {
message("I/O Error");
return FS_ERR_IO;
}
if(FS_STATUS != FS_ERR_OK) {
return FS_STATUS;
}
off = (int16_t)(((uint16_t)FS_SIZEMSB) << 8) | (uint16_t)FS_SIZELSB;
return off;
}
int file_tell(int file) {
uint16_t off;
timeout = CARD_TIMEOUT;
FS_FILE = file;
FS_COMMAND = FS_TELL;
FS_BUSY = 0xFF;
FS_EXECUTE = 0x00;
while(FS_BUSY && (timeout > 0)) {
timeout--;
}
if(FS_BUSY) {
message("I/O Error");
return FS_ERR_IO;
}
if(FS_STATUS != FS_ERR_OK) {
return FS_STATUS;
}
off = (((uint16_t)FS_SIZEMSB) << 8) | (uint16_t)FS_SIZELSB;
return off;
}
void main (void) {
int paint_menu = 1;
int file;
if(!prompt_slot()) {
return;
}
cfgbuf = (uint8_t *)CFG_BUFFER;
fsbuf = (uint8_t *)FS_BUFFER;
paint_backdrop("Please Wait");
gotoy(11); gotox(13);
cputs("Uploading font,");
gotoy(12); gotox(8);
cputs("your screen may flicker.");
cfg_cmd("MODE=FS");
while(memcmp(cfgbuf+24, "FSREADY.", 8) && (timeout > 0)) {
timeout--;
}
if(timeout == 0) {
message("Communication Timeout");
clrscr();
return;
}
file = file_open("font", FS_O_WR | FS_O_CREATE);
if(file >= 0) {
file_write(file, (char *)font, 2048);
file_close(file);
}
paint_backdrop("Please Wait");
gotoy(11); gotox(13);
cputs("Rebooting card,");
gotoy(12); gotox(8);
cputs("your screen may flicker.");
cfg_cmd("REBOOT");
clrscr();
puts("Done.\n");
}

View File

@ -6,22 +6,280 @@
#include <string.h>
#include <unistd.h>
#define PICOPAL_SLOT 3
#include "../common/picopal.h"
void main (void)
{
unsigned char *font = (unsigned char *)0x2000;
int i;
uint16_t cardslot = 3;
uint8_t *cfgbuf;
uint8_t *fsbuf;
uint8_t *font = (uint8_t *)0x2000;
puts("Loading font to PicoPal in slot 3...");
void paint_backdrop(char *str) {
int w, i;
PICOPAL_ALSB = 0x00;
PICOPAL_AMSB = 0x00;
for(i = 0; i < 0x800; i++) {
PICOPAL_WRFONT = font[i];
w = strlen(str);
if(w > 20) {
w = 20;
}
clrscr();
gotoy(0); gotox(1);
cputs("V2 Analog");
gotoy(0); gotox(39 - w);
if((w == 19) && str[19])
w = 16;
for(i = 0; i < w; i++) {
cputc(str[i]);
}
if((i == 17) && str[i])
cputs("...");
gotoy(1); gotox(0);
cputs("----------------------------------------");
gotoy(22); gotox(0);
cputs("----------------------------------------");
gotoy(23); gotox(4);
cputs("https://www.v2retrocomputing.com");
}
void message(char *str) {
int w, x, i, c;
if(strlen(str) > 34) {
w = 34;
} else {
w = strlen(str);
}
x = 20 - ((w+6)/2);
gotoy(9); gotox(x);
cputs(" +-");
for(i = 0; i < (w); i++) {
cputc('-');
}
cputs("-+ ");
gotoy(10); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(11); gotox(x);
cputs(" ! ");
for(c = 0; c < w; c++) {
cputc(str[c]);
}
cputs(" ! ");
gotoy(12); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(13); gotox(x);
cputs(" ! ");
for(i = 0; i < ((w-4)/2); i++) {
cputc(' ');
}
cputs("[OK]");
i += 4;
for(; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(14); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(15); gotox(x);
cputs(" +-");
for(i = 0; i < w; i++) {
cputc('-');
}
cputs("-+ ");
for(;;) {
switch(cgetc()) {
case 0x0A:
case 0x0D:
case 0x1B:
case 'O':
case 'o':
return;
}
}
}
int confirm(char *str) {
int w, x, i, c;
if(strlen(str) > 34) {
w = 34;
} else {
w = strlen(str);
}
x = 20 - ((w+6)/2);
gotoy(9); gotox(x);
cputs(" +-");
for(i = 0; i < (w); i++) {
cputc('-');
}
cputs("-+ ");
gotoy(10); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(11); gotox(x);
cputs(" ! ");
for(c = 0; c < w; c++) {
cputc(str[c]);
}
cputs(" ! ");
gotoy(12); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(13); gotox(x);
cputs(" ! ");
for(i = 0; i < ((w-12)/2); i++) {
cputc(' ');
}
cputs("[YES] / [NO]");
i += 12;
for(; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(14); gotox(x);
cputs(" ! ");
for(i = 0; i < w; i++) {
cputc(' ');
}
cputs(" ! ");
gotoy(15); gotox(x);
cputs(" +-");
for(i = 0; i < w; i++) {
cputc('-');
}
cputs("-+ ");
for(;;) {
switch(cgetc()) {
case 0x0A:
case 0x0D:
case 'Y':
case 'y':
return 1;
case 0x1B:
case 'N':
case 'n':
return 0;
}
}
}
void cfg_cmd(char *cmd) {
int i = 0;
uint16_t delay;
while(i < 31) {
if(*cmd) {
cfgbuf[i++] = *cmd++;
} else {
cfgbuf[i++] = 0x00;
}
}
cfgbuf[31] = 0x00;
delay = 0x1fff;
while(delay > 0) delay--;
}
int prompt_slot(void) {
int c;
paint_backdrop("Font Upload");
gotoy(11); gotox(2);
cputs("Which slot is the card installed in?");
gotoy(13); gotox(14);
printf("Default = %i", cardslot);
for(;;) {
c = cgetc();
if((c >= '1') && (c <= '7')) {
cardslot = c - '0';
return 1;
} else if((c == 0x0A) || (c == 0x0D)) {
return 1;
} else if(c == 0x1B) {
return 0;
}
}
}
void main (void) {
int paint_menu = 1;
uint16_t i;
if(!prompt_slot()) {
return;
}
cfgbuf = (uint8_t *)CFG_BUFFER;
fsbuf = (uint8_t *)FS_BUFFER;
paint_backdrop("Please Wait");
gotoy(11); gotox(13);
cputs("Uploading font,");
gotoy(12); gotox(8);
cputs("your screen may flicker.");
cfg_cmd("BANK=SAVE");
cfg_cmd("BANK=FONT0");
for(i = 0; i < 0x200; i++) {
FS_BUFFER[i] = font[i];
}
cfg_cmd("BANK=FONT1");
for(i = 0; i < 0x200; i++) {
FS_BUFFER[i] = font[i+512];
}
cfg_cmd("BANK=FONT2");
for(i = 0; i < 0x200; i++) {
FS_BUFFER[i] = font[i+1024];
}
cfg_cmd("BANK=FONT3");
for(i = 0; i < 0x200; i++) {
FS_BUFFER[i] = font[i+1536];
}
cfg_cmd("BANK=RESTORE");
clrscr();
puts("Done.\n");
}

View File

@ -1,6 +1,11 @@
cmake_minimum_required(VERSION 3.16)
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "build-lc")
set(PICO_BOARD pico)
else()
set(PICO_BOARD pico_w)
endif()
set(PICO_TARGET_LINKER_SCRIPT memmap_ota.ld)
# Pull in SDK (must be before project)
@ -23,7 +28,7 @@ pico_generate_pio_header(v2-analog-${PICO_BOARD}
target_sources(v2-analog-${PICO_BOARD} PUBLIC
common/ota.o
common/buffers.c
common/flash_upload.c
common/flash.c
common/abus.c
common/config.c
common/main.c

View File

@ -33,9 +33,9 @@ next_bus_cycle:
write_cycle:
; the current time is P0+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
set PINS, 0b110 [14] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns)
set PINS, 0b110 [15] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns)
in PINS, 10 ; read R/W, ~DEVSEL, and Data[7:0], then autopush
wait 0 GPIO, PHI0_GPIO [6] ; wait for PHI0 to fall
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall
jmp next_bus_cycle
read_cycle:
@ -45,7 +45,7 @@ read_cycle:
in PINS, 10 ; read R/W, ~DEVSEL, and dontcare[7:0], then autopush
irq set READ_DATA_TRIGGER_IRQ ; trigger the data read state machine to put data on the data bus
wait 0 GPIO, PHI0_GPIO [6] ; wait for PHI0 to fall
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall
wait 0 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
.wrap
@ -79,8 +79,8 @@ wait_loop:
pull noblock ; extra early pull to clear out any standing values from the FIFO
set PINS, 0b01 ; enable Data tranceiver with output direction
mov OSR, ~NULL
out PINDIRS, 8 [30] ; set data pins as outputs
mov OSR, ~NULL [3]
out PINDIRS, 8 [31] ; set data pins as outputs
pull noblock ; pull value from the FIFO as late as possible
out PINS, 8

View File

@ -1,5 +1,8 @@
#include "buffers.h"
volatile uint8_t cardslot = 0;
volatile uint32_t busactive = 0;
volatile uint8_t apple_memory[64*1024];
volatile uint8_t private_memory[64*1024];

View File

@ -2,11 +2,15 @@
#include <stdint.h>
extern volatile uint8_t config_memory[32];
extern volatile uint8_t cardslot;
extern volatile uint32_t busactive;
extern volatile uint8_t apple_memory[64*1024];
extern volatile uint8_t private_memory[64*1024];
#define config_cmdbuf ((uint8_t*)(apple_memory+0xC0F0+(cardslot<<8)))
#define config_errbuf ((uint8_t*)(apple_memory+0xC0F8+(cardslot<<8)))
extern volatile uint8_t *text_p1;
extern volatile uint8_t *text_p2;
extern volatile uint8_t *text_p3;

View File

@ -1,246 +1,333 @@
#include "common/config.h"
#include "common/buffers.h"
#include "common/flash.h"
#include "pico_hal.h"
volatile uint8_t config_memory[32];
volatile v2mode_t cfg_mode = MODE_UNKNOWN;
volatile v2mode_t current_mode = MODE_UNKNOWN;
v2mode_t v2mode;
usbmux_t usbmux;
serialmux_t serialmux;
wifimode_t wifimode;
compat_t machine;
uint8_t wifi_ssid[32];
uint8_t wifi_psk[32];
volatile usbmux_t usbmux;
volatile serialmux_t serialmux;
volatile wifimode_t wifimode;
extern bool userfont;
volatile compat_t cfg_machine = MACHINE_AUTO;
volatile compat_t current_machine = MACHINE_AUTO;
volatile uint8_t wifi_ssid[32];
volatile uint8_t wifi_psk[32];
extern volatile bool userfont;
char ERR_READY[8] = { 'R', 'E', 'A', 'D', 'Y', 0, 0, 0 };
char ERR_EOF[8] = { 'E', 'O', 'F', 0, 0, 0, 0, 0 };
char ERR_NOFILE[8] = { 'E', 'O', 'F', 0, 0, 0, 0, 0 };
void parse_config(uint8_t *buffer) {
if(!memcmp("MODE=", buffer, 5)) {
if(!strcmp("DIAG", buffer+5)) {
v2mode = MODE_DIAG;
} else if(!strcmp("FS", buffer+5)) {
v2mode = MODE_FS;
} else if(!strcmp("VGA", buffer+5)) {
v2mode = MODE_VGACARD;
} else if(!strcmp("Z80", buffer+5)) {
v2mode = MODE_APPLICARD;
} else if(!strcmp("SERIAL", buffer+5)) {
v2mode = MODE_SERIAL;
} else if(!strcmp("PARALLEL", buffer+5)) {
v2mode = MODE_PARALLEL;
} else if(!strcmp("SNESMAX", buffer+5)) {
v2mode = MODE_SNESMAX;
if(!memcmp("C=", buffer, 2)) {
if(!strcmp("DIAG", buffer+2)) {
cfg_mode = MODE_DIAG;
} else if(!strcmp("FS", buffer+2)) {
cfg_mode = MODE_FS;
} else if(!strcmp("VGA", buffer+2)) {
cfg_mode = MODE_VGACARD;
} else if(!strcmp("Z80", buffer+2)) {
cfg_mode = MODE_APPLICARD;
} else if(!strcmp("SER", buffer+2)) {
cfg_mode = MODE_SERIAL;
} else if(!strcmp("PAR", buffer+2)) {
cfg_mode = MODE_PARALLEL;
} else if(!strcmp("SNES", buffer+2)) {
cfg_mode = MODE_SNESMAX;
}
} else if(!memcmp("MACHINE=", buffer, 8)) {
if(!strcmp("II", buffer+8)) {
machine = APPLE_II;
} else if(!memcmp("H=", buffer, 2)) {
if(!strcmp("AUTO", buffer+2)) {
cfg_machine = MACHINE_AUTO;
} else if(!strcmp("II", buffer+2)) {
cfg_machine = MACHINE_II;
soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS);
} else if(!strcmp("IIE", buffer+8)) {
machine = APPLE_IIE;
} else if(!strcmp("IIE", buffer+2)) {
cfg_machine = MACHINE_IIE;
soft_switches &= ~SOFTSW_IIGS_REGS;
soft_switches |= SOFTSW_IIE_REGS;
} else if(!strcmp("IIGS", buffer+8)) {
machine = APPLE_IIGS;
} else if(!strcmp("IIGS", buffer+2)) {
cfg_machine = MACHINE_IIGS;
soft_switches |= SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS;
}
} else if(!memcmp("MUX=", buffer, 4)) {
if(!strcmp("USB", buffer+4)) {
} else if(!memcmp("S=", buffer, 2)) {
if(!strcmp("USB", buffer+2)) {
serialmux = SERIAL_USB;
} else if(!strcmp("MODEM", buffer+4)) {
} else if(!strcmp("WIFI", buffer+2)) {
serialmux = SERIAL_WIFI;
} else if(!strcmp("PRINTER", buffer+4)) {
} else if(!strcmp("PRN", buffer+2)) {
serialmux = SERIAL_PRINTER;
} else if(!strcmp("LOOP", buffer+4)) {
} else if(!strcmp("LOOP", buffer+2)) {
serialmux = SERIAL_LOOP;
}
} else if(!memcmp("USB=", buffer, 4)) {
if(!strcmp("CDC_GUEST", buffer+4)) {
} else if(!memcmp("U=", buffer, 2)) {
if(!strcmp("CG", buffer+2)) {
usbmux = USB_GUEST_CDC;
} else if(!strcmp("CDC_HOST", buffer+4)) {
} else if(!strcmp("CH", buffer+2)) {
usbmux = USB_HOST_CDC;
}
} else if(!memcmp("WIFI=", buffer, 5)) {
if(!strcmp("CLIENT", buffer+5)) {
} else if(!memcmp("W=", buffer, 2)) {
if(!strcmp("C", buffer+2)) {
wifimode = WIFI_CLIENT;
} else if(!strcmp("AP", buffer+5)) {
} else if(!strcmp("A", buffer+2)) {
wifimode = WIFI_AP;
}
} else if(!memcmp("SSID=", buffer, 5)) {
strncpy(wifi_ssid, buffer+5, 25);
} else if(!memcmp("PSK=", buffer, 4)) {
strncpy(wifi_psk, buffer+5, 26);
} else if(!memcmp("WN=", buffer, 3)) {
strncpy((char*)wifi_ssid, buffer+5, 24);
} else if(!memcmp("WP=", buffer, 3)) {
strncpy((char*)wifi_psk, buffer+5, 24);
}
}
void default_config() {
v2mode = MODE_VGACARD;
cfg_mode = MODE_VGACARD;
serialmux = SERIAL_LOOP;
usbmux = USB_GUEST_CDC;
wifimode = WIFI_AP;
strcpy(wifi_ssid, "V2RetroNet");
strcpy(wifi_psk, "Analog");
machine = COMPAT_AUTO;
soft_switches = 0;
strcpy((char*)wifi_ssid, "V2RetroNet");
strcpy((char*)wifi_psk, "Analog");
cfg_machine = MACHINE_AUTO;
}
void write_config() {
uint8_t config_temp[32];
int make_config(uint8_t *buf, uint16_t len) {
uint16_t ptr = 0;
if(v2mode == MODE_DIAG) return;
if(v2mode == MODE_REBOOT) return;
int file = pico_open("config", LFS_O_WRONLY | LFS_O_CREAT);
if(file < 0)
return;
switch(v2mode) {
case MODE_FS:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MODE=FS");
pico_write(file, config_temp, 32);
break;
memset(buf, 0, len);
switch(cfg_mode) {
default:
case MODE_VGACARD:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MODE=VGA");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "C=VGA");
ptr += 32;
break;
case MODE_APPLICARD:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MODE=Z80");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "C=Z80");
ptr += 32;
break;
case MODE_SERIAL:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MODE=SERIAL");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "C=SER");
ptr += 32;
break;
case MODE_PARALLEL:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MODE=PARALLEL");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "C=PAR");
ptr += 32;
break;
case MODE_SNESMAX:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MODE=SNESMAX");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "C=SNES");
ptr += 32;
break;
case MODE_ETHERNET:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MODE=ETHERNET");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "C=NET");
ptr += 32;
break;
case MODE_FS:
strcpy(buf+ptr, "C=FS");
ptr += 32;
break;
}
switch(machine) {
case APPLE_II:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MACHINE=II");
pico_write(file, config_temp, 32);
switch(cfg_machine) {
default:
case MACHINE_AUTO:
strcpy(buf+ptr, "H=AUTO");
ptr += 32;
break;
case APPLE_IIE:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MACHINE=IIE");
pico_write(file, config_temp, 32);
case MACHINE_II:
strcpy(buf+ptr, "H=II");
ptr += 32;
break;
case APPLE_IIGS:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MACHINE=IIGS");
pico_write(file, config_temp, 32);
case MACHINE_IIE:
strcpy(buf+ptr, "H=IIE");
ptr += 32;
break;
case MACHINE_IIGS:
strcpy(buf+ptr, "H=IIGS");
ptr += 32;
break;
}
switch(serialmux) {
default:
case SERIAL_LOOP:
strcpy(buf+ptr, "M=LOOP");
ptr += 32;
break;
case SERIAL_USB:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MUX=USB");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "M=USB");
ptr += 32;
break;
case SERIAL_WIFI:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MUX=WIFI");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "M=WIFI");
ptr += 32;
break;
case SERIAL_PRINTER:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MUX=PRINTER");
pico_write(file, config_temp, 32);
break;
case SERIAL_LOOP:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "MUX=LOOP");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "M=PRN");
ptr += 32;
break;
}
switch(usbmux) {
case USB_GUEST_CDC:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "USB=CDC_GUEST");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "U=CG");
ptr += 32;
break;
case USB_HOST_CDC:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "USB=CDC_HOST");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "U=CH");
ptr += 32;
break;
}
switch(wifimode) {
case WIFI_CLIENT:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "WIFI=CLIENT");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "W=C");
ptr += 32;
break;
case WIFI_AP:
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "WIFI=AP");
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "W=A");
ptr += 32;
break;
}
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "SSID=");
strncat(config_temp, wifi_ssid, 25);
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "WS=");
strncpy(buf+ptr+2, (char*)wifi_ssid, 24);
ptr += 32;
memset(config_temp, 0, sizeof(config_temp));
strcpy(config_temp, "PSK=");
strncat(config_temp, wifi_psk, 25);
pico_write(file, config_temp, 32);
strcpy(buf+ptr, "WP=");
strncpy(buf+ptr+2, (char*)wifi_psk, 24);
ptr += 32;
return ptr;
}
void write_config() {
uint8_t config_temp[1024];
int config_len;
config_len = make_config(config_temp, sizeof(config_temp));
int file = pico_open("config", LFS_O_WRONLY | LFS_O_CREAT);
if(file < 0)
return;
pico_write(file, config_temp, config_len);
pico_close(file);
}
void read_config() {
uint8_t config_temp[32];
uint8_t config_temp[1024];
int file = pico_open("config", LFS_O_RDONLY);
int br = 0;
int config_len = 0;
if(file < 0)
return;
do {
br = pico_read(file, config_temp, 32);
if(br > 0) {
parse_config(config_temp);
}
} while(br > 0);
memset(config_temp, 0, sizeof(config_temp));
config_len = pico_read(file, config_temp, sizeof(config_temp));
pico_close(file);
if(config_len > 0) {
for(int ptr = 0; ptr < config_len; ptr+=32) {
parse_config(config_temp+ptr);
}
}
}
volatile uint8_t *videx_page_tmp = (private_memory+0xF000);
extern uint8_t character_rom[4096];
extern uint8_t character_rom[2048];
void upload_config() {
int file = pico_open("config", LFS_O_RDONLY);
memset((uint8_t*)(apple_memory + 0xC800), 0, 1024);
if(file < 0) {
make_config((uint8_t*)(apple_memory + 0xC800), 1024);
} else {
pico_read(file, (uint8_t*)(apple_memory + 0xC800), 1024);
pico_close(file);
}
memcpy(config_errbuf, ERR_READY, sizeof(ERR_READY));
}
void download_config(uint16_t ptr) {
int file = pico_open("config", LFS_O_WRONLY | LFS_O_CREAT);
if(file < 0) {
memcpy(config_errbuf, ERR_NOFILE, sizeof(ERR_NOFILE));
return;
}
pico_write(file, (uint8_t*)(apple_memory + ptr), 1024);
pico_close(file);
memcpy(config_errbuf, ERR_READY, sizeof(ERR_READY));
}
void upload_font(uint8_t page) {
int file;
if(page > 1) {
memcpy(config_errbuf, ERR_EOF, sizeof(ERR_EOF));
return;
}
file = pico_open("font", LFS_O_RDONLY);
if(file < 0) {
memcpy((uint8_t*)(apple_memory + 0xC800), (character_rom + (1024*page)), 1024);
} else {
pico_lseek(file, 1024 * page, LFS_SEEK_SET);
pico_read(file, (uint8_t*)(apple_memory + 0xC800), 1024);
pico_close(file);
}
memcpy(config_errbuf, ERR_READY, sizeof(ERR_READY));
}
void download_font(uint16_t ptr) {
int file = pico_open("font", LFS_O_WRONLY | LFS_O_CREAT);
memcpy(character_rom, (uint8_t*)(apple_memory + ptr), 2048);
if(file < 0) {
memcpy(config_errbuf, ERR_NOFILE, sizeof(ERR_NOFILE));
return;
}
pico_write(file, (uint8_t*)(apple_memory + ptr), 2048);
pico_close(file);
memcpy(config_errbuf, ERR_READY, sizeof(ERR_READY));
}
void config_format() {
pico_unmount();
if(pico_mount(1) != LFS_ERR_OK) {
memcpy(config_errbuf, ERR_NOFILE, sizeof(ERR_NOFILE));
} else {
memcpy(config_errbuf, ERR_READY, sizeof(ERR_READY));
}
}
void config_handler() {
if(config_memory[31] != 0) return;
if(config_cmdbuf[7] != 0) return;
if(!strcmp("BANK=SAVE", (uint8_t*)config_memory)) {
videx_page_tmp = videx_page;
} else if(!strcmp("BANK=RESTORE", (uint8_t*)config_memory)) {
videx_page = videx_page_tmp;
} else if(!memcmp("BANK=FONT", (uint8_t*)config_memory, 9)) {
videx_page = character_rom + (((config_memory[9] - '0') & 3) * 1024);
} else if(!strcmp("WRITE_CONFIG", (uint8_t*)config_memory)) {
write_config();
} else if(!strcmp("REBOOT", (uint8_t*)config_memory)) {
v2mode = MODE_REBOOT;
} else parse_config((uint8_t*)config_memory);
config_cmdbuf[7] = 0xff;
if(!memcmp("H=", (uint8_t*)config_cmdbuf, 2)) {
parse_config((uint8_t*)config_cmdbuf);
} else if(!memcmp("UF", (uint8_t*)config_cmdbuf, 2)) {
upload_font(config_cmdbuf[2]);
} else if(!memcmp("DF", (uint8_t*)config_cmdbuf, 2)) {
download_font((config_cmdbuf[2] << 0) | (config_cmdbuf[3] << 8));
flash_reboot();
} else if(!memcmp("UC", (uint8_t*)config_cmdbuf, 2)) {
upload_config();
} else if(!memcmp("DC", (uint8_t*)config_cmdbuf, 2)) {
download_config((config_cmdbuf[2] << 0) | (config_cmdbuf[3] << 8));
flash_reboot();
} else if(!memcmp("FORMAT", (uint8_t*)config_cmdbuf, 6)) {
config_format();
flash_reboot();
}
memset(config_cmdbuf, 0x00, 7);
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <stdint.h>
#define CONFIG_SYSCLOCK 126.0 /* MHz */
// Pin configuration
@ -19,6 +21,7 @@
typedef enum {
MODE_REBOOT = 0,
MODE_UNKNOWN,
MODE_DIAG,
MODE_FS,
MODE_VGACARD,
@ -29,7 +32,8 @@ typedef enum {
MODE_ETHERNET
} v2mode_t;
extern v2mode_t v2mode;
extern volatile v2mode_t cfg_mode;
extern volatile v2mode_t current_mode;
typedef enum {
SERIAL_LOOP = 0,
@ -38,7 +42,7 @@ typedef enum {
SERIAL_PRINTER,
} serialmux_t;
extern serialmux_t serialmux;
extern volatile serialmux_t serialmux;
typedef enum {
USB_HOST_CDC,
@ -46,23 +50,24 @@ typedef enum {
USB_GUEST_MIDI,
} usbmux_t;
extern usbmux_t usbmux;
extern volatile usbmux_t usbmux;
typedef enum {
WIFI_CLIENT = 0,
WIFI_AP,
} wifimode_t;
extern wifimode_t wifimode;
extern volatile wifimode_t wifimode;
typedef enum {
APPLE_II = 0,
APPLE_IIE = 1,
APPLE_IIGS = 2,
COMPAT_AUTO = 0xff
MACHINE_II = 0,
MACHINE_IIE = 1,
MACHINE_IIGS = 2,
MACHINE_AUTO = 0xff
} compat_t;
extern compat_t machine;
extern volatile compat_t cfg_machine;
extern volatile compat_t current_machine;
enum {
ABUS_MAIN_SM = 0,
@ -74,7 +79,9 @@ enum {
#define CARD_IOSEL (((address & 0xcf00) >= 0xc100) && ((address & 0xcf00) < 0xc700))
#define CARD_IOSTROBE ((address & 0xc800) == 0xc800)
int make_config(uint8_t *buf, uint16_t len);
void read_config();
void write_config();
void config_handler();
void default_config();

View File

@ -0,0 +1,25 @@
#include <pico/stdlib.h>
#include <pico/multicore.h>
#include <hardware/flash.h>
#include <hardware/watchdog.h>
#include <hardware/resets.h>
#include "config.h"
#ifdef RASPBERRYPI_PICO_W
#include <pico/cyw43_arch.h>
#endif
void __time_critical_func(flash_reboot)() __attribute__ ((noreturn));
// Reboot the Pico
void __time_critical_func(flash_reboot)() {
save_and_disable_interrupts();
multicore_reset_core1();
reset_block((1<<11) | (1<<10) | (1<<2));
watchdog_enable(2, 1);
for(;;);
}

View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
extern void flash_reboot() __attribute__ ((noreturn));

View File

@ -1,21 +0,0 @@
#pragma once
#include <stdint.h>
extern uint8_t flash_control;
extern uint8_t flash_status;
extern uint8_t flash_data;
extern uint32_t flash_address;
enum {
FLASH_STATUS_READY = 0x00,
FLASH_STATUS_BUSY = 0x01,
FLASH_STATUS_ECMD = 0xE0, // ERROR: Unknown Command
FLASH_STATUS_EPRM = 0xE2, // ERROR: Incorrect Parameter
FLASH_STATUS_ECRC = 0xE4, // ERROR: Invalid Checksum
FLASH_CONTROL_IDLE = 0x00,
FLASH_CONTROL_ERASE = 0x45,
FLASH_CONTROL_UPLOAD = 0x55,
FLASH_CONTROL_REBOOT = 0x52,
};

View File

@ -1,111 +0,0 @@
#include <pico/stdlib.h>
#include <pico/multicore.h>
#include <hardware/flash.h>
#include <hardware/watchdog.h>
#include <hardware/resets.h>
#include "config.h"
#ifdef RASPBERRYPI_PICO_W
#include <pico/cyw43_arch.h>
#endif
void flash_reboot() __attribute__ ((noreturn));
// Reboot the Pico
void flash_reboot() {
multicore_reset_core1();
reset_block((1<<11) | (1<<10) | (1<<2));
watchdog_enable(1, 1);
for(;;);
}
#if 0
static uint16_t crc16_tab[256];
uint32_t crc16_initdone = 0;
static void flash_crc16_init() {
for (uint i=0; i<256; i++) {
uint16_t crc = 0;
uint16_t c = i;
for (uint j=0; j<8; j++) {
if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ 0xA001;
else crc = crc >> 1;
c = c >> 1;
}
crc16_tab[i] = crc;
}
crc16_initdone = 1;
}
int flash_check_crc16(uint8_t *p, uint32_t size, uint8_t *c) {
uint16_t crc = 0x0000;
if(!crc16_initdone) flash_crc16_init();
for(uint32_t i = 0; i < size; i++) {
crc = (crc >> 8) ^ crc16_tab[ (crc ^ (uint16_t) *p++) & 0x00FF ];
}
return (crc != ((uint16_t)c[0]) | (((uint16_t)c[1]) << 8));
}
// Erase a flash sector under Apple II control
void flash_doerase() {
uint32_t erase_offset = ((uint32_t)terminal_address) << 12;
terminal_reg[0xE] = FLASH_STATUS_BUSY;
if((terminal_reg[0x9] == ~terminal_reg[0x1]) && (terminal_reg[0xA] == ~terminal_reg[0x2])) {
flash_range_erase(erase_offset, FLASH_SECTOR_SIZE);
terminal_reg[0xE] = FLASH_STATUS_READY;
} else {
terminal_reg[0xE] = FLASH_STATUS_EPRM;
}
}
// Write 4096 bytes from Apple II Memory $3000-$3FFF to flash
void flash_dowrite() {
uint32_t write_offset = ((uint32_t)terminal_address) << 12;
if((terminal_reg[0x9] == ~terminal_reg[0x1]) && (terminal_reg[0xA] == ~terminal_reg[0x2])) {
if(flash_check_crc16((uint8_t*)hires_memory+0x1000, FLASH_SECTOR_SIZE, (uint8_t*)terminal_reg+0xC) != 0) {
terminal_reg[0xE] = FLASH_STATUS_ECRC;
} else {
flash_range_program(write_offset, hires_memory+0x1000, FLASH_SECTOR_SIZE);
terminal_reg[0xE] = FLASH_STATUS_READY;
}
} else {
terminal_reg[0xE] = FLASH_STATUS_EPRM;
}
}
void flash_dowork() {
uint32_t op = flash_control;
flash_control = FLASH_CONTROL_IDLE;
switch(op) {
case FLASH_CONTROL_REBOOT:
flash_reboot();
break;
#if 0
case FLASH_CONTROL_ERASE:
flash_doerase();
break;
case FLASH_CONTROL_UPLOAD:
flash_dowrite();
break;
#endif
default:
terminal_reg[0xE] = FLASH_STATUS_ECMD;
break;
}
}
#endif

View File

@ -1,49 +1,61 @@
#include <stdio.h>
#include <pico/stdlib.h>
#include <pico/multicore.h>
#include <hardware/pio.h>
#include "common/abus.h"
#include "common/config.h"
#include "common/modes.h"
#include "common/buffers.h"
#include "common/flash.h"
#include "pico_hal.h"
#ifdef RASPBERRYPI_PICO_W
#include <pico/cyw43_arch.h>
#endif
volatile uint8_t core1_running = 0;
static void core1_loop() {
static void __time_critical_func(core1_loop)() {
for(;;) {
switch(v2mode) {
uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
uint32_t address = (value >> 10) & 0xffff;
// device read access
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) {
if(CARD_SELECT) {
pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, apple_memory[address]);
}
}
if(CARD_SELECT) {
if(CARD_DEVSEL) {
cardslot = (address >> 4) & 0x7;
} else if(CARD_IOSEL) {
cardslot = (address >> 8) & 0x7;
// Config memory in card slot-rom address space
if(((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) && ((address & 0xF0) == 0xF0)) {
apple_memory[address] = value;
}
}
}
switch(current_mode) {
case MODE_DIAG:
core1_running = 1;
diag_businterface();
core1_running = 0;
diag_businterface(address, value);
break;
case MODE_FS:
core1_running = 1;
fs_businterface();
core1_running = 0;
fs_businterface(address, value);
break;
case MODE_VGACARD:
core1_running = 1;
vga_businterface();
core1_running = 0;
vga_businterface(address, value);
break;
case MODE_APPLICARD:
core1_running = 1;
z80_businterface();
core1_running = 0;
z80_businterface(address, value);
break;
case MODE_SERIAL:
core1_running = 1;
serial_businterface();
core1_running = 0;
serial_businterface(address, value);
break;
case MODE_PARALLEL:
core1_running = 1;
parallel_businterface();
core1_running = 0;
parallel_businterface(address, value);
break;
}
}
@ -51,16 +63,15 @@ static void core1_loop() {
static void core0_loop() {
for(;;) {
switch(v2mode) {
case MODE_REBOOT:
flash_reboot();
break;
switch(current_mode) {
case MODE_DIAG:
diagmain();
break;
case MODE_FS:
fsmain();
break;
default:
current_mode = MODE_VGACARD;
case MODE_VGACARD:
vgamain();
break;
@ -73,13 +84,7 @@ static void core0_loop() {
case MODE_PARALLEL:
parallelmain();
break;
default:
v2mode = MODE_VGACARD;
}
while(core1_running) {
sleep_ms(5);
};
}
}
@ -88,19 +93,24 @@ int main() {
set_sys_clock_khz(CONFIG_SYSCLOCK*1000, true);
abus_init();
memcpy(config_errbuf, "V2ANALOG", 8);
memset(config_cmdbuf, 0xFF, 8);
multicore_launch_core1(core1_loop);
// Sensible defaults if there is no config / fs
default_config();
multicore_launch_core1(core1_loop);
// Try mounting the LittleFS, or format if it isn't there.
if(pico_mount(0) == LFS_ERR_OK) {
read_config();
} else if(pico_mount(1) == LFS_ERR_OK) {
read_config();
} else {
pico_mount(1);
}
current_mode = cfg_mode;
core0_loop();
return 0;

View File

@ -1,20 +1,20 @@
void vgamain();
void vga_businterface();
void vga_businterface(uint32_t address, uint32_t value);
void z80main();
void z80_businterface();
void z80_businterface(uint32_t address, uint32_t value);
void serialmain();
void serial_businterface();
void serial_businterface(uint32_t address, uint32_t value);
void parallelmain();
void parallel_businterface();
void parallel_businterface(uint32_t address, uint32_t value);
void diag_businterface();
void diagmain();
void diag_businterface(uint32_t address, uint32_t value);
void fs_businterface();
void fsmain();
void fs_businterface(uint32_t address, uint32_t value);
void flash_reboot() __attribute__ ((noreturn));

View File

@ -5,39 +5,9 @@
#include "abus.pio.h"
#include "diag/businterface.h"
static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_t value) {
void __time_critical_func(diag_businterface)(uint32_t address, uint32_t value) {
// Shadow parts of the Apple's memory by observing the bus write cycles
if(CARD_SELECT) {
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
apple_memory[address] = value;
}
// Config memory in card slot-rom address space
if(CARD_IOSEL) {
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
config_memory[address & 0x1F] = value;
if((address & 0xFF) == 0xFF)
config_handler();
}
}
}
}
void __time_critical_func(diag_businterface)() {
while(v2mode == MODE_DIAG) {
uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
uint32_t dout;
uint32_t address = (value >> 10) & 0xffff;
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) {
if(CARD_SELECT) {
dout = apple_memory[address];
// device read access
pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, dout);
}
}
shadow_memory(address, value);
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
apple_memory[address] = value;
}
}

View File

@ -25,7 +25,7 @@ void diagmain() {
memset((uint8_t*)(apple_memory+0xC700), 0xC7, 0x100);
memset((uint8_t*)(apple_memory+0xC800), 0xC8, 0x800);
while(v2mode == MODE_DIAG) {
while(current_mode == MODE_DIAG) {
sleep_ms(50);
}
}

View File

@ -6,7 +6,9 @@
#include "fs/businterface.h"
#include "fs/fs.h"
static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_t value) {
volatile uint8_t fs_slot = 0;
void __time_critical_func(fs_businterface)(uint32_t address, uint32_t value) {
// Shadow parts of the Apple's memory by observing the bus write cycles
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
if(address < 0x200) {
@ -28,23 +30,12 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_
if(CARD_DEVSEL) {
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
apple_memory[address] = value;
if((address & 0xCF8F) == 0xC08F)
fs_handler((address & 0x70) >> 4);
}
}
if(CARD_IOSTROBE) {
apple_memory[address] = value;
}
// Config memory in card slot-rom address space
if(CARD_IOSEL) {
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
config_memory[address & 0x1F] = value;
if((address & 0xFF) == 0xFF)
config_handler();
}
}
}
// Shadow the soft-switches by observing all read & write bus cycles
@ -73,23 +64,3 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_
}
}
}
void __time_critical_func(fs_businterface)() {
while(v2mode == MODE_DIAG) {
uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
uint32_t dout;
uint32_t address = (value >> 10) & 0xffff;
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) {
if(CARD_SELECT) {
dout = apple_memory[address];
// device read access
pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, dout);
}
}
shadow_memory(address, value);
}
}

View File

@ -196,7 +196,7 @@ void fs_handler(uint8_t slot) {
void fsmain() {
int i;
memset((uint8_t*)(apple_memory+0xC000), 0x00, 0x1000);
memset((uint8_t*)(apple_memory+0xC000), 0xFF, 0x1000);
for(i = 0; i < FS_MAXFILE; i++) {
fs_file[i].handle = -1;
@ -207,15 +207,12 @@ void fsmain() {
fs_file[0].handle = pico_open("boot.dsk", LFS_O_RDONLY);
fs_file[0].valid = (fs_file[0].handle >= 0);
strcpy((uint8_t*)(apple_memory+0xC1E0), "FSREADY.");
strcpy((uint8_t*)(apple_memory+0xC2E0), "FSREADY.");
strcpy((uint8_t*)(apple_memory+0xC3E0), "FSREADY.");
strcpy((uint8_t*)(apple_memory+0xC4E0), "FSREADY.");
strcpy((uint8_t*)(apple_memory+0xC5E0), "FSREADY.");
strcpy((uint8_t*)(apple_memory+0xC6E0), "FSREADY.");
strcpy((uint8_t*)(apple_memory+0xC7E0), "FSREADY.");
strcpy((char*)(apple_memory+0xC0E0+(cardslot << 8)), "FSREADY.");
while(v2mode == MODE_FS) {
while(current_mode == MODE_FS) {
config_handler();
if(cardslot != 0)
fs_handler(cardslot);
sleep_ms(50);
}

View File

@ -28,45 +28,9 @@ static inline void __time_critical_func(parallel_write)(uint32_t address, uint32
}
}
static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_t value) {
void __time_critical_func(parallel_businterface)(uint32_t address, uint32_t value) {
// Shadow parts of the Apple's memory by observing the bus write cycles
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
if(CARD_SELECT) {
if(CARD_DEVSEL) {
parallel_write(address, value);
} else if(address < 0xC000) {
apple_memory[address] = value;
}
// Config memory in card slot-rom address space
if(CARD_IOSEL) {
config_memory[address & 0x1F] = value;
if((address & 0xFF) == 0xFF)
config_handler();
}
}
}
}
void __time_critical_func(parallel_businterface)() {
while(v2mode == MODE_PARALLEL) {
uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
uint32_t dout;
uint32_t address = (value >> 10) & 0xffff;
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) {
if(CARD_SELECT) {
if(CARD_DEVSEL) {
dout = ((address & 0xf) == 0) ? parallel_status : 0xff;
} else {
dout = apple_memory[address];
}
// device read access
pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, dout);
}
}
shadow_memory(address, value);
if((CARD_SELECT) && (CARD_DEVSEL) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
parallel_write(address, value);
}
}

View File

@ -14,6 +14,8 @@ void parallelmain() {
// Copy Grappler ROM to Extended ROM area
memcpy((void*)(apple_memory + 0xC800), (void*)(grappler_rom), 0x800);
while(v2mode == MODE_PARALLEL) {
while(current_mode == MODE_PARALLEL) {
config_handler();
sleep_ms(50);
}
}

View File

@ -25,7 +25,7 @@ static inline void __time_critical_func(serial_write)(uint32_t address, uint32_t
}
}
static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_t value) {
void __time_critical_func(serial_businterface)(uint32_t address, uint32_t value) {
// Shadow parts of the Apple's memory by observing the bus write cycles
if(CARD_SELECT) {
if(CARD_DEVSEL) {
@ -35,37 +35,5 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_
serial_read(address);
}
}
// Config memory in card slot-rom address space
if(CARD_IOSEL) {
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
config_memory[address & 0x1F] = value;
if((address & 0xFF) == 0xFF)
config_handler();
}
}
}
}
void __time_critical_func(serial_businterface)() {
while(v2mode == MODE_SERIAL) {
uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
uint32_t dout;
uint32_t address = (value >> 10) & 0xffff;
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) {
if(CARD_SELECT) {
if(CARD_DEVSEL) {
dout = serial_reg[address & 0xf];
} else {
dout = apple_memory[address & 0xffff];
}
// device read access
pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, dout);
}
}
shadow_memory(address, value);
}
}

View File

@ -14,7 +14,8 @@ void serialmain() {
memcpy((void*)(apple_memory + 0xC100), (void*)(ssc_rom + 0x700), 0x100);
memcpy((void*)(apple_memory + 0xC200), (void*)(apple_memory + 0xC100), 0x600);
while(v2mode == MODE_SERIAL) {
while(current_mode == MODE_SERIAL) {
config_handler();
switch(serialmux) {
#if 0
case SERIAL_USB:

View File

@ -17,7 +17,7 @@ static inline void __time_critical_func(videx_crtc_write)(uint32_t value) {
}
static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_t value) {
void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
// Shadow the soft-switches by observing all read & write bus cycles
if((address & 0xff80) == 0xc000) {
switch(address & 0x7f) {
@ -25,141 +25,142 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches &= ~SOFTSW_80STORE;
}
return;
break;
case 0x01:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches |= SOFTSW_80STORE;
}
return;
break;
case 0x04:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches &= ~SOFTSW_AUX_WRITE;
}
return;
break;
case 0x05:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches |= SOFTSW_AUX_WRITE;
}
return;
break;
case 0x08:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches &= ~SOFTSW_AUXZP;
}
return;
break;
case 0x09:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches |= SOFTSW_AUXZP;
}
return;
break;
case 0x0c:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches &= ~SOFTSW_80COL;
}
return;
break;
case 0x0d:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches |= SOFTSW_80COL;
}
return;
break;
case 0x0e:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches &= ~SOFTSW_ALTCHAR;
}
return;
break;
case 0x0f:
if((soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches |= SOFTSW_ALTCHAR;
}
return;
break;
case 0x21:
if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
if((SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
if(value & 0x80) {
soft_switches |= SOFTSW_MONOCHROME;
} else {
soft_switches &= ~SOFTSW_MONOCHROME;
}
}
return;
break;
case 0x22:
if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
terminal_tbcolor = value & 0xff;
}
return;
break;
case 0x29:
if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches = (soft_switches & ~(SOFTSW_NEWVID_MASK << SOFTSW_NEWVID_SHIFT)) | ((value & SOFTSW_NEWVID_MASK) << SOFTSW_NEWVID_SHIFT);
}
return;
break;
case 0x34:
if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
terminal_border = value & 0x0f;
}
return;
break;
case 0x35:
if((soft_switches & SOFTSW_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches = (soft_switches & ~(SOFTSW_SHADOW_MASK << SOFTSW_SHADOW_SHIFT)) | ((value & SOFTSW_SHADOW_MASK) << SOFTSW_SHADOW_SHIFT);
}
return;
break;
case 0x50:
soft_switches &= ~SOFTSW_TEXT_MODE;
return;
break;
case 0x51:
soft_switches |= SOFTSW_TEXT_MODE;
return;
break;
case 0x52:
soft_switches &= ~SOFTSW_MIX_MODE;
return;
break;
case 0x53:
soft_switches |= SOFTSW_MIX_MODE;
return;
break;
case 0x54:
soft_switches &= ~SOFTSW_PAGE_2;
return;
break;
case 0x55:
soft_switches |= SOFTSW_PAGE_2;
return;
break;
case 0x56:
soft_switches &= ~SOFTSW_HIRES_MODE;
return;
break;
case 0x57:
soft_switches |= SOFTSW_HIRES_MODE;
return;
break;
case 0x5e:
if(soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) {
soft_switches |= SOFTSW_DGR;
}
return;
break;
case 0x5f:
if(soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) {
soft_switches &= ~SOFTSW_DGR;
}
return;
break;
case 0x7e:
if((soft_switches & SOFTSW_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches |= SOFTSW_IOUDIS;
}
return;
break;
case 0x7f:
if((soft_switches & SOFTSW_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
soft_switches &= ~SOFTSW_IOUDIS;
}
return;
break;
}
return;
}
// Shadow parts of the Apple's memory by observing the bus write cycles
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
if((machine == COMPAT_AUTO) && (a2_first_write == 0)) {
if(current_machine == MACHINE_AUTO) {
a2_first_write = (address << 16) | (value & 0x3FF);
if(a2_first_write == 0xC0330100) { // Apple IIgs ROM03 Clock Access
machine = APPLE_IIGS;
current_machine = MACHINE_IIGS;
soft_switches &= ~SOFTSW_IIE_REGS;
soft_switches |= SOFTSW_IIGS_REGS;
} else if(a2_first_write == 0x01F901FB) { // Apple II Plus
machine = APPLE_II;
current_machine = MACHINE_II;
soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS);
} else if(a2_first_write == 0x01F5018B) { // Apple IIe Platinum
machine = APPLE_IIE;
current_machine = MACHINE_IIE;
soft_switches |= SOFTSW_IIE_REGS;
soft_switches &= ~SOFTSW_IIGS_REGS;
} else {
@ -197,9 +198,10 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_
return;
}
#if 0
// Videx 80 Column Card
if(CARD_SELECT) {
if((address >= 0xCC00) && (address < 0xD000)) {
if((address >= 0xC800) && (address < 0xCC00)) {
videx_page[(address & 0x3FF)] = value & 0xff;
}
@ -213,47 +215,14 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_
break;
}
}
// Config memory in card slot-rom address space
if(CARD_IOSEL) {
config_memory[address & 0x1F] = value;
if((address & 0xFF) == 0xFF)
config_handler();
}
}
#endif
}
#if 0
// Any access to Videx I/O sets the VRAM page visible in 0xCC00-0xD000
if(CARD_SELECT && CARD_DEVSEL) {
videx_page = videx_memory + ((address & 0x0C) << 9);
}
}
void __time_critical_func(vga_businterface)() {
while(v2mode == MODE_VGACARD) {
uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
uint32_t address = (value >> 10) & 0xffff;
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) {
if(CARD_SELECT) {
uint32_t dout;
switch(address >> 10) {
case (0xC000 >> 10):
dout = (address & 1) ? videx_crtc_reg : 0xff;
break;
case (0xCC00 >> 10):
dout = videx_memory[address & 0x3FF];
break;
default:
dout = apple_memory[address];
}
// device read access
pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, dout);
}
}
shadow_memory(address, value);
}
#endif
}

View File

@ -12,24 +12,24 @@ uint16_t text_fore;
uint16_t text_back;
uint16_t text_border;
compat_t machinefont = APPLE_II;
compat_t machinefont = MACHINE_II;
bool userfont = false;
// Initialize the character generator ROM
void switch_font() {
switch(machine) {
switch(current_machine) {
default:
case APPLE_II:
case MACHINE_II:
memcpy(character_rom, default_character_rom, 2048);
break;
case APPLE_IIE:
case MACHINE_IIE:
memcpy(character_rom, appleiie_character_rom, 2048);
break;
case APPLE_IIGS:
case MACHINE_IIGS:
memcpy(character_rom, appleiigs_character_rom, 2048);
break;
}
machinefont = machine;
machinefont = current_machine;
}
void load_font() {
@ -66,67 +66,106 @@ void render_init() {
render_test_init();
}
uint32_t testdone=0;
// Blank screen
void __time_critical_func(render_blank)() {
struct vga_scanline *sl = vga_prepare_scanline();
uint sl_pos = 0;
while(sl_pos < VGA_WIDTH/16) {
sl->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 8 pixels per word
sl_pos++;
}
sl->length = sl_pos;
sl->repeat_count = 479;
vga_submit_scanline(sl);
}
uint32_t screentimeout = 0;
uint32_t testdone = 0;
void __noinline __time_critical_func(render_loop)() {
while(v2mode == MODE_VGACARD) {
if(!userfont && (machinefont != machine)) {
switch_font();
}
update_text_flasher();
text_fore = lores_palette[TERMINAL_FORE];
text_back = lores_palette[TERMINAL_BACK];
text_border = lores_palette[TERMINAL_BORDER];
if(soft_switches & SOFTSW_TEST) {
while(current_mode == MODE_VGACARD) {
config_handler();
#if 0
if((busactive == 0) && (screentimeout > (30 * 60))) {
render_blank();
} else if((busactive == 0) && (screentimeout > (15 * 60))) {
render_testpattern();
// Automatically dismiss the test pattern when the Apple II initializes
// soft switches during startup.
if(((soft_switches & SOFTSW_MODE_MASK) != 0) && (testdone == 0)) {
soft_switches &= ~SOFTSW_TEST;
testdone = 1;
render_about_init();
}
} else if(soft_switches & SOFTSW_VIDEX) {
render_videx();
} else if(soft_switches & SOFTSW_SHR) {
render_shr();
screentimeout++;
} else if((busactive == 0) && (screentimeout == 15 * 60)) {
render_test_sleep();
render_testpattern();
screentimeout++;
} else {
switch(soft_switches & SOFTSW_MODE_MASK) {
case 0:
if(soft_switches & SOFTSW_DGR) {
render_dgr();
} else {
render_lores();
}
break;
case SOFTSW_MIX_MODE:
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
render_mixed_dgr();
} else {
render_mixed_lores();
}
break;
case SOFTSW_HIRES_MODE:
if(soft_switches & SOFTSW_DGR) {
render_dhgr();
} else {
render_hires();
}
break;
case SOFTSW_HIRES_MODE|SOFTSW_MIX_MODE:
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
render_mixed_dhgr();
} else {
render_mixed_hires();
}
break;
default:
render_text();
break;
if(busactive == 0) {
screentimeout++;
} else {
screentimeout = 0;
}
}
busactive = 0;
#endif
if(!userfont && (machinefont != current_machine)) {
switch_font();
}
update_text_flasher();
text_fore = lores_palette[TERMINAL_FORE];
text_back = lores_palette[TERMINAL_BACK];
text_border = lores_palette[TERMINAL_BORDER];
if(soft_switches & SOFTSW_TEST) {
render_testpattern();
// Automatically dismiss the test pattern when the Apple II is seen.
if(((soft_switches & SOFTSW_MODE_MASK) != 0) && (testdone == 0)) {
soft_switches &= ~SOFTSW_TEST;
testdone = 1;
render_about_init();
}
#if 0
} else if(soft_switches & SOFTSW_VIDEX) {
render_videx();
} else if(soft_switches & SOFTSW_SHR) {
render_shr();
#endif
} else {
switch(soft_switches & SOFTSW_MODE_MASK) {
case 0:
if(soft_switches & SOFTSW_DGR) {
render_dgr();
} else {
render_lores();
}
break;
case SOFTSW_MIX_MODE:
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
render_mixed_dgr();
} else {
render_mixed_lores();
}
break;
case SOFTSW_HIRES_MODE:
if(soft_switches & SOFTSW_DGR) {
render_dhgr();
} else {
render_hires();
}
break;
case SOFTSW_HIRES_MODE|SOFTSW_MIX_MODE:
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
render_mixed_dhgr();
} else {
render_mixed_hires();
}
break;
default:
render_text();
break;
}
}
// }
}
}

View File

@ -14,6 +14,7 @@ extern void render_loop();
extern void render_testpattern();
extern void render_test_init();
extern void render_about_init();
extern void render_test_sleep();
extern void update_text_flasher();
extern void render_text();
@ -43,3 +44,5 @@ extern uint_fast32_t text_flasher_mask;
extern void flash_dowork();
extern void vga_init();
extern void vga_deinit();

View File

@ -100,11 +100,11 @@ static void __time_critical_func(render_hires_line)(bool p2, uint line) {
if(soft_switches & SOFTSW_MONOCHROME) {
// Consume 14 dots
for(j = 0; j < 14; j++) {
uint32_t pixeldata = (dots & 0x2000) ? (0x1ff|THEN_EXTEND_1) : (0x000|THEN_EXTEND_1);
pixeldata |= (dots & 0x1000) ?
((uint32_t)0x1ff|THEN_EXTEND_1) << 16 :
((uint32_t)0x000|THEN_EXTEND_1) << 16;
for(j = 0; j < 7; j++) {
uint32_t pixeldata = (dots & 0x80000000) ? (0x1ff) : (0x000);
pixeldata |= (dots & 0x40000000) ?
((uint32_t)0x1ff) << 16 :
((uint32_t)0x000) << 16;
dots <<= 2;
sl->data[sl_pos] = pixeldata;
sl_pos++;

View File

@ -14,10 +14,20 @@
char error_message[16*24+1];
void render_test_sleep() {
memcpy(error_message + 208, " APPLE II BUS ", 16);
memcpy(error_message + 224, " ACTIVITY ", 16);
memcpy(error_message + 240, " NOT DETECTED ", 16);
memcpy(error_message + 272, "SCREEN BLANKING ", 16);
memcpy(error_message + 288, " IN 15 SECONDS ", 16);
memcpy(error_message + 304, " ", 16);
}
void render_test_init() {
memset(error_message, ' ', 16*24);
memcpy(error_message + 0, "HW: ANALOG-REV-1", 16);
memcpy(error_message + 16, "FW: 23-01-16-119", 16);
memcpy(error_message + 16, "FW: 23-01-19-131", 16);
memcpy(error_message + 64, " COPYRIGHT (C) ", 16);
memcpy(error_message + 80, " DAVID KUDER ", 16);

View File

@ -11,5 +11,5 @@ void __noinline __time_critical_func(vgamain)() {
vga_init();
render_init();
render_loop();
vga_deinit();
// vga_deinit();
}

View File

@ -179,8 +179,6 @@ void vga_init() {
// Enable all state machines in sync to ensure their instruction cycles line up
pio_enable_sm_mask_in_sync(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM));
multicore_lockout_victim_init();
}

View File

@ -32,8 +32,6 @@ struct vga_scanline {
};
void vga_init();
void vga_deinit();
void vga_prepare_frame();
struct vga_scanline *vga_prepare_scanline();

View File

@ -1,10 +1,12 @@
#include <string.h>
#include <hardware/pio.h>
#include "common/config.h"
#include "common/buffers.h"
#include "abus.pio.h"
#include "z80/businterface.h"
#include "z80/z80buf.h"
volatile uint8_t *pcpi_reg = apple_memory + 0xC0C0;
static inline void __time_critical_func(pcpi_read)(uint32_t address) {
switch(address & 0x7) {
@ -43,8 +45,8 @@ static inline void __time_critical_func(pcpi_write)(uint32_t address, uint32_t v
}
}
static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_t value) {
void __time_critical_func(z80_businterface)(uint32_t address, uint32_t value) {
pcpi_reg = apple_memory + (0xC080 | (cardslot << 4));
// Shadow parts of the Apple's memory by observing the bus write cycles
if(CARD_SELECT) {
if(CARD_DEVSEL) {
@ -54,33 +56,6 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_
pcpi_read(address);
}
}
// Config memory in card slot-rom address space
if(CARD_IOSEL) {
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
config_memory[address & 0x1F] = value;
if((address & 0xFF) == 0xFF)
config_handler();
}
}
}
}
void __time_critical_func(z80_businterface)() {
while(v2mode == MODE_APPLICARD) {
uint32_t value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
uint32_t dout;
uint32_t address = (value >> 10) & 0xffff;
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0) {
if(CARD_SELECT) {
dout = pcpi_reg[address & 0x7];
// device read access
pio_sm_put_blocking(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, dout);
}
}
shadow_memory(address, value);
}
}

View File

@ -9,7 +9,7 @@ extern volatile uint8_t z80_nmi;
extern volatile uint8_t z80_res;
extern uint8_t z80_rom[2*1024];
#define z80_ram private_memory
#define pcpi_reg slot4io
extern volatile uint8_t *pcpi_reg;
#define clr_z80_stat { pcpi_reg[2] &= ~0x80; }
#define set_z80_stat { pcpi_reg[2] |= 0x80; }

View File

@ -9,7 +9,7 @@ volatile uint8_t rom_shadow = 1;
volatile uint8_t ram_bank = 0;
volatile uint8_t ram_common = 0;
#define Z80break (z80_res || (v2mode != MODE_APPLICARD))
#define Z80break (z80_res || (current_mode != MODE_APPLICARD) || (config_cmdbuf[7] == 0))
uint8_t cpu_in(uint16_t address) {
uint8_t rv = 0;
@ -85,23 +85,31 @@ void _RamWrite(uint16_t address, uint8_t value) {
#include "z80cpu.h"
void z80main() {
while(v2mode == MODE_APPLICARD) {
rom_shadow = 1;
ram_bank = 0;
ram_common = 0;
z80_res = 1;
z80_nmi = 0;
z80_irq = 0;
z80_res = 0;
while(current_mode == MODE_APPLICARD) {
config_handler();
if(cardslot != 0) {
if(z80_res) {
rom_shadow = 1;
ram_bank = 0;
ram_common = 0;
// 6502 -> Z80
clr_z80_stat;
z80_nmi = 0;
z80_irq = 0;
z80_res = 0;
// Z80 -> 6502
clr_6502_stat;
// 6502 -> Z80
clr_z80_stat;
Z80reset();
Z80run();
// Z80 -> 6502
clr_6502_stat;
Z80reset();
}
Z80run();
}
}
}