diff --git a/utilities/Makefile b/utilities/Makefile index 25adee6..f146b04 100644 --- a/utilities/Makefile +++ b/utilities/Makefile @@ -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 $(NULLDEV) - @$(DEL) uploadfont uploadfont.map 2>$(NULLDEV) diff --git a/utilities/common/picopal.h b/utilities/common/picopal.h index 5ade35e..8ac8dfc 100644 --- a/utilities/common/picopal.h +++ b/utilities/common/picopal.h @@ -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; diff --git a/utilities/configtool/configtool.c b/utilities/configtool/configtool.c index 7a67de7..f9f46fb 100644 --- a/utilities/configtool/configtool.c +++ b/utilities/configtool/configtool.c @@ -5,44 +5,1386 @@ #include #include #include +#include -#define PICOPAL_SLOT 3 #include "../common/picopal.h" -void cardconfig(void) { - puts("1. Firmware Mode\n"); - if(v2mode == MODE_SERIAL) { - puts("2. Device Mux\n"); - puts("3. Baudrate\n"); +volatile uint16_t cardslot = 3; + +#define BASL 0x28 + +#define menutop 3 +#define menuleft 2 + +v2mode_t v2mode = MODE_VGACARD; + +serialmux_t serialmux = SERIAL_PRINTER; +uint16_t baud = 19200; + +usbmux_t usbmux = USB_GUEST_CDC; +compat_t machine = MACHINE_APPLE_IIGS; +wifimode_t wifimode = WIFI_AP; +char wifi_ssid[32] = "V2RetroNet"; +char wifi_psk[32] = "Analog"; +char wifi_address[32] = "DHCP"; + +char jd_host[32] = "192.168.0.1"; +uint16_t jd_port = 9100; + +char config_data[1024]; +uint16_t config_size = 0; +uint8_t *config_cmdbuf; +uint8_t *config_errbuf; +uint8_t *upload_buf = (uint8_t *)(0xC800); + +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 }; + +#define CARD_TIMEOUT 0x3fff +uint16_t timeout = CARD_TIMEOUT; + +void default_config() { + v2mode = MODE_VGACARD; + serialmux = SERIAL_PRINTER; + baud = 19200; + usbmux = USB_GUEST_CDC; + + wifimode = WIFI_AP; + strcpy(wifi_ssid, "V2RetroNet"); + strcpy(wifi_psk, "Analog"); + strcpy(wifi_address, "DHCP"); + + strcpy(jd_host, "192.168.0.1"); + jd_port = 9100; + machine = MACHINE_AUTO; +} + +void paint_backdrop(char *str) { + int w, i; + + w = strlen(str); + if(w > 20) { + w = 20; } - if(v2mode == MODE_PARALLEL) { - puts("2. Device Mux\n"); - if(muxmode == MUX_PRINTER) { - puts("3. Host\n"); - puts("4. Port\n"); + + 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; } } } -void wificonfig(void) { - puts("1. WIFI Mode\n"); - puts("2. Network Name\n"); - puts("3. Pre-Shared Key\n"); +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_cmd0(char *cmd) { + char cfg_temp[32]; + + memset(cfg_temp, 0, 32); + strncpy(cfg_temp, cmd, 32); + memcpy(config_cmdbuf, cfg_temp, 32); +} + +void cfg_cmd1(char *cmd, uint16_t param0) { + uint8_t cfg_temp[32]; + + memset(cfg_temp, 0, 32); + memcpy(cfg_temp, cmd, 2); + cfg_temp[2] = param0 & 0xFF; + cfg_temp[3] = (param0 >> 8) & 0xFF; + memcpy(config_cmdbuf, cfg_temp, 32); +} + +void cfg_cmd2(char *cmd, uint16_t param0, uint16_t param1) { + uint8_t cfg_temp[32]; + + memset(cfg_temp, 0, 32); + memcpy(cfg_temp, cmd, 2); + cfg_temp[2] = param0 & 0xFF; + cfg_temp[3] = (param0 >> 8) & 0xFF; + cfg_temp[4] = param1 & 0xFF; + cfg_temp[5] = (param1 >> 8) & 0xFF; + memcpy(config_cmdbuf, cfg_temp, 32); +} + +void parse_config(char *buffer) { + if(!memcmp("C=", buffer, 2)) { + if(!strcmp("DIAG", buffer+2)) { + v2mode = MODE_DIAG; + } else if(!strcmp("FS", buffer+2)) { + v2mode = MODE_FS; + } else if(!strcmp("VGA", buffer+2)) { + v2mode = MODE_VGACARD; + } else if(!strcmp("Z80", buffer+2)) { + v2mode = MODE_APPLICARD; + } else if(!strcmp("SER", buffer+2)) { + v2mode = MODE_SERIAL; + } else if(!strcmp("PAR", buffer+2)) { + v2mode = MODE_PARALLEL; + } else if(!strcmp("MIDI", buffer+2)) { + v2mode = MODE_MIDI; + } else if(!strcmp("SNES", buffer+2)) { + v2mode = MODE_SNESMAX; + } else if(!strcmp("NET", buffer+2)) { + v2mode = MODE_ETHERNET; + } + } else if(!memcmp("H=", buffer, 2)) { + if(!strcmp("AUTO", buffer+2)) { + machine = MACHINE_AUTO; + } else if(!strcmp("II", buffer+2)) { + machine = MACHINE_APPLE_II; + } else if(!strcmp("IIE", buffer+2)) { + machine = MACHINE_APPLE_IIE; + } else if(!strcmp("IIGS", buffer+2)) { + machine = MACHINE_APPLE_IIGS; + } + } else if(!memcmp("M=", buffer, 2)) { + if(!strcmp("USB", buffer+2)) { + serialmux = SERIAL_USB; + } else if(!strcmp("WIFI", buffer+2)) { + serialmux = SERIAL_WIFI; + } else if(!strcmp("PRN", buffer+2)) { + serialmux = SERIAL_PRINTER; + } else if(!strcmp("LOOP", buffer+2)) { + serialmux = SERIAL_LOOP; + } + } else if(!memcmp("U=", buffer, 2)) { + if(!strcmp("CG", buffer+2)) { + usbmux = USB_GUEST_CDC; + } else if(!strcmp("CH", buffer+2)) { + usbmux = USB_HOST_CDC; + } + } else if(!memcmp("W=", buffer, 2)) { + if(!strcmp("C", buffer+2)) { + wifimode = WIFI_CLIENT; + } else if(!strcmp("A", buffer+2)) { + wifimode = WIFI_AP; + } + } else if(!memcmp("WS=", buffer, 3)) { + strncpy(wifi_ssid, buffer+3, 25); + } else if(!memcmp("WP=", buffer, 3)) { + strncpy(wifi_psk, buffer+3, 26); + } else if(!memcmp("IP=", buffer, 3)) { + strncpy(wifi_address, buffer+3, 16); + } else if(!memcmp("JDH=", buffer, 4)) { + strncpy(jd_host, buffer+4, 16); + } else if(!memcmp("JDP=", buffer, 4)) { + jd_port = strtoul(buffer+4, NULL, 0); + } else if(!memcmp("SB=", buffer, 3)) { + baud = strtoul(buffer+3, NULL, 0); + } +} + +void build_config(void) { + char *config_temp = config_data; + + memset(config_data, 0, sizeof(config_data)); + switch(v2mode) { + case MODE_FS: + strcpy(config_temp, "C=FS"); + config_temp += 32; + break; + case MODE_VGACARD: + strcpy(config_temp, "C=VGA"); + config_temp += 32; + break; + case MODE_APPLICARD: + strcpy(config_temp, "C=Z80"); + config_temp += 32; + break; + case MODE_SERIAL: + strcpy(config_temp, "C=SER"); + config_temp += 32; + break; + case MODE_PARALLEL: + strcpy(config_temp, "C=PAR"); + config_temp += 32; + break; + case MODE_MIDI: + strcpy(config_temp, "C=MIDI"); + config_temp += 32; + break; + case MODE_SNESMAX: + strcpy(config_temp, "C=SNES"); + config_temp += 32; + break; + case MODE_ETHERNET: + strcpy(config_temp, "C=NET"); + config_temp += 32; + break; + } + switch(machine) { + case MACHINE_AUTO: + strcpy(config_temp, "H=AUTO"); + config_temp += 32; + break; + case MACHINE_APPLE_II: + strcpy(config_temp, "H=II"); + config_temp += 32; + break; + case MACHINE_APPLE_IIE: + strcpy(config_temp, "H=IIE"); + config_temp += 32; + break; + case MACHINE_APPLE_IIGS: + strcpy(config_temp, "H=IIGS"); + config_temp += 32; + break; + } + switch(serialmux) { + case SERIAL_USB: + strcpy(config_temp, "M=USB"); + config_temp += 32; + break; + case SERIAL_WIFI: + strcpy(config_temp, "M=WIFI"); + config_temp += 32; + break; + case SERIAL_PRINTER: + strcpy(config_temp, "M=PRN"); + config_temp += 32; + break; + case SERIAL_LOOP: + strcpy(config_temp, "M=LOOP"); + config_temp += 32; + break; + } + switch(usbmux) { + case USB_GUEST_CDC: + strcpy(config_temp, "U=CG"); + config_temp += 32; + break; + case USB_HOST_CDC: + strcpy(config_temp, "U=CH"); + config_temp += 32; + break; + } + + switch(wifimode) { + case WIFI_CLIENT: + strcpy(config_temp, "W=C"); + config_temp += 32; + break; + case WIFI_AP: + strcpy(config_temp, "W=A"); + config_temp += 32; + break; + } + + strcpy(config_temp, "WS="); + strncpy(config_temp+3, wifi_ssid, 24); + config_temp += 32; + + strcpy(config_temp, "WP="); + strncpy(config_temp+3, wifi_psk, 24); + config_temp += 32; + + strcpy(config_temp, "IP="); + strncpy(config_temp+3, wifi_address, 16); + config_temp += 32; + + strcpy(config_temp, "JDH="); + strncpy(config_temp+4, jd_host, 16); + config_temp += 32; + + sprintf(config_temp, "JDP=%d", jd_port); + config_temp += 32; + + sprintf(config_temp, "SB=%d", baud); + config_temp += 32; +} + +void read_config(void) { + int i; + uint8_t dummy; + timeout = CARD_TIMEOUT; + + // Release the $C800 region from any other card + dummy = *(uint8_t*)0xCFFF; + + // Ask card to upload it's config to the Apple II host. + // We only support Page0 in this version of the utility. + cfg_cmd1("UC", 0); + while(memcmp(config_errbuf, ERR_READY, 8) && (timeout > 0)) { + timeout--; + } + if(timeout == 0) { + // Release the $C800 region for use by other cards + dummy = *(uint8_t*)0xCFFF; + + message("Communication Timeout"); + default_config(); + return; + } else { + memcpy(config_data, upload_buf, 1024); + + // Release the $C800 region for use by other cards + dummy = *(uint8_t*)0xCFFF; + } + + for(i = 0; i < sizeof(config_data); i+=32) { + if(config_data[i] != 0) + parse_config(config_data+i); + } +} + +int write_config(void) { + uint8_t dummy; + timeout = CARD_TIMEOUT; + + build_config(); + + paint_backdrop("Please Wait"); + gotoy(11); gotox(10); + cputs("Saving configuration,"); + gotoy(12); gotox(8); + cputs("your screen may flicker."); + + // Release the $C800 region from any other card + dummy = *(uint8_t*)0xCFFF; + + // Ask card to download it's config from the Apple II host. + // We only support Page0 in this version of the utility. + cfg_cmd2("DC", (uint16_t)config_data, 0); + while(memcmp(config_errbuf, ERR_READY, 8) && (timeout > 0)) { + timeout--; + } + + // Release the $C800 region for use by other cards + dummy = *(uint8_t*)0xCFFF; + + return 1; +} + +void apply_config(void) { + uint8_t dummy; + timeout = CARD_TIMEOUT; + + paint_backdrop("Please Wait"); + gotoy(10); gotox(13); + cputs("Rebooting card"); + gotoy(11); gotox(9); + cputs("to apply configuration,"); + gotoy(12); gotox(8); + cputs("your screen may flicker."); + + // Release the $C800 region from any other card + dummy = *(uint8_t*)0xCFFF; + + // Ask card to reboot. + cfg_cmd0("REBOOT"); + + // Release the $C800 region for use by other cards + dummy = *(uint8_t*)0xCFFF; + + while(timeout--); +} + +int format_card(void) { + uint8_t dummy; + timeout = CARD_TIMEOUT; + + paint_backdrop("Please Wait"); + gotoy(11); gotox(13); + cputs("Formatting card,"); + gotoy(12); gotox(8); + cputs("your screen may flicker."); + + // Release the $C800 region from any other card + dummy = *(uint8_t*)0xCFFF; + + // Ask card to download it's config from the Apple II host. + // We only support Page0 in this version of the utility. + cfg_cmd0("FORMAT"); + while(memcmp(config_errbuf, ERR_READY, 8) && (timeout > 0)) { + timeout--; + } + + // Release the $C800 region for use by other cards + dummy = *(uint8_t*)0xCFFF; + + return 1; +} + +void mode_menu(void) { + int paint_menu = 1; + + for(;;) { + if(paint_menu) { + paint_backdrop("Firmware Mode"); + + gotoy(menutop+0); gotox(menuleft); + cputs("1. VGA Video"); + gotoy(menutop+2); gotox(menuleft); + cputs("2. PCPI Applicard"); + gotoy(menutop+4); gotox(menuleft); +#if 0 + cputs("3. Serial"); + gotoy(menutop+6); gotox(menuleft); + cputs("4. Parallel"); +#endif + + gotoy(menutop+17); gotox(menuleft); + cputs("9. Back to Card Options"); + paint_menu = 0; + } + + switch(cgetc()) { + case '1': + v2mode = MODE_VGACARD; + return; + case '2': + v2mode = MODE_APPLICARD; + return; +#if 0 + case '3': + v2mode = MODE_SERIAL; + return; + case '4': + v2mode = MODE_PARALLEL; + return; +#endif + case 0x1B: + case '9': + return; + } + } +} + +void mux_menu(void) { + int paint_menu = 1; + + for(;;) { + if(paint_menu) { + paint_backdrop("Serial Mux"); + + gotoy(menutop+0); gotox(menuleft); + cputs("1. Printer"); + gotoy(menutop+2); gotox(menuleft); + cputs("2. USB"); + + if(v2mode == MODE_SERIAL) { + gotoy(menutop+4); gotox(menuleft); + cputs("3. WiFi Modem"); + gotoy(menutop+6); gotox(menuleft); + cputs("4. Loopback"); + } + + gotoy(menutop+17); gotox(menuleft); + cputs("9. Back to Card Options"); + } + + switch(cgetc()) { + case '1': + serialmux = SERIAL_PRINTER; + return; + case '2': + serialmux = SERIAL_USB; + return; + case '3': + if(v2mode == MODE_SERIAL) { + serialmux = SERIAL_WIFI; + return; + } + break; + case '4': + if(v2mode == MODE_SERIAL) { + serialmux = SERIAL_LOOP; + return; + } + break; + case 0x1B: + case '9': + return; + } + } +} + +void baud_menu(void) { + int paint_menu = 1; + + for(;;) { + if(paint_menu) { + paint_backdrop("Baudrate"); + + gotoy(menutop+0); gotox(menuleft); + cputs("1. 75"); + gotoy(menutop+2); gotox(menuleft); + cputs("2. 300"); + gotoy(menutop+4); gotox(menuleft); + cputs("3. 600"); + gotoy(menutop+6); gotox(menuleft); + cputs("4. 1200"); + gotoy(menutop+8); gotox(menuleft); + cputs("5. 2400"); + gotoy(menutop+10); gotox(menuleft); + cputs("6. 4800"); + gotoy(menutop+12); gotox(menuleft); + cputs("7. 9600"); + gotoy(menutop+14); gotox(menuleft); + cputs("8. 19200"); + gotoy(menutop+17); gotox(menuleft); + cputs("9. Back to Card Options"); + paint_menu = 0; + } + + switch(cgetc()) { + case '1': + baud = 75; + return; + case '2': + baud = 300; + return; + case '3': + baud = 600; + return; + case '4': + baud = 1200; + return; + case '5': + baud = 2400; + return; + case '6': + baud = 4800; + return; + case '7': + baud = 9600; + return; + case '8': + baud = 19200; + return; + case 0x1B: + case '9': + return; + } + } +} + + +void jdhost_edit(void) { + char temp_host[32]; + int c, l; + int paint_menu = 1; + + strcpy(temp_host, jd_host); + l = strlen(temp_host); + + for(;;) { + if(paint_menu) { + paint_backdrop("JetDirect"); + gotoy(menutop+0); gotox(menuleft); + cputs("IP Address:"); + gotoy(menutop+2); gotox(menuleft+4); + cputs("_________________________"); + gotoy(menutop+2); gotox(menuleft+4); + cputs(temp_host); + paint_menu = 0; + } + + gotox(menuleft+4+l); + (*(char**)BASL)[menuleft+4+l] = 95; + c = cgetc(); + if(c == 0x08) { + if(l > 0) { + // Remove flashing cursor + gotox(menuleft+4+l); + cputc('_'); + + // Remove deleted character + l--; + gotox(menuleft+4+l); + cputc('_'); + temp_host[l] = 0; + } + } else if((c == 0x0A) || (c == 0x0D)) { + strcpy(jd_host, temp_host); + return; + } else if(c == 0x1B) { + if(confirm("Go back without saving?")) { + return; + } + paint_menu = 1; + } else if(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || (c == '.')) { + if(l < 24) { + gotox(menuleft+4+l); + cputc(c); + temp_host[l] = c; + l++; + temp_host[l] = 0; + } + } + } +} + +void jdport_edit(void) { + char temp_port[8]; + int c, l; + int paint_menu = 1; + + sprintf(temp_port, "%i", jd_port); + l = strlen(temp_port); + + for(;;) { + if(paint_menu) { + paint_backdrop("JetDirect"); + gotoy(menutop+0); gotox(menuleft); + cputs("TCP Port:"); + gotoy(menutop+2); gotox(menuleft+4); + cputs("______"); + gotoy(menutop+2); gotox(menuleft+4); + cputs(temp_port); + paint_menu = 0; + } + + gotox(menuleft+4+l); + (*(char**)BASL)[menuleft+4+l] = 95; + c = cgetc(); + if(c == 0x08) { + if(l > 0) { + // Remove flashing cursor + gotox(menuleft+4+l); + cputc('_'); + + // Remove deleted character + l--; + gotox(menuleft+4+l); + cputc('_'); + temp_port[l] = 0; + } + } else if((c == 0x0A) || (c == 0x0D)) { + jd_port = strtoul(temp_port, NULL, 0); + return; + } else if(c == 0x1B) { + gotox(menuleft+4+l); + cputc('_'); + if(confirm("Go back without saving?")) { + return; + } + paint_menu = 1; + } else if((c >= '0') && (c <= '9')) { + if(l < 5) { + gotox(menuleft+4+l); + cputc(c); + temp_port[l] = c; + l++; + temp_port[l] = 0; + } + } + } +} + +void ssid_edit(void) { + char temp_ssid[32]; + int c, l; + int paint_menu = 1; + + strcpy(temp_ssid, wifi_ssid); + l = strlen(temp_ssid); + + for(;;) { + if(paint_menu) { + paint_backdrop("WiFi"); + gotoy(menutop+0); gotox(menuleft); + cputs("Network Name (SSID):"); + gotoy(menutop+2); gotox(menuleft+4); + cputs("_________________________"); + gotoy(menutop+2); gotox(menuleft+4); + cputs(temp_ssid); + paint_menu = 0; + } + + gotox(menuleft+4+l); + (*(char**)BASL)[menuleft+4+l] = 95; + c = cgetc(); + if(c == 0x08) { + if(l > 0) { + // Remove flashing cursor + gotox(menuleft+4+l); + cputc('_'); + + // Remove deleted character + l--; + gotox(menuleft+4+l); + cputc('_'); + temp_ssid[l] = 0; + } + } else if((c == 0x0A) || (c == 0x0D)) { + strcpy(wifi_ssid, temp_ssid); + return; + } else if(c == 0x1B) { + gotox(menuleft+4+l); + cputc('_'); + if(confirm("Go back without saving?")) { + return; + } + paint_menu = 1; + } else if(c >= 32) { + if(l < 24) { + gotox(menuleft+4+l); + cputc(c); + temp_ssid[l] = c; + l++; + temp_ssid[l] = 0; + } + } + } +} + +void psk_edit(void) { + char temp_psk[32]; + int c, l; + int paint_menu = 1; + + strcpy(temp_psk, wifi_psk); + l = strlen(temp_psk); + + for(;;) { + if(paint_menu) { + paint_backdrop("WiFi"); + gotoy(menutop+0); gotox(menuleft); + cputs("Passphrase (PSK):"); + gotoy(menutop+1); gotox(menuleft+4); + cputs("_________________________"); + gotoy(menutop+1); gotox(menuleft+4); + cputs(temp_psk); + paint_menu = 0; + } + + gotox(menuleft+4+l); + (*(char**)BASL)[menuleft+4+l] = 95; + c = cgetc(); + if(c == 0x08) { + if(l > 0) { + // Remove flashing cursor + gotox(menuleft+4+l); + cputc('_'); + + // Remove deleted character + l--; + gotox(menuleft+4+l); + cputc('_'); + temp_psk[l] = 0; + } + } else if((c == 0x0A) || (c == 0x0D)) { + strcpy(wifi_psk, temp_psk); + return; + } else if(c == 0x1B) { + gotox(menuleft+4+l); + cputc('_'); + if(confirm("Go back without saving?")) { + return; + } + paint_menu = 1; + } else if(c >= 32) { + if(l < 24) { + gotox(menuleft+4+l); + cputc(c); + temp_psk[l] = c; + l++; + temp_psk[l] = 0; + } + } + } +} + +void address_edit(void) { + char temp_address[32]; + int c, l; + int paint_menu = 1; + + strcpy(temp_address, wifi_address); + l = strlen(temp_address); + + for(;;) { + if(paint_menu) { + paint_backdrop("WiFi"); + gotoy(menutop+0); gotox(menuleft); + cputs("Enter IP Address or \"DHCP\":"); + gotoy(menutop+2); gotox(menuleft+4); + cputs("________________"); + gotoy(menutop+2); gotox(menuleft+4); + cputs(temp_address); + paint_menu = 0; + } + + gotox(menuleft+4+l); + (*(char**)BASL)[menuleft+4+l] = 95; + c = cgetc(); + if(c == 0x08) { + if(l > 0) { + // Remove flashing cursor + gotox(menuleft+4+l); + cputc('_'); + + // Remove deleted character + l--; + gotox(menuleft+4+l); + cputc('_'); + temp_address[l] = 0; + } + } else if((c == 0x0A) || (c == 0x0D)) { + strcpy(wifi_address, temp_address); + return; + } else if(c == 0x1B) { + gotox(menuleft+4+l); + cputc('_'); + if(confirm("Go back without saving?")) { + return; + } + paint_menu = 1; + } else if(c >= 32) { + if(l < 15) { + gotox(menuleft+4+l); + cputc(c); + temp_address[l] = c; + l++; + temp_address[l] = 0; + } + } + } +} + + +void card_menu(void) { + int paint_menu = 1; + + for(;;) { + if(paint_menu) { + paint_backdrop("Card Options"); + + gotoy(menutop+0); gotox(menuleft); + cputs("1. Mode: "); + switch(v2mode) { + case MODE_VGACARD: + cputs("VGA Video"); + break; + case MODE_APPLICARD: + cputs("Applicard"); + break; + case MODE_FS: + cputs("Filesystem"); + break; + case MODE_MIDI: + cputs("MIDI"); + break; + case MODE_SNESMAX: + cputs("SNESMAX"); + break; + case MODE_ETHERNET: + cputs("Ethernet"); + break; + case MODE_SERIAL: + cputs("Serial"); + gotoy(menutop+2); gotox(menuleft); + printf("2. Baudrate: %i", baud); + gotoy(menutop+4); gotox(menuleft); + cputs("3. Device Mux: "); + switch(serialmux) { + case SERIAL_PRINTER: + cputs("Printer"); + gotoy(menutop+6); gotox(menuleft); + printf("4. Host: %s", jd_host); + gotoy(menutop+8); gotox(menuleft); + printf("5. Port: %i", jd_port); + break; + case SERIAL_USB: + cputs("USB"); + gotoy(menutop+10); gotox(menuleft); + cputs("6. USB Mode: "); + switch(usbmux) { + case USB_HOST_CDC: + cputs("CDC Host"); + break; + case USB_GUEST_CDC: + cputs("CDC Guest"); + break; + } + break; + break; + case SERIAL_LOOP: + cputs("Loopback"); + break; + case SERIAL_WIFI: + cputs("WiFi Modem"); + break; + } + break; + case MODE_PARALLEL: + cputs("Parallel"); + gotoy(menutop+4); gotox(menuleft); + cputs("3. Device Mux: "); + switch(serialmux) { + case SERIAL_PRINTER: + cputs("Printer"); + gotoy(menutop+6); gotox(menuleft); + printf("4. Host: %s", jd_host); + gotoy(menutop+8); gotox(menuleft); + printf("5. Port: %i", jd_port); + break; + case SERIAL_USB: + cputs("USB"); + gotoy(menutop+10); gotox(menuleft); + cputs("6. USB Mode: "); + switch(usbmux) { + case USB_HOST_CDC: + cputs("CDC Host"); + break; + case USB_GUEST_CDC: + cputs("CDC Guest"); + break; + } + break; + default: + cputs(">NUL:"); + } + break; + } + + gotoy(menutop+17); gotox(menuleft); + cputs("9. Back to Main Menu"); + paint_menu = 0; + } + switch(cgetc()) { + case '1': + mode_menu(); + paint_menu = 1; + break; + case '2': + if(v2mode == MODE_SERIAL) { + baud_menu(); + paint_menu = 1; + } + break; + case '3': + if((v2mode == MODE_SERIAL) || (v2mode == MODE_PARALLEL)) { + mux_menu(); + paint_menu = 1; + } + break; + case '4': + if(((v2mode == MODE_SERIAL) || (v2mode == MODE_PARALLEL)) && (serialmux == SERIAL_PRINTER)) { + jdhost_edit(); + paint_menu = 1; + } + break; + case '5': + if(((v2mode == MODE_SERIAL) || (v2mode == MODE_PARALLEL)) && (serialmux == SERIAL_PRINTER)) { + jdport_edit(); + paint_menu = 1; + } + break; + case '6': + if(((v2mode == MODE_SERIAL) || (v2mode == MODE_PARALLEL)) && (serialmux == SERIAL_USB)) { + usbmux = (usbmux == USB_HOST_CDC) ? USB_GUEST_CDC : USB_HOST_CDC; + paint_menu = 1; + } + break; + case 0x1B: + case '9': + return; + } + } +} + +void wifi_menu(void) { + int paint_menu = 1; + int c; + for(;;) { + if(paint_menu) { + paint_backdrop("WiFi Options"); + + gotoy(menutop+0); gotox(menuleft); + cputs("1. WIFI Mode:"); + gotoy(menutop+2); gotox(8); + switch(wifimode) { + case WIFI_AP: + cputs("Access Point"); + break; + case WIFI_CLIENT: + cputs("Client"); + break; + default: + cputs("Unknown"); + } + gotoy(menutop+4); gotox(menuleft); + cputs("2. Network Name:"); + gotoy(menutop+6); gotox(8); + cputs(wifi_ssid); + gotoy(menutop+8); gotox(menuleft); + cputs("3. Pre-Shared Key:"); + gotoy(menutop+10); gotox(8); + for(c = 0; c < strlen(wifi_psk); c++) { + cputc('*'); + } + gotoy(menutop+12); gotox(menuleft); + cputs("4. IP Address:"); + gotoy(menutop+14); gotox(8); + if(wifimode == WIFI_AP) { + cputs("10.65.50.1"); + } else { + cputs(wifi_address); + } + + gotoy(menutop+17); gotox(menuleft); + puts("9. Back to Main Menu"); + paint_menu = 0; + } + + switch(cgetc()) { + case '1': + wifimode = (wifimode == WIFI_AP) ? WIFI_CLIENT : WIFI_AP; + paint_menu = 1; + break; + case '2': + ssid_edit(); + paint_menu = 1; + break; + case '3': + psk_edit(); + paint_menu = 1; + break; + case '4': + if(wifimode == WIFI_AP) { + message("Address is fixed in this mode."); + paint_menu = 1; + } else { + address_edit(); + paint_menu = 1; + } + break; + case 0x1B: + case '9': + return; + } + } +} + +void machine_menu(void) { + int paint_menu = 1; + for(;;) { + if(paint_menu) { + paint_backdrop("Machine Options"); + + gotoy(menutop+0); gotox(menuleft); + cputs("1. Host Type:"); + gotoy(menutop+2); gotox(8); + switch(machine) { + case MACHINE_AUTO: + cputs("Auto Detect"); + break; + case MACHINE_APPLE_IIGS: + cputs("Apple IIgs"); + break; + case MACHINE_APPLE_IIE: + cputs("Apple IIe"); + break; + default: + cputs("Apple II / II+"); + } + + gotoy(menutop+17); gotox(menuleft); + puts("9. Back to Main Menu"); + paint_menu = 0; + } + + switch(cgetc()) { + case '1': + machine = (machine + 1); + if(machine >= MACHINE_MAXVALUE) + machine = 0; + paint_menu = 1; + break; + case 0x1B: + case '9': + return; + } + } +} + +int prompt_slot(void) { + int c; + paint_backdrop("Config Utility"); + + 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) { - unsigned char *config = (unsigned char *)0x2000; - int i; + int paint_menu = 1; - puts("1. Card Configuration\n"); - puts("4. WIFI Configuration\n"); - - PICOPAL_ALSB = 0x00; - PICOPAL_AMSB = 0x00; - - for(i = 0; i < 0x800; i++) { - PICOPAL_WRFONT = font[i]; + if(!prompt_slot()) { + return; } - puts("Done.\n"); + config_cmdbuf = (uint8_t *)(0xC0F0 | (cardslot << 8)); + config_errbuf = (uint8_t *)(0xC0F8 | (cardslot << 8)); + + paint_backdrop("Please Wait"); + gotoy(11); gotox(9); + cputs("Reading configuration,"); + gotoy(12); gotox(8); + cputs("your screen may flicker."); + + read_config(); + + for(;;) { + if(paint_menu) { + paint_backdrop("Main Menu"); + + gotoy(menutop+0); gotox(menuleft); + cputs("1. Card options"); + gotoy(menutop+2); gotox(menuleft); + cputs("2. Machine options"); + +#if 0 + gotoy(menutop+4); gotox(menuleft); + cputs("3. WIFI options"); + gotoy(menutop+9); gotox(menuleft); + cputs("5. Backup settings"); + gotoy(menutop+11); gotox(menuleft); + cputs("6. Restore settings"); +#endif + gotoy(menutop+13); gotox(menuleft); + cputs("7. Format card storage"); + gotoy(menutop+15); gotox(menuleft); + cputs("8. Quit without saving"); + gotoy(menutop+17); gotox(menuleft); + cputs("9. Save & Exit"); + paint_menu = 0; + } + + switch(cgetc()) { + case '1': + card_menu(); + paint_menu = 1; + break; + case '2': + machine_menu(); + paint_menu = 1; + break; +#if 0 + case '3': + wifi_menu(); + paint_menu = 1; + break; + case '5': + case '6': + message("Function Not Implemented"); + paint_menu = 1; + break; +#endif + case '7': + if(confirm("Format Card?")) { + format_card(); + clrscr(); + rebootafterexit(); + return; + } + paint_menu = 1; + break; + case '8': + if(confirm("Quit without saving?")) { + clrscr(); + return; + } + paint_menu = 1; + break; + case '9': + if(confirm("Save and exit?")) { + write_config(); + clrscr(); + rebootafterexit(); + return; + } + paint_menu = 1; + break; + } + } } diff --git a/utilities/modes/Makefile b/utilities/modes/Makefile new file mode 100644 index 0000000..9420175 --- /dev/null +++ b/utilities/modes/Makefile @@ -0,0 +1,56 @@ + +# Run 'make SYS='; 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) diff --git a/utilities/modes/modeswitch.c b/utilities/modes/modeswitch.c new file mode 100644 index 0000000..14941dd --- /dev/null +++ b/utilities/modes/modeswitch.c @@ -0,0 +1,299 @@ +// cl65 -t apple2 --start-addr 0x4000 uploadfont.c + +#include +#include +#include +#include +#include + +#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; + } + } + +} diff --git a/utilities/uploadfont/Makefile b/utilities/uploadfont/Makefile index 035ad85..ca386a0 100644 --- a/utilities/uploadfont/Makefile +++ b/utilities/uploadfont/Makefile @@ -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) diff --git a/utilities/uploadfont/flashfont.c b/utilities/uploadfont/flashfont.c new file mode 100644 index 0000000..92e4daa --- /dev/null +++ b/utilities/uploadfont/flashfont.c @@ -0,0 +1,449 @@ +// cl65 -t apple2 --start-addr 0x4000 uploadfont.c + +#include +#include +#include +#include +#include + +#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"); +} diff --git a/utilities/uploadfont/uploadfont.c b/utilities/uploadfont/uploadfont.c index 4304028..de5fcd2 100644 --- a/utilities/uploadfont/uploadfont.c +++ b/utilities/uploadfont/uploadfont.c @@ -6,22 +6,280 @@ #include #include -#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"); } diff --git a/v2-analog-rev1/CMakeLists.txt b/v2-analog-rev1/CMakeLists.txt index 03674e9..227bfb5 100644 --- a/v2-analog-rev1/CMakeLists.txt +++ b/v2-analog-rev1/CMakeLists.txt @@ -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 diff --git a/v2-analog-rev1/common/abus.pio b/v2-analog-rev1/common/abus.pio index be5ebd2..dec3861 100644 --- a/v2-analog-rev1/common/abus.pio +++ b/v2-analog-rev1/common/abus.pio @@ -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 diff --git a/v2-analog-rev1/common/buffers.c b/v2-analog-rev1/common/buffers.c index d5b9983..f3f49e3 100644 --- a/v2-analog-rev1/common/buffers.c +++ b/v2-analog-rev1/common/buffers.c @@ -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]; diff --git a/v2-analog-rev1/common/buffers.h b/v2-analog-rev1/common/buffers.h index 4475cc1..e84ff4c 100644 --- a/v2-analog-rev1/common/buffers.h +++ b/v2-analog-rev1/common/buffers.h @@ -2,11 +2,15 @@ #include -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; diff --git a/v2-analog-rev1/common/config.c b/v2-analog-rev1/common/config.c index b043ba7..6d8f599 100644 --- a/v2-analog-rev1/common/config.c +++ b/v2-analog-rev1/common/config.c @@ -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); } diff --git a/v2-analog-rev1/common/config.h b/v2-analog-rev1/common/config.h index b61af2c..702b317 100644 --- a/v2-analog-rev1/common/config.h +++ b/v2-analog-rev1/common/config.h @@ -1,5 +1,7 @@ #pragma once +#include + #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(); + diff --git a/v2-analog-rev1/common/flash.c b/v2-analog-rev1/common/flash.c new file mode 100644 index 0000000..3e72410 --- /dev/null +++ b/v2-analog-rev1/common/flash.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include "config.h" + +#ifdef RASPBERRYPI_PICO_W +#include +#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(;;); +} + diff --git a/v2-analog-rev1/common/flash.h b/v2-analog-rev1/common/flash.h new file mode 100644 index 0000000..8cecd75 --- /dev/null +++ b/v2-analog-rev1/common/flash.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern void flash_reboot() __attribute__ ((noreturn)); diff --git a/v2-analog-rev1/common/flash_regs.h b/v2-analog-rev1/common/flash_regs.h deleted file mode 100644 index 351c218..0000000 --- a/v2-analog-rev1/common/flash_regs.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -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, -}; diff --git a/v2-analog-rev1/common/flash_upload.c b/v2-analog-rev1/common/flash_upload.c deleted file mode 100644 index fa261fe..0000000 --- a/v2-analog-rev1/common/flash_upload.c +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include -#include -#include -#include -#include "config.h" - -#ifdef RASPBERRYPI_PICO_W -#include -#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 - diff --git a/v2-analog-rev1/common/main.c b/v2-analog-rev1/common/main.c index d79286a..cb8c4be 100644 --- a/v2-analog-rev1/common/main.c +++ b/v2-analog-rev1/common/main.c @@ -1,49 +1,61 @@ #include #include #include +#include #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 #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; diff --git a/v2-analog-rev1/common/modes.h b/v2-analog-rev1/common/modes.h index 0efb4ad..3235494 100644 --- a/v2-analog-rev1/common/modes.h +++ b/v2-analog-rev1/common/modes.h @@ -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)); diff --git a/v2-analog-rev1/diag/businterface.c b/v2-analog-rev1/diag/businterface.c index bc04ae3..ba6f525 100644 --- a/v2-analog-rev1/diag/businterface.c +++ b/v2-analog-rev1/diag/businterface.c @@ -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; } } diff --git a/v2-analog-rev1/diag/diag.c b/v2-analog-rev1/diag/diag.c index 0003d43..432746d 100644 --- a/v2-analog-rev1/diag/diag.c +++ b/v2-analog-rev1/diag/diag.c @@ -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); } } diff --git a/v2-analog-rev1/fs/businterface.c b/v2-analog-rev1/fs/businterface.c index 90d57f0..9803aed 100644 --- a/v2-analog-rev1/fs/businterface.c +++ b/v2-analog-rev1/fs/businterface.c @@ -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); - } -} diff --git a/v2-analog-rev1/fs/fs.c b/v2-analog-rev1/fs/fs.c index 3b55f23..4ff093e 100644 --- a/v2-analog-rev1/fs/fs.c +++ b/v2-analog-rev1/fs/fs.c @@ -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); } diff --git a/v2-analog-rev1/parallel/businterface.c b/v2-analog-rev1/parallel/businterface.c index ccf3f1c..b83dbce 100644 --- a/v2-analog-rev1/parallel/businterface.c +++ b/v2-analog-rev1/parallel/businterface.c @@ -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); } } diff --git a/v2-analog-rev1/parallel/parallel.c b/v2-analog-rev1/parallel/parallel.c index 2b48a88..f31f4a2 100644 --- a/v2-analog-rev1/parallel/parallel.c +++ b/v2-analog-rev1/parallel/parallel.c @@ -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); } } diff --git a/v2-analog-rev1/serial/businterface.c b/v2-analog-rev1/serial/businterface.c index 7ac8fe2..7ad42b0 100644 --- a/v2-analog-rev1/serial/businterface.c +++ b/v2-analog-rev1/serial/businterface.c @@ -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); } } diff --git a/v2-analog-rev1/serial/serial.c b/v2-analog-rev1/serial/serial.c index 4693407..7992412 100644 --- a/v2-analog-rev1/serial/serial.c +++ b/v2-analog-rev1/serial/serial.c @@ -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: diff --git a/v2-analog-rev1/vga/businterface.c b/v2-analog-rev1/vga/businterface.c index a402451..6c44db5 100644 --- a/v2-analog-rev1/vga/businterface.c +++ b/v2-analog-rev1/vga/businterface.c @@ -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 } diff --git a/v2-analog-rev1/vga/render.c b/v2-analog-rev1/vga/render.c index 589b4d9..e18a4a5 100644 --- a/v2-analog-rev1/vga/render.c +++ b/v2-analog-rev1/vga/render.c @@ -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; + } + } +// } } } diff --git a/v2-analog-rev1/vga/render.h b/v2-analog-rev1/vga/render.h index 13ef480..f86bb1e 100644 --- a/v2-analog-rev1/vga/render.h +++ b/v2-analog-rev1/vga/render.h @@ -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(); diff --git a/v2-analog-rev1/vga/render_hires.c b/v2-analog-rev1/vga/render_hires.c index 5379bbd..031bef9 100644 --- a/v2-analog-rev1/vga/render_hires.c +++ b/v2-analog-rev1/vga/render_hires.c @@ -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++; diff --git a/v2-analog-rev1/vga/render_test.c b/v2-analog-rev1/vga/render_test.c index 4c1987b..a3b6b24 100644 --- a/v2-analog-rev1/vga/render_test.c +++ b/v2-analog-rev1/vga/render_test.c @@ -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); diff --git a/v2-analog-rev1/vga/vgamain.c b/v2-analog-rev1/vga/vgamain.c index f95d0ee..26ddf15 100644 --- a/v2-analog-rev1/vga/vgamain.c +++ b/v2-analog-rev1/vga/vgamain.c @@ -11,5 +11,5 @@ void __noinline __time_critical_func(vgamain)() { vga_init(); render_init(); render_loop(); - vga_deinit(); +// vga_deinit(); } diff --git a/v2-analog-rev1/vga/vgaout.c b/v2-analog-rev1/vga/vgaout.c index 6e1c051..f95bd0a 100644 --- a/v2-analog-rev1/vga/vgaout.c +++ b/v2-analog-rev1/vga/vgaout.c @@ -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(); } diff --git a/v2-analog-rev1/vga/vgaout.h b/v2-analog-rev1/vga/vgaout.h index 2fea76e..6d53661 100644 --- a/v2-analog-rev1/vga/vgaout.h +++ b/v2-analog-rev1/vga/vgaout.h @@ -32,8 +32,6 @@ struct vga_scanline { }; -void vga_init(); -void vga_deinit(); void vga_prepare_frame(); struct vga_scanline *vga_prepare_scanline(); diff --git a/v2-analog-rev1/z80/businterface.c b/v2-analog-rev1/z80/businterface.c index b101a8c..59b02f2 100644 --- a/v2-analog-rev1/z80/businterface.c +++ b/v2-analog-rev1/z80/businterface.c @@ -1,10 +1,12 @@ #include #include #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); - } -} diff --git a/v2-analog-rev1/z80/z80buf.h b/v2-analog-rev1/z80/z80buf.h index 8a2a8e9..8b5367d 100644 --- a/v2-analog-rev1/z80/z80buf.h +++ b/v2-analog-rev1/z80/z80buf.h @@ -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; } diff --git a/v2-analog-rev1/z80/z80main.c b/v2-analog-rev1/z80/z80main.c index 568b23e..6621649 100644 --- a/v2-analog-rev1/z80/z80main.c +++ b/v2-analog-rev1/z80/z80main.c @@ -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(); + } } }