Build for 20230414 - Fixed config interface

This commit is contained in:
David Kuder 2023-04-14 01:46:32 -04:00
parent 9b41d7a15f
commit 7707330977
17 changed files with 482 additions and 186 deletions

View File

@ -10,6 +10,7 @@ build_firmware() {
( mkdir -p build/$1 && cd build/$1 && cmake ../.. )
fi
make -C build/$1
#tools/mksparse build/$1/$1.bin build/$1/$1.ota
}
build_firmware v2-analog-lc-4ns-z80

View File

@ -1,7 +1,7 @@
#define NEWCONFIG_MAGIC 0x0001434E // "NC\x01\x00"
#define NEWCONFIG_EOF_MARKER 0x00464F45 // "EOF\x00"
#define CFGTOKEN_REVISION 0x0001434E // "RV\xXX\x00"
#define CFGTOKEN_REVISION 0x00015652 // "RV\xXX\x00"
#define CFGTOKEN_MODE_VGA 0x0000564D // "MV\x00\x00" VGA
#define CFGTOKEN_MODE_PCPI 0x00005A4D // "MZ\x00\x00" PCPI Applicard
@ -41,6 +41,8 @@
#define CFGTOKEN_JD_HOST 0x0000484A // "JH\x00\x01" JetDirect Hostname
#define CFGTOKEN_JD_PORT 0x0200444A // "JD\x00\x01" JetDirect Port
#define CFGTOKEN_FONT_00 0x00004656 // "VF\xXX\x00" Custom default font
#define CFGTOKEN_MONO_00 0x00005056 // "VP\x00\x00" Full Color Video
#define CFGTOKEN_MONO_80 0x00805056 // "VP\x80\x00" B&W Video
#define CFGTOKEN_MONO_90 0x00905056 // "VP\x90\x00" B&W Inverse

View File

@ -6,6 +6,8 @@
#ifdef FUNCTION_VGA
#include "vga/render.h"
#include "vga/vgaout.h"
extern volatile uint8_t romx_textbank;
extern volatile uint8_t romx_changed;
#endif
#ifdef FUNCTION_Z80
#include "z80/z80buf.h"
@ -83,6 +85,10 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
cfg_machine = MACHINE_BASIS;
break;
#ifdef FUNCTION_VGA
case CFGTOKEN_FONT_00:
romx_textbank = (config[i] >> 16) & 0x2F;
romx_changed = 1;
break;
case CFGTOKEN_MONO_00:
mono_palette = (config[i] >> 16) & 0xF;
break;
@ -128,11 +134,11 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
break;
case CFGTOKEN_WIFI_SSID:
memset((char*)wifi_ssid, 0, sizeof(wifi_ssid));
strncpy((char*)wifi_ssid, (char*)(config+i+1), (config[i] >> 24));
strncpy((char*)wifi_ssid, (char*)(&config[i+1]), (config[i] >> 24));
break;
case CFGTOKEN_WIFI_PSK:
memset((char*)wifi_psk, 0, sizeof(wifi_psk));
strncpy((char*)wifi_psk, (char*)(config+i+1), (config[i] >> 24));
strncpy((char*)wifi_psk, (char*)(&config[i+1]), (config[i] >> 24));
break;
case CFGTOKEN_WIFI_IP:
wifi_address = config[i+1];
@ -142,7 +148,7 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
break;
case CFGTOKEN_JD_HOST:
memset((uint8_t*)jd_host, 0, sizeof(jd_host));
strncpy(jd_host, (char*)(config+i+1), (config[i] >> 24));
strncpy(jd_host, (char*)(&config[i+1]), (config[i] >> 24));
break;
case CFGTOKEN_JD_PORT:
jd_port = config[i+1];
@ -169,13 +175,13 @@ void DELAYED_COPY_CODE(default_config)() {
cfg_machine = MACHINE_AUTO;
}
int DELAYED_COPY_CODE(make_config)(uint8_t rev) {
int DELAYED_COPY_CODE(make_config)(uint32_t rev) {
int i = 0;
memset(config_temp, 0, sizeof(config_temp));
config_temp[i++] = NEWCONFIG_MAGIC;
config_temp[i++] = CFGTOKEN_REVISION | (((uint16_t)rev) << 16);
config_temp[i++] = CFGTOKEN_REVISION | ((rev & 0xff) << 16);
switch(cfg_machine) {
default:
@ -258,21 +264,19 @@ int DELAYED_COPY_CODE(make_config)(uint8_t rev) {
}
config_temp[i] = CFGTOKEN_WIFI_SSID | (((uint32_t)strlen((char*)wifi_ssid)+1) << 24);
strcpy((char*)(config_temp+i+1), (char*)wifi_ssid);
strcpy((char*)(&config_temp[i+1]), (char*)wifi_ssid);
i += 1 + (((config_temp[i] >> 24) + 3) >> 2);
config_temp[i] = CFGTOKEN_WIFI_PSK | (((uint32_t)strlen((char*)wifi_psk)+1) << 24);
strcpy((char*)(config_temp+i+1), (char*)wifi_psk);
strcpy((char*)(&config_temp[i+1]), (char*)wifi_psk);
i += 1 + (((config_temp[i] >> 24) + 3) >> 2);
#endif
#ifdef FUNCTION_VGA
config_temp[i++] = CFGTOKEN_FONT_00 | ((romx_textbank & 0x2F) << 20);
config_temp[i++] = CFGTOKEN_MONO_00 | ((mono_palette & 0xF) << 20);
config_temp[i++] = CFGTOKEN_TBCOLOR | ((terminal_tbcolor & 0xFF) << 16);
config_temp[i++] = CFGTOKEN_BORDER | ((terminal_border & 0xF) << 16);
// TODO: Font
//config_temp[i++] = CFGTOKEN_FONTSLOT | ((terminal_font & 0x1F) << 16);
#endif
config_temp[i++] = NEWCONFIG_EOF_MARKER;
@ -323,6 +327,7 @@ bool DELAYED_COPY_CODE(is_primary_config_newer)() {
return (a == ((b+1) & 0xff));
}
bool DELAYED_COPY_CODE(read_config)() {
if(is_config_valid(FLASH_CONFIG_ONETIME)) {
internal_flags &= ~IFLAGS_TEST;
@ -390,38 +395,33 @@ bool DELAYED_COPY_CODE(write_config)(bool onetime) {
return retval;
}
#ifdef FUNCTION_VGA
uint8_t DELAYED_COPY_CODE(test_font)(uint16_t param0) {
int i;
uint8_t DELAYED_COPY_CODE(get_config_block)() {
uint16_t last_config_block;
uint16_t next_config_block;
for(i = 0; i < 4096; i++) {
character_rom[i] = apple_memory[param0+i];
last_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
next_config_block = last_config_block;
if(is_config_valid(FLASH_CONFIG_PRIMARY)) {
if(!is_config_valid(FLASH_CONFIG_SECONDARY) || (is_primary_config_newer())) {
last_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
next_config_block = (FLASH_CONFIG_SECONDARY-XIP_BASE) / 4096;
} else {
last_config_block = (FLASH_CONFIG_SECONDARY-XIP_BASE) / 4096;
next_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
}
} else if(is_config_valid(FLASH_CONFIG_SECONDARY)) {
last_config_block = (FLASH_CONFIG_SECONDARY-XIP_BASE) / 4096;
next_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
}
return REPLY_OK;
}
uint8_t DELAYED_COPY_CODE(write_font)(uint16_t param0, uint16_t param1) {
int i;
if(param1 > 0x27) return REPLY_EPARAM;
// Disable video output to stop DMA and IRQs
vga_dpms_sleep();
for(i = 0; i < 4096; i++) {
character_rom[i] = apple_memory[param0+i];
}
flash_range_erase((FLASH_FONT(param1)-XIP_BASE), FONT_SIZE);
flash_range_program((FLASH_FONT(param1)-XIP_BASE), character_rom, FONT_SIZE);
// Enable video output now that we are done
vga_dpms_wake();
config_rpybuf[5] = (next_config_block >> 8) & 0xFF;
config_rpybuf[4] = (next_config_block >> 0) & 0xFF;
config_rpybuf[3] = (last_config_block >> 8) & 0xFF;
config_rpybuf[2] = (last_config_block >> 0) & 0xFF;
return REPLY_OK;
}
#endif
uint8_t DELAYED_COPY_CODE(cf_readblock)(uint16_t param0) {
if(param0 >= (FLASH_SIZE/4096)) return REPLY_EPARAM;
@ -454,7 +454,7 @@ uint8_t DELAYED_COPY_CODE(cf_writeblock)(uint16_t param0) {
vga_dpms_sleep();
#endif
flash_range_program(param0 * 4096, (void*)cfbuf, 4096);
flash_range_program(((uint32_t)param0) * 4096, (void*)cfbuf, 4096);
#ifdef FUNCTION_VGA
// Enable video output now that we are done
@ -477,7 +477,66 @@ uint8_t DELAYED_COPY_CODE(cf_eraseblock)(uint16_t param0) {
vga_dpms_sleep();
#endif
flash_range_erase(param0 * 4096, 4096);
flash_range_erase(((uint32_t)param0) * 4096, 4096);
#ifdef FUNCTION_VGA
// Enable video output now that we are done
vga_dpms_wake();
#endif
return REPLY_OK;
}
#ifdef FUNCTION_VGA
uint8_t DELAYED_COPY_CODE(test_font)() {
int i;
for(i = 0; i < 2048; i++) {
character_rom[i] = cfbuf[i];
}
userfont = true;
return REPLY_OK;
}
#endif
uint8_t DELAYED_COPY_CODE(read_font)(uint16_t param0) {
if(param0 > 0x27) return REPLY_EPARAM;
return cf_readblock((FLASH_FONT(param0)-XIP_BASE) / 4096);
}
uint8_t DELAYED_COPY_CODE(erase_font)(uint16_t param0) {
int i;
if(param0 > 0x27) return REPLY_EPARAM;
#ifdef FUNCTION_VGA
// Disable video output to stop DMA and IRQs
vga_dpms_sleep();
#endif
flash_range_erase((FLASH_FONT(param0)-XIP_BASE), FONT_SIZE);
#ifdef FUNCTION_VGA
// Enable video output now that we are done
vga_dpms_wake();
#endif
return REPLY_OK;
}
uint8_t DELAYED_COPY_CODE(write_font)(uint16_t param0) {
int i;
if(param0 > 0x27) return REPLY_EPARAM;
#ifdef FUNCTION_VGA
// Disable video output to stop DMA and IRQs
vga_dpms_sleep();
#endif
flash_range_program((FLASH_FONT(param0)-XIP_BASE), (void*)cfbuf, FONT_SIZE);
#ifdef FUNCTION_VGA
// Enable video output now that we are done
@ -516,22 +575,37 @@ void DELAYED_COPY_CODE(config_handler)() {
config_rpybuf[0] = REPLY_BUSY;
switch(config_cmdbuf[0]) {
#ifdef FUNCTION_VGA
case 'C':
switch(config_cmdbuf[1]) {
default:
retval = REPLY_ECMD;
break;
#ifdef FUNCTION_VGA
case 'T':
// One-time load of font data (lost at reboot)
retval = test_font(param0);
case 'I':
retval = test_font();
case 'S':
romx_textbank = param0 & 0x2F;
romx_changed = 1;
retval = REPLY_OK;
#endif
case 'r':
// Read font from flash
retval = read_font(param0);
cfptr = 0;
break;
case 'w':
// Save font to flash
retval = write_font(param0, param1);
retval = write_font(param0);
cfptr = 0;
break;
case 'e':
// Erase font from flash
retval = erase_font(param0);
cfptr = 0;
break;
}
break;
#endif
case 'H':
retval = REPLY_OK;
switch(config_cmdbuf[1]) {
@ -579,6 +653,11 @@ void DELAYED_COPY_CODE(config_handler)() {
default:
retval = REPLY_ECMD;
break;
case 'c':
// Current Config Block
retval = get_config_block();
cfptr = 0;
break;
case 'r':
// Read block
retval = cf_readblock(param0);

View File

@ -101,7 +101,7 @@ extern volatile compat_t current_machine;
void default_config();
int make_config(uint8_t rev);
int make_config(uint32_t rev);
bool read_config();
bool write_config(bool onetime);

View File

@ -4,8 +4,10 @@
#include <hardware/resets.h>
#include <hardware/dma.h>
#include <hardware/flash.h>
#include "config.h"
#include "flash.h"
#include "common/config.h"
#include "common/buffers.h"
#include "common/flash.h"
#include <string.h>
#ifdef RASPBERRYPI_PICO_W
#include <pico/cyw43_arch.h>
@ -62,14 +64,14 @@ void __noinline __time_critical_func(flash_ota)() {
uint32_t sniffed_crc = dma_sniffer_get_data_accumulator();
if (0ul == sniffed_crc) {
uint8_t *ptr = (const uint8_t *)FLASH_OTA_AREA
uint8_t *ptr = (uint8_t *)FLASH_OTA_AREA;
uint32_t offset;
flash_range_erase(0, FLASH_OTA_SIZE);
// Copy from OTA area to Boot
for(offset = 0; offset < FLASH_OTA_SIZE; offset+=65536);
memcpy(private_memory, ptr+offset, 65536);
flash_range_program(offset, private_memory, 65536);
for(offset = 0; offset < FLASH_OTA_SIZE; offset+=65536) {
memcpy((uint8_t *)private_memory, ptr+offset, 65536);
flash_range_program(offset, (const uint8_t *)private_memory, 65536);
}
flash_range_erase((uint32_t)(FLASH_OTA_AREA-XIP_BASE), FLASH_OTA_SIZE);

View File

@ -43,37 +43,45 @@ static void __noinline __time_critical_func(core1_loop)() {
// Config memory in card slot-rom address space
if(ACCESS_WRITE) {
if((address & 0xFF) == 0xED) {
if((address & 0xFF) == 0xEC) {
apple_memory[address] = value;
cfptr = (cfptr & 0x1F00) | value;
apple_memory[address] = cfbuf[cfptr];
cfptr = (cfptr & 0x0F00) | value;
apple_memory[address+2] = cfbuf[cfptr]; // $CnEE
apple_memory[address+3] = cfbuf[cfptr]; // $CnEF
}
if((address & 0xFF) == 0xEE) {
apple_memory[address] = value & 0x1F;
cfptr = ((cfptr & 0xFF) | (value << 8)) & 0x1FFF;
apple_memory[address] = cfbuf[cfptr];
if((address & 0xFF) == 0xED) {
apple_memory[address] = value & 0x0F;
cfptr = ((cfptr & 0xFF) | (((uint16_t)value) << 8)) & 0xFFF;
apple_memory[address+1] = cfbuf[cfptr]; // $CnEE
apple_memory[address+2] = cfbuf[cfptr]; // $CnEF
}
if((address & 0xFF) == 0xEF) {
apple_memory[address] = value;
cfbuf[cfptr] = value;
cfptr = (cfptr + 1) & 0x0FFF;
apple_memory[address-1] = cfbuf[cfptr]; // $CnEE
apple_memory[address] = cfbuf[cfptr]; // $CnEF
}
if((address & 0xFF) >= 0xF0) {
apple_memory[address] = value;
}
}
if((address & 0xFF) == 0xEF) {
cfptr = (cfptr + 1) & 0x1FFF;
apple_memory[address] = cfbuf[cfptr];
} else if((address & 0xFF) == 0xEE) {
cfptr = (cfptr + 1) & 0x0FFF;
apple_memory[address] = cfbuf[cfptr]; // $CnEE
apple_memory[address+1] = cfbuf[cfptr]; // $CnEF
apple_memory[address-1] = (cfptr >> 8) & 0xff;
apple_memory[address-2] = cfptr & 0xff;
}
// Stop further processing by businterface
continue;
}
#ifdef FUNCTION_VGA
} else if(current_machine == MACHINE_AUTO) {
if((apple_memory[0x0417] == 0xE7) && (apple_memory[0x416] == 0xC9)) { // Apple IIgs
if((apple_memory[0x0403] == 0xD8) && (apple_memory[0x404] == 0xE5)) { // ROMXe
current_machine = MACHINE_IIE;
internal_flags |= IFLAGS_IIE_REGS;
internal_flags &= ~IFLAGS_IIGS_REGS;
} else if((apple_memory[0x0412] == 0xC5) && (apple_memory[0x0413] == 0xD8)) { // ROMX
current_machine = MACHINE_II;
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
} else if((apple_memory[0x0417] == 0xE7) && (apple_memory[0x416] == 0xC9)) { // Apple IIgs
current_machine = MACHINE_IIGS;
internal_flags &= ~IFLAGS_IIE_REGS;
internal_flags |= IFLAGS_IIGS_REGS;

View File

@ -157,7 +157,7 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
}
} else if(romx_unlocked == 3) {
if(romx_type == 0xFA) {
if((address >> 4) == 0xF81) {
if((address & 0xFFF0) == 0xF810) {
romx_textbank = address & 0xF;
}
if(address == 0xF851) {
@ -165,10 +165,10 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
romx_unlocked = 0;
}
} else if(romx_type == 0xCA) {
if((address >> 4) == 0xCFD) {
if((address & 0xFFF0) == 0xCFD0) {
romx_textbank = address & 0xF;
}
if((address >> 4) == 0xCFE) {
if((address & 0xFFF0) == 0xCFE0) {
romx_changed = 1;
romx_unlocked = 0;
}
@ -237,8 +237,8 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
terminal_memory[terminal_row*80+terminal_col] = value;
break;
case 0x0B:
if(value <= 0x27) {
romx_textbank = value;
if((value & 0xFF) <= 0x27) {
romx_textbank = (value & 0xFF);
romx_changed = 1;
}
break;

View File

@ -27,10 +27,10 @@ uint16_t DELAYED_COPY_DATA(mono_colors)[14] = {
// Initialize the character generator ROM
static void DELAYED_COPY_CODE(switch_font)() {
if(userfont) {
return;
} else if(romx_changed) {
if(romx_changed) {
memcpy32(character_rom, (void*)FLASH_FONT(romx_textbank), 4096);
} else if(userfont) {
return;
} else if(current_machine != machinefont) {
switch(current_machine) {
default:

View File

@ -37,7 +37,9 @@ void DELAYED_COPY_CODE(render_terminal_line)(unsigned int line) {
uint sl_pos = 0;
// Pad 40 pixels on the left to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word
for(uint col=0; col < 80; ) {
// Grab 14 pixels from the next two characters
@ -62,7 +64,9 @@ void DELAYED_COPY_CODE(render_terminal_line)(unsigned int line) {
}
// Pad 40 pixels on the right to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word
sl->length = sl_pos;
sl->repeat_count = 1;

View File

@ -46,9 +46,16 @@ static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) {
const uint8_t *line_bufb = (const uint8_t *)((p2 ? text_p4 : text_p3) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
// Pad 40 pixels on the left to center horizontally
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl_pos++;
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
for(i = 0; i < 40; i++) {
@ -88,9 +95,16 @@ static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) {
}
// Pad 40 pixels on the right to center horizontally
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl_pos++;
sl1->length = sl_pos;
sl1->repeat_count = 7;

View File

@ -55,7 +55,9 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line) {
const uint8_t *line_memb = (const uint8_t *)((p2 ? hgr_p4 : hgr_p3) + dhgr_line_to_mem_offset(line));
// Pad 40 pixels on the left to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word
// DHGR is weird. Nuff said.
uint32_t dots = 0;
@ -123,7 +125,9 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line) {
}
// Pad 40 pixels on the right to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word
sl->length = sl_pos;
sl->repeat_count = 1;

View File

@ -45,7 +45,9 @@ static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) {
const uint8_t *line_mem = (const uint8_t *)((p2 ? hgr_p2 : hgr_p1) + hires_line_to_mem_offset(line));
// Pad 40 pixels on the left to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word
// Each hires byte contains 7 pixels which may be shifted right 1/2 a pixel. That is
// represented here by 14 'dots' to precisely describe the half-pixel positioning.
@ -105,7 +107,9 @@ static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) {
}
// Pad 40 pixels on the right to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word
sl->length = sl_pos;
sl->repeat_count = 1;

View File

@ -69,8 +69,14 @@ static void DELAYED_COPY_CODE(render_lores_line)(bool p2, uint line) {
const uint8_t *line_buf = (const uint8_t *)((p2 ? text_p2 : text_p1) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
// Pad 40 pixels on the left to center horizontally
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl_pos++;
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
@ -109,8 +115,14 @@ static void DELAYED_COPY_CODE(render_lores_line)(bool p2, uint line) {
}
// Pad 40 pixels on the right to center horizontally
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl_pos++;
sl1->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl2->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl_pos++;
sl1->length = sl_pos;

View File

@ -66,7 +66,9 @@ void DELAYED_COPY_CODE(render_text40_line)(bool p2, unsigned int line) {
uint sl_pos = 0;
// Pad 40 pixels on the left to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
for(uint col=0; col < 40; ) {
// Grab 14 pixels from the next two characters
@ -91,7 +93,9 @@ void DELAYED_COPY_CODE(render_text40_line)(bool p2, unsigned int line) {
}
// Pad 40 pixels on the right to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl->length = sl_pos;
sl->repeat_count = 1;
@ -110,7 +114,9 @@ void DELAYED_COPY_CODE(render_text80_line)(bool p2, unsigned int line) {
uint sl_pos = 0;
// Pad 40 pixels on the left to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
for(uint col=0; col < 40; ) {
// Grab 14 pixels from the next two characters
@ -134,7 +140,9 @@ void DELAYED_COPY_CODE(render_text80_line)(bool p2, unsigned int line) {
}
// Pad 40 pixels on the right to center horizontally
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word
sl->length = sl_pos;
sl->repeat_count = 1;

View File

@ -9,39 +9,88 @@
volatile uint8_t *pcpi_reg = apple_memory + 0xC0C0;
static inline void __time_critical_func(pcpi_read)(uint32_t address) {
switch(address & 0x7) {
case 0: // Read Data from Z80
switch(address & 0xF) {
case 0x0: // Read Data from Z80
clr_6502_stat;
break;
case 5: // Z80 Reset
case 0x5: // Z80 Reset
z80_res = 1;
break;
case 6: // Z80 INT
case 0x6: // Z80 INT
//z80_irq = 1;
break;
case 7: // Z80 NMI
case 0x7: // Z80 NMI
z80_nmi = 1;
break;
case 0x8: // 6551 A Data Register
pcpi_reg[0x08] = auart_read(0);
pcpi_reg[0x09] = auart_status(0);
break;
case 0x9: // 6551 A Status Register
pcpi_reg[0x08] = zuart_peek(0);
pcpi_reg[0x09] = auart_status(0);
break;
case 0xA: // 6551 A Command Register
break;
case 0xB: // 6551 A Control Register
break;
case 0xC: // 6551 B Data Register
pcpi_reg[0x0C] = auart_read(1);
pcpi_reg[0x0D] = auart_status(1);
break;
case 0xD: // 6551 B Status Register
pcpi_reg[0x0C] = zuart_peek(1);
pcpi_reg[0x0D] = auart_status(1);
break;
case 0xE: // 6551 B Command Register
break;
case 0xF: // 6551 B Control Register
break;
}
}
static inline void __time_critical_func(pcpi_write)(uint32_t address, uint32_t value) {
switch(address & 0x7) {
case 0:
case 2:
case 3:
case 4:
break;
case 1: // Write Data to Z80
switch(address & 0xF) {
case 0x1: // Write Data to Z80
pcpi_reg[1] = value & 0xff;
set_z80_stat;
break;
case 5:
case 6:
case 7:
case 0x5: // Z80 Reset
case 0x6: // Z80 INT
case 0x7: // Z80 NMI
pcpi_read(address);
break;
case 0x8: // 6551 A Data Register
zuart_write(0, value);
pcpi_reg[0x08] = zuart_peek(0);
pcpi_reg[0x09] = auart_status(0);
break;
case 0x9: // 6551 A Reset Register
pcpi_reg[0x08] = zuart_peek(0);
pcpi_reg[0x09] = auart_status(0);
break;
case 0xA: // 6551 A Command Register
pcpi_reg[0x0A] = auart_command(0, value);
break;
case 0xB: // 6551 A Control Register
pcpi_reg[0x0B] = auart_control(0, value);
break;
case 0xC: // 6551 B Data Register
zuart_write(1, value);
pcpi_reg[0x0C] = zuart_peek(1);
pcpi_reg[0x0D] = auart_status(1);
break;
case 0xD: // 6551 B Reset Register
pcpi_reg[0x0C] = zuart_peek(1);
pcpi_reg[0x0D] = auart_status(1);
break;
case 0xE: // 6551 B Command Register
pcpi_reg[0x0E] = auart_command(1, value);
break;
case 0xF: // 6551 B Control Register
pcpi_reg[0x0F] = auart_control(1, value);
break;
}
}

View File

@ -38,3 +38,10 @@ typedef struct sio_s {
extern volatile sio_t sio[2];
extern volatile uint8_t sio_vector;
extern uint8_t auart_read(bool port);
extern uint8_t zuart_peek(bool port);
extern uint8_t auart_status(bool port);
extern uint8_t auart_command(bool port, uint8_t value);
extern uint8_t auart_control(bool port, uint8_t value);
extern uint8_t zuart_write(bool port, uint8_t value);

View File

@ -27,6 +27,183 @@ volatile uint8_t sio_vector;
#define Z80break (z80_res || (config_cmdbuf[7] == 0) || (!z80_cycle++))
uint8_t DELAYED_COPY_CODE(zuart_read)(bool port) {
uint8_t rv = 0;
if(sio[port].datavalid) {
rv = sio[port].data;
sio[port].datavalid = 0;
}
switch(serialmux[port]) {
case SERIAL_LOOP:
break;
case SERIAL_USB:
if(tud_cdc_n_available(port)) {
sio[port].data = tud_cdc_n_read_char(port);
sio[port].datavalid = 1;
}
break;
case SERIAL_UART:
if(port) {
if(uart_is_readable(uart1)) {
sio[port].data = uart_getc(uart1);
sio[port].datavalid = 1;
}
} else {
if(uart_is_readable(uart0)) {
sio[port].data = uart_getc(uart0);
sio[port].datavalid = 1;
}
}
break;
}
return rv;
}
uint8_t DELAYED_COPY_CODE(zuart_peek)(bool port) {
uint8_t rv = 0;
if(sio[port].datavalid) {
rv = sio[port].data;
}
return rv;
}
uint8_t DELAYED_COPY_CODE(auart_read)(bool port) {
zuart_read(port);
return zuart_peek(port);
}
uint8_t DELAYED_COPY_CODE(auart_status)(bool port) {
uint8_t rv;
if(!sio[port].datavalid) {
zuart_read(port);
}
rv = sio[port].datavalid ? 0x08 : 0x00;
switch(serialmux[port]) {
case SERIAL_LOOP:
rv |= ((sio[port].control[5] & 0x02) ? 0x40 : 0x00) |
((sio[port].control[5] & 0x80) ? 0x20 : 0x00) |
(sio[port].datavalid ? 0x00 : 0x10);
break;
case SERIAL_USB:
rv |= ((tud_cdc_n_get_line_state(port) & 2) ? 0x00 : 0x40) |
(tud_cdc_n_connected(port) ? 0x00 : 0x20) |
(tud_cdc_n_write_available(port) ? 0x10 : 0x00);
break;
case SERIAL_UART:
if(port) {
rv |= (uart_is_writable(uart1) ? 0x10 : 0x00);
} else {
rv |= (uart_is_writable(uart0) ? 0x10 : 0x00);
}
break;
}
return rv;
}
uint8_t DELAYED_COPY_CODE(auart_control)(bool port, uint8_t value) {
return value;
}
uint8_t DELAYED_COPY_CODE(auart_command)(bool port, uint8_t value) {
if(value & 0x1) {
sio[port].control[5] |= 0x80;
} else {
sio[port].control[5] &= ~0x80;
}
if(value & 0xC) {
sio[port].control[5] |= 0x02;
} else {
sio[port].control[5] &= ~0x02;
}
return value;
}
uint8_t DELAYED_COPY_CODE(zuart_write)(bool port, uint8_t value) {
switch(serialmux[port]) {
case SERIAL_LOOP:
if(sio[port].datavalid) {
sio[port].status[1] |= 0x20;
}
sio[port].datavalid = 1;
sio[port].data = value;
break;
case SERIAL_UART:
if(tud_cdc_n_write_available(port)) {
tud_cdc_n_write_char(port, value);
}
break;
case SERIAL_USB:
if(port) {
if(uart_is_writable(uart1)) {
uart_putc(uart1, value);
}
} else {
if(uart_is_writable(uart0)) {
uart_putc(uart0, value);
}
}
break;
}
return value;
}
uint8_t DELAYED_COPY_CODE(zuart_status)(bool port) {
uint8_t rv = 0;
switch(sio[port].control[0] & 0x7) {
case 0:
if(!sio[port].datavalid) {
zuart_read(port);
}
rv = sio[port].datavalid ? 0x01 : 0x00;
switch(serialmux[port]) {
case SERIAL_LOOP:
rv |= ((sio[port].control[5] & 0x02) ? 0x20 : 0x00) |
((sio[port].control[5] & 0x80) ? 0x08 : 0x00) |
(sio[port].datavalid ? 0x00 : 0x04);
break;
case SERIAL_USB:
rv |= ((tud_cdc_n_get_line_state(port) & 2) ? 0x20 : 0x00) |
(tud_cdc_n_connected(port) ? 0x08 : 0x00) |
(tud_cdc_n_write_available(port) ? 0x04 : 0x00);
break;
case SERIAL_UART:
if(port) {
rv |= 0x20 |
(uart_is_writable(uart1) ? 0x00 : 0x04);
} else {
rv |= 0x20 |
(uart_is_writable(uart0) ? 0x00 : 0x04);
}
break;
}
break;
case 1:
rv = sio[(port)].status[1];
break;
case 2:
if(port)
rv = sio_vector;
break;
}
sio[(port)].control[0] &= 0xF8;
return rv;
}
uint8_t DELAYED_COPY_CODE(cpu_in)(uint16_t address) {
uint8_t rv = 0;
if(address & 0x80) {
@ -42,69 +219,11 @@ uint8_t DELAYED_COPY_CODE(cpu_in)(uint16_t address) {
break;
case 0xFC:
case 0xFE:
switch(serialmux[(address & 0x01)]) {
case SERIAL_LOOP:
if(sio[(address & 0x01)].datavalid) {
sio[(address & 0x01)].datavalid = 0;
rv = sio[(address & 0x01)].data;
}
break;
case SERIAL_USB:
if(tud_cdc_n_available((address & 0x01))) {
rv = tud_cdc_n_read_char((address & 0x01));
}
break;
case SERIAL_UART:
if(address & 0x01) {
if(uart_is_readable(uart1)) {
rv = uart_getc(uart1);
}
} else {
if(uart_is_readable(uart0)) {
rv = uart_getc(uart0);
}
}
break;
}
rv = zuart_read(address & 0x02);
break;
case 0xFD:
case 0xFF:
switch(sio[(address & 0x01)].control[0] & 0x7) {
case 0:
switch(serialmux[(address & 0x01)]) {
case SERIAL_LOOP:
rv = ((sio[(address & 0x01)].control[5] & 0x02) ? 0x20 : 0x00) |
((sio[(address & 0x01)].control[5] & 0x80) ? 0x08 : 0x00) |
(sio[(address & 0x01)].datavalid ? 0x01 : 0x04);
break;
case SERIAL_USB:
rv = ((tud_cdc_n_get_line_state(address & 0x01) & 2) ? 0x20 : 0x00) |
(tud_cdc_n_connected(address & 0x01) ? 0x08 : 0x00) |
(tud_cdc_n_write_available(address & 0x01) ? 0x04 : 0x00) |
(tud_cdc_n_available(address & 0x01) ? 0x01 : 0x00);
break;
case SERIAL_UART:
if(address & 0x01) {
rv = 0x20 |
(uart_is_writable(uart1) ? 0x00 : 0x04) |
(uart_is_readable(uart1) ? 0x01 : 0x00);
} else {
rv = 0x20 |
(uart_is_writable(uart0) ? 0x00 : 0x04) |
(uart_is_readable(uart0) ? 0x01 : 0x00);
}
break;
}
break;
case 1:
rv = sio[(address & 0x01)].status[1];
break;
case 2:
if(address & 0x01)
rv = sio_vector;
break;
}
sio[(address & 0x01)].control[0] &= 0xF8;
rv = zuart_status(address & 0x02);
break;
}
} else {
@ -161,24 +280,7 @@ void DELAYED_COPY_CODE(cpu_out)(uint16_t address, uint8_t value) {
break;
case 0xFC:
case 0xFE:
switch(serialmux[(address & 0x01)]) {
case SERIAL_LOOP:
if(sio[(address & 0x01)].datavalid) {
sio[(address & 0x01)].status[1] |= 0x20;
}
sio[(address & 0x01)].datavalid = 1;
sio[(address & 0x01)].data = value;
break;
case SERIAL_UART:
if(tud_cdc_n_write_available(address & 0x01))
tud_cdc_n_write_char(address & 0x01, value);
break;
case SERIAL_USB:
if(uart_is_writable(uart0)) {
uart_putc(uart0, value);
}
break;
}
zuart_write((address & 0x02), value);
break;
case 0xFD:
case 0xFF: