diff --git a/v2-analog-rev1/CMakeLists.txt b/v2-analog-rev1/CMakeLists.txt index 8c744af..03674e9 100644 --- a/v2-analog-rev1/CMakeLists.txt +++ b/v2-analog-rev1/CMakeLists.txt @@ -29,6 +29,8 @@ target_sources(v2-analog-${PICO_BOARD} PUBLIC common/main.c diag/businterface.c diag/diag.c + fs/businterface.c + fs/fs.c vga/vgamain.c vga/businterface.c vga/vgabuf.c @@ -36,9 +38,10 @@ target_sources(v2-analog-${PICO_BOARD} PUBLIC vga/render_hires.c vga/render_lores.c vga/render_text.c - vga/render_terminal.c + vga/render_videx.c vga/render_dhgr.c vga/render_dgr.c + vga/render_shr.c vga/render_test.c vga/terminal_rom.c vga/character_rom.c @@ -61,11 +64,16 @@ target_link_libraries(v2-analog-${PICO_BOARD} PUBLIC pico_multicore pico_stdlib littlefs-lib - pico_cyw43_arch_lwip_poll hardware_dma hardware_pio ) +if(${PICO_BOARD} MATCHES "pico_w") +target_link_libraries(v2-analog-${PICO_BOARD} PUBLIC + pico_cyw43_arch_lwip_poll +) +endif(${PICO_BOARD} MATCHES "pico_w") + pico_enable_stdio_usb(v2-analog-${PICO_BOARD} 0) pico_enable_stdio_uart(v2-analog-${PICO_BOARD} 0) diff --git a/v2-analog-rev1/common/abus.pio b/v2-analog-rev1/common/abus.pio index b6561d3..be5ebd2 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 [15] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns) + set PINS, 0b110 [14] ; 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 [7] ; wait for PHI0 to fall + wait 0 GPIO, PHI0_GPIO [6] ; 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 [7] ; wait for PHI0 to fall + wait 0 GPIO, PHI0_GPIO [6] ; 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 diff --git a/v2-analog-rev1/common/buffers.h b/v2-analog-rev1/common/buffers.h index a994d44..4475cc1 100644 --- a/v2-analog-rev1/common/buffers.h +++ b/v2-analog-rev1/common/buffers.h @@ -1,3 +1,5 @@ +#pragma once + #include extern volatile uint8_t config_memory[32]; @@ -48,3 +50,47 @@ extern volatile uint8_t *slot7rom; /* Videx VideoTerm */ extern volatile uint8_t *videx_page; + +extern volatile uint32_t soft_switches; + +#define SOFTSW_TEXT_MODE 0x00000001 +#define SOFTSW_MIX_MODE 0x00000002 +#define SOFTSW_HIRES_MODE 0x00000004 +#define SOFTSW_MODE_MASK 0x00000007 +#define SOFTSW_PAGE_2 0x00000008 + +// Apple IIe/c/gs softswitches +#define SOFTSW_80STORE 0x00000100 +#define SOFTSW_AUX_READ 0x00000200 +#define SOFTSW_AUX_WRITE 0x00000400 +#define SOFTSW_AUXZP 0x00000800 +#define SOFTSW_SLOT3ROM 0x00001000 +#define SOFTSW_80COL 0x00002000 +#define SOFTSW_ALTCHAR 0x00004000 +#define SOFTSW_DGR 0x00008000 + +#define SOFTSW_NEWVID_MASK 0xE0 +#define SOFTSW_NEWVID_SHIFT 11 + +#define SOFTSW_MONOCHROME 0x00010000 +#define SOFTSW_LINEARIZE 0x00020000 +#define SOFTSW_SHR 0x00040000 + +#define SOFTSW_IOUDIS 0x00080000 + +#define SOFTSW_SHADOW_MASK 0x7F +#define SOFTSW_SHADOW_SHIFT 20 + +#define SOFTSW_SHADOW_TEXT 0x00100000 +#define SOFTSW_SHADOW_HGR1 0x00200000 +#define SOFTSW_SHADOW_HGR2 0x00400000 +#define SOFTSW_SHADOW_SHR 0x00800000 +#define SOFTSW_SHADOW_AUXHGR 0x01000000 +#define SOFTSW_SHADOW_ALTDISP 0x02000000 +#define SOFTSW_SHADOW_IO 0x04000000 + +// V2 Analog specific softswitches +#define SOFTSW_VIDEX 0x10000000 +#define SOFTSW_TEST 0x20000000 +#define SOFTSW_IIE_REGS 0x40000000 +#define SOFTSW_IIGS_REGS 0x80000000 diff --git a/v2-analog-rev1/common/config.c b/v2-analog-rev1/common/config.c index 467e7b8..b043ba7 100644 --- a/v2-analog-rev1/common/config.c +++ b/v2-analog-rev1/common/config.c @@ -8,13 +8,18 @@ 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]; +extern bool userfont; + 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)) { @@ -26,6 +31,18 @@ void parse_config(uint8_t *buffer) { } else if(!strcmp("SNESMAX", buffer+5)) { v2mode = MODE_SNESMAX; } + } else if(!memcmp("MACHINE=", buffer, 8)) { + if(!strcmp("II", buffer+8)) { + machine = APPLE_II; + soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + } else if(!strcmp("IIE", buffer+8)) { + machine = APPLE_IIE; + soft_switches &= ~SOFTSW_IIGS_REGS; + soft_switches |= SOFTSW_IIE_REGS; + } else if(!strcmp("IIGS", buffer+8)) { + machine = APPLE_IIGS; + soft_switches |= SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS; + } } else if(!memcmp("MUX=", buffer, 4)) { if(!strcmp("USB", buffer+4)) { serialmux = SERIAL_USB; @@ -62,6 +79,8 @@ void default_config() { wifimode = WIFI_AP; strcpy(wifi_ssid, "V2RetroNet"); strcpy(wifi_psk, "Analog"); + machine = COMPAT_AUTO; + soft_switches = 0; } void write_config() { @@ -75,6 +94,11 @@ void write_config() { 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; case MODE_VGACARD: memset(config_temp, 0, sizeof(config_temp)); strcpy(config_temp, "MODE=VGA"); @@ -106,6 +130,23 @@ void write_config() { pico_write(file, config_temp, 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); + break; + case APPLE_IIE: + memset(config_temp, 0, sizeof(config_temp)); + strcpy(config_temp, "MACHINE=IIE"); + pico_write(file, config_temp, 32); + break; + case APPLE_IIGS: + memset(config_temp, 0, sizeof(config_temp)); + strcpy(config_temp, "MACHINE=IIGS"); + pico_write(file, config_temp, 32); + break; + } switch(serialmux) { case SERIAL_USB: memset(config_temp, 0, sizeof(config_temp)); @@ -185,10 +226,19 @@ void read_config() { pico_close(file); } +volatile uint8_t *videx_page_tmp = (private_memory+0xF000); +extern uint8_t character_rom[4096]; + void config_handler() { if(config_memory[31] != 0) return; - if(!strcmp("WRITE_CONFIG", (uint8_t*)config_memory)) { + 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; diff --git a/v2-analog-rev1/common/config.h b/v2-analog-rev1/common/config.h index eb41ab7..b61af2c 100644 --- a/v2-analog-rev1/common/config.h +++ b/v2-analog-rev1/common/config.h @@ -20,6 +20,7 @@ typedef enum { MODE_REBOOT = 0, MODE_DIAG, + MODE_FS, MODE_VGACARD, MODE_APPLICARD, MODE_SERIAL, @@ -54,6 +55,15 @@ typedef enum { extern wifimode_t wifimode; +typedef enum { + APPLE_II = 0, + APPLE_IIE = 1, + APPLE_IIGS = 2, + COMPAT_AUTO = 0xff +} compat_t; + +extern compat_t machine; + enum { ABUS_MAIN_SM = 0, ABUS_DEVICE_READ_SM = 1, diff --git a/v2-analog-rev1/common/flash_upload.c b/v2-analog-rev1/common/flash_upload.c index 6ee8d91..fa261fe 100644 --- a/v2-analog-rev1/common/flash_upload.c +++ b/v2-analog-rev1/common/flash_upload.c @@ -1,11 +1,14 @@ #include -#include #include #include #include #include #include "config.h" +#ifdef RASPBERRYPI_PICO_W +#include +#endif + void flash_reboot() __attribute__ ((noreturn)); // Reboot the Pico diff --git a/v2-analog-rev1/common/main.c b/v2-analog-rev1/common/main.c index 2121ab2..d79286a 100644 --- a/v2-analog-rev1/common/main.c +++ b/v2-analog-rev1/common/main.c @@ -20,6 +20,11 @@ static void core1_loop() { diag_businterface(); core1_running = 0; break; + case MODE_FS: + core1_running = 1; + fs_businterface(); + core1_running = 0; + break; case MODE_VGACARD: core1_running = 1; vga_businterface(); @@ -53,6 +58,9 @@ static void core0_loop() { case MODE_DIAG: diagmain(); break; + case MODE_FS: + fsmain(); + break; case MODE_VGACARD: vgamain(); break; @@ -84,6 +92,8 @@ int main() { // 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(); @@ -91,8 +101,6 @@ int main() { read_config(); } - multicore_launch_core1(core1_loop); - core0_loop(); return 0; diff --git a/v2-analog-rev1/common/modes.h b/v2-analog-rev1/common/modes.h index f3fdfde..0efb4ad 100644 --- a/v2-analog-rev1/common/modes.h +++ b/v2-analog-rev1/common/modes.h @@ -14,4 +14,7 @@ void parallel_businterface(); void diag_businterface(); void diagmain(); +void fs_businterface(); +void fsmain(); + void flash_reboot() __attribute__ ((noreturn)); diff --git a/v2-analog-rev1/fs/businterface.c b/v2-analog-rev1/fs/businterface.c new file mode 100644 index 0000000..90d57f0 --- /dev/null +++ b/v2-analog-rev1/fs/businterface.c @@ -0,0 +1,95 @@ +#include +#include +#include "common/config.h" +#include "common/buffers.h" +#include "abus.pio.h" +#include "fs/businterface.h" +#include "fs/fs.h" + +static inline void __time_critical_func(shadow_memory)(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) { + if((soft_switches & (SOFTSW_80STORE | SOFTSW_AUXZP)) == (SOFTSW_80STORE | SOFTSW_AUXZP)) { + private_memory[address] = value & 0xff; + } else { + apple_memory[address] = value & 0xff; + } + } else if((address < 0xC000) || (address >= 0xD000)) { + if((soft_switches & (SOFTSW_80STORE | SOFTSW_AUX_WRITE)) == (SOFTSW_80STORE | SOFTSW_AUX_WRITE)) { + private_memory[address] = value & 0xff; + } else { + apple_memory[address] = value & 0xff; + } + } + } + + if(CARD_SELECT) { + 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 + if((soft_switches & SOFTSW_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) { + if((address & 0xff80) == 0xc000) { + switch(address & 0x7f) { + case 0x00: + soft_switches &= ~SOFTSW_80STORE; + break; + case 0x01: + soft_switches |= SOFTSW_80STORE; + break; + case 0x04: + soft_switches &= ~SOFTSW_AUX_WRITE; + break; + case 0x05: + soft_switches |= SOFTSW_AUX_WRITE; + break; + case 0x08: + soft_switches &= ~SOFTSW_AUXZP; + break; + case 0x09: + soft_switches |= SOFTSW_AUXZP; + break; + } + } + } +} + + +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/businterface.h b/v2-analog-rev1/fs/businterface.h new file mode 100644 index 0000000..d04c54f --- /dev/null +++ b/v2-analog-rev1/fs/businterface.h @@ -0,0 +1,3 @@ +#pragma once + +void diag_businterface(); diff --git a/v2-analog-rev1/fs/fs.c b/v2-analog-rev1/fs/fs.c new file mode 100644 index 0000000..3b55f23 --- /dev/null +++ b/v2-analog-rev1/fs/fs.c @@ -0,0 +1,231 @@ +#include +#include +#include +#include "common/config.h" +#include "common/buffers.h" +#include "fs/businterface.h" +#include "fs/fs.h" +#include "pico_hal.h" + +typedef struct { + int handle; + bool valid; +} fs_file_t; + +#define FS_MAXFILE 8 +fs_file_t fs_file[FS_MAXFILE]; + +void fs_open(volatile uint8_t *fsregs) { + int file; + for(int i = 0; i < FS_MAXFILE; i++) { + if(!fs_file[i].valid) { + int flags = 0; + if(fsregs[FS_FLAGS] & FS_O_RD) + flags |= LFS_O_RDONLY; + if(fsregs[FS_FLAGS] & FS_O_WR) + flags |= LFS_O_WRONLY; + if(fsregs[FS_FLAGS] & FS_O_CREATE) + flags |= LFS_O_CREAT; + if(fsregs[FS_FLAGS] & FS_O_APPEND) + flags |= LFS_O_APPEND; + if(fsregs[FS_FLAGS] & FS_O_EXISTING) + flags |= LFS_O_EXCL; + if(fsregs[FS_FLAGS] & FS_O_TRUNC) + flags |= LFS_O_TRUNC; + + if((flags & LFS_O_RDWR) != 0) { + // Ensure pathname is 128 bytes or less. + apple_memory[0xC880] = 0x00; + file = pico_open((char*)(apple_memory + 0xC800), flags); + } else { + fsregs[FS_STATUS] = FS_ERR_INVAL; + fsregs[FS_FILE] = FS_ERR_INVAL; + return; + } + + if(file < 0) { + fsregs[FS_STATUS] = file; + fsregs[FS_FILE] = file; + return; + } else { + fs_file[i].handle = file; + fs_file[i].valid = true; + fsregs[FS_STATUS] = FS_ERR_OK; + fsregs[FS_FILE] = i; + return; + } + } + } + + fsregs[FS_STATUS] = FS_ERR_NOMEM; +} + +void fs_close(volatile uint8_t *fsregs) { + int i = fsregs[FS_FILE]; + if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0)) { + fsregs[FS_STATUS] = FS_ERR_INVAL; + return; + } + + pico_close(fs_file[i].handle); + fs_file[i].handle = -1; + fs_file[i].valid = false; +} + +void fs_read(volatile uint8_t *fsregs) { + int i = fsregs[FS_FILE]; + uint16_t size = (((uint16_t)fsregs[FS_OFFMSB]) << 8) | ((uint16_t)fsregs[FS_SIZELSB]); + + if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0) || (size > 512)) { + fsregs[FS_STATUS] = FS_ERR_INVAL; + return; + } + if(size == 0) { + fsregs[FS_STATUS] = FS_ERR_OK; + } + + int rv = pico_read(fs_file[i].handle, (uint8_t*)(apple_memory+0xC800), size); + if(rv < 0) { + fsregs[FS_STATUS] = rv; + } else { + fsregs[FS_SIZELSB] = rv & 0xFF; + fsregs[FS_SIZEMSB] = (rv >> 8); + fsregs[FS_STATUS] = FS_ERR_OK; + } +} + +void fs_write(volatile uint8_t *fsregs) { + int i = fsregs[FS_FILE]; + uint16_t size = (((uint16_t)fsregs[FS_OFFMSB]) << 8) | ((uint16_t)fsregs[FS_SIZELSB]); + + if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0) || (size > 512)) { + fsregs[FS_STATUS] = FS_ERR_INVAL; + return; + } + if(size == 0) { + fsregs[FS_STATUS] = FS_ERR_OK; + } + + int rv = pico_write(fs_file[i].handle, (uint8_t*)(apple_memory+0xC800), size); + if(rv < 0) { + fsregs[FS_STATUS] = rv; + } else { + fsregs[FS_SIZELSB] = rv & 0xFF; + fsregs[FS_SIZEMSB] = (rv >> 8); + fsregs[FS_STATUS] = FS_ERR_OK; + } +} + +void fs_seek(volatile uint8_t *fsregs) { + int i = fsregs[FS_FILE]; + int16_t off = (int16_t)((((uint16_t)fsregs[FS_OFFMSB]) << 8) | ((uint16_t)fsregs[FS_OFFLSB])); + int whence = fsregs[FS_WHENCE]; + + if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0)) { + fsregs[FS_STATUS] = FS_ERR_INVAL; + return; + } + + int rv = pico_lseek(fs_file[i].handle, off, whence); + if(rv < 0) { + fsregs[FS_STATUS] = rv; + } else { + fsregs[FS_OFFLSB] = rv & 0xFF; + fsregs[FS_OFFMSB] = (rv >> 8); + fsregs[FS_STATUS] = FS_ERR_OK; + } +} + +void fs_tell(volatile uint8_t *fsregs) { + int i = fsregs[FS_FILE]; + + if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0)) { + fsregs[FS_STATUS] = FS_ERR_INVAL; + return; + } + + int rv = pico_tell(fs_file[i].handle); + if(rv < 0) { + fsregs[FS_STATUS] = rv; + } else { + fsregs[FS_OFFLSB] = rv & 0xFF; + fsregs[FS_OFFMSB] = (rv >> 8); + fsregs[FS_STATUS] = FS_ERR_OK; + } +} + +void prodos_command(volatile uint8_t *fsregs) { +} + +void fs_handler(uint8_t slot) { + volatile uint8_t *fsregs = apple_memory + 0xC080 + (slot << 4); + if(fsregs[FS_EXECUTE] != 0x00) { + fsregs[FS_STATUS] = FS_ERR_INVAL; + return; + } + + fsregs[FS_BUSY] = 0xff; + + switch(fsregs[FS_COMMAND]) { + case FS_OPEN: + fs_open(fsregs); + break; + case FS_CLOSE: + fs_close(fsregs); + break; + case FS_READ: + fs_read(fsregs); + break; + case FS_WRITE: + fs_write(fsregs); + break; + case FS_SEEK: + fs_seek(fsregs); + break; + case FS_TELL: + fs_tell(fsregs); + break; + case PRODOS_COMMAND: + prodos_command(fsregs); + break; + } + + fsregs[FS_BUSY] = 0x00; +} + +void fsmain() { + int i; + + memset((uint8_t*)(apple_memory+0xC000), 0x00, 0x1000); + + for(i = 0; i < FS_MAXFILE; i++) { + fs_file[i].handle = -1; + fs_file[i].valid = false; + } + + // Attempt to open boot disk image + 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."); + + while(v2mode == MODE_FS) { + sleep_ms(50); + } + + // Close any open handles + for(i = 0; i < FS_MAXFILE; i++) { + if(fs_file[i].valid) { + pico_close(fs_file[i].handle); + fs_file[i].handle = -1; + fs_file[i].valid = false; + } + } +} + diff --git a/v2-analog-rev1/fs/fs.h b/v2-analog-rev1/fs/fs.h new file mode 100644 index 0000000..718b37f --- /dev/null +++ b/v2-analog-rev1/fs/fs.h @@ -0,0 +1,54 @@ +#pragma once + +#define FS_COMMAND 0x0 +#define FS_FILE 0x1 +#define FS_FLAGS 0x1 +#define FS_SIZELSB 0x2 +#define FS_SIZEMSB 0x3 +#define FS_OFFLSB 0x2 +#define FS_OFFMSB 0x3 +#define FS_WHENCE 0x4 +#define FS_BUSY 0xD +#define FS_STATUS 0xE +#define FS_EXECUTE 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, + PRODOS_COMMAND = 0x20, +} 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; + +void fs_handler(uint8_t slot); diff --git a/v2-analog-rev1/vga/businterface.c b/v2-analog-rev1/vga/businterface.c index 014e487..a402451 100644 --- a/v2-analog-rev1/vga/businterface.c +++ b/v2-analog-rev1/vga/businterface.c @@ -7,7 +7,7 @@ volatile uint8_t *videx_page = videx_memory; - +uint32_t a2_first_write = 0; static inline void __time_critical_func(videx_crtc_addr)(uint32_t value) { } @@ -18,21 +18,183 @@ 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) { + // Shadow the soft-switches by observing all read & write bus cycles + if((address & 0xff80) == 0xc000) { + switch(address & 0x7f) { + case 0x00: + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + case 0x21: + if((soft_switches & SOFTSW_IIGS_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; + 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; + 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; + 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; + 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; + case 0x50: + soft_switches &= ~SOFTSW_TEXT_MODE; + return; + case 0x51: + soft_switches |= SOFTSW_TEXT_MODE; + return; + case 0x52: + soft_switches &= ~SOFTSW_MIX_MODE; + return; + case 0x53: + soft_switches |= SOFTSW_MIX_MODE; + return; + case 0x54: + soft_switches &= ~SOFTSW_PAGE_2; + return; + case 0x55: + soft_switches |= SOFTSW_PAGE_2; + return; + case 0x56: + soft_switches &= ~SOFTSW_HIRES_MODE; + return; + case 0x57: + soft_switches |= SOFTSW_HIRES_MODE; + return; + case 0x5e: + if(soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) { + soft_switches |= SOFTSW_DGR; + } + return; + case 0x5f: + if(soft_switches & (SOFTSW_IIGS_REGS | SOFTSW_IIE_REGS)) { + soft_switches &= ~SOFTSW_DGR; + } + return; + 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; + 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; + } + } + // 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)) { + a2_first_write = (address << 16) | (value & 0x3FF); + if(a2_first_write == 0xC0330100) { // Apple IIgs ROM03 Clock Access + machine = APPLE_IIGS; + soft_switches &= ~SOFTSW_IIE_REGS; + soft_switches |= SOFTSW_IIGS_REGS; + } else if(a2_first_write == 0x01F901FB) { // Apple II Plus + machine = APPLE_II; + soft_switches &= ~(SOFTSW_IIE_REGS | SOFTSW_IIGS_REGS); + } else if(a2_first_write == 0x01F5018B) { // Apple IIe Platinum + machine = APPLE_IIE; + soft_switches |= SOFTSW_IIE_REGS; + soft_switches &= ~SOFTSW_IIGS_REGS; + } else { + a2_first_write = 0; + } + } + // Mirror Video Memory from MAIN & AUX banks - if(terminal_switches & TERMINAL_AUX_WRITE) { - if((address >= 0x400) && (address < 0xC00)) { + if(soft_switches & SOFTSW_LINEARIZE) { + if((address >= 0x2000) && (address < 0xC000)) { private_memory[address] = value & 0xff; - } else if((address >= 0x2000) && (address < 0x6000)) { + return; + } + } + + if(soft_switches & SOFTSW_80STORE) { + if(soft_switches & SOFTSW_PAGE_2) { + if((address >= 0x400) && (address < 0x800)) { + private_memory[address] = value & 0xff; + return; + } else if((soft_switches & SOFTSW_HIRES_MODE) && (address >= 0x2000) && (address < 0x4000)) { + private_memory[address] = value & 0xff; + return; + } + } + } else if(soft_switches & SOFTSW_AUX_WRITE) { + if((address >= 0x200) && (address < 0xC000)) { private_memory[address] = value & 0xff; + return; } - } else { - if((address >= 0x400) && (address < 0xC00)) { - apple_memory[address] = value & 0xff; - } else if((address >= 0x2000) && (address < 0x6000)) { - apple_memory[address] = value & 0xff; - } + } + + if((address >= 0x200) && (address < 0xC000)) { + apple_memory[address] = value & 0xff; + return; } // Videx 80 Column Card @@ -62,63 +224,9 @@ static inline void __time_critical_func(shadow_memory)(uint32_t address, uint32_ } // Any access to Videx I/O sets the VRAM page visible in 0xCC00-0xD000 - if(CARD_DEVSEL) { + if(CARD_SELECT && CARD_DEVSEL) { videx_page = videx_memory + ((address & 0x0C) << 9); } - - // Shadow the soft-switches by observing all read & write bus cycles - if((address & 0xff80) == 0xc000) { - switch(address & 0x7f) { - case 0x0c: - if(terminal_switches & TERMINAL_IIE_REGS) - terminal_switches &= ~((uint32_t)TERMINAL_80COL); - break; - case 0x0d: - if(terminal_switches & TERMINAL_IIE_REGS) - terminal_switches |= TERMINAL_80COL; - break; - case 0x22: - if((terminal_switches & TERMINAL_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) - terminal_tbcolor = value & 0xff; - break; - case 0x34: - if((terminal_switches & TERMINAL_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) - terminal_border = value & 0x0f; - break; - case 0x50: - soft_switches &= ~((uint32_t)SOFTSW_TEXT_MODE); - break; - case 0x51: - soft_switches |= SOFTSW_TEXT_MODE; - break; - case 0x52: - soft_switches &= ~((uint32_t)SOFTSW_MIX_MODE); - break; - case 0x53: - soft_switches |= SOFTSW_MIX_MODE; - break; - case 0x54: - soft_switches &= ~((uint32_t)SOFTSW_PAGE_2); - break; - case 0x55: - soft_switches |= SOFTSW_PAGE_2; - break; - case 0x56: - soft_switches &= ~((uint32_t)SOFTSW_HIRES_MODE); - break; - case 0x57: - soft_switches |= SOFTSW_HIRES_MODE; - break; - case 0x5e: - if(terminal_switches & TERMINAL_IIE_REGS) - terminal_switches |= TERMINAL_DGR; - break; - case 0x5f: - if(terminal_switches & TERMINAL_IIE_REGS) - terminal_switches &= ~((uint32_t)TERMINAL_DGR); - break; - } - } } diff --git a/v2-analog-rev1/vga/character_rom.c b/v2-analog-rev1/vga/character_rom.c index 995596b..f005061 100644 --- a/v2-analog-rev1/vga/character_rom.c +++ b/v2-analog-rev1/vga/character_rom.c @@ -1,2576 +1,395 @@ -#include "character_rom.h" - - -const uint8_t default_character_rom[256*8] = { - // - // Inverse Set (0-63) - // - - // Inverse '@' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00101010, - 0b00101110, - 0b00101100, - 0b00100000, - 0b00011110, - - // Inverse 'A' - 0b00000000, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00100010, - 0b00111110, - 0b00100010, - 0b00100010, - - // Inverse 'B' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - - // Inverse 'C' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100010, - 0b00011100, - - // Inverse 'D' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00111100, - - // Inverse 'E' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00100000, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00111110, - - // Inverse 'F' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00100000, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00100000, - - // Inverse 'G' - 0b00000000, - 0b00011110, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100110, - 0b00100010, - 0b00011110, - - // Inverse 'H' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00111110, - 0b00100010, - 0b00100010, - 0b00100010, - - // Inverse 'I' - 0b00000000, - 0b00011100, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00011100, - - // Inverse 'J' - 0b00000000, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00100010, - 0b00011100, - - // Inverse 'K' - 0b00000000, - 0b00100010, - 0b00100100, - 0b00101000, - 0b00110000, - 0b00101000, - 0b00100100, - 0b00100010, - - // Inverse 'L' - 0b00000000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00111110, - - // Inverse 'M' - 0b00000000, - 0b00100010, - 0b00110110, - 0b00101010, - 0b00101010, - 0b00100010, - 0b00100010, - 0b00100010, - - // Inverse 'N' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00110010, - 0b00101010, - 0b00100110, - 0b00100010, - 0b00100010, - - // Inverse 'O' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00011100, - - // Inverse 'P' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00100000, - - // Inverse 'Q' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00101010, - 0b00100100, - 0b00011010, - - // Inverse 'R' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00101000, - 0b00100100, - 0b00100010, - - // Inverse 'S' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100000, - 0b00011100, - 0b00000010, - 0b00100010, - 0b00011100, - - // Inverse 'T' - 0b00000000, - 0b00111110, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - - // Inverse 'U' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00011100, - - // Inverse 'V' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - - // Inverse 'W' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00101010, - 0b00101010, - 0b00110110, - 0b00100010, - - // Inverse 'X' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00100010, - - // Inverse 'Y' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - - // Inverse 'Z' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00111110, - - // Inverse '[' - 0b00000000, - 0b00111110, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00111110, - - // Inverse '\' - 0b00000000, - 0b00000000, - 0b00100000, - 0b00010000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000000, - - // Inverse ']' - 0b00000000, - 0b00111110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00111110, - - // Inverse '^' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00000000, - 0b00000000, - - // Inverse '_' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - - // Inverse ' ' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Inverse '!' - 0b00000000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00001000, - - // Inverse '"' - 0b00000000, - 0b00010100, - 0b00010100, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Inverse '#' - 0b00000000, - 0b00010100, - 0b00010100, - 0b00111110, - 0b00010100, - 0b00111110, - 0b00010100, - 0b00010100, - - // Inverse '$' - 0b00000000, - 0b00001000, - 0b00011110, - 0b00101000, - 0b00011100, - 0b00001010, - 0b00111100, - 0b00001000, - - // Inverse '%' - 0b00000000, - 0b00110000, - 0b00110010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100110, - 0b00000110, - - // Inverse '&' - 0b00000000, - 0b00010000, - 0b00101000, - 0b00101000, - 0b00010000, - 0b00101010, - 0b00100100, - 0b00011010, - - // Inverse ''' - 0b00000000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Inverse '(' - 0b00000000, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00010000, - 0b00001000, - - // Inverse ')' - 0b00000000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000100, - 0b00001000, - - // Inverse '*' - 0b00000000, - 0b00001000, - 0b00101010, - 0b00011100, - 0b00001000, - 0b00011100, - 0b00101010, - 0b00001000, - - // Inverse '+' - 0b00000000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00111110, - 0b00001000, - 0b00001000, - 0b00000000, - - // Inverse ',' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00010000, - - // Inverse '-' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00000000, - 0b00000000, - - // Inverse '.' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - - // Inverse '/' - 0b00000000, - 0b00000000, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00000000, - - // Inverse '0' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100110, - 0b00101010, - 0b00110010, - 0b00100010, - 0b00011100, - - // Inverse '1' - 0b00000000, - 0b00001000, - 0b00011000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00011100, - - // Inverse '2' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00000010, - 0b00001100, - 0b00010000, - 0b00100000, - 0b00111110, - - // Inverse '3' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001100, - 0b00000010, - 0b00100010, - 0b00011110, - - // Inverse '4' - 0b00000000, - 0b00000100, - 0b00001100, - 0b00010100, - 0b00100100, - 0b00111110, - 0b00000100, - 0b00000100, - - // Inverse '5' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00111100, - 0b00000010, - 0b00000010, - 0b00100010, - 0b00011100, - - // Inverse '6' - 0b00000000, - 0b00001110, - 0b00010000, - 0b00100000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00011100, - - // Inverse '7' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00010000, - 0b00010000, - - // Inverse '8' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011100, - - // Inverse '9' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011110, - 0b00000010, - 0b00000100, - 0b00111000, - - // Inverse ':' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00000000, - - // Inverse ';' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00010000, - - // Inverse '<' - 0b00000000, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00010000, - 0b00001000, - 0b00000100, - - // Inverse '=' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00000000, - - // Inverse '>' - 0b00000000, - 0b00010000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - - // Inverse '?' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00000100, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00001000, - - // - // Flashing Set (64-127) - // - - // Flashing '@' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10101010, - 0b10101110, - 0b10101100, - 0b10100000, - 0b10011110, - - // Flashing 'A' - 0b10000000, - 0b10001000, - 0b10010100, - 0b10100010, - 0b10100010, - 0b10111110, - 0b10100010, - 0b10100010, - - // Flashing 'B' - 0b10000000, - 0b10111100, - 0b10100010, - 0b10100010, - 0b10111100, - 0b10100010, - 0b10100010, - 0b10111100, - - // Flashing 'C' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10100000, - 0b10100000, - 0b10100000, - 0b10100010, - 0b10011100, - - // Flashing 'D' - 0b10000000, - 0b10111100, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10111100, - - // Flashing 'E' - 0b10000000, - 0b10111110, - 0b10100000, - 0b10100000, - 0b10111100, - 0b10100000, - 0b10100000, - 0b10111110, - - // Flashing 'F' - 0b10000000, - 0b10111110, - 0b10100000, - 0b10100000, - 0b10111100, - 0b10100000, - 0b10100000, - 0b10100000, - - // Flashing 'G' - 0b10000000, - 0b10011110, - 0b10100000, - 0b10100000, - 0b10100000, - 0b10100110, - 0b10100010, - 0b10011110, - - // Flashing 'H' - 0b10000000, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10111110, - 0b10100010, - 0b10100010, - 0b10100010, - - // Flashing 'I' - 0b10000000, - 0b10011100, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10011100, - - // Flashing 'J' - 0b10000000, - 0b10000010, - 0b10000010, - 0b10000010, - 0b10000010, - 0b10000010, - 0b10100010, - 0b10011100, - - // Flashing 'K' - 0b10000000, - 0b10100010, - 0b10100100, - 0b10101000, - 0b10110000, - 0b10101000, - 0b10100100, - 0b10100010, - - // Flashing 'L' - 0b10000000, - 0b10100000, - 0b10100000, - 0b10100000, - 0b10100000, - 0b10100000, - 0b10100000, - 0b10111110, - - // Flashing 'M' - 0b10000000, - 0b10100010, - 0b10110110, - 0b10101010, - 0b10101010, - 0b10100010, - 0b10100010, - 0b10100010, - - // Flashing 'N' - 0b10000000, - 0b10100010, - 0b10100010, - 0b10110010, - 0b10101010, - 0b10100110, - 0b10100010, - 0b10100010, - - // Flashing 'O' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10011100, - - // Flashing 'P' - 0b10000000, - 0b10111100, - 0b10100010, - 0b10100010, - 0b10111100, - 0b10100000, - 0b10100000, - 0b10100000, - - // Flashing 'Q' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10101010, - 0b10100100, - 0b10011010, - - // Flashing 'R' - 0b10000000, - 0b10111100, - 0b10100010, - 0b10100010, - 0b10111100, - 0b10101000, - 0b10100100, - 0b10100010, - - // Flashing 'S' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10100000, - 0b10011100, - 0b10000010, - 0b10100010, - 0b10011100, - - // Flashing 'T' - 0b10000000, - 0b10111110, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - - // Flashing 'U' - 0b10000000, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10011100, - - // Flashing 'V' - 0b10000000, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10010100, - 0b10001000, - - // Flashing 'W' - 0b10000000, - 0b10100010, - 0b10100010, - 0b10100010, - 0b10101010, - 0b10101010, - 0b10110110, - 0b10100010, - - // Flashing 'X' - 0b10000000, - 0b10100010, - 0b10100010, - 0b10010100, - 0b10001000, - 0b10010100, - 0b10100010, - 0b10100010, - - // Flashing 'Y' - 0b10000000, - 0b10100010, - 0b10100010, - 0b10010100, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - - // Flashing 'Z' - 0b10000000, - 0b10111110, - 0b10000010, - 0b10000100, - 0b10001000, - 0b10010000, - 0b10100000, - 0b10111110, - - // Flashing '[' - 0b10000000, - 0b10111110, - 0b10110000, - 0b10110000, - 0b10110000, - 0b10110000, - 0b10110000, - 0b10111110, - - // Flashing '\' - 0b10000000, - 0b10000000, - 0b10100000, - 0b10010000, - 0b10001000, - 0b10000100, - 0b10000010, - 0b10000000, - - // Flashing ']' - 0b10000000, - 0b10111110, - 0b10000110, - 0b10000110, - 0b10000110, - 0b10000110, - 0b10000110, - 0b10111110, - - // Flashing '^' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10001000, - 0b10010100, - 0b10100010, - 0b10000000, - 0b10000000, - - // Flashing '_' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10111110, - - // Flashing ' ' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - - // Flashing '!' - 0b10000000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10000000, - 0b10001000, - - // Flashing '"' - 0b10000000, - 0b10010100, - 0b10010100, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - - // Flashing '#' - 0b10000000, - 0b10010100, - 0b10010100, - 0b10111110, - 0b10010100, - 0b10111110, - 0b10010100, - 0b10010100, - - // Flashing '$' - 0b10000000, - 0b10001000, - 0b10011110, - 0b10101000, - 0b10011100, - 0b10001010, - 0b10111100, - 0b10001000, - - // Flashing '%' - 0b10000000, - 0b10110000, - 0b10110010, - 0b10000100, - 0b10001000, - 0b10010000, - 0b10100110, - 0b10000110, - - // Flashing '&' - 0b10000000, - 0b10010000, - 0b10101000, - 0b10101000, - 0b10010000, - 0b10101010, - 0b10100100, - 0b10011010, - - // Flashing ''' - 0b10000000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - - // Flashing '(' - 0b10000000, - 0b10001000, - 0b10010000, - 0b10100000, - 0b10100000, - 0b10100000, - 0b10010000, - 0b10001000, - - // Flashing ')' - 0b10000000, - 0b10001000, - 0b10000100, - 0b10000010, - 0b10000010, - 0b10000010, - 0b10000100, - 0b10001000, - - // Flashing '*' - 0b10000000, - 0b10001000, - 0b10101010, - 0b10011100, - 0b10001000, - 0b10011100, - 0b10101010, - 0b10001000, - - // Flashing '+' - 0b10000000, - 0b10000000, - 0b10001000, - 0b10001000, - 0b10111110, - 0b10001000, - 0b10001000, - 0b10000000, - - // Flashing ',' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10001000, - 0b10001000, - 0b10010000, - - // Flashing '-' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10111110, - 0b10000000, - 0b10000000, - 0b10000000, - - // Flashing '.' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10001000, - - // Flashing '/' - 0b10000000, - 0b10000000, - 0b10000010, - 0b10000100, - 0b10001000, - 0b10010000, - 0b10100000, - 0b10000000, - - // Flashing '0' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10100110, - 0b10101010, - 0b10110010, - 0b10100010, - 0b10011100, - - // Flashing '1' - 0b10000000, - 0b10001000, - 0b10011000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b10011100, - - // Flashing '2' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10000010, - 0b10001100, - 0b10010000, - 0b10100000, - 0b10111110, - - // Flashing '3' - 0b10000000, - 0b10111110, - 0b10000010, - 0b10000100, - 0b10001100, - 0b10000010, - 0b10100010, - 0b10011110, - - // Flashing '4' - 0b10000000, - 0b10000100, - 0b10001100, - 0b10010100, - 0b10100100, - 0b10111110, - 0b10000100, - 0b10000100, - - // Flashing '5' - 0b10000000, - 0b10111110, - 0b10100000, - 0b10111100, - 0b10000010, - 0b10000010, - 0b10100010, - 0b10011100, - - // Flashing '6' - 0b10000000, - 0b10001110, - 0b10010000, - 0b10100000, - 0b10111100, - 0b10100010, - 0b10100010, - 0b10011100, - - // Flashing '7' - 0b10000000, - 0b10111110, - 0b10000010, - 0b10000100, - 0b10001000, - 0b10010000, - 0b10010000, - 0b10010000, - - // Flashing '8' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10100010, - 0b10011100, - 0b10100010, - 0b10100010, - 0b10011100, - - // Flashing '9' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10100010, - 0b10011110, - 0b10000010, - 0b10000100, - 0b10111000, - - // Flashing ':' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10001000, - 0b10000000, - 0b10001000, - 0b10000000, - 0b10000000, - - // Flashing ';' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10001000, - 0b10000000, - 0b10001000, - 0b10001000, - 0b10010000, - - // Flashing '<' - 0b10000000, - 0b10000100, - 0b10001000, - 0b10010000, - 0b10100000, - 0b10010000, - 0b10001000, - 0b10000100, - - // Flashing '=' - 0b10000000, - 0b10000000, - 0b10000000, - 0b10111110, - 0b10000000, - 0b10111110, - 0b10000000, - 0b10000000, - - // Flashing '>' - 0b10000000, - 0b10010000, - 0b10001000, - 0b10000100, - 0b10000010, - 0b10000100, - 0b10001000, - 0b10010000, - - // Flashing '?' - 0b10000000, - 0b10011100, - 0b10100010, - 0b10000100, - 0b10001000, - 0b10001000, - 0b10000000, - 0b10001000, - - // - // Normal Set (128-255) - // - - // Normal '@' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00101010, - 0b00101110, - 0b00101100, - 0b00100000, - 0b00011110, - - // Normal 'A' - 0b00000000, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00100010, - 0b00111110, - 0b00100010, - 0b00100010, - - // Normal 'B' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - - // Normal 'C' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100010, - 0b00011100, - - // Normal 'D' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00111100, - - // Normal 'E' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00100000, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00111110, - - // Normal 'F' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00100000, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00100000, - - // Normal 'G' - 0b00000000, - 0b00011110, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100110, - 0b00100010, - 0b00011110, - - // Normal 'H' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00111110, - 0b00100010, - 0b00100010, - 0b00100010, - - // Normal 'I' - 0b00000000, - 0b00011100, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00011100, - - // Normal 'J' - 0b00000000, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00100010, - 0b00011100, - - // Normal 'K' - 0b00000000, - 0b00100010, - 0b00100100, - 0b00101000, - 0b00110000, - 0b00101000, - 0b00100100, - 0b00100010, - - // Normal 'L' - 0b00000000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00111110, - - // Normal 'M' - 0b00000000, - 0b00100010, - 0b00110110, - 0b00101010, - 0b00101010, - 0b00100010, - 0b00100010, - 0b00100010, - - // Normal 'N' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00110010, - 0b00101010, - 0b00100110, - 0b00100010, - 0b00100010, - - // Normal 'O' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal 'P' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00100000, - - // Normal 'Q' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00101010, - 0b00100100, - 0b00011010, - - // Normal 'R' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00101000, - 0b00100100, - 0b00100010, - - // Normal 'S' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100000, - 0b00011100, - 0b00000010, - 0b00100010, - 0b00011100, - - // Normal 'T' - 0b00000000, - 0b00111110, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - - // Normal 'U' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal 'V' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - - // Normal 'W' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00101010, - 0b00101010, - 0b00110110, - 0b00100010, - - // Normal 'X' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00100010, - - // Normal 'Y' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - - // Normal 'Z' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00111110, - - // Normal '[' - 0b00000000, - 0b00111110, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00111110, - - // Normal '\' - 0b00000000, - 0b00000000, - 0b00100000, - 0b00010000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000000, - - // Normal ']' - 0b00000000, - 0b00111110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00111110, - - // Normal '^' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00000000, - 0b00000000, - - // Normal '_' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - - // Normal ' ' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '!' - 0b00000000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00001000, - - // Normal '"' - 0b00000000, - 0b00010100, - 0b00010100, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '#' - 0b00000000, - 0b00010100, - 0b00010100, - 0b00111110, - 0b00010100, - 0b00111110, - 0b00010100, - 0b00010100, - - // Normal '$' - 0b00000000, - 0b00001000, - 0b00011110, - 0b00101000, - 0b00011100, - 0b00001010, - 0b00111100, - 0b00001000, - - // Normal '%' - 0b00000000, - 0b00110000, - 0b00110010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100110, - 0b00000110, - - // Normal '&' - 0b00000000, - 0b00010000, - 0b00101000, - 0b00101000, - 0b00010000, - 0b00101010, - 0b00100100, - 0b00011010, - - // Normal ''' - 0b00000000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '(' - 0b00000000, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00010000, - 0b00001000, - - // Normal ')' - 0b00000000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000100, - 0b00001000, - - // Normal '*' - 0b00000000, - 0b00001000, - 0b00101010, - 0b00011100, - 0b00001000, - 0b00011100, - 0b00101010, - 0b00001000, - - // Normal '+' - 0b00000000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00111110, - 0b00001000, - 0b00001000, - 0b00000000, - - // Normal ',' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00010000, - - // Normal '-' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '.' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - - // Normal '/' - 0b00000000, - 0b00000000, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00000000, - - // Normal '0' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100110, - 0b00101010, - 0b00110010, - 0b00100010, - 0b00011100, - - // Normal '1' - 0b00000000, - 0b00001000, - 0b00011000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00011100, - - // Normal '2' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00000010, - 0b00001100, - 0b00010000, - 0b00100000, - 0b00111110, - - // Normal '3' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001100, - 0b00000010, - 0b00100010, - 0b00011110, - - // Normal '4' - 0b00000000, - 0b00000100, - 0b00001100, - 0b00010100, - 0b00100100, - 0b00111110, - 0b00000100, - 0b00000100, - - // Normal '5' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00111100, - 0b00000010, - 0b00000010, - 0b00100010, - 0b00011100, - - // Normal '6' - 0b00000000, - 0b00001110, - 0b00010000, - 0b00100000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal '7' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00010000, - 0b00010000, - - // Normal '8' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal '9' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011110, - 0b00000010, - 0b00000100, - 0b00111000, - - // Normal ':' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00000000, - - // Normal ';' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00010000, - - // Normal '<' - 0b00000000, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00010000, - 0b00001000, - 0b00000100, - - // Normal '=' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00000000, - - // Normal '>' - 0b00000000, - 0b00010000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - - // Normal '?' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00000100, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00001000, - - // Normal '@' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00101010, - 0b00101110, - 0b00101100, - 0b00100000, - 0b00011110, - - // Normal 'A' - 0b00000000, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00100010, - 0b00111110, - 0b00100010, - 0b00100010, - - // Normal 'B' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - - // Normal 'C' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100010, - 0b00011100, - - // Normal 'D' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00111100, - - // Normal 'E' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00100000, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00111110, - - // Normal 'F' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00100000, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00100000, - - // Normal 'G' - 0b00000000, - 0b00011110, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100110, - 0b00100010, - 0b00011110, - - // Normal 'H' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00111110, - 0b00100010, - 0b00100010, - 0b00100010, - - // Normal 'I' - 0b00000000, - 0b00011100, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00011100, - - // Normal 'J' - 0b00000000, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00100010, - 0b00011100, - - // Normal 'K' - 0b00000000, - 0b00100010, - 0b00100100, - 0b00101000, - 0b00110000, - 0b00101000, - 0b00100100, - 0b00100010, - - // Normal 'L' - 0b00000000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00111110, - - // Normal 'M' - 0b00000000, - 0b00100010, - 0b00110110, - 0b00101010, - 0b00101010, - 0b00100010, - 0b00100010, - 0b00100010, - - // Normal 'N' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00110010, - 0b00101010, - 0b00100110, - 0b00100010, - 0b00100010, - - // Normal 'O' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal 'P' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00100000, - 0b00100000, - 0b00100000, - - // Normal 'Q' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00101010, - 0b00100100, - 0b00011010, - - // Normal 'R' - 0b00000000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00111100, - 0b00101000, - 0b00100100, - 0b00100010, - - // Normal 'S' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100000, - 0b00011100, - 0b00000010, - 0b00100010, - 0b00011100, - - // Normal 'T' - 0b00000000, - 0b00111110, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - - // Normal 'U' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal 'V' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - - // Normal 'W' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00100010, - 0b00101010, - 0b00101010, - 0b00110110, - 0b00100010, - - // Normal 'X' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00100010, - - // Normal 'Y' - 0b00000000, - 0b00100010, - 0b00100010, - 0b00010100, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - - // Normal 'Z' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00111110, - - // Normal '[' - 0b00000000, - 0b00111110, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00110000, - 0b00111110, - - // Normal '\' - 0b00000000, - 0b00000000, - 0b00100000, - 0b00010000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000000, - - // Normal ']' - 0b00000000, - 0b00111110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00000110, - 0b00111110, - - // Normal '^' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00010100, - 0b00100010, - 0b00000000, - 0b00000000, - - // Normal '_' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - - // Normal ' ' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '!' - 0b00000000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00001000, - - // Normal '"' - 0b00000000, - 0b00010100, - 0b00010100, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '#' - 0b00000000, - 0b00010100, - 0b00010100, - 0b00111110, - 0b00010100, - 0b00111110, - 0b00010100, - 0b00010100, - - // Normal '$' - 0b00000000, - 0b00001000, - 0b00011110, - 0b00101000, - 0b00011100, - 0b00001010, - 0b00111100, - 0b00001000, - - // Normal '%' - 0b00000000, - 0b00110000, - 0b00110010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100110, - 0b00000110, - - // Normal '&' - 0b00000000, - 0b00010000, - 0b00101000, - 0b00101000, - 0b00010000, - 0b00101010, - 0b00100100, - 0b00011010, - - // Normal ''' - 0b00000000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '(' - 0b00000000, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00010000, - 0b00001000, - - // Normal ')' - 0b00000000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000010, - 0b00000010, - 0b00000100, - 0b00001000, - - // Normal '*' - 0b00000000, - 0b00001000, - 0b00101010, - 0b00011100, - 0b00001000, - 0b00011100, - 0b00101010, - 0b00001000, - - // Normal '+' - 0b00000000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00111110, - 0b00001000, - 0b00001000, - 0b00000000, - - // Normal ',' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00010000, - - // Normal '-' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00000000, - 0b00000000, - - // Normal '.' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - - // Normal '/' - 0b00000000, - 0b00000000, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00000000, - - // Normal '0' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100110, - 0b00101010, - 0b00110010, - 0b00100010, - 0b00011100, - - // Normal '1' - 0b00000000, - 0b00001000, - 0b00011000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00001000, - 0b00011100, - - // Normal '2' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00000010, - 0b00001100, - 0b00010000, - 0b00100000, - 0b00111110, - - // Normal '3' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001100, - 0b00000010, - 0b00100010, - 0b00011110, - - // Normal '4' - 0b00000000, - 0b00000100, - 0b00001100, - 0b00010100, - 0b00100100, - 0b00111110, - 0b00000100, - 0b00000100, - - // Normal '5' - 0b00000000, - 0b00111110, - 0b00100000, - 0b00111100, - 0b00000010, - 0b00000010, - 0b00100010, - 0b00011100, - - // Normal '6' - 0b00000000, - 0b00001110, - 0b00010000, - 0b00100000, - 0b00111100, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal '7' - 0b00000000, - 0b00111110, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00010000, - 0b00010000, - - // Normal '8' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011100, - - // Normal '9' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00100010, - 0b00011110, - 0b00000010, - 0b00000100, - 0b00111000, - - // Normal ':' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00000000, - - // Normal ';' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00001000, - 0b00000000, - 0b00001000, - 0b00001000, - 0b00010000, - - // Normal '<' - 0b00000000, - 0b00000100, - 0b00001000, - 0b00010000, - 0b00100000, - 0b00010000, - 0b00001000, - 0b00000100, - - // Normal '=' - 0b00000000, - 0b00000000, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00111110, - 0b00000000, - 0b00000000, - - // Normal '>' - 0b00000000, - 0b00010000, - 0b00001000, - 0b00000100, - 0b00000010, - 0b00000100, - 0b00001000, - 0b00010000, - - // Normal '?' - 0b00000000, - 0b00011100, - 0b00100010, - 0b00000100, - 0b00001000, - 0b00001000, - 0b00000000, - 0b00001000, -}; +#include "character_rom.h" + +const uint8_t default_character_rom[2048] = { + 0x00, 0x1c, 0x22, 0x2a, 0x2e, 0x2c, 0x20, 0x1e, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, + 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x22, 0x22, 0x3c, 0x00, 0x1c, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1c, + 0x00, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x3e, 0x20, 0x20, 0x3c, 0x20, 0x20, 0x3e, + 0x00, 0x3e, 0x20, 0x20, 0x3c, 0x20, 0x20, 0x20, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x26, 0x22, 0x1e, + 0x00, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, + 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3e, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, + 0x00, 0x22, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, + 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x2a, 0x24, 0x1a, + 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x28, 0x24, 0x22, 0x00, 0x1c, 0x22, 0x20, 0x1c, 0x02, 0x22, 0x1c, + 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, + 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, + 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x3e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3e, 0x00, 0x3e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, + 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3e, + 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, + 0x00, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, + 0x00, 0x08, 0x1e, 0x28, 0x1c, 0x0a, 0x3c, 0x08, 0x00, 0x30, 0x32, 0x04, 0x08, 0x10, 0x26, 0x06, + 0x00, 0x10, 0x28, 0x28, 0x10, 0x2a, 0x24, 0x1a, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, + 0x00, 0x08, 0x2a, 0x1c, 0x08, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, + 0x00, 0x1c, 0x22, 0x26, 0x2a, 0x32, 0x22, 0x1c, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1c, + 0x00, 0x1c, 0x22, 0x02, 0x0c, 0x10, 0x20, 0x3e, 0x00, 0x3e, 0x02, 0x04, 0x0c, 0x02, 0x22, 0x1e, + 0x00, 0x04, 0x0c, 0x14, 0x24, 0x3e, 0x04, 0x04, 0x00, 0x3e, 0x20, 0x3c, 0x02, 0x02, 0x22, 0x1c, + 0x00, 0x0e, 0x10, 0x20, 0x3c, 0x22, 0x22, 0x1c, 0x00, 0x3e, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, + 0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x1c, 0x00, 0x1c, 0x22, 0x22, 0x1e, 0x02, 0x04, 0x38, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x10, + 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x1c, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08, + 0x7f, 0x63, 0x5d, 0x55, 0x51, 0x53, 0x5f, 0x61, 0x7f, 0x77, 0x6b, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5d, 0x5d, 0x43, 0x7f, 0x63, 0x5d, 0x5f, 0x5f, 0x5f, 0x5d, 0x63, + 0x7f, 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x41, + 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x59, 0x5d, 0x61, + 0x7f, 0x5d, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x5d, 0x7f, 0x63, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, + 0x7f, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, 0x5d, 0x5b, 0x57, 0x4f, 0x57, 0x5b, 0x5d, + 0x7f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x41, 0x7f, 0x5d, 0x49, 0x55, 0x55, 0x5d, 0x5d, 0x5d, + 0x7f, 0x5d, 0x5d, 0x4d, 0x55, 0x59, 0x5d, 0x5d, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x55, 0x5b, 0x65, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x57, 0x5b, 0x5d, 0x7f, 0x63, 0x5d, 0x5f, 0x63, 0x7d, 0x5d, 0x63, + 0x7f, 0x41, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, + 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x5d, + 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x5d, 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x77, 0x77, 0x77, + 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x41, + 0x7f, 0x7f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7f, 0x7f, 0x41, 0x79, 0x79, 0x79, 0x79, 0x79, 0x41, + 0x7f, 0x7f, 0x7f, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x77, + 0x7f, 0x6b, 0x6b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x6b, 0x6b, 0x41, 0x6b, 0x41, 0x6b, 0x6b, + 0x7f, 0x77, 0x61, 0x57, 0x63, 0x75, 0x43, 0x77, 0x7f, 0x4f, 0x4d, 0x7b, 0x77, 0x6f, 0x59, 0x79, + 0x7f, 0x6f, 0x57, 0x57, 0x6f, 0x55, 0x5b, 0x65, 0x7f, 0x77, 0x77, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x77, 0x6f, 0x5f, 0x5f, 0x5f, 0x6f, 0x77, 0x7f, 0x77, 0x7b, 0x7d, 0x7d, 0x7d, 0x7b, 0x77, + 0x7f, 0x77, 0x55, 0x63, 0x77, 0x63, 0x55, 0x77, 0x7f, 0x7f, 0x77, 0x77, 0x41, 0x77, 0x77, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x6f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x7f, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x7f, + 0x7f, 0x63, 0x5d, 0x59, 0x55, 0x4d, 0x5d, 0x63, 0x7f, 0x77, 0x67, 0x77, 0x77, 0x77, 0x77, 0x63, + 0x7f, 0x63, 0x5d, 0x7d, 0x73, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x7d, 0x7b, 0x73, 0x7d, 0x5d, 0x61, + 0x7f, 0x7b, 0x73, 0x6b, 0x5b, 0x41, 0x7b, 0x7b, 0x7f, 0x41, 0x5f, 0x43, 0x7d, 0x7d, 0x5d, 0x63, + 0x7f, 0x71, 0x6f, 0x5f, 0x43, 0x5d, 0x5d, 0x63, 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x6f, 0x6f, + 0x7f, 0x63, 0x5d, 0x5d, 0x63, 0x5d, 0x5d, 0x63, 0x7f, 0x63, 0x5d, 0x5d, 0x61, 0x7d, 0x7b, 0x47, + 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x77, 0x6f, + 0x7f, 0x7b, 0x77, 0x6f, 0x5f, 0x6f, 0x77, 0x7b, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x41, 0x7f, 0x7f, + 0x7f, 0x6f, 0x77, 0x7b, 0x7d, 0x7b, 0x77, 0x6f, 0x7f, 0x63, 0x5d, 0x7b, 0x77, 0x77, 0x7f, 0x77, + 0x7f, 0x63, 0x5d, 0x55, 0x51, 0x53, 0x5f, 0x61, 0x7f, 0x77, 0x6b, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5d, 0x5d, 0x43, 0x7f, 0x63, 0x5d, 0x5f, 0x5f, 0x5f, 0x5d, 0x63, + 0x7f, 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x41, + 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x59, 0x5d, 0x61, + 0x7f, 0x5d, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x5d, 0x7f, 0x63, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, + 0x7f, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, 0x5d, 0x5b, 0x57, 0x4f, 0x57, 0x5b, 0x5d, + 0x7f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x41, 0x7f, 0x5d, 0x49, 0x55, 0x55, 0x5d, 0x5d, 0x5d, + 0x7f, 0x5d, 0x5d, 0x4d, 0x55, 0x59, 0x5d, 0x5d, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x55, 0x5b, 0x65, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x57, 0x5b, 0x5d, 0x7f, 0x63, 0x5d, 0x5f, 0x63, 0x7d, 0x5d, 0x63, + 0x7f, 0x41, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, + 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x5d, + 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x5d, 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x77, 0x77, 0x77, + 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x41, + 0x7f, 0x7f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7f, 0x7f, 0x41, 0x79, 0x79, 0x79, 0x79, 0x79, 0x41, + 0x7f, 0x7f, 0x7f, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x77, + 0x7f, 0x6b, 0x6b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x6b, 0x6b, 0x41, 0x6b, 0x41, 0x6b, 0x6b, + 0x7f, 0x77, 0x61, 0x57, 0x63, 0x75, 0x43, 0x77, 0x7f, 0x4f, 0x4d, 0x7b, 0x77, 0x6f, 0x59, 0x79, + 0x7f, 0x6f, 0x57, 0x57, 0x6f, 0x55, 0x5b, 0x65, 0x7f, 0x77, 0x77, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x77, 0x6f, 0x5f, 0x5f, 0x5f, 0x6f, 0x77, 0x7f, 0x77, 0x7b, 0x7d, 0x7d, 0x7d, 0x7b, 0x77, + 0x7f, 0x77, 0x55, 0x63, 0x77, 0x63, 0x55, 0x77, 0x7f, 0x7f, 0x77, 0x77, 0x41, 0x77, 0x77, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x6f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x7f, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x7f, + 0x7f, 0x63, 0x5d, 0x59, 0x55, 0x4d, 0x5d, 0x63, 0x7f, 0x77, 0x67, 0x77, 0x77, 0x77, 0x77, 0x63, + 0x7f, 0x63, 0x5d, 0x7d, 0x73, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x7d, 0x7b, 0x73, 0x7d, 0x5d, 0x61, + 0x7f, 0x7b, 0x73, 0x6b, 0x5b, 0x41, 0x7b, 0x7b, 0x7f, 0x41, 0x5f, 0x43, 0x7d, 0x7d, 0x5d, 0x63, + 0x7f, 0x71, 0x6f, 0x5f, 0x43, 0x5d, 0x5d, 0x63, 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x6f, 0x6f, + 0x7f, 0x63, 0x5d, 0x5d, 0x63, 0x5d, 0x5d, 0x63, 0x7f, 0x63, 0x5d, 0x5d, 0x61, 0x7d, 0x7b, 0x47, + 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x77, 0x6f, + 0x7f, 0x7b, 0x77, 0x6f, 0x5f, 0x6f, 0x77, 0x7b, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x41, 0x7f, 0x7f, + 0x7f, 0x6f, 0x77, 0x7b, 0x7d, 0x7b, 0x77, 0x6f, 0x7f, 0x63, 0x5d, 0x7b, 0x77, 0x77, 0x7f, 0x77, + 0x7f, 0x63, 0x5d, 0x55, 0x51, 0x53, 0x5f, 0x61, 0x7f, 0x77, 0x6b, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5d, 0x5d, 0x43, 0x7f, 0x63, 0x5d, 0x5f, 0x5f, 0x5f, 0x5d, 0x63, + 0x7f, 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x41, + 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x59, 0x5d, 0x61, + 0x7f, 0x5d, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x5d, 0x7f, 0x63, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, + 0x7f, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, 0x5d, 0x5b, 0x57, 0x4f, 0x57, 0x5b, 0x5d, + 0x7f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x41, 0x7f, 0x5d, 0x49, 0x55, 0x55, 0x5d, 0x5d, 0x5d, + 0x7f, 0x5d, 0x5d, 0x4d, 0x55, 0x59, 0x5d, 0x5d, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x55, 0x5b, 0x65, + 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x57, 0x5b, 0x5d, 0x7f, 0x63, 0x5d, 0x5f, 0x63, 0x7d, 0x5d, 0x63, + 0x7f, 0x41, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, + 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x5d, + 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x5d, 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x77, 0x77, 0x77, + 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x41, + 0x7f, 0x7f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7f, 0x7f, 0x41, 0x79, 0x79, 0x79, 0x79, 0x79, 0x41, + 0x7f, 0x7f, 0x7f, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x77, + 0x7f, 0x6b, 0x6b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x6b, 0x6b, 0x41, 0x6b, 0x41, 0x6b, 0x6b, + 0x7f, 0x77, 0x61, 0x57, 0x63, 0x75, 0x43, 0x77, 0x7f, 0x4f, 0x4d, 0x7b, 0x77, 0x6f, 0x59, 0x79, + 0x7f, 0x6f, 0x57, 0x57, 0x6f, 0x55, 0x5b, 0x65, 0x7f, 0x77, 0x77, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x77, 0x6f, 0x5f, 0x5f, 0x5f, 0x6f, 0x77, 0x7f, 0x77, 0x7b, 0x7d, 0x7d, 0x7d, 0x7b, 0x77, + 0x7f, 0x77, 0x55, 0x63, 0x77, 0x63, 0x55, 0x77, 0x7f, 0x7f, 0x77, 0x77, 0x41, 0x77, 0x77, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x6f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x7f, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x7f, + 0x7f, 0x63, 0x5d, 0x59, 0x55, 0x4d, 0x5d, 0x63, 0x7f, 0x77, 0x67, 0x77, 0x77, 0x77, 0x77, 0x63, + 0x7f, 0x63, 0x5d, 0x7d, 0x73, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x7d, 0x7b, 0x73, 0x7d, 0x5d, 0x61, + 0x7f, 0x7b, 0x73, 0x6b, 0x5b, 0x41, 0x7b, 0x7b, 0x7f, 0x41, 0x5f, 0x43, 0x7d, 0x7d, 0x5d, 0x63, + 0x7f, 0x71, 0x6f, 0x5f, 0x43, 0x5d, 0x5d, 0x63, 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x6f, 0x6f, + 0x7f, 0x63, 0x5d, 0x5d, 0x63, 0x5d, 0x5d, 0x63, 0x7f, 0x63, 0x5d, 0x5d, 0x61, 0x7d, 0x7b, 0x47, + 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x77, 0x6f, + 0x7f, 0x7b, 0x77, 0x6f, 0x5f, 0x6f, 0x77, 0x7b, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x41, 0x7f, 0x7f, + 0x7f, 0x6f, 0x77, 0x7b, 0x7d, 0x7b, 0x77, 0x6f, 0x7f, 0x63, 0x5d, 0x7b, 0x77, 0x77, 0x7f, 0x77 +}; + +const uint8_t appleiie_character_rom[2048] = { + 0x1c, 0x22, 0x2a, 0x2e, 0x2c, 0x20, 0x1e, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, + 0x3c, 0x22, 0x22, 0x3c, 0x22, 0x22, 0x3c, 0x00, 0x1c, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, + 0x3c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x3e, 0x20, 0x20, 0x3c, 0x20, 0x20, 0x3e, 0x00, + 0x3e, 0x20, 0x20, 0x3c, 0x20, 0x20, 0x20, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x26, 0x22, 0x1e, 0x00, + 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3e, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, + 0x22, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, + 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x2a, 0x24, 0x1a, 0x00, + 0x3c, 0x22, 0x22, 0x3c, 0x28, 0x24, 0x22, 0x00, 0x1c, 0x22, 0x20, 0x1c, 0x02, 0x22, 0x1c, 0x00, + 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, + 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, + 0x3e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3e, 0x00, 0x3e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00, + 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3e, 0x00, + 0x00, 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, + 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, + 0x08, 0x1e, 0x28, 0x1c, 0x0a, 0x3c, 0x08, 0x00, 0x30, 0x32, 0x04, 0x08, 0x10, 0x26, 0x06, 0x00, + 0x10, 0x28, 0x28, 0x10, 0x2a, 0x24, 0x1a, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, + 0x08, 0x2a, 0x1c, 0x08, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, + 0x1c, 0x22, 0x26, 0x2a, 0x32, 0x22, 0x1c, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, + 0x1c, 0x22, 0x02, 0x0c, 0x10, 0x20, 0x3e, 0x00, 0x3e, 0x02, 0x04, 0x0c, 0x02, 0x22, 0x1c, 0x00, + 0x04, 0x0c, 0x14, 0x24, 0x3e, 0x04, 0x04, 0x00, 0x3e, 0x20, 0x3c, 0x02, 0x02, 0x22, 0x1c, 0x00, + 0x0e, 0x10, 0x20, 0x3c, 0x22, 0x22, 0x1c, 0x00, 0x3e, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00, + 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x1c, 0x00, 0x1c, 0x22, 0x22, 0x1e, 0x02, 0x04, 0x38, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x10, 0x00, + 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x1c, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, + 0x7b, 0x77, 0x49, 0x00, 0x01, 0x01, 0x40, 0x49, 0x7b, 0x77, 0x49, 0x3e, 0x3d, 0x3d, 0x56, 0x49, + 0x7f, 0x7f, 0x5f, 0x4f, 0x47, 0x43, 0x49, 0x5e, 0x00, 0x5d, 0x6b, 0x77, 0x77, 0x6b, 0x55, 0x00, + 0x7f, 0x7e, 0x7d, 0x3b, 0x57, 0x6f, 0x6f, 0x7f, 0x00, 0x01, 0x02, 0x64, 0x28, 0x10, 0x10, 0x00, + 0x78, 0x7c, 0x40, 0x39, 0x30, 0x79, 0x01, 0x5f, 0x7f, 0x73, 0x0f, 0x7f, 0x0f, 0x67, 0x77, 0x78, + 0x77, 0x6f, 0x5f, 0x00, 0x5f, 0x6f, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, + 0x77, 0x77, 0x77, 0x77, 0x36, 0x55, 0x63, 0x77, 0x77, 0x63, 0x55, 0x36, 0x77, 0x77, 0x77, 0x77, + 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x6e, 0x4e, 0x00, 0x4f, 0x6f, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1b, 0x73, 0x63, 0x40, 0x63, 0x73, 0x7b, 0x04, + 0x6c, 0x67, 0x63, 0x01, 0x63, 0x67, 0x6f, 0x10, 0x7e, 0x76, 0x77, 0x00, 0x41, 0x63, 0x76, 0x7e, + 0x7e, 0x76, 0x63, 0x41, 0x00, 0x77, 0x76, 0x7e, 0x7f, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x77, 0x7b, 0x7d, 0x00, 0x7d, 0x7b, 0x77, 0x7f, + 0x55, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x55, + 0x7f, 0x41, 0x3e, 0x3f, 0x3f, 0x3f, 0x00, 0x7f, 0x7f, 0x7f, 0x01, 0x7e, 0x7e, 0x7e, 0x00, 0x7f, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x77, 0x63, 0x41, 0x00, 0x41, 0x63, 0x77, 0x7f, + 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x6b, 0x6b, 0x08, 0x7f, 0x08, 0x6b, 0x6b, 0x7f, + 0x00, 0x7e, 0x7e, 0x66, 0x66, 0x7e, 0x7e, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x1e, 0x22, 0x1e, 0x00, + 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x1e, 0x00, + 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x20, 0x1e, 0x00, + 0x0c, 0x12, 0x10, 0x3c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x1e, 0x02, 0x1c, + 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1c, 0x00, + 0x04, 0x00, 0x0c, 0x04, 0x04, 0x04, 0x24, 0x18, 0x20, 0x20, 0x22, 0x24, 0x38, 0x24, 0x22, 0x00, + 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x36, 0x2a, 0x2a, 0x2a, 0x22, 0x00, + 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, + 0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, + 0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x1c, 0x02, 0x3c, 0x00, + 0x10, 0x10, 0x3c, 0x10, 0x10, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1a, 0x00, + 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x00, + 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x1c, + 0x00, 0x00, 0x3e, 0x04, 0x08, 0x10, 0x3e, 0x00, 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x0c, 0x0c, 0x06, 0x0c, 0x0c, 0x38, 0x00, + 0x1a, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x14, 0x2a, 0x14, 0x2a, 0x00, 0x00, + 0x63, 0x5d, 0x55, 0x51, 0x53, 0x5f, 0x61, 0x7f, 0x77, 0x6b, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5d, 0x5d, 0x43, 0x7f, 0x63, 0x5d, 0x5f, 0x5f, 0x5f, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x41, 0x7f, + 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x59, 0x5d, 0x61, 0x7f, + 0x5d, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x5d, 0x7f, 0x63, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, 0x5d, 0x5b, 0x57, 0x4f, 0x57, 0x5b, 0x5d, 0x7f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x41, 0x7f, 0x5d, 0x49, 0x55, 0x55, 0x5d, 0x5d, 0x5d, 0x7f, + 0x5d, 0x5d, 0x4d, 0x55, 0x59, 0x5d, 0x5d, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x55, 0x5b, 0x65, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x57, 0x5b, 0x5d, 0x7f, 0x63, 0x5d, 0x5f, 0x63, 0x7d, 0x5d, 0x63, 0x7f, + 0x41, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x5d, 0x7f, + 0x5d, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x5d, 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x77, 0x77, 0x77, 0x7f, + 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x41, 0x7f, + 0x7f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7f, 0x7f, 0x41, 0x79, 0x79, 0x79, 0x79, 0x79, 0x41, 0x7f, + 0x7f, 0x7f, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x77, 0x7f, + 0x6b, 0x6b, 0x6b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x6b, 0x6b, 0x41, 0x6b, 0x41, 0x6b, 0x6b, 0x7f, + 0x77, 0x61, 0x57, 0x63, 0x75, 0x43, 0x77, 0x7f, 0x4f, 0x4d, 0x7b, 0x77, 0x6f, 0x59, 0x79, 0x7f, + 0x6f, 0x57, 0x57, 0x6f, 0x55, 0x5b, 0x65, 0x7f, 0x77, 0x77, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x77, 0x6f, 0x5f, 0x5f, 0x5f, 0x6f, 0x77, 0x7f, 0x77, 0x7b, 0x7d, 0x7d, 0x7d, 0x7b, 0x77, 0x7f, + 0x77, 0x55, 0x63, 0x77, 0x63, 0x55, 0x77, 0x7f, 0x7f, 0x77, 0x77, 0x41, 0x77, 0x77, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x6f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x7f, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x7f, 0x7f, + 0x63, 0x5d, 0x59, 0x55, 0x4d, 0x5d, 0x63, 0x7f, 0x77, 0x67, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x63, 0x5d, 0x7d, 0x73, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x7d, 0x7b, 0x73, 0x7d, 0x5d, 0x63, 0x7f, + 0x7b, 0x73, 0x6b, 0x5b, 0x41, 0x7b, 0x7b, 0x7f, 0x41, 0x5f, 0x43, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, + 0x71, 0x6f, 0x5f, 0x43, 0x5d, 0x5d, 0x63, 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x6f, 0x6f, 0x7f, + 0x63, 0x5d, 0x5d, 0x63, 0x5d, 0x5d, 0x63, 0x7f, 0x63, 0x5d, 0x5d, 0x61, 0x7d, 0x7b, 0x47, 0x7f, + 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x77, 0x6f, 0x7f, + 0x7b, 0x77, 0x6f, 0x5f, 0x6f, 0x77, 0x7b, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x41, 0x7f, 0x7f, 0x7f, + 0x6f, 0x77, 0x7b, 0x7d, 0x7b, 0x77, 0x6f, 0x7f, 0x63, 0x5d, 0x7b, 0x77, 0x77, 0x7f, 0x77, 0x7f, + 0x63, 0x5d, 0x55, 0x51, 0x53, 0x5f, 0x61, 0x7f, 0x77, 0x6b, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5d, 0x5d, 0x43, 0x7f, 0x63, 0x5d, 0x5f, 0x5f, 0x5f, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x41, 0x7f, + 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x59, 0x5d, 0x61, 0x7f, + 0x5d, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x5d, 0x7f, 0x63, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, 0x5d, 0x5b, 0x57, 0x4f, 0x57, 0x5b, 0x5d, 0x7f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x41, 0x7f, 0x5d, 0x49, 0x55, 0x55, 0x5d, 0x5d, 0x5d, 0x7f, + 0x5d, 0x5d, 0x4d, 0x55, 0x59, 0x5d, 0x5d, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x55, 0x5b, 0x65, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x57, 0x5b, 0x5d, 0x7f, 0x63, 0x5d, 0x5f, 0x63, 0x7d, 0x5d, 0x63, 0x7f, + 0x41, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x5d, 0x7f, + 0x5d, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x5d, 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x77, 0x77, 0x77, 0x7f, + 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x41, 0x7f, + 0x7f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7f, 0x7f, 0x41, 0x79, 0x79, 0x79, 0x79, 0x79, 0x41, 0x7f, + 0x7f, 0x7f, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, + 0x6f, 0x77, 0x7b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x63, 0x7d, 0x61, 0x5d, 0x61, 0x7f, + 0x5f, 0x5f, 0x43, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x7f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x61, 0x7f, + 0x7d, 0x7d, 0x61, 0x5d, 0x5d, 0x5d, 0x61, 0x7f, 0x7f, 0x7f, 0x63, 0x5d, 0x41, 0x5f, 0x61, 0x7f, + 0x73, 0x6d, 0x6f, 0x43, 0x6f, 0x6f, 0x6f, 0x7f, 0x7f, 0x7f, 0x63, 0x5d, 0x5d, 0x61, 0x7d, 0x63, + 0x5f, 0x5f, 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x7f, 0x77, 0x7f, 0x67, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x7b, 0x7f, 0x73, 0x7b, 0x7b, 0x7b, 0x5b, 0x67, 0x5f, 0x5f, 0x5d, 0x5b, 0x47, 0x5b, 0x5d, 0x7f, + 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, 0x7f, 0x7f, 0x49, 0x55, 0x55, 0x55, 0x5d, 0x7f, + 0x7f, 0x7f, 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x7f, 0x7f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x7f, 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x7f, 0x7f, 0x61, 0x5d, 0x5d, 0x61, 0x7d, 0x7d, + 0x7f, 0x7f, 0x51, 0x4f, 0x5f, 0x5f, 0x5f, 0x7f, 0x7f, 0x7f, 0x61, 0x5f, 0x63, 0x7d, 0x43, 0x7f, + 0x6f, 0x6f, 0x43, 0x6f, 0x6f, 0x6d, 0x73, 0x7f, 0x7f, 0x7f, 0x5d, 0x5d, 0x5d, 0x59, 0x65, 0x7f, + 0x7f, 0x7f, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x7f, 0x7f, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x7f, + 0x7f, 0x7f, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x5d, 0x5d, 0x5d, 0x61, 0x7d, 0x63, + 0x7f, 0x7f, 0x41, 0x7b, 0x77, 0x6f, 0x41, 0x7f, 0x71, 0x67, 0x67, 0x4f, 0x67, 0x67, 0x71, 0x7f, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x47, 0x73, 0x73, 0x79, 0x73, 0x73, 0x47, 0x7f, + 0x65, 0x53, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, 0x6b, 0x55, 0x6b, 0x55, 0x7f, 0x7f +}; + +const uint8_t appleiigs_character_rom[2048] = { + 0x1c, 0x22, 0x2a, 0x2e, 0x2c, 0x20, 0x1e, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, + 0x3c, 0x22, 0x22, 0x3c, 0x22, 0x22, 0x3c, 0x00, 0x1c, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, + 0x3c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x3e, 0x20, 0x20, 0x3c, 0x20, 0x20, 0x3e, 0x00, + 0x3e, 0x20, 0x20, 0x3c, 0x20, 0x20, 0x20, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x26, 0x22, 0x1e, 0x00, + 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3e, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, + 0x22, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, + 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x2a, 0x24, 0x1a, 0x00, + 0x3c, 0x22, 0x22, 0x3c, 0x28, 0x24, 0x22, 0x00, 0x1c, 0x22, 0x20, 0x1c, 0x02, 0x22, 0x1c, 0x00, + 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, + 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, + 0x3e, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3e, 0x00, 0x3e, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00, + 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3e, 0x00, + 0x00, 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, + 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, + 0x08, 0x1e, 0x28, 0x1c, 0x0a, 0x3c, 0x08, 0x00, 0x30, 0x32, 0x04, 0x08, 0x10, 0x26, 0x06, 0x00, + 0x10, 0x28, 0x28, 0x10, 0x2a, 0x24, 0x1a, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, + 0x08, 0x2a, 0x1c, 0x08, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, + 0x1c, 0x22, 0x26, 0x2a, 0x32, 0x22, 0x1c, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, + 0x1c, 0x22, 0x02, 0x0c, 0x10, 0x20, 0x3e, 0x00, 0x3e, 0x02, 0x04, 0x0c, 0x02, 0x22, 0x1c, 0x00, + 0x04, 0x0c, 0x14, 0x24, 0x3e, 0x04, 0x04, 0x00, 0x3e, 0x20, 0x3c, 0x02, 0x02, 0x22, 0x1c, 0x00, + 0x0e, 0x10, 0x20, 0x3c, 0x22, 0x22, 0x1c, 0x00, 0x3e, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00, + 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x1c, 0x00, 0x1c, 0x22, 0x22, 0x1e, 0x02, 0x04, 0x38, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x10, 0x00, + 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x1c, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, + 0x7b, 0x77, 0x49, 0x00, 0x01, 0x01, 0x40, 0x49, 0x7b, 0x77, 0x49, 0x3e, 0x3d, 0x3d, 0x56, 0x49, + 0x7f, 0x7f, 0x5f, 0x4f, 0x47, 0x43, 0x49, 0x5e, 0x00, 0x5d, 0x6b, 0x77, 0x77, 0x6b, 0x55, 0x00, + 0x7f, 0x7e, 0x7d, 0x3b, 0x57, 0x6f, 0x6f, 0x7f, 0x00, 0x01, 0x02, 0x64, 0x28, 0x10, 0x10, 0x00, + 0x01, 0x01, 0x01, 0x11, 0x31, 0x7f, 0x30, 0x10, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x7f, 0x00, + 0x77, 0x6f, 0x5f, 0x00, 0x5f, 0x6f, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, + 0x77, 0x77, 0x77, 0x77, 0x36, 0x55, 0x63, 0x77, 0x77, 0x63, 0x55, 0x36, 0x77, 0x77, 0x77, 0x77, + 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x6e, 0x4e, 0x00, 0x4f, 0x6f, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1b, 0x73, 0x63, 0x40, 0x63, 0x73, 0x7b, 0x04, + 0x6c, 0x67, 0x63, 0x01, 0x63, 0x67, 0x6f, 0x10, 0x7e, 0x76, 0x77, 0x00, 0x41, 0x63, 0x76, 0x7e, + 0x7e, 0x76, 0x63, 0x41, 0x00, 0x77, 0x76, 0x7e, 0x7f, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x77, 0x7b, 0x7d, 0x00, 0x7d, 0x7b, 0x77, 0x7f, + 0x55, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x55, 0x2a, 0x55, + 0x7f, 0x41, 0x3e, 0x3f, 0x3f, 0x3f, 0x00, 0x7f, 0x7f, 0x7f, 0x01, 0x7e, 0x7e, 0x7e, 0x00, 0x7f, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x77, 0x63, 0x41, 0x00, 0x41, 0x63, 0x77, 0x7f, + 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x6b, 0x6b, 0x08, 0x7f, 0x08, 0x6b, 0x6b, 0x7f, + 0x00, 0x7e, 0x7e, 0x66, 0x66, 0x7e, 0x7e, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x1e, 0x22, 0x1e, 0x00, + 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x1e, 0x00, + 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x20, 0x1e, 0x00, + 0x0c, 0x12, 0x10, 0x3c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x1e, 0x02, 0x1c, + 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1c, 0x00, + 0x04, 0x00, 0x0c, 0x04, 0x04, 0x04, 0x24, 0x18, 0x20, 0x20, 0x22, 0x24, 0x38, 0x24, 0x22, 0x00, + 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x36, 0x2a, 0x2a, 0x2a, 0x22, 0x00, + 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, + 0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, + 0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x1c, 0x02, 0x3c, 0x00, + 0x10, 0x10, 0x3c, 0x10, 0x10, 0x12, 0x0c, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1a, 0x00, + 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x00, + 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x1c, + 0x00, 0x00, 0x3e, 0x04, 0x08, 0x10, 0x3e, 0x00, 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x0c, 0x0c, 0x06, 0x0c, 0x0c, 0x38, 0x00, + 0x1a, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x14, 0x2a, 0x14, 0x2a, 0x00, 0x00, + 0x63, 0x5d, 0x55, 0x51, 0x53, 0x5f, 0x61, 0x7f, 0x77, 0x6b, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5d, 0x5d, 0x43, 0x7f, 0x63, 0x5d, 0x5f, 0x5f, 0x5f, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x41, 0x7f, + 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x59, 0x5d, 0x61, 0x7f, + 0x5d, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x5d, 0x7f, 0x63, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, 0x5d, 0x5b, 0x57, 0x4f, 0x57, 0x5b, 0x5d, 0x7f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x41, 0x7f, 0x5d, 0x49, 0x55, 0x55, 0x5d, 0x5d, 0x5d, 0x7f, + 0x5d, 0x5d, 0x4d, 0x55, 0x59, 0x5d, 0x5d, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x55, 0x5b, 0x65, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x57, 0x5b, 0x5d, 0x7f, 0x63, 0x5d, 0x5f, 0x63, 0x7d, 0x5d, 0x63, 0x7f, + 0x41, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x5d, 0x7f, + 0x5d, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x5d, 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x77, 0x77, 0x77, 0x7f, + 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x41, 0x7f, + 0x7f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7f, 0x7f, 0x41, 0x79, 0x79, 0x79, 0x79, 0x79, 0x41, 0x7f, + 0x7f, 0x7f, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x77, 0x7f, + 0x6b, 0x6b, 0x6b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x6b, 0x6b, 0x41, 0x6b, 0x41, 0x6b, 0x6b, 0x7f, + 0x77, 0x61, 0x57, 0x63, 0x75, 0x43, 0x77, 0x7f, 0x4f, 0x4d, 0x7b, 0x77, 0x6f, 0x59, 0x79, 0x7f, + 0x6f, 0x57, 0x57, 0x6f, 0x55, 0x5b, 0x65, 0x7f, 0x77, 0x77, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x77, 0x6f, 0x5f, 0x5f, 0x5f, 0x6f, 0x77, 0x7f, 0x77, 0x7b, 0x7d, 0x7d, 0x7d, 0x7b, 0x77, 0x7f, + 0x77, 0x55, 0x63, 0x77, 0x63, 0x55, 0x77, 0x7f, 0x7f, 0x77, 0x77, 0x41, 0x77, 0x77, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x77, 0x6f, 0x7f, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x7f, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x7f, 0x7f, + 0x63, 0x5d, 0x59, 0x55, 0x4d, 0x5d, 0x63, 0x7f, 0x77, 0x67, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x63, 0x5d, 0x7d, 0x73, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x7d, 0x7b, 0x73, 0x7d, 0x5d, 0x63, 0x7f, + 0x7b, 0x73, 0x6b, 0x5b, 0x41, 0x7b, 0x7b, 0x7f, 0x41, 0x5f, 0x43, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, + 0x71, 0x6f, 0x5f, 0x43, 0x5d, 0x5d, 0x63, 0x7f, 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x6f, 0x6f, 0x7f, + 0x63, 0x5d, 0x5d, 0x63, 0x5d, 0x5d, 0x63, 0x7f, 0x63, 0x5d, 0x5d, 0x61, 0x7d, 0x7b, 0x47, 0x7f, + 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x77, 0x7f, 0x77, 0x77, 0x6f, 0x7f, + 0x7b, 0x77, 0x6f, 0x5f, 0x6f, 0x77, 0x7b, 0x7f, 0x7f, 0x7f, 0x41, 0x7f, 0x41, 0x7f, 0x7f, 0x7f, + 0x6f, 0x77, 0x7b, 0x7d, 0x7b, 0x77, 0x6f, 0x7f, 0x63, 0x5d, 0x7b, 0x77, 0x77, 0x7f, 0x77, 0x7f, + 0x63, 0x5d, 0x55, 0x51, 0x53, 0x5f, 0x61, 0x7f, 0x77, 0x6b, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5d, 0x5d, 0x43, 0x7f, 0x63, 0x5d, 0x5f, 0x5f, 0x5f, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x41, 0x7f, + 0x41, 0x5f, 0x5f, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x59, 0x5d, 0x61, 0x7f, + 0x5d, 0x5d, 0x5d, 0x41, 0x5d, 0x5d, 0x5d, 0x7f, 0x63, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x5d, 0x63, 0x7f, 0x5d, 0x5b, 0x57, 0x4f, 0x57, 0x5b, 0x5d, 0x7f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x41, 0x7f, 0x5d, 0x49, 0x55, 0x55, 0x5d, 0x5d, 0x5d, 0x7f, + 0x5d, 0x5d, 0x4d, 0x55, 0x59, 0x5d, 0x5d, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x5f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x55, 0x5b, 0x65, 0x7f, + 0x43, 0x5d, 0x5d, 0x43, 0x57, 0x5b, 0x5d, 0x7f, 0x63, 0x5d, 0x5f, 0x63, 0x7d, 0x5d, 0x63, 0x7f, + 0x41, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x5d, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x5d, 0x7f, + 0x5d, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x5d, 0x7f, 0x5d, 0x5d, 0x6b, 0x77, 0x77, 0x77, 0x77, 0x7f, + 0x41, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x41, 0x7f, 0x41, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x41, 0x7f, + 0x7f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7f, 0x7f, 0x41, 0x79, 0x79, 0x79, 0x79, 0x79, 0x41, 0x7f, + 0x7f, 0x7f, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, + 0x6f, 0x77, 0x7b, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x63, 0x7d, 0x61, 0x5d, 0x61, 0x7f, + 0x5f, 0x5f, 0x43, 0x5d, 0x5d, 0x5d, 0x43, 0x7f, 0x7f, 0x7f, 0x61, 0x5f, 0x5f, 0x5f, 0x61, 0x7f, + 0x7d, 0x7d, 0x61, 0x5d, 0x5d, 0x5d, 0x61, 0x7f, 0x7f, 0x7f, 0x63, 0x5d, 0x41, 0x5f, 0x61, 0x7f, + 0x73, 0x6d, 0x6f, 0x43, 0x6f, 0x6f, 0x6f, 0x7f, 0x7f, 0x7f, 0x63, 0x5d, 0x5d, 0x61, 0x7d, 0x63, + 0x5f, 0x5f, 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x7f, 0x77, 0x7f, 0x67, 0x77, 0x77, 0x77, 0x63, 0x7f, + 0x7b, 0x7f, 0x73, 0x7b, 0x7b, 0x7b, 0x5b, 0x67, 0x5f, 0x5f, 0x5d, 0x5b, 0x47, 0x5b, 0x5d, 0x7f, + 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x63, 0x7f, 0x7f, 0x7f, 0x49, 0x55, 0x55, 0x55, 0x5d, 0x7f, + 0x7f, 0x7f, 0x43, 0x5d, 0x5d, 0x5d, 0x5d, 0x7f, 0x7f, 0x7f, 0x63, 0x5d, 0x5d, 0x5d, 0x63, 0x7f, + 0x7f, 0x7f, 0x43, 0x5d, 0x5d, 0x43, 0x5f, 0x5f, 0x7f, 0x7f, 0x61, 0x5d, 0x5d, 0x61, 0x7d, 0x7d, + 0x7f, 0x7f, 0x51, 0x4f, 0x5f, 0x5f, 0x5f, 0x7f, 0x7f, 0x7f, 0x61, 0x5f, 0x63, 0x7d, 0x43, 0x7f, + 0x6f, 0x6f, 0x43, 0x6f, 0x6f, 0x6d, 0x73, 0x7f, 0x7f, 0x7f, 0x5d, 0x5d, 0x5d, 0x59, 0x65, 0x7f, + 0x7f, 0x7f, 0x5d, 0x5d, 0x5d, 0x6b, 0x77, 0x7f, 0x7f, 0x7f, 0x5d, 0x5d, 0x55, 0x55, 0x49, 0x7f, + 0x7f, 0x7f, 0x5d, 0x6b, 0x77, 0x6b, 0x5d, 0x7f, 0x7f, 0x7f, 0x5d, 0x5d, 0x5d, 0x61, 0x7d, 0x63, + 0x7f, 0x7f, 0x41, 0x7b, 0x77, 0x6f, 0x41, 0x7f, 0x71, 0x67, 0x67, 0x4f, 0x67, 0x67, 0x71, 0x7f, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x47, 0x73, 0x73, 0x79, 0x73, 0x73, 0x47, 0x7f, + 0x65, 0x53, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, 0x6b, 0x55, 0x6b, 0x55, 0x7f, 0x7f +}; + diff --git a/v2-analog-rev1/vga/character_rom.h b/v2-analog-rev1/vga/character_rom.h index 188597f..0178870 100644 --- a/v2-analog-rev1/vga/character_rom.h +++ b/v2-analog-rev1/vga/character_rom.h @@ -2,5 +2,6 @@ #include - -extern const uint8_t default_character_rom[256*8]; +extern const uint8_t default_character_rom[2048]; +extern const uint8_t appleiie_character_rom[2048]; +extern const uint8_t appleiigs_character_rom[2048]; diff --git a/v2-analog-rev1/vga/render.c b/v2-analog-rev1/vga/render.c index 2d069b6..589b4d9 100644 --- a/v2-analog-rev1/vga/render.c +++ b/v2-analog-rev1/vga/render.c @@ -6,18 +6,61 @@ #include "vga/render.h" #include "vga/character_rom.h" #include "vga/vgaout.h" +#include "pico_hal.h" uint16_t text_fore; uint16_t text_back; uint16_t text_border; +compat_t machinefont = APPLE_II; +bool userfont = false; + +// Initialize the character generator ROM +void switch_font() { + switch(machine) { + default: + case APPLE_II: + memcpy(character_rom, default_character_rom, 2048); + break; + case APPLE_IIE: + memcpy(character_rom, appleiie_character_rom, 2048); + break; + case APPLE_IIGS: + memcpy(character_rom, appleiigs_character_rom, 2048); + break; + } + machinefont = machine; +} + +void load_font() { + int file = pico_open("font", LFS_O_RDONLY); + int br = 0; + + userfont = false; + + if(file < 0) { + return; + } + + br = pico_read(file, character_rom, 2048); + if(br == 2048) { + userfont = true; + } + + pico_close(file); + return; +} + void render_init() { int i; - // Initialize the character generator ROM - memcpy(character_rom, default_character_rom, sizeof(character_rom)); - soft_switches = 0; - terminal_switches = TERMINAL_TEST | TERMINAL_IIE_REGS | TERMINAL_IIGS_REGS; - terminal_tbcolor = 0x0f; + + load_font(); + if(!userfont) + switch_font(); + + if((soft_switches & SOFTSW_MODE_MASK) == 0) + soft_switches |= SOFTSW_TEST; + terminal_tbcolor = 0xf0; terminal_border = 0x00; render_test_init(); @@ -26,58 +69,62 @@ void render_init() { 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(terminal_switches & TERMINAL_TEST) { + if(soft_switches & SOFTSW_TEST) { 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)) { - terminal_switches &= (~(uint32_t)TERMINAL_TEST); + 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(); } else { switch(soft_switches & SOFTSW_MODE_MASK) { case 0: - if(terminal_switches & TERMINAL_DGR) { + if(soft_switches & SOFTSW_DGR) { render_dgr(); } else { render_lores(); } break; case SOFTSW_MIX_MODE: - if(terminal_switches & (TERMINAL_80COL | TERMINAL_DGR) == (TERMINAL_80COL | TERMINAL_DGR)) { + if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) { render_mixed_dgr(); } else { render_mixed_lores(); } break; case SOFTSW_HIRES_MODE: - if(terminal_switches & TERMINAL_DGR) { + if(soft_switches & SOFTSW_DGR) { render_dhgr(); } else { render_hires(); } break; case SOFTSW_HIRES_MODE|SOFTSW_MIX_MODE: - if(terminal_switches & TERMINAL_DGR) { + if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) { render_mixed_dhgr(); } else { render_mixed_hires(); } break; default: - if(terminal_switches & TERMINAL_80COL) { - render_terminal(); - } else { - render_text(); - } + render_text(); break; } } diff --git a/v2-analog-rev1/vga/render.h b/v2-analog-rev1/vga/render.h index 1957732..13ef480 100644 --- a/v2-analog-rev1/vga/render.h +++ b/v2-analog-rev1/vga/render.h @@ -17,10 +17,11 @@ extern void render_about_init(); extern void update_text_flasher(); extern void render_text(); -extern void render_text_line(unsigned int line); +extern void render_text40_line(bool p2, unsigned int line); +extern void render_text80_line(bool p2, unsigned int line); -extern void render_terminal(); -extern void render_terminal_line(unsigned int line); +extern void render_videx(); +extern void render_videx_line(unsigned int line); extern void render_border(); @@ -36,6 +37,8 @@ extern void render_mixed_dhgr(); extern void render_dgr(); extern void render_mixed_dgr(); +extern void render_shr(); + extern uint_fast32_t text_flasher_mask; extern void flash_dowork(); diff --git a/v2-analog-rev1/vga/render_dgr.c b/v2-analog-rev1/vga/render_dgr.c index 3d49076..9974dd3 100644 --- a/v2-analog-rev1/vga/render_dgr.c +++ b/v2-analog-rev1/vga/render_dgr.c @@ -6,22 +6,20 @@ extern uint16_t lores_palette[16]; -static void render_dgr_line(uint line); +static void render_dgr_line(bool p2, uint line); void __time_critical_func(render_dgr)() { vga_prepare_frame(); - // Skip 48 lines to center vertically - struct vga_scanline *skip_sl = vga_prepare_scanline(); - for(int i=0; i < 48; i++) { - skip_sl->data[i] = (uint32_t)THEN_WAIT_HSYNC << 16; - } - skip_sl->length = 48; - vga_submit_scanline(skip_sl); + render_border(); + + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); for(uint line=0; line < 24; line++) { - render_dgr_line(line); + render_dgr_line(p2, line); } + + render_border(); } @@ -30,17 +28,19 @@ void __time_critical_func(render_mixed_dgr)() { render_border(); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + for(uint line=0; line < 20; line++) { - render_dgr_line(line); + render_dgr_line(p2, line); } - if(terminal_switches & TERMINAL_80COL) { + if(soft_switches & SOFTSW_80COL) { for(uint line=20; line < 24; line++) { - render_terminal_line(line); + render_text80_line(p2, line); } } else { for(uint line=20; line < 24; line++) { - render_text_line(line); + render_text40_line(p2, line); } } @@ -48,28 +48,28 @@ void __time_critical_func(render_mixed_dgr)() { } -static void __time_critical_func(render_dgr_line)(uint line) { +static void __time_critical_func(render_dgr_line)(bool p2, uint line) { // Construct two scanlines for the two different colored cells at the same time struct vga_scanline *sl1 = vga_prepare_scanline(); struct vga_scanline *sl2 = vga_prepare_scanline(); uint sl_pos = 0; uint i; - const uint8_t *page = (const uint8_t *)text_memory; - const uint8_t *line_buf = page + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40); + const uint8_t *line_bufa = (const uint8_t *)((p2 ? text_p2 : text_p1) + ((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 - while(sl_pos < 40/8) { + for(i = 0; i < 40/8; i++) { 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++; } for(i=0; i < 40; i++) { - uint32_t color1 = lores_palette[line_buf[i | (1 << 10)] & 0xf]; - uint32_t color2 = lores_palette[(line_buf[i | (1 << 10)] >> 4) & 0xf]; - uint32_t color3 = lores_palette[line_buf[i] & 0xf]; - uint32_t color4 = lores_palette[(line_buf[i] >> 4) & 0xf]; + uint32_t color1 = lores_palette[line_bufb[i] & 0xf]; + uint32_t color2 = lores_palette[(line_bufb[i] >> 4) & 0xf]; + uint32_t color3 = lores_palette[line_bufa[i] & 0xf]; + uint32_t color4 = lores_palette[(line_bufa[i] >> 4) & 0xf]; // Each double lores pixel is 7 double hires pixels, or 7 VGA pixels wide sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16); @@ -77,7 +77,8 @@ static void __time_critical_func(render_dgr_line)(uint line) { sl_pos++; } - for(i=0; i < 40/8; i++) { + // Pad 40 pixels on the right to center horizontally + for(i = 0; i < 40/8; i++) { 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++; diff --git a/v2-analog-rev1/vga/render_dhgr.c b/v2-analog-rev1/vga/render_dhgr.c index c3873f7..2a437a5 100644 --- a/v2-analog-rev1/vga/render_dhgr.c +++ b/v2-analog-rev1/vga/render_dhgr.c @@ -5,7 +5,7 @@ #include "render.h" #include "vgaout.h" -static void render_dhgr_line(uint line); +static void render_dhgr_line(bool p2, uint line); #define _RGB333(r, g, b) ( \ (((((uint)(r) * 256 / 36) + 128) / 256) << 6) | \ @@ -16,18 +16,18 @@ static void render_dhgr_line(uint line); uint16_t dhgr_palette[16] = { _RGB333(0x00,0x00,0x00), // black 0000 _RGB333(0x00,0x00,0xb4), // d.blue 1000 - _RGB333(0x00,0x48,0x00), // d.green 0100 - _RGB333(0x00,0x90,0xfc), // h.blue 1100 - _RGB333(0x24,0x24,0x00), // brown 0010 + _RGB333(0x00,0x90,0x00), // d.green 0100 + _RGB333(0x00,0x6c,0xd8), // h.blue 1100 + _RGB333(0x6c,0x6c,0x00), // brown 0010 _RGB333(0x90,0x90,0x90), // l.gray 1010 _RGB333(0x00,0xd8,0x24), // h.green 0110 - _RGB333(0x90,0xfc,0xb4), // aqua 1110 - _RGB333(0x6c,0x00,0x6c), // magenta 0001 + _RGB333(0x90,0xfc,0x90), // aqua 1110 + _RGB333(0xd8,0x00,0x6c), // magenta 0001 _RGB333(0xb4,0x24,0xfc), // h.violet 1001 _RGB333(0x48,0x48,0x48), // d.gray 0101 - _RGB333(0x6c,0x6c,0xfc), // l.blue 1101 - _RGB333(0xfc,0x48,0x00), // h.orange 0011 - _RGB333(0xfc,0x6c,0xfc), // pink 1011 + _RGB333(0x6c,0x6c,0xff), // l.blue 1101 + _RGB333(0xfc,0x6c,0x24), // h.orange 0011 + _RGB333(0xff,0xd8,0xff), // pink 1011 _RGB333(0xd8,0xd8,0x00), // yellow 0111 _RGB333(0xff,0xff,0xff), // white 1111 }; @@ -43,8 +43,10 @@ void __time_critical_func(render_dhgr)() { render_border(); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + for(uint line=0; line < 192; line++) { - render_dhgr_line(line); + render_dhgr_line(p2, line); } render_border(); @@ -56,17 +58,19 @@ void __time_critical_func(render_mixed_dhgr)() { render_border(); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + for(uint line=0; line < 160; line++) { - render_dhgr_line(line); + render_dhgr_line(p2, line); } - if(terminal_switches & TERMINAL_80COL) { + if(soft_switches & SOFTSW_80COL) { for(uint line=20; line < 24; line++) { - render_terminal_line(line); + render_text80_line(p2, line); } } else { for(uint line=20; line < 24; line++) { - render_text_line(line); + render_text40_line(p2, line); } } @@ -74,19 +78,18 @@ void __time_critical_func(render_mixed_dhgr)() { } -static void __time_critical_func(render_dhgr_line)(uint line) { +static void __time_critical_func(render_dhgr_line)(bool p2, uint line) { struct vga_scanline *sl = vga_prepare_scanline(); uint sl_pos = 0; uint i; - const uint8_t *page = (const uint8_t *)hires_memory; - const uint8_t *line_mem = page + dhgr_line_to_mem_offset(line); + const uint8_t *line_mema = (const uint8_t *)((p2 ? hgr_p2 : hgr_p1) + 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 - while(sl_pos < 40/8) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } + 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 // DHGR is weird. Nuff said. uint32_t dots = 0; @@ -96,68 +99,70 @@ static void __time_critical_func(render_dhgr_line)(uint line) { i = 0; while(i < 40) { // Load in the next 28 subpixels - dots = (line_mem[i | 8192] & 0x7f) << 0; - dots |= (line_mem[i] & 0x7f) << 7; + dots = (line_memb[i] & 0x7f) << 0; + dots |= (line_mema[i] & 0x7f) << 7; i++; - dots |= (line_mem[i | 8192] & 0x7f) << 14; - dots |= (line_mem[i] & 0x7f) << 21; + dots |= (line_memb[i] & 0x7f) << 14; + dots |= (line_mema[i] & 0x7f) << 21; i++; - // Consume 6 pixels (24 subpixel bits) -#if 0 - for(j = 0; j < 12; j++) { - pixeldata = ((dots & 1) ? (text_fore) : (text_back)); - dots >>= 1; - pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16; - dots >>= 1; - sl->data[sl_pos++] = pixeldata; + if(soft_switches & SOFTSW_MONOCHROME) { + // Consume 6 pixels (24 subpixel bits) + for(j = 0; j < 12; j++) { + pixeldata = ((dots & 1) ? (0x1ff) : (0x000)); + dots >>= 1; + pixeldata |= (((dots & 1) ? (0x1ff) : (0x000))) << 16; + dots >>= 1; + sl->data[sl_pos++] = pixeldata; + } + } else { + // Consume 6 pixels (24 subpixel bits) + for(j = 0; j < 3; j++) { + pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3); + dots >>= 4; + pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16; + dots >>= 4; + sl->data[sl_pos++] = pixeldata; + } } -#else - for(j = 0; j < 3; j++) { - pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3); - dots >>= 4; - pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16; - dots >>= 4; - sl->data[sl_pos++] = pixeldata; - } -#endif // 4 subpixels roll over to the next block // Load in the next 28 subpixels - dots |= (line_mem[i | 8192] & 0x7f) << 4; - dots |= (line_mem[i] & 0x7f) << 11; + dots |= (line_memb[i] & 0x7f) << 4; + dots |= (line_mema[i] & 0x7f) << 11; i++; - dots |= (line_mem[i | 8192] & 0x7f) << 18; - dots |= (line_mem[i] & 0x7f) << 25; + dots |= (line_memb[i] & 0x7f) << 18; + dots |= (line_mema[i] & 0x7f) << 25; i++; - // Consume 8 pixels (32 subpixel bits) -#if 0 - for(j = 0; j < 16; j++) { - pixeldata = ((dots & 1) ? (text_fore) : (text_back)); - dots >>= 1; - pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16; - dots >>= 1; - sl->data[sl_pos++] = pixeldata; + if(soft_switches & SOFTSW_MONOCHROME) { + // Consume 8 pixels (32 subpixel bits) + for(j = 0; j < 16; j++) { + pixeldata = ((dots & 1) ? (0x1ff) : (0x000)); + dots >>= 1; + pixeldata |= (((dots & 1) ? (0x1ff) : (0x000))) << 16; + dots >>= 1; + sl->data[sl_pos++] = pixeldata; + } + } else { + // Consume 8 pixels (32 subpixel bits) + for(j = 0; j < 4; j++) { + pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3); + dots >>= 4; + pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16; + dots >>= 4; + sl->data[sl_pos++] = pixeldata; + } } -#else - for(j = 0; j < 4; j++) { - pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3); - dots >>= 4; - pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16; - dots >>= 4; - sl->data[sl_pos++] = pixeldata; - } -#endif } - - for(i = 0; i < 40/8; i++) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } + // Pad 40 pixels on the left to center horizontally + 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; vga_submit_scanline(sl); } + diff --git a/v2-analog-rev1/vga/render_hires.c b/v2-analog-rev1/vga/render_hires.c index c5ea1ef..5379bbd 100644 --- a/v2-analog-rev1/vga/render_hires.c +++ b/v2-analog-rev1/vga/render_hires.c @@ -6,8 +6,7 @@ #include "vgaout.h" -static void render_hires_line(uint line); - +static void render_hires_line(bool p2, uint line); static uint hires_line_to_mem_offset(uint line) { return ((line & 0x07) << 10) | ((line & 0x38) << 4) | (((line & 0xc0) >> 6) * 40); @@ -19,8 +18,10 @@ void __time_critical_func(render_hires)() { render_border(); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + for(uint line=0; line < 192; line++) { - render_hires_line(line); + render_hires_line(p2, line); } render_border(); @@ -32,17 +33,19 @@ void __time_critical_func(render_mixed_hires)() { render_border(); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + for(uint line=0; line < 160; line++) { - render_hires_line(line); + render_hires_line(p2, line); } - if(terminal_switches & TERMINAL_80COL) { + if(soft_switches & SOFTSW_80COL) { for(uint line=20; line < 24; line++) { - render_terminal_line(line); + render_text80_line(p2, line); } } else { for(uint line=20; line < 24; line++) { - render_text_line(line); + render_text40_line(p2, line); } } @@ -50,18 +53,16 @@ void __time_critical_func(render_mixed_hires)() { } -static void __time_critical_func(render_hires_line)(uint line) { +static void __time_critical_func(render_hires_line)(bool p2, uint line) { struct vga_scanline *sl = vga_prepare_scanline(); uint sl_pos = 0; - const uint8_t *page = (const uint8_t *)((soft_switches & SOFTSW_PAGE_2) ? hgr_p2 : hgr_p1); - const uint8_t *line_mem = page + 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 - while(sl_pos < 40/8) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } + 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 // 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. @@ -83,7 +84,7 @@ static void __time_critical_func(render_hires_line)(uint line) { // pixel uint32_t dots = 0; uint oddness = 0; - uint i; + uint i, j; // Load in the first 14 dots dots |= (uint32_t)hires_dot_patterns[line_mem[0]] << 15; @@ -97,20 +98,33 @@ static void __time_critical_func(render_hires_line)(uint line) { } dots |= (uint32_t)hires_dot_patterns[b] << 1; - // Consume 14 dots - for(uint j=0; j < 7; j++) { - uint dot_pattern = oddness | ((dots >> 24) & 0xff); - sl->data[sl_pos] = hires_color_patterns[dot_pattern]; - sl_pos++; - dots <<= 2; - oddness ^= 0x100; + 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; + dots <<= 2; + sl->data[sl_pos] = pixeldata; + sl_pos++; + } + } else { + // Consume 14 dots + for(uint j=0; j < 7; j++) { + uint dot_pattern = oddness | ((dots >> 24) & 0xff); + sl->data[sl_pos] = hires_color_patterns[dot_pattern]; + sl_pos++; + dots <<= 2; + oddness ^= 0x100; + } } } - for(i=0; i < 40/8; i++) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } + // Pad 40 pixels on the right to center horizontally + 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; diff --git a/v2-analog-rev1/vga/render_lores.c b/v2-analog-rev1/vga/render_lores.c index e07b3b3..49266e6 100644 --- a/v2-analog-rev1/vga/render_lores.c +++ b/v2-analog-rev1/vga/render_lores.c @@ -31,7 +31,7 @@ uint16_t lores_palette[16] = { #undef _RGB333 -static void render_lores_line(uint line); +static void render_lores_line(bool p2, uint line); void __time_critical_func(render_lores)() { @@ -39,8 +39,10 @@ void __time_critical_func(render_lores)() { render_border(); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + for(uint line=0; line < 24; line++) { - render_lores_line(line); + render_lores_line(p2, line); } render_border(); @@ -52,17 +54,19 @@ void __time_critical_func(render_mixed_lores)() { render_border(); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + for(uint line=0; line < 20; line++) { - render_lores_line(line); + render_lores_line(p2, line); } - if(terminal_switches & TERMINAL_80COL) { + if(soft_switches & SOFTSW_80COL) { for(uint line=20; line < 24; line++) { - render_terminal_line(line); + render_text80_line(p2, line); } } else { for(uint line=20; line < 24; line++) { - render_text_line(line); + render_text40_line(p2, line); } } @@ -70,18 +74,17 @@ void __time_critical_func(render_mixed_lores)() { } -static void __time_critical_func(render_lores_line)(uint line) { +static void __time_critical_func(render_lores_line)(bool p2, uint line) { // Construct two scanlines for the two different colored cells at the same time struct vga_scanline *sl1 = vga_prepare_scanline(); struct vga_scanline *sl2 = vga_prepare_scanline(); uint sl_pos = 0; uint i; - const uint8_t *page = (const uint8_t *)((soft_switches & SOFTSW_PAGE_2) ? text_p2 : text_p1); - const uint8_t *line_buf = page + ((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 - while(sl_pos < 40/8) { + for(i = 0; i < 40/8; i++) { 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++; @@ -94,8 +97,12 @@ static void __time_critical_func(render_lores_line)(uint line) { uint32_t color4 = lores_palette[(line_buf[i+1] >> 4) & 0xf]; // Each lores pixel is 7 hires pixels, or 14 VGA pixels wide - sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16); - sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color4|THEN_EXTEND_6) << 16); + sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color1|THEN_EXTEND_6) << 16); + sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color2|THEN_EXTEND_6) << 16); + sl_pos++; + + sl1->data[sl_pos] = (color3|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16); + sl2->data[sl_pos] = (color4|THEN_EXTEND_6) | ((color4|THEN_EXTEND_6) << 16); sl_pos++; } diff --git a/v2-analog-rev1/vga/render_shr.c b/v2-analog-rev1/vga/render_shr.c new file mode 100644 index 0000000..ff83401 --- /dev/null +++ b/v2-analog-rev1/vga/render_shr.c @@ -0,0 +1,129 @@ +#include +#include "hires_color_patterns.h" +#include "hires_dot_patterns.h" +#include "vgabuf.h" +#include "render.h" +#include "vgaout.h" + +extern uint16_t dhgr_palette[16]; + +static void render_shr_line(uint16_t line); + +static uint16_t __time_critical_func(rgb444_to_rgb333)(uint16_t a) { + return ((a & 0xe00) >> 3) | ((a & 0xe0) >> 2) | ((a & 0xe) >> 1); +} + +// Skip 40 lines to center vertically +void __time_critical_func(render_shr_border)() { + 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 = 39; + vga_submit_scanline(sl); +} + +void __time_critical_func(render_shr)() { + vga_prepare_frame(); + + render_shr_border(); + + for(uint line=0; line < 200; line++) { + render_shr_line(line); + } + + render_shr_border(); +} + +static void __time_critical_func(render_shr_line)(uint16_t line) { + struct vga_scanline *sl = vga_prepare_scanline(); + uint sl_pos = 0; + uint i; + + uint8_t control = private_memory[0x9D00 + line]; + uint32_t line_palette_offset = (control & 0xF) << 5; + + volatile uint16_t *shr_palette = (volatile uint16_t*)(private_memory + 0x9E00 + line_palette_offset); + volatile uint8_t *line_mem = (volatile uint8_t *)(private_memory + 0x2000 + (line * 160)); + + // SHR is weird. Nuff said. + uint32_t dots = 0; + uint32_t pixeldata; + uint16_t color_a = 0, color_b = 0; + int j; + + i = 0; +#if 1 + if(control & 0x80) { // 640 Pixels + while(i < 160) { + // Load in the next 4 subpixels + dots = line_mem[i++]; + + pixeldata = (dhgr_palette[(dots >> 6) & 0x3]); + pixeldata |= (dhgr_palette[(dots >> 4) & 0x3]) << 16; + sl->data[sl_pos++] = pixeldata; + + pixeldata = (dhgr_palette[(dots >> 2) & 0x3]); + pixeldata |= (dhgr_palette[(dots >> 0) & 0x3]) << 16; + sl->data[sl_pos++] = pixeldata; + } +#else + if(control & 0x80) { // 640 Pixels + while(i < 160) { + // Load in the next 2 pixels + dots = (line_mem[i++] & 0xff); + + color_a = ((dots >> 4) & 0xf); + color_b = ((dots >> 0) & 0xf); + + // Consume 2 pixels + pixeldata = rgb444_to_rgb333(shr_palette[color_a]) | THEN_EXTEND_1; + pixeldata |= (rgb444_to_rgb333(shr_palette[color_b]) | THEN_EXTEND_1) << 16; + sl->data[sl_pos++] = pixeldata; + } +#endif + } else if(control & 0x40) { // 320 Pixels w/ color fill + while(i < 160) { + // Load in the next 4 subpixels + dots = (line_mem[i++] & 0xff); + + // Consume 2 pixels + if(dots & 0xf0) { + color_a = ((dots >> 4) & 0xf); + } else { + color_a = color_b; + } + if(dots & 0x0f) { + color_b = ((dots >> 0) & 0xf); + } else { + color_b = color_a; + } + + pixeldata = rgb444_to_rgb333(shr_palette[color_a]) | THEN_EXTEND_1; + pixeldata |= (rgb444_to_rgb333(shr_palette[color_b]) | THEN_EXTEND_1) << 16; + sl->data[sl_pos++] = pixeldata; + } + } else { // 320 Pixels + while(i < 160) { + // Load in the next 2 pixels + dots = (line_mem[i++] & 0xff); + + color_a = ((dots >> 4) & 0xf); + color_b = ((dots >> 0) & 0xf); + + // Consume 2 pixels + pixeldata = rgb444_to_rgb333(shr_palette[color_a]) | THEN_EXTEND_1; + pixeldata |= (rgb444_to_rgb333(shr_palette[color_b]) | THEN_EXTEND_1) << 16; + sl->data[sl_pos++] = pixeldata; + } + } + + sl->length = sl_pos; + sl->repeat_count = 1; + vga_submit_scanline(sl); +} diff --git a/v2-analog-rev1/vga/render_test.c b/v2-analog-rev1/vga/render_test.c index b8101a7..4c1987b 100644 --- a/v2-analog-rev1/vga/render_test.c +++ b/v2-analog-rev1/vga/render_test.c @@ -1,12 +1,15 @@ #include #include -#include #include #include "vga/vgabuf.h" #include "vga/render.h" #include "vga/vgaout.h" #include "vga/logo.h" +#ifdef RASPBERRYPI_PICO_W +#include +#endif + #define _PIXPAIR(p1, p2) ((uint32_t)(p1) | (((uint32_t)p2) << 16)) char error_message[16*24+1]; @@ -14,7 +17,7 @@ char error_message[16*24+1]; 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-06-000", 16); + memcpy(error_message + 16, "FW: 23-01-16-119", 16); memcpy(error_message + 64, " COPYRIGHT (C) ", 16); memcpy(error_message + 80, " DAVID KUDER ", 16); @@ -31,10 +34,14 @@ void render_test_init() { memcpy(error_message + 288, "CHECK FOR PROPER", 16); memcpy(error_message + 304, " CARD INSERTION ", 16); +#ifdef RASPBERRYPI_PICO_W memcpy(error_message + 352, " SERIAL NUMBER: ", 16); // Get Pico's Flash Serial Number (Board ID) and terminating null. pico_get_unique_board_id_string(error_message + 368, 17); +#else + memcpy(error_message + 368, " V2-ANALOG-LC ", 16); +#endif } // Clear the error message, in case the user sets 0x20 in terminal switches @@ -100,8 +107,8 @@ void __noinline __time_critical_func(render_testpattern)() { uint32_t bits_b = char_text_bits(error_message[(w & 0x1f0) | (i+1)], (w/2) & 0x7); uint32_t bits = (bits_a << 7) | bits_b; for(uint j=0; j < 7; j++) { - uint32_t pixeldata = (bits & 0x2000) ? (0x1ff|THEN_EXTEND_1) : (0 | THEN_EXTEND_1); - pixeldata |= (bits & 0x1000) ? ((0x1ff|THEN_EXTEND_1) << 16) : ((0 | THEN_EXTEND_1) << 16); + uint32_t pixeldata = (bits & 0x2000) ? (0|THEN_EXTEND_1) : (0x1ff | THEN_EXTEND_1); + pixeldata |= (bits & 0x1000) ? ((0|THEN_EXTEND_1) << 16) : ((0x1ff | THEN_EXTEND_1) << 16); bits <<= 2; sl->data[sl_pos++] = pixeldata; } @@ -162,8 +169,8 @@ void __noinline __time_critical_func(render_testpattern)() { uint32_t bits_b = char_text_bits(error_message[(w & 0x1f0) | (i+1)], (w/2) & 0x7); uint32_t bits = (bits_a << 7) | bits_b; for(uint j=0; j < 7; j++) { - uint32_t pixeldata = (bits & 0x2000) ? (0x1ff|THEN_EXTEND_1) : (0 | THEN_EXTEND_1); - pixeldata |= (bits & 0x1000) ? ((0x1ff|THEN_EXTEND_1) << 16) : ((0 | THEN_EXTEND_1) << 16); + uint32_t pixeldata = (bits & 0x2000) ? (0|THEN_EXTEND_1) : (0x1ff | THEN_EXTEND_1); + pixeldata |= (bits & 0x1000) ? ((0|THEN_EXTEND_1) << 16) : ((0x1ff | THEN_EXTEND_1) << 16); bits <<= 2; sl->data[sl_pos++] = pixeldata; } @@ -203,8 +210,8 @@ void __noinline __time_critical_func(render_testpattern)() { uint32_t bits_b = char_text_bits(error_message[(w & 0x1f0) | (i+1)], (w/2) & 0x7); uint32_t bits = (bits_a << 7) | bits_b; for(uint j=0; j < 7; j++) { - uint32_t pixeldata = (bits & 0x2000) ? (0x1ff|THEN_EXTEND_1) : (0 | THEN_EXTEND_1); - pixeldata |= (bits & 0x1000) ? ((0x1ff|THEN_EXTEND_1) << 16) : ((0 | THEN_EXTEND_1) << 16); + uint32_t pixeldata = (bits & 0x2000) ? (0|THEN_EXTEND_1) : (0x1ff | THEN_EXTEND_1); + pixeldata |= (bits & 0x1000) ? ((0|THEN_EXTEND_1) << 16) : ((0x1ff | THEN_EXTEND_1) << 16); bits <<= 2; sl->data[sl_pos++] = pixeldata; } diff --git a/v2-analog-rev1/vga/render_text.c b/v2-analog-rev1/vga/render_text.c index 7bfe0d0..8ca3b5b 100644 --- a/v2-analog-rev1/vga/render_text.c +++ b/v2-analog-rev1/vga/render_text.c @@ -11,26 +11,27 @@ static uint64_t next_flash_tick = 0; void update_text_flasher() { uint64_t now = time_us_64(); if(now > next_flash_tick) { - text_flasher_mask ^= 0xff; + text_flasher_mask ^= 0x7f; next_flash_tick = now + 250000u; } } static inline uint_fast8_t __time_critical_func(char_text_bits)(uint_fast8_t ch, uint_fast8_t glyph_line) { - uint_fast8_t bits = character_rom[((uint_fast16_t)ch << 3) | glyph_line]; - if(ch & 0x80) { + uint_fast8_t bits = character_rom[((uint_fast16_t)ch << 3) | glyph_line] & 0x7f; + + if((soft_switches & SOFTSW_ALTCHAR) || (ch & 0x80)) { // normal character - return bits & 0x7f; + return bits; } - if((bits & 0x80) == 0) { - // inverse character - return bits ^ 0x7f; - } else { + if(ch & 0x40) { // flashing character - return (bits ^ text_flasher_mask) & 0x7f; + return (bits ^ text_flasher_mask); } + + // inverse character + return bits; } @@ -39,8 +40,8 @@ void __time_critical_func(render_border)() { struct vga_scanline *sl = vga_prepare_scanline(); uint sl_pos = 0; - while(sl_pos < VGA_WIDTH/8) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word + 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++; } @@ -54,27 +55,33 @@ void __time_critical_func(render_text)() { render_border(); - for(int line=0; line < 24; line++) { - render_text_line(line); + bool p2 = !(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2); + + if(soft_switches & SOFTSW_80COL) { + for(uint line=0; line < 24; line++) { + render_text80_line(p2, line); + } + } else { + for(uint line=0; line < 24; line++) { + render_text40_line(p2, line); + } } render_border(); } - -void __time_critical_func(render_text_line)(unsigned int line) { - const uint8_t *page = (const uint8_t *)((soft_switches & SOFTSW_PAGE_2) ? text_p2 : text_p1); - const uint8_t *line_buf = page + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40); +void __time_critical_func(render_text40_line)(bool p2, unsigned int line) { + const uint8_t *page = (const uint8_t *)(p2 ? text_p2 : text_p1); + const uint8_t *line_buf = (const uint8_t *)(page + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40)); for(uint glyph_line=0; glyph_line < 8; glyph_line++) { struct vga_scanline *sl = vga_prepare_scanline(); uint sl_pos = 0; // Pad 40 pixels on the left to center horizontally - while(sl_pos < 40/8) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } + 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 @@ -87,10 +94,10 @@ void __time_critical_func(render_text_line)(unsigned int line) { // Translate each pair of bits into a pair of pixels for(int i=0; i < 7; i++) { - uint32_t pixeldata = (bits & 0x2000) ? (text_fore|THEN_EXTEND_1) : (text_back|THEN_EXTEND_1); + uint32_t pixeldata = (bits & 0x2000) ? (text_back|THEN_EXTEND_1) : (text_fore|THEN_EXTEND_1); pixeldata |= (bits & 0x1000) ? - ((uint32_t)text_fore|THEN_EXTEND_1) << 16 : - ((uint32_t)text_back|THEN_EXTEND_1) << 16; + ((uint32_t)text_back|THEN_EXTEND_1) << 16 : + ((uint32_t)text_fore|THEN_EXTEND_1) << 16; bits <<= 2; sl->data[sl_pos] = pixeldata; @@ -98,10 +105,58 @@ void __time_critical_func(render_text_line)(unsigned int line) { } } - for(uint i=0; i < 40/8; i++) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } + // Pad 40 pixels on the right to center horizontally + 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; + vga_submit_scanline(sl); + } +} + + +void __time_critical_func(render_text80_line)(bool p2, unsigned int line) { + const uint8_t *page_a = (const uint8_t *)(p2 ? text_p2 : text_p1); + const uint8_t *page_b = (const uint8_t *)(p2 ? text_p4 : text_p3); + const uint8_t *line_buf_a = page_a + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40); + const uint8_t *line_buf_b = page_b + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40); + + for(uint glyph_line=0; glyph_line < 8; glyph_line++) { + struct vga_scanline *sl = vga_prepare_scanline(); + uint sl_pos = 0; + + // Pad 40 pixels on the left to center horizontally + 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 four characters + uint32_t bits_a = char_text_bits(line_buf_a[col], glyph_line); + uint32_t bits_b = char_text_bits(line_buf_b[col], glyph_line); + col++; + + uint32_t bits = (bits_b << 7) | bits_a; + + // Translate each pair of bits into a pair of pixels + for(int i=0; i < 7; i++) { + uint32_t pixeldata = (bits & 0x2000) ? (text_back) : (text_fore); + pixeldata |= (bits & 0x1000) ? + ((uint32_t)text_back) << 16 : + ((uint32_t)text_fore) << 16; + bits <<= 2; + + sl->data[sl_pos] = pixeldata; + sl_pos++; + } + } + + // Pad 40 pixels on the right to center horizontally + 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; diff --git a/v2-analog-rev1/vga/render_terminal.c b/v2-analog-rev1/vga/render_videx.c similarity index 67% rename from v2-analog-rev1/vga/render_terminal.c rename to v2-analog-rev1/vga/render_videx.c index f7e9b53..ba17a75 100644 --- a/v2-analog-rev1/vga/render_terminal.c +++ b/v2-analog-rev1/vga/render_videx.c @@ -1,82 +1,81 @@ -#include -#include "vgabuf.h" -#include "render.h" -#include "character_rom.h" -#include "vgaout.h" - -static inline uint_fast8_t __time_critical_func(char_terminal_bits)(uint_fast8_t ch, uint_fast8_t glyph_line) { - uint_fast8_t bits = character_rom[((uint_fast16_t)ch << 3) | glyph_line]; - if(ch & 0x80) { - // normal character - return bits & 0x7f; - } - - if((bits & 0x80) == 0) { - // inverse character - return bits ^ 0x7f; - } else { - // flashing character - return (bits ^ text_flasher_mask) & 0x7f; - } -} - - -void __time_critical_func(render_terminal)() { - vga_prepare_frame(); - - render_border(); - - for(int line=0; line < 24; line++) { - render_terminal_line(line); - } - - render_border(); -} - - -void __time_critical_func(render_terminal_line)(unsigned int line) { - const uint8_t *page = (const uint8_t *)videx_memory; - const uint8_t *line_buf = page + (line * 80); - - for(uint glyph_line=0; glyph_line < 8; glyph_line++) { - struct vga_scanline *sl = vga_prepare_scanline(); - uint sl_pos = 0; - - // Pad 40 pixels on the left to center horizontally - while(sl_pos < 40/8) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } - - for(uint col=0; col < 80; ) { - // Grab 14 pixels from the next two characters - uint32_t bits_a = char_terminal_bits(line_buf[col], glyph_line); - col++; - uint32_t bits_b = char_terminal_bits(line_buf[col], glyph_line); - col++; - - uint32_t bits = (bits_a << 7) | bits_b; - - // Translate each pair of bits into a pair of pixels - for(int i=0; i < 7; i++) { - uint32_t pixeldata = (bits & 0x2000) ? (text_fore) : (text_back); - pixeldata |= (bits & 0x1000) ? - (((uint32_t)text_fore) << 16) : - (((uint32_t)text_back) << 16); - bits <<= 2; - - sl->data[sl_pos] = pixeldata; - sl_pos++; - } - } - - for(uint i=0; i < 40/8; i++) { - sl->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word - sl_pos++; - } - - sl->length = sl_pos; - sl->repeat_count = 1; - vga_submit_scanline(sl); - } -} +#include +#include "vgabuf.h" +#include "render.h" +#include "character_rom.h" +#include "vgaout.h" + +static inline uint_fast8_t __time_critical_func(char_terminal_bits)(uint_fast8_t ch, uint_fast8_t glyph_line) { + uint_fast8_t bits = character_rom[((uint_fast16_t)ch << 3) | glyph_line]; + if(ch & 0x80) { + // normal character + return bits & 0x7f; + } + + if((bits & 0x80) == 0) { + // inverse character + return bits ^ 0x7f; + } else { + // flashing character + return (bits ^ text_flasher_mask) & 0x7f; + } +} + + +void __time_critical_func(render_videx)() { + vga_prepare_frame(); + + render_border(); + + for(int line=0; line < 24; line++) { + render_videx_line(line); + } + + render_border(); +} + + +void __time_critical_func(render_videx_line)(unsigned int line) { + const uint8_t *page = (const uint8_t *)videx_memory; + const uint8_t *line_buf = page + (line * 80); + + for(uint glyph_line=0; glyph_line < 8; glyph_line++) { + struct vga_scanline *sl = vga_prepare_scanline(); + uint sl_pos = 0; + + // Pad 40 pixels on the left to center horizontally + 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 < 80; ) { + // Grab 14 pixels from the next two characters + uint32_t bits_a = char_terminal_bits(line_buf[col], glyph_line); + col++; + uint32_t bits_b = char_terminal_bits(line_buf[col], glyph_line); + col++; + + uint32_t bits = (bits_a << 7) | bits_b; + + // Translate each pair of bits into a pair of pixels + for(int i=0; i < 7; i++) { + uint32_t pixeldata = (bits & 0x2000) ? (text_fore) : (text_back); + pixeldata |= (bits & 0x1000) ? + (((uint32_t)text_fore) << 16) : + (((uint32_t)text_back) << 16); + bits <<= 2; + + sl->data[sl_pos] = pixeldata; + sl_pos++; + } + } + + // Pad 40 pixels on the left to center horizontally + 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; + vga_submit_scanline(sl); + } +} diff --git a/v2-analog-rev1/vga/vga.pio b/v2-analog-rev1/vga/vga.pio index c0495de..89d2fab 100644 --- a/v2-analog-rev1/vga/vga.pio +++ b/v2-analog-rev1/vga/vga.pio @@ -36,7 +36,7 @@ pixel_out: public wait_vsync: wait 0 irq VSYNC_IRQ_NUM public wait_hsync: - wait 0 irq HSYNC_IRQ_NUM [9] + wait 0 irq HSYNC_IRQ_NUM [1] public extend_7: nop [1] public extend_6: diff --git a/v2-analog-rev1/vga/vgabuf.c b/v2-analog-rev1/vga/vgabuf.c index 0a763c6..8393d7a 100644 --- a/v2-analog-rev1/vga/vgabuf.c +++ b/v2-analog-rev1/vga/vgabuf.c @@ -5,7 +5,7 @@ volatile uint32_t soft_switches = 0; // The currently programmed character generator ROM for text mode -uint8_t character_rom[2048]; +uint8_t character_rom[4096]; volatile uint8_t videx_crtc_reg; diff --git a/v2-analog-rev1/vga/vgabuf.h b/v2-analog-rev1/vga/vgabuf.h index b7f4ebe..1a657f3 100644 --- a/v2-analog-rev1/vga/vgabuf.h +++ b/v2-analog-rev1/vga/vgabuf.h @@ -3,40 +3,20 @@ #include #include "common/buffers.h" -enum { - SOFTSW_TEXT_MODE = 0x01, - SOFTSW_MIX_MODE = 0x02, - SOFTSW_HIRES_MODE = 0x04, - SOFTSW_MODE_MASK = 0x07, - - SOFTSW_PAGE_2 = 0x08, -}; - #define text_memory text_p1 #define hires_memory hgr_p1 #define videx_memory (private_memory+0xF000) -extern volatile uint32_t soft_switches; -extern uint8_t character_rom[2048]; +extern uint8_t character_rom[4096]; extern uint8_t terminal_rom[2048]; extern volatile uint8_t videx_crtc_reg; extern volatile uint8_t videx_addr; -extern volatile uint8_t terminal_switches; #define terminal_tbcolor apple_memory[0xC022] #define terminal_border apple_memory[0xC034] -enum { - TERMINAL_80COL = 0x01, - TERMINAL_DGR = 0x02, - TERMINAL_AUX_WRITE = 0x10, - TERMINAL_TEST = 0x20, - TERMINAL_IIE_REGS = 0x40, - TERMINAL_IIGS_REGS = 0x80, -}; - -#define TERMINAL_FORE (terminal_tbcolor & 0xf) -#define TERMINAL_BACK ((terminal_tbcolor>>4) & 0xf) +#define TERMINAL_FORE ((terminal_tbcolor>>4) & 0xf) +#define TERMINAL_BACK (terminal_tbcolor & 0xf) #define TERMINAL_BORDER (terminal_border & 0xf) diff --git a/v2-analog-rev1/vga/vgaout.c b/v2-analog-rev1/vga/vgaout.c index b5b4096..6e1c051 100644 --- a/v2-analog-rev1/vga/vgaout.c +++ b/v2-analog-rev1/vga/vgaout.c @@ -20,7 +20,7 @@ #define HSYNC_TIMING_VALUE (((PIXELS_PER_LINE) / 8) - 23) #define VSYNC_TIMING_VALUE ((LINES_PER_FRAME) - 4) -#define NUM_SCANLINE_BUFFERS 8 +#define NUM_SCANLINE_BUFFERS 32 enum { VGA_HSYNC_SM = 0, @@ -151,7 +151,7 @@ static void vga_dma_irq_handler() { active_scanline->_flags &= ~(uint_fast8_t)FLAG_BUSY; const uint32_t irq_status = spin_lock_blocking(lock); - scanline_queue_tail = (scanline_queue_tail + 1) % NUM_SCANLINE_BUFFERS; + scanline_queue_tail = (scanline_queue_tail + 1) & (NUM_SCANLINE_BUFFERS-1); trigger_ready_scanline_dma(); spin_unlock(lock, irq_status); } @@ -244,7 +244,7 @@ struct vga_scanline *vga_prepare_scanline() { scanline->_flags = FLAG_BUSY; scanline->_sync = (uint32_t)THEN_WAIT_HSYNC << 16; - scanline_queue_head = (scanline_queue_head + 1) % NUM_SCANLINE_BUFFERS; + scanline_queue_head = (scanline_queue_head + 1) & (NUM_SCANLINE_BUFFERS-1); return scanline; } diff --git a/v2-analog-rev1/vga/vgaout.h b/v2-analog-rev1/vga/vgaout.h index 8a7b48c..2fea76e 100644 --- a/v2-analog-rev1/vga/vgaout.h +++ b/v2-analog-rev1/vga/vgaout.h @@ -28,7 +28,7 @@ struct vga_scanline { volatile uint_fast8_t _flags; uint32_t _sync; - uint32_t data[(VGA_WIDTH)+1]; + uint32_t data[(VGA_WIDTH/2)+8]; };