mirror of
https://github.com/V2RetroComputing/analog-firmware.git
synced 2024-06-15 09:29:34 +00:00
Build for 20230414 - Fixed config interface
This commit is contained in:
parent
9b41d7a15f
commit
7707330977
1
build.sh
1
build.sh
|
@ -10,6 +10,7 @@ build_firmware() {
|
||||||
( mkdir -p build/$1 && cd build/$1 && cmake ../.. )
|
( mkdir -p build/$1 && cd build/$1 && cmake ../.. )
|
||||||
fi
|
fi
|
||||||
make -C build/$1
|
make -C build/$1
|
||||||
|
#tools/mksparse build/$1/$1.bin build/$1/$1.ota
|
||||||
}
|
}
|
||||||
|
|
||||||
build_firmware v2-analog-lc-4ns-z80
|
build_firmware v2-analog-lc-4ns-z80
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#define NEWCONFIG_MAGIC 0x0001434E // "NC\x01\x00"
|
#define NEWCONFIG_MAGIC 0x0001434E // "NC\x01\x00"
|
||||||
#define NEWCONFIG_EOF_MARKER 0x00464F45 // "EOF\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_VGA 0x0000564D // "MV\x00\x00" VGA
|
||||||
#define CFGTOKEN_MODE_PCPI 0x00005A4D // "MZ\x00\x00" PCPI Applicard
|
#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_HOST 0x0000484A // "JH\x00\x01" JetDirect Hostname
|
||||||
#define CFGTOKEN_JD_PORT 0x0200444A // "JD\x00\x01" JetDirect Port
|
#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_00 0x00005056 // "VP\x00\x00" Full Color Video
|
||||||
#define CFGTOKEN_MONO_80 0x00805056 // "VP\x80\x00" B&W Video
|
#define CFGTOKEN_MONO_80 0x00805056 // "VP\x80\x00" B&W Video
|
||||||
#define CFGTOKEN_MONO_90 0x00905056 // "VP\x90\x00" B&W Inverse
|
#define CFGTOKEN_MONO_90 0x00905056 // "VP\x90\x00" B&W Inverse
|
||||||
|
|
165
common/config.c
165
common/config.c
|
@ -6,6 +6,8 @@
|
||||||
#ifdef FUNCTION_VGA
|
#ifdef FUNCTION_VGA
|
||||||
#include "vga/render.h"
|
#include "vga/render.h"
|
||||||
#include "vga/vgaout.h"
|
#include "vga/vgaout.h"
|
||||||
|
extern volatile uint8_t romx_textbank;
|
||||||
|
extern volatile uint8_t romx_changed;
|
||||||
#endif
|
#endif
|
||||||
#ifdef FUNCTION_Z80
|
#ifdef FUNCTION_Z80
|
||||||
#include "z80/z80buf.h"
|
#include "z80/z80buf.h"
|
||||||
|
@ -83,6 +85,10 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||||
cfg_machine = MACHINE_BASIS;
|
cfg_machine = MACHINE_BASIS;
|
||||||
break;
|
break;
|
||||||
#ifdef FUNCTION_VGA
|
#ifdef FUNCTION_VGA
|
||||||
|
case CFGTOKEN_FONT_00:
|
||||||
|
romx_textbank = (config[i] >> 16) & 0x2F;
|
||||||
|
romx_changed = 1;
|
||||||
|
break;
|
||||||
case CFGTOKEN_MONO_00:
|
case CFGTOKEN_MONO_00:
|
||||||
mono_palette = (config[i] >> 16) & 0xF;
|
mono_palette = (config[i] >> 16) & 0xF;
|
||||||
break;
|
break;
|
||||||
|
@ -128,11 +134,11 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||||
break;
|
break;
|
||||||
case CFGTOKEN_WIFI_SSID:
|
case CFGTOKEN_WIFI_SSID:
|
||||||
memset((char*)wifi_ssid, 0, sizeof(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;
|
break;
|
||||||
case CFGTOKEN_WIFI_PSK:
|
case CFGTOKEN_WIFI_PSK:
|
||||||
memset((char*)wifi_psk, 0, sizeof(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;
|
break;
|
||||||
case CFGTOKEN_WIFI_IP:
|
case CFGTOKEN_WIFI_IP:
|
||||||
wifi_address = config[i+1];
|
wifi_address = config[i+1];
|
||||||
|
@ -142,7 +148,7 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||||
break;
|
break;
|
||||||
case CFGTOKEN_JD_HOST:
|
case CFGTOKEN_JD_HOST:
|
||||||
memset((uint8_t*)jd_host, 0, sizeof(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;
|
break;
|
||||||
case CFGTOKEN_JD_PORT:
|
case CFGTOKEN_JD_PORT:
|
||||||
jd_port = config[i+1];
|
jd_port = config[i+1];
|
||||||
|
@ -169,13 +175,13 @@ void DELAYED_COPY_CODE(default_config)() {
|
||||||
cfg_machine = MACHINE_AUTO;
|
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;
|
int i = 0;
|
||||||
|
|
||||||
memset(config_temp, 0, sizeof(config_temp));
|
memset(config_temp, 0, sizeof(config_temp));
|
||||||
|
|
||||||
config_temp[i++] = NEWCONFIG_MAGIC;
|
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) {
|
switch(cfg_machine) {
|
||||||
default:
|
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);
|
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);
|
i += 1 + (((config_temp[i] >> 24) + 3) >> 2);
|
||||||
|
|
||||||
config_temp[i] = CFGTOKEN_WIFI_PSK | (((uint32_t)strlen((char*)wifi_psk)+1) << 24);
|
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);
|
i += 1 + (((config_temp[i] >> 24) + 3) >> 2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FUNCTION_VGA
|
#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_MONO_00 | ((mono_palette & 0xF) << 20);
|
||||||
config_temp[i++] = CFGTOKEN_TBCOLOR | ((terminal_tbcolor & 0xFF) << 16);
|
config_temp[i++] = CFGTOKEN_TBCOLOR | ((terminal_tbcolor & 0xFF) << 16);
|
||||||
config_temp[i++] = CFGTOKEN_BORDER | ((terminal_border & 0xF) << 16);
|
config_temp[i++] = CFGTOKEN_BORDER | ((terminal_border & 0xF) << 16);
|
||||||
|
|
||||||
// TODO: Font
|
|
||||||
//config_temp[i++] = CFGTOKEN_FONTSLOT | ((terminal_font & 0x1F) << 16);
|
|
||||||
#endif
|
#endif
|
||||||
config_temp[i++] = NEWCONFIG_EOF_MARKER;
|
config_temp[i++] = NEWCONFIG_EOF_MARKER;
|
||||||
|
|
||||||
|
@ -323,6 +327,7 @@ bool DELAYED_COPY_CODE(is_primary_config_newer)() {
|
||||||
return (a == ((b+1) & 0xff));
|
return (a == ((b+1) & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DELAYED_COPY_CODE(read_config)() {
|
bool DELAYED_COPY_CODE(read_config)() {
|
||||||
if(is_config_valid(FLASH_CONFIG_ONETIME)) {
|
if(is_config_valid(FLASH_CONFIG_ONETIME)) {
|
||||||
internal_flags &= ~IFLAGS_TEST;
|
internal_flags &= ~IFLAGS_TEST;
|
||||||
|
@ -390,38 +395,33 @@ bool DELAYED_COPY_CODE(write_config)(bool onetime) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FUNCTION_VGA
|
uint8_t DELAYED_COPY_CODE(get_config_block)() {
|
||||||
uint8_t DELAYED_COPY_CODE(test_font)(uint16_t param0) {
|
uint16_t last_config_block;
|
||||||
int i;
|
uint16_t next_config_block;
|
||||||
|
|
||||||
for(i = 0; i < 4096; i++) {
|
last_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
|
||||||
character_rom[i] = apple_memory[param0+i];
|
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;
|
config_rpybuf[5] = (next_config_block >> 8) & 0xFF;
|
||||||
|
config_rpybuf[4] = (next_config_block >> 0) & 0xFF;
|
||||||
// Disable video output to stop DMA and IRQs
|
config_rpybuf[3] = (last_config_block >> 8) & 0xFF;
|
||||||
vga_dpms_sleep();
|
config_rpybuf[2] = (last_config_block >> 0) & 0xFF;
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
return REPLY_OK;
|
return REPLY_OK;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t DELAYED_COPY_CODE(cf_readblock)(uint16_t param0) {
|
uint8_t DELAYED_COPY_CODE(cf_readblock)(uint16_t param0) {
|
||||||
if(param0 >= (FLASH_SIZE/4096)) return REPLY_EPARAM;
|
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();
|
vga_dpms_sleep();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
flash_range_program(param0 * 4096, (void*)cfbuf, 4096);
|
flash_range_program(((uint32_t)param0) * 4096, (void*)cfbuf, 4096);
|
||||||
|
|
||||||
#ifdef FUNCTION_VGA
|
#ifdef FUNCTION_VGA
|
||||||
// Enable video output now that we are done
|
// 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();
|
vga_dpms_sleep();
|
||||||
#endif
|
#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
|
#ifdef FUNCTION_VGA
|
||||||
// Enable video output now that we are done
|
// Enable video output now that we are done
|
||||||
|
@ -516,22 +575,37 @@ void DELAYED_COPY_CODE(config_handler)() {
|
||||||
config_rpybuf[0] = REPLY_BUSY;
|
config_rpybuf[0] = REPLY_BUSY;
|
||||||
|
|
||||||
switch(config_cmdbuf[0]) {
|
switch(config_cmdbuf[0]) {
|
||||||
#ifdef FUNCTION_VGA
|
|
||||||
case 'C':
|
case 'C':
|
||||||
switch(config_cmdbuf[1]) {
|
switch(config_cmdbuf[1]) {
|
||||||
default:
|
default:
|
||||||
retval = REPLY_ECMD;
|
retval = REPLY_ECMD;
|
||||||
break;
|
break;
|
||||||
|
#ifdef FUNCTION_VGA
|
||||||
case 'T':
|
case 'T':
|
||||||
// One-time load of font data (lost at reboot)
|
// One-time load of font data (lost at reboot)
|
||||||
retval = test_font(param0);
|
retval = test_font();
|
||||||
case 'I':
|
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
|
// 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;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case 'H':
|
case 'H':
|
||||||
retval = REPLY_OK;
|
retval = REPLY_OK;
|
||||||
switch(config_cmdbuf[1]) {
|
switch(config_cmdbuf[1]) {
|
||||||
|
@ -579,6 +653,11 @@ void DELAYED_COPY_CODE(config_handler)() {
|
||||||
default:
|
default:
|
||||||
retval = REPLY_ECMD;
|
retval = REPLY_ECMD;
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
// Current Config Block
|
||||||
|
retval = get_config_block();
|
||||||
|
cfptr = 0;
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
// Read block
|
// Read block
|
||||||
retval = cf_readblock(param0);
|
retval = cf_readblock(param0);
|
||||||
|
|
|
@ -101,7 +101,7 @@ extern volatile compat_t current_machine;
|
||||||
|
|
||||||
|
|
||||||
void default_config();
|
void default_config();
|
||||||
int make_config(uint8_t rev);
|
int make_config(uint32_t rev);
|
||||||
bool read_config();
|
bool read_config();
|
||||||
bool write_config(bool onetime);
|
bool write_config(bool onetime);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
#include <hardware/resets.h>
|
#include <hardware/resets.h>
|
||||||
#include <hardware/dma.h>
|
#include <hardware/dma.h>
|
||||||
#include <hardware/flash.h>
|
#include <hardware/flash.h>
|
||||||
#include "config.h"
|
#include "common/config.h"
|
||||||
#include "flash.h"
|
#include "common/buffers.h"
|
||||||
|
#include "common/flash.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef RASPBERRYPI_PICO_W
|
#ifdef RASPBERRYPI_PICO_W
|
||||||
#include <pico/cyw43_arch.h>
|
#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();
|
uint32_t sniffed_crc = dma_sniffer_get_data_accumulator();
|
||||||
if (0ul == sniffed_crc) {
|
if (0ul == sniffed_crc) {
|
||||||
uint8_t *ptr = (const uint8_t *)FLASH_OTA_AREA
|
uint8_t *ptr = (uint8_t *)FLASH_OTA_AREA;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
flash_range_erase(0, FLASH_OTA_SIZE);
|
flash_range_erase(0, FLASH_OTA_SIZE);
|
||||||
|
|
||||||
// Copy from OTA area to Boot
|
// Copy from OTA area to Boot
|
||||||
for(offset = 0; offset < FLASH_OTA_SIZE; offset+=65536);
|
for(offset = 0; offset < FLASH_OTA_SIZE; offset+=65536) {
|
||||||
memcpy(private_memory, ptr+offset, 65536);
|
memcpy((uint8_t *)private_memory, ptr+offset, 65536);
|
||||||
flash_range_program(offset, private_memory, 65536);
|
flash_range_program(offset, (const uint8_t *)private_memory, 65536);
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_range_erase((uint32_t)(FLASH_OTA_AREA-XIP_BASE), FLASH_OTA_SIZE);
|
flash_range_erase((uint32_t)(FLASH_OTA_AREA-XIP_BASE), FLASH_OTA_SIZE);
|
||||||
|
|
|
@ -43,37 +43,45 @@ static void __noinline __time_critical_func(core1_loop)() {
|
||||||
|
|
||||||
// Config memory in card slot-rom address space
|
// Config memory in card slot-rom address space
|
||||||
if(ACCESS_WRITE) {
|
if(ACCESS_WRITE) {
|
||||||
if((address & 0xFF) == 0xED) {
|
if((address & 0xFF) == 0xEC) {
|
||||||
apple_memory[address] = value;
|
apple_memory[address] = value;
|
||||||
cfptr = (cfptr & 0x1F00) | value;
|
cfptr = (cfptr & 0x0F00) | value;
|
||||||
apple_memory[address] = cfbuf[cfptr];
|
apple_memory[address+2] = cfbuf[cfptr]; // $CnEE
|
||||||
|
apple_memory[address+3] = cfbuf[cfptr]; // $CnEF
|
||||||
}
|
}
|
||||||
if((address & 0xFF) == 0xEE) {
|
if((address & 0xFF) == 0xED) {
|
||||||
apple_memory[address] = value & 0x1F;
|
apple_memory[address] = value & 0x0F;
|
||||||
cfptr = ((cfptr & 0xFF) | (value << 8)) & 0x1FFF;
|
cfptr = ((cfptr & 0xFF) | (((uint16_t)value) << 8)) & 0xFFF;
|
||||||
apple_memory[address] = cfbuf[cfptr];
|
apple_memory[address+1] = cfbuf[cfptr]; // $CnEE
|
||||||
|
apple_memory[address+2] = cfbuf[cfptr]; // $CnEF
|
||||||
}
|
}
|
||||||
if((address & 0xFF) == 0xEF) {
|
if((address & 0xFF) == 0xEF) {
|
||||||
apple_memory[address] = value;
|
|
||||||
cfbuf[cfptr] = 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) {
|
if((address & 0xFF) >= 0xF0) {
|
||||||
apple_memory[address] = value;
|
apple_memory[address] = value;
|
||||||
}
|
}
|
||||||
}
|
} else if((address & 0xFF) == 0xEE) {
|
||||||
if((address & 0xFF) == 0xEF) {
|
cfptr = (cfptr + 1) & 0x0FFF;
|
||||||
cfptr = (cfptr + 1) & 0x1FFF;
|
apple_memory[address] = cfbuf[cfptr]; // $CnEE
|
||||||
apple_memory[address] = cfbuf[cfptr];
|
apple_memory[address+1] = cfbuf[cfptr]; // $CnEF
|
||||||
apple_memory[address-1] = (cfptr >> 8) & 0xff;
|
apple_memory[address-1] = (cfptr >> 8) & 0xff;
|
||||||
apple_memory[address-2] = cfptr & 0xff;
|
apple_memory[address-2] = cfptr & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop further processing by businterface
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
#ifdef FUNCTION_VGA
|
#ifdef FUNCTION_VGA
|
||||||
} else if(current_machine == MACHINE_AUTO) {
|
} 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;
|
current_machine = MACHINE_IIGS;
|
||||||
internal_flags &= ~IFLAGS_IIE_REGS;
|
internal_flags &= ~IFLAGS_IIE_REGS;
|
||||||
internal_flags |= IFLAGS_IIGS_REGS;
|
internal_flags |= IFLAGS_IIGS_REGS;
|
||||||
|
|
|
@ -157,7 +157,7 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
||||||
}
|
}
|
||||||
} else if(romx_unlocked == 3) {
|
} else if(romx_unlocked == 3) {
|
||||||
if(romx_type == 0xFA) {
|
if(romx_type == 0xFA) {
|
||||||
if((address >> 4) == 0xF81) {
|
if((address & 0xFFF0) == 0xF810) {
|
||||||
romx_textbank = address & 0xF;
|
romx_textbank = address & 0xF;
|
||||||
}
|
}
|
||||||
if(address == 0xF851) {
|
if(address == 0xF851) {
|
||||||
|
@ -165,10 +165,10 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
||||||
romx_unlocked = 0;
|
romx_unlocked = 0;
|
||||||
}
|
}
|
||||||
} else if(romx_type == 0xCA) {
|
} else if(romx_type == 0xCA) {
|
||||||
if((address >> 4) == 0xCFD) {
|
if((address & 0xFFF0) == 0xCFD0) {
|
||||||
romx_textbank = address & 0xF;
|
romx_textbank = address & 0xF;
|
||||||
}
|
}
|
||||||
if((address >> 4) == 0xCFE) {
|
if((address & 0xFFF0) == 0xCFE0) {
|
||||||
romx_changed = 1;
|
romx_changed = 1;
|
||||||
romx_unlocked = 0;
|
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;
|
terminal_memory[terminal_row*80+terminal_col] = value;
|
||||||
break;
|
break;
|
||||||
case 0x0B:
|
case 0x0B:
|
||||||
if(value <= 0x27) {
|
if((value & 0xFF) <= 0x27) {
|
||||||
romx_textbank = value;
|
romx_textbank = (value & 0xFF);
|
||||||
romx_changed = 1;
|
romx_changed = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -27,10 +27,10 @@ uint16_t DELAYED_COPY_DATA(mono_colors)[14] = {
|
||||||
|
|
||||||
// Initialize the character generator ROM
|
// Initialize the character generator ROM
|
||||||
static void DELAYED_COPY_CODE(switch_font)() {
|
static void DELAYED_COPY_CODE(switch_font)() {
|
||||||
if(userfont) {
|
if(romx_changed) {
|
||||||
return;
|
|
||||||
} else if(romx_changed) {
|
|
||||||
memcpy32(character_rom, (void*)FLASH_FONT(romx_textbank), 4096);
|
memcpy32(character_rom, (void*)FLASH_FONT(romx_textbank), 4096);
|
||||||
|
} else if(userfont) {
|
||||||
|
return;
|
||||||
} else if(current_machine != machinefont) {
|
} else if(current_machine != machinefont) {
|
||||||
switch(current_machine) {
|
switch(current_machine) {
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -37,7 +37,9 @@ void DELAYED_COPY_CODE(render_terminal_line)(unsigned int line) {
|
||||||
uint sl_pos = 0;
|
uint sl_pos = 0;
|
||||||
|
|
||||||
// Pad 40 pixels on the left to center horizontally
|
// 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; ) {
|
for(uint col=0; col < 80; ) {
|
||||||
// Grab 14 pixels from the next two characters
|
// 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
|
// 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->length = sl_pos;
|
||||||
sl->repeat_count = 1;
|
sl->repeat_count = 1;
|
||||||
|
|
|
@ -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));
|
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
|
// 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
|
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_31) | ((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++;
|
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)) {
|
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
|
||||||
for(i = 0; i < 40; i++) {
|
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
|
// 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
|
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_31) | ((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++;
|
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->length = sl_pos;
|
||||||
sl1->repeat_count = 7;
|
sl1->repeat_count = 7;
|
||||||
|
|
|
@ -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));
|
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
|
// 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.
|
// DHGR is weird. Nuff said.
|
||||||
uint32_t dots = 0;
|
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
|
// 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->length = sl_pos;
|
||||||
sl->repeat_count = 1;
|
sl->repeat_count = 1;
|
||||||
|
|
|
@ -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));
|
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
|
// 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
|
// 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.
|
// 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
|
// 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->length = sl_pos;
|
||||||
sl->repeat_count = 1;
|
sl->repeat_count = 1;
|
||||||
|
|
|
@ -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));
|
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
|
// 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
|
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_31) | ((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++;
|
sl_pos++;
|
||||||
|
|
||||||
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
|
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
|
// 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
|
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_31) | ((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++;
|
sl_pos++;
|
||||||
|
|
||||||
sl1->length = sl_pos;
|
sl1->length = sl_pos;
|
||||||
|
|
|
@ -66,7 +66,9 @@ void DELAYED_COPY_CODE(render_text40_line)(bool p2, unsigned int line) {
|
||||||
uint sl_pos = 0;
|
uint sl_pos = 0;
|
||||||
|
|
||||||
// Pad 40 pixels on the left to center horizontally
|
// 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; ) {
|
for(uint col=0; col < 40; ) {
|
||||||
// Grab 14 pixels from the next two characters
|
// 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
|
// 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->length = sl_pos;
|
||||||
sl->repeat_count = 1;
|
sl->repeat_count = 1;
|
||||||
|
@ -110,7 +114,9 @@ void DELAYED_COPY_CODE(render_text80_line)(bool p2, unsigned int line) {
|
||||||
uint sl_pos = 0;
|
uint sl_pos = 0;
|
||||||
|
|
||||||
// Pad 40 pixels on the left to center horizontally
|
// 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; ) {
|
for(uint col=0; col < 40; ) {
|
||||||
// Grab 14 pixels from the next two characters
|
// 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
|
// 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->length = sl_pos;
|
||||||
sl->repeat_count = 1;
|
sl->repeat_count = 1;
|
||||||
|
|
|
@ -9,39 +9,88 @@
|
||||||
volatile uint8_t *pcpi_reg = apple_memory + 0xC0C0;
|
volatile uint8_t *pcpi_reg = apple_memory + 0xC0C0;
|
||||||
|
|
||||||
static inline void __time_critical_func(pcpi_read)(uint32_t address) {
|
static inline void __time_critical_func(pcpi_read)(uint32_t address) {
|
||||||
switch(address & 0x7) {
|
switch(address & 0xF) {
|
||||||
case 0: // Read Data from Z80
|
case 0x0: // Read Data from Z80
|
||||||
clr_6502_stat;
|
clr_6502_stat;
|
||||||
break;
|
break;
|
||||||
case 5: // Z80 Reset
|
case 0x5: // Z80 Reset
|
||||||
z80_res = 1;
|
z80_res = 1;
|
||||||
break;
|
break;
|
||||||
case 6: // Z80 INT
|
case 0x6: // Z80 INT
|
||||||
//z80_irq = 1;
|
//z80_irq = 1;
|
||||||
break;
|
break;
|
||||||
case 7: // Z80 NMI
|
case 0x7: // Z80 NMI
|
||||||
z80_nmi = 1;
|
z80_nmi = 1;
|
||||||
break;
|
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) {
|
static inline void __time_critical_func(pcpi_write)(uint32_t address, uint32_t value) {
|
||||||
switch(address & 0x7) {
|
switch(address & 0xF) {
|
||||||
case 0:
|
case 0x1: // Write Data to Z80
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
break;
|
|
||||||
case 1: // Write Data to Z80
|
|
||||||
pcpi_reg[1] = value & 0xff;
|
pcpi_reg[1] = value & 0xff;
|
||||||
set_z80_stat;
|
set_z80_stat;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 0x5: // Z80 Reset
|
||||||
case 6:
|
case 0x6: // Z80 INT
|
||||||
case 7:
|
case 0x7: // Z80 NMI
|
||||||
pcpi_read(address);
|
pcpi_read(address);
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,3 +38,10 @@ typedef struct sio_s {
|
||||||
|
|
||||||
extern volatile sio_t sio[2];
|
extern volatile sio_t sio[2];
|
||||||
extern volatile uint8_t sio_vector;
|
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);
|
||||||
|
|
258
z80/z80main.c
258
z80/z80main.c
|
@ -27,6 +27,183 @@ volatile uint8_t sio_vector;
|
||||||
|
|
||||||
#define Z80break (z80_res || (config_cmdbuf[7] == 0) || (!z80_cycle++))
|
#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 DELAYED_COPY_CODE(cpu_in)(uint16_t address) {
|
||||||
uint8_t rv = 0;
|
uint8_t rv = 0;
|
||||||
if(address & 0x80) {
|
if(address & 0x80) {
|
||||||
|
@ -42,69 +219,11 @@ uint8_t DELAYED_COPY_CODE(cpu_in)(uint16_t address) {
|
||||||
break;
|
break;
|
||||||
case 0xFC:
|
case 0xFC:
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
switch(serialmux[(address & 0x01)]) {
|
rv = zuart_read(address & 0x02);
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0xFD:
|
case 0xFD:
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
switch(sio[(address & 0x01)].control[0] & 0x7) {
|
rv = zuart_status(address & 0x02);
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -161,24 +280,7 @@ void DELAYED_COPY_CODE(cpu_out)(uint16_t address, uint8_t value) {
|
||||||
break;
|
break;
|
||||||
case 0xFC:
|
case 0xFC:
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
switch(serialmux[(address & 0x01)]) {
|
zuart_write((address & 0x02), value);
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0xFD:
|
case 0xFD:
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user