Compare commits
6 Commits
6d83fc50eb
...
0185620ff5
Author | SHA1 | Date |
---|---|---|
David Kuder | 0185620ff5 | |
David Kuder | e94cfac000 | |
David Kuder | d5e001f2c1 | |
David Kuder | ea4af57302 | |
David Kuder | 8531bb7881 | |
David Kuder | 006ff637a6 |
|
@ -21,27 +21,29 @@
|
|||
; x - select Data, active low
|
||||
.wrap_target
|
||||
next_bus_cycle:
|
||||
set PINS, 0b011 ; enable AddrHi tranceiver
|
||||
wait 1 GPIO, PHI0_GPIO ; wait for PHI0 to rise. Data propagation through the transceiver should
|
||||
set PINS, 0b111 ; enable CPLD OE
|
||||
wait 1 GPIO, PHI0_GPIO [4] ; wait for PHI0 to rise. Data propagation through the transceiver should
|
||||
; be complete by the time this happens.
|
||||
in PINS, 6 ; read CPLD[5:0]
|
||||
set PINS, 0b011 [5] ; enable AddrHi tranceiver
|
||||
in PINS, 8 ; read AddrHi[7:0]
|
||||
set PINS, 0b101 [12] ; enable AddrLo tranceiver and delay for transceiver propagation delay
|
||||
set PINS, 0b101 [5] ; enable AddrLo tranceiver and delay for transceiver propagation delay
|
||||
in PINS, 8 ; read AddrLo[7:0]
|
||||
|
||||
jmp PIN, read_cycle ; jump based on the state of the R/W pin
|
||||
|
||||
write_cycle:
|
||||
; the current time is P0+82ns (P0 + 10ns + 2 clocks (input synchronizers) + 16 instructions)
|
||||
; the current time is P0+98ns (P0 + 10ns + 2 clocks (input synchronizers) + 20 instructions)
|
||||
|
||||
set PINS, 0b110 [21] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+170ns)
|
||||
set PINS, 0b110 [17] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+170ns)
|
||||
in PINS, 10 ; read R/W, ~DEVSEL, and Data[7:0], then autopush
|
||||
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall
|
||||
jmp next_bus_cycle
|
||||
|
||||
read_cycle:
|
||||
; the current time is P0+82ns (P0 + 10ns + 2 clocks (input synchronizers) + 16 instructions)
|
||||
; the current time is P0+98ns (P0 + 10ns + 2 clocks (input synchronizers) + 16 instructions)
|
||||
|
||||
set PINS, 0b110 [4] ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+102ns+buffer delay)
|
||||
set PINS, 0b110 [5] ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+118ns)
|
||||
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
|
||||
|
@ -66,7 +68,7 @@ wait_loop:
|
|||
wait 1 irq READ_DATA_TRIGGER_IRQ ; wait for the data portion of a read cycle (from the main SM)
|
||||
jmp PIN, wait_loop ; skip if this device is not being addressed
|
||||
|
||||
; the current time is P0+114ns (P0 + 10ns + 2 clocks (input synchronizers) + 24 instructions) and
|
||||
; the current time is P0+130ns and
|
||||
; this read cycle is addressed to this device.
|
||||
;
|
||||
; Phase 0 is typically 489 ns long.
|
||||
|
@ -76,16 +78,16 @@ wait_loop:
|
|||
|
||||
irq set DATA_BUSY_IRQ
|
||||
|
||||
set PINS, 0b01 [10] ; enable Data tranceiver with output direction [160ns]
|
||||
mov OSR, ~NULL [31] ; [288ns]
|
||||
out PINDIRS, 8 [31] ; set data pins as outputs [416ns]
|
||||
set PINS, 0b01 [7] ; enable Data tranceiver with output direction [P0+162ns]
|
||||
mov OSR, ~NULL [31] ; [P0+290ns]
|
||||
out PINDIRS, 8 [31] ; set data pins as outputs [P0+418ns]
|
||||
|
||||
pull noblock ; pull value from the FIFO as late as possible [420ns]
|
||||
out PINS, 8 ; [424ns]
|
||||
pull noblock ; pull value from the FIFO as late as possible [P0+422ns]
|
||||
out PINS, 8 ; [P0+426ns]
|
||||
|
||||
; the current time is P0+424ns (P0 + 10ns + 2 clocks (input synchronizers) + 101 instructions)
|
||||
; the current time is P0+426ns
|
||||
|
||||
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 15ns (2 clocks (input synchronizers) + 7 instructions)
|
||||
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 12ns (2 clocks (input synchronizers) + 7 instructions)
|
||||
set PINS, 0b10 ; disable Data tranceiver to tri-state the data bus
|
||||
|
||||
mov OSR, NULL
|
||||
|
|
|
@ -57,8 +57,13 @@ static void abus_main_setup(PIO pio, uint sm) {
|
|||
// map the SET pin group to the bus transceiver enable signals
|
||||
sm_config_set_set_pins(&c, CONFIG_PIN_APPLEBUS_CONTROL_BASE+1, 3);
|
||||
|
||||
#ifdef ANALOG_GS
|
||||
// configure left shift into ISR & autopush every 32 bits
|
||||
sm_config_set_in_shift(&c, false, true, 32);
|
||||
#else
|
||||
// configure left shift into ISR & autopush every 26 bits
|
||||
sm_config_set_in_shift(&c, false, true, 26);
|
||||
#endif
|
||||
|
||||
pio_sm_init(pio, sm, program_offset, &c);
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ void abus_init();
|
|||
#define CARD_IOSEL (((address & 0xff00) >= 0xc100) && ((address & 0xff00) < 0xc700))
|
||||
#define CARD_IOSTROBE ((address & 0xf800) == 0xc800)
|
||||
|
||||
#define ACCESS_READ ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0)
|
||||
#define ACCESS_WRITE ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)
|
||||
|
||||
enum {
|
||||
ABUS_MAIN_SM = 0,
|
||||
ABUS_DEVICE_READ_SM = 1,
|
||||
|
|
|
@ -68,45 +68,51 @@ extern volatile uint32_t soft_switches;
|
|||
|
||||
extern volatile uint32_t internal_flags;
|
||||
|
||||
#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
|
||||
#define SOFTSW_TEXT_MODE 0x00000001ul
|
||||
#define SOFTSW_MIX_MODE 0x00000002ul
|
||||
#define SOFTSW_HIRES_MODE 0x00000004ul
|
||||
#define SOFTSW_MODE_MASK 0x00000007ul
|
||||
#define SOFTSW_PAGE_2 0x00000008ul
|
||||
|
||||
// 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_80STORE 0x00000100ul
|
||||
#define SOFTSW_AUX_READ 0x00000200ul
|
||||
#define SOFTSW_AUX_WRITE 0x00000400ul
|
||||
#define SOFTSW_AUXZP 0x00000800ul
|
||||
#define SOFTSW_SLOT3ROM 0x00001000ul
|
||||
#define SOFTSW_80COL 0x00002000ul
|
||||
#define SOFTSW_ALTCHAR 0x00004000ul
|
||||
#define SOFTSW_DGR 0x00008000ul
|
||||
|
||||
#define SOFTSW_NEWVID_MASK 0xE0
|
||||
#define SOFTSW_NEWVID_MASK 0xE0ul
|
||||
#define SOFTSW_NEWVID_SHIFT 11
|
||||
|
||||
#define SOFTSW_MONOCHROME 0x00010000
|
||||
#define SOFTSW_LINEARIZE 0x00020000
|
||||
#define SOFTSW_SHR 0x00040000
|
||||
#define SOFTSW_MONOCHROME 0x00010000ul
|
||||
#define SOFTSW_LINEARIZE 0x00020000ul
|
||||
#define SOFTSW_SHR 0x00040000ul
|
||||
|
||||
#define SOFTSW_IOUDIS 0x00080000
|
||||
#define SOFTSW_IOUDIS 0x00080000ul
|
||||
|
||||
#define SOFTSW_SHADOW_MASK 0x7F
|
||||
#define SOFTSW_SHADOW_MASK 0x7Ful
|
||||
#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
|
||||
#define SOFTSW_SHADOW_TEXT 0x00100000ul
|
||||
#define SOFTSW_SHADOW_HGR1 0x00200000ul
|
||||
#define SOFTSW_SHADOW_HGR2 0x00400000ul
|
||||
#define SOFTSW_SHADOW_SHR 0x00800000ul
|
||||
#define SOFTSW_SHADOW_AUXHGR 0x01000000ul
|
||||
#define SOFTSW_SHADOW_ALTDISP 0x02000000ul
|
||||
#define SOFTSW_SHADOW_IO 0x04000000ul
|
||||
|
||||
// V2 Analog specific softswitches
|
||||
#define IFLAGS_OLDCOLOR 0x08000000
|
||||
#define SOFTSW_TERMINAL 0x10000000
|
||||
#define IFLAGS_TEST 0x20000000
|
||||
#define IFLAGS_IIE_REGS 0x40000000
|
||||
#define IFLAGS_IIGS_REGS 0x80000000
|
||||
#define IFLAGS_VIDEO7 0x04000000ul
|
||||
#define IFLAGS_OLDCOLOR 0x08000000ul
|
||||
#define IFLAGS_TERMINAL 0x10000000ul
|
||||
#define IFLAGS_TEST 0x20000000ul
|
||||
#define IFLAGS_IIE_REGS 0x40000000ul
|
||||
#define IFLAGS_IIGS_REGS 0x80000000ul
|
||||
|
||||
#define IFLAGS_V7_MODE0 0x00000000ul
|
||||
#define IFLAGS_V7_MODE1 0x00000001ul
|
||||
#define IFLAGS_V7_MODE2 0x00000002ul
|
||||
#define IFLAGS_V7_MODE3 0x00000003ul
|
||||
|
|
|
@ -55,3 +55,6 @@
|
|||
|
||||
#define CFGTOKEN_TBCOLOR 0x00005456 // "VT\xXX\x00" Custom default TBCOLOR
|
||||
#define CFGTOKEN_BORDER 0x00004256 // "VB\xXX\x00" Custom default BORDER
|
||||
|
||||
#define CFGTOKEN_VIDEO7 0x00003756 // "V7\xXX\x00" Video 7 Enable / Disable
|
||||
#define CFGTOKEN_RGBCOLOR 0x00005043 // "CP\xXX\x04" RGB Palette Entry Override
|
||||
|
|
|
@ -68,21 +68,29 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
|||
switch(config[i] & 0x0000FFFF) {
|
||||
case CFGTOKEN_HOST_AUTO:
|
||||
cfg_machine = MACHINE_AUTO;
|
||||
internal_flags |= (IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
case CFGTOKEN_HOST_II:
|
||||
cfg_machine = MACHINE_II;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
case CFGTOKEN_HOST_IIE:
|
||||
cfg_machine = MACHINE_IIE;
|
||||
internal_flags |= IFLAGS_IIE_REGS;
|
||||
internal_flags &= ~IFLAGS_IIGS_REGS;
|
||||
break;
|
||||
case CFGTOKEN_HOST_IIGS:
|
||||
cfg_machine = MACHINE_IIGS;
|
||||
internal_flags &= ~IFLAGS_IIE_REGS;
|
||||
internal_flags |= IFLAGS_IIGS_REGS;
|
||||
break;
|
||||
case CFGTOKEN_HOST_PRAVETZ:
|
||||
cfg_machine = MACHINE_PRAVETZ;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
case CFGTOKEN_HOST_BASIS:
|
||||
cfg_machine = MACHINE_BASIS;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
#ifdef FUNCTION_VGA
|
||||
case CFGTOKEN_FONT_00:
|
||||
|
@ -98,6 +106,17 @@ bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
|||
case CFGTOKEN_BORDER:
|
||||
terminal_border = (config[i] >> 16) & 0xF;
|
||||
break;
|
||||
case CFGTOKEN_RGBCOLOR:
|
||||
lores_palette[(config[i] >> 16) & 0xF] = config[i+1];
|
||||
dhgr_palette[((config[i] >> 17) & 0x7) | ((config[i] >> 13) & 0x8)] = config[i+1];
|
||||
break;
|
||||
case CFGTOKEN_VIDEO7:
|
||||
if((config[i] >> 16) & 1) {
|
||||
internal_flags |= IFLAGS_VIDEO7;
|
||||
} else {
|
||||
internal_flags &= ~IFLAGS_VIDEO7;
|
||||
}
|
||||
break;
|
||||
#elif defined(FUNCTION_Z80)
|
||||
case CFGTOKEN_MUX_LOOP:
|
||||
serialmux[(config[i] >> 16) & 1] = SERIAL_LOOP;
|
||||
|
@ -172,7 +191,17 @@ void DELAYED_COPY_CODE(default_config)() {
|
|||
strcpy((char*)wifi_ssid, "V2RetroNet");
|
||||
strcpy((char*)wifi_psk, "Analog");
|
||||
#endif
|
||||
#ifdef ANALOG_GS
|
||||
cfg_machine = MACHINE_IIGS;
|
||||
current_machine = MACHINE_IIGS;
|
||||
internal_flags &= ~IFLAGS_IIE_REGS;
|
||||
internal_flags |= IFLAGS_IIGS_REGS;
|
||||
#else
|
||||
cfg_machine = MACHINE_AUTO;
|
||||
current_machine = MACHINE_AUTO;
|
||||
internal_flags |= (IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
#endif
|
||||
internal_flags |= IFLAGS_VIDEO7;
|
||||
}
|
||||
|
||||
int DELAYED_COPY_CODE(make_config)(uint32_t rev) {
|
||||
|
@ -277,6 +306,13 @@ int DELAYED_COPY_CODE(make_config)(uint32_t rev) {
|
|||
config_temp[i++] = CFGTOKEN_MONO_00 | ((mono_palette & 0xF) << 20);
|
||||
config_temp[i++] = CFGTOKEN_TBCOLOR | ((terminal_tbcolor & 0xFF) << 16);
|
||||
config_temp[i++] = CFGTOKEN_BORDER | ((terminal_border & 0xF) << 16);
|
||||
|
||||
config_temp[i++] = CFGTOKEN_VIDEO7 | ((internal_flags & IFLAGS_VIDEO7) ? (1ul<<16) : 0);
|
||||
|
||||
for(uint32_t j = 0; j < 16; j++) {
|
||||
config_temp[i++] = CFGTOKEN_RGBCOLOR | (j << 16);
|
||||
config_temp[i++] = lores_palette[j];
|
||||
}
|
||||
#endif
|
||||
config_temp[i++] = NEWCONFIG_EOF_MARKER;
|
||||
|
||||
|
@ -320,12 +356,14 @@ uint8_t DELAYED_COPY_CODE(get_config_rev)(uint32_t address) {
|
|||
// Every time we write the config we overwrite the older slot,
|
||||
// ensuring we don't leave the user without a configuration.
|
||||
// We increment the revision number each time, wrapping back to 0x00 from 0xFF.
|
||||
#if 0
|
||||
bool DELAYED_COPY_CODE(is_primary_config_newer)() {
|
||||
uint8_t a=get_config_rev(FLASH_CONFIG_PRIMARY);
|
||||
uint8_t b=get_config_rev(FLASH_CONFIG_SECONDARY);
|
||||
|
||||
return ((int8_t)(a-b)) >= 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool DELAYED_COPY_CODE(read_config)() {
|
||||
if(is_config_valid(FLASH_CONFIG_ONETIME)) {
|
||||
|
@ -334,6 +372,13 @@ bool DELAYED_COPY_CODE(read_config)() {
|
|||
if(parse_config(FLASH_CONFIG_ONETIME))
|
||||
return true;
|
||||
}
|
||||
|
||||
if(is_config_valid(FLASH_CONFIG_PRIMARY)) {
|
||||
if(parse_config(FLASH_CONFIG_PRIMARY))
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(is_config_valid(FLASH_CONFIG_PRIMARY)) {
|
||||
if(!is_config_valid(FLASH_CONFIG_SECONDARY) || (is_primary_config_newer())) {
|
||||
if(parse_config(FLASH_CONFIG_PRIMARY))
|
||||
|
@ -344,6 +389,7 @@ bool DELAYED_COPY_CODE(read_config)() {
|
|||
if(parse_config(FLASH_CONFIG_SECONDARY))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
default_config();
|
||||
return false;
|
||||
|
@ -359,6 +405,10 @@ bool DELAYED_COPY_CODE(write_config)(bool onetime) {
|
|||
vga_dpms_sleep();
|
||||
#endif
|
||||
|
||||
write_secondary = false;
|
||||
rev = get_config_rev(FLASH_CONFIG_PRIMARY);
|
||||
|
||||
#if 0
|
||||
if(is_config_valid(FLASH_CONFIG_PRIMARY) && is_config_valid(FLASH_CONFIG_SECONDARY)) {
|
||||
write_secondary = is_primary_config_newer();
|
||||
rev = write_secondary ? get_config_rev(FLASH_CONFIG_PRIMARY) : get_config_rev(FLASH_CONFIG_SECONDARY);
|
||||
|
@ -369,9 +419,9 @@ bool DELAYED_COPY_CODE(write_config)(bool onetime) {
|
|||
write_secondary = false;
|
||||
rev = get_config_rev(FLASH_CONFIG_SECONDARY);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(make_config(rev + 1) <= CONFIG_SIZE) {
|
||||
|
||||
if(onetime) {
|
||||
flash_range_erase((FLASH_CONFIG_ONETIME-XIP_BASE), CONFIG_SIZE);
|
||||
flash_range_program((FLASH_CONFIG_ONETIME-XIP_BASE), (const uint8_t *)config_temp, CONFIG_SIZE);
|
||||
|
@ -401,6 +451,7 @@ uint8_t DELAYED_COPY_CODE(get_config_block)() {
|
|||
last_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
|
||||
next_config_block = last_config_block;
|
||||
|
||||
#if 0
|
||||
if(is_config_valid(FLASH_CONFIG_PRIMARY)) {
|
||||
if(!is_config_valid(FLASH_CONFIG_SECONDARY) || (is_primary_config_newer())) {
|
||||
last_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
|
||||
|
@ -413,6 +464,7 @@ uint8_t DELAYED_COPY_CODE(get_config_block)() {
|
|||
last_config_block = (FLASH_CONFIG_SECONDARY-XIP_BASE) / 4096;
|
||||
next_config_block = (FLASH_CONFIG_PRIMARY-XIP_BASE) / 4096;
|
||||
}
|
||||
#endif
|
||||
|
||||
config_rpybuf[5] = (next_config_block >> 8) & 0xFF;
|
||||
config_rpybuf[4] = (next_config_block >> 0) & 0xFF;
|
||||
|
@ -574,6 +626,31 @@ void DELAYED_COPY_CODE(config_handler)() {
|
|||
config_rpybuf[0] = REPLY_BUSY;
|
||||
|
||||
switch(config_cmdbuf[0]) {
|
||||
case 'P':
|
||||
switch(config_cmdbuf[1]) {
|
||||
default:
|
||||
retval = REPLY_ECMD;
|
||||
break;
|
||||
#ifdef FUNCTION_VGA
|
||||
case 'r':
|
||||
memcpy((void *)cfbuf, lores_palette, 16*2);
|
||||
cfptr = 0;
|
||||
retval = REPLY_OK;
|
||||
break;
|
||||
case 'T':
|
||||
for(uint j = 0; j < 16; j++) {
|
||||
#ifdef ANALOG_GS
|
||||
lores_palette[j] = ((uint16_t *)cfbuf)[j] & 0xFFF;
|
||||
#else
|
||||
lores_palette[j] = ((uint16_t *)cfbuf)[j] & 0x1FF;
|
||||
#endif
|
||||
}
|
||||
cfptr = 0;
|
||||
retval = REPLY_OK;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
switch(config_cmdbuf[1]) {
|
||||
default:
|
||||
|
|
|
@ -19,9 +19,6 @@
|
|||
#include <pico/cyw43_arch.h>
|
||||
#endif
|
||||
|
||||
#define ACCESS_READ ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0)
|
||||
#define ACCESS_WRITE ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)
|
||||
|
||||
static void __noinline __time_critical_func(core1_loop)() {
|
||||
uint32_t value;
|
||||
uint32_t address;
|
||||
|
@ -49,25 +46,25 @@ static void __noinline __time_critical_func(core1_loop)() {
|
|||
// Config memory in card slot-rom address space
|
||||
if(ACCESS_WRITE) {
|
||||
if((address & 0xFF) == 0xEC) {
|
||||
apple_memory[address] = value;
|
||||
cfptr = (cfptr & 0x0F00) | value;
|
||||
apple_memory[address] = (value & 0xff);
|
||||
cfptr = (cfptr & 0x0F00) | (value & 0xff);
|
||||
apple_memory[address+2] = cfbuf[cfptr]; // $CnEE
|
||||
apple_memory[address+3] = cfbuf[cfptr]; // $CnEF
|
||||
}
|
||||
if((address & 0xFF) == 0xED) {
|
||||
apple_memory[address] = value & 0x0F;
|
||||
apple_memory[address] = (value & 0x0F);
|
||||
cfptr = ((cfptr & 0xFF) | (((uint16_t)value) << 8)) & 0xFFF;
|
||||
apple_memory[address+1] = cfbuf[cfptr]; // $CnEE
|
||||
apple_memory[address+2] = cfbuf[cfptr]; // $CnEF
|
||||
}
|
||||
if((address & 0xFF) == 0xEF) {
|
||||
cfbuf[cfptr] = value;
|
||||
cfbuf[cfptr] = (value & 0xff);
|
||||
cfptr = (cfptr + 1) & 0x0FFF;
|
||||
apple_memory[address-1] = cfbuf[cfptr]; // $CnEE
|
||||
apple_memory[address] = cfbuf[cfptr]; // $CnEF
|
||||
}
|
||||
if((address & 0xFF) >= 0xF0) {
|
||||
apple_memory[address] = value;
|
||||
apple_memory[address] = (value & 0xff);
|
||||
}
|
||||
} else if((address & 0xFF) == 0xEE) {
|
||||
cfptr = (cfptr + 1) & 0x0FFF;
|
||||
|
@ -79,7 +76,12 @@ static void __noinline __time_critical_func(core1_loop)() {
|
|||
}
|
||||
#ifdef FUNCTION_VGA
|
||||
} else if(current_machine == MACHINE_AUTO) {
|
||||
if((apple_memory[0x404] == 0xE5) && (apple_memory[0x0403] == 0xD8)) { // ROMXe
|
||||
if(value & 0x08000000) {
|
||||
// Hardware jumpered for IIGS mode.
|
||||
current_machine = MACHINE_IIGS;
|
||||
internal_flags &= ~IFLAGS_IIE_REGS;
|
||||
internal_flags |= IFLAGS_IIGS_REGS;
|
||||
} else if((apple_memory[0x404] == 0xE5) && (apple_memory[0x0403] == 0xD8)) { // ROMXe
|
||||
current_machine = MACHINE_IIE;
|
||||
internal_flags |= IFLAGS_IIE_REGS;
|
||||
internal_flags &= ~IFLAGS_IIGS_REGS;
|
||||
|
@ -111,25 +113,27 @@ static void __noinline __time_critical_func(core1_loop)() {
|
|||
#endif
|
||||
} else switch(reset_state) {
|
||||
case 0:
|
||||
if((value & 0x3FFFF00) == ((0xFFFC << 10) | 0x300))
|
||||
if((value & 0x7FFFF00) == ((0xFFFC << 10) | 0x300))
|
||||
reset_state++;
|
||||
break;
|
||||
case 1:
|
||||
if((value & 0x3FFFF00) == ((0xFFFD << 10) | 0x300))
|
||||
if((value & 0x7FFFF00) == ((0xFFFD << 10) | 0x300))
|
||||
reset_state++;
|
||||
else
|
||||
reset_state=0;
|
||||
break;
|
||||
case 2:
|
||||
if((value & 0x3FFFF00) == ((0xFA62 << 10) | 0x300))
|
||||
if((value & 0x7FFFF00) == ((0xFA62 << 10) | 0x300))
|
||||
reset_state++;
|
||||
else
|
||||
reset_state=0;
|
||||
break;
|
||||
case 3:
|
||||
#ifdef FUNCTION_VGA
|
||||
soft_switches = SOFTSW_TEXT_MODE;
|
||||
soft_switches |= SOFTSW_TEXT_MODE;
|
||||
soft_switches &= ~SOFTSW_80COL;
|
||||
soft_switches &= ~SOFTSW_DGR;
|
||||
internal_flags &= ~(IFLAGS_TERMINAL | IFLAGS_TEST | IFLAGS_V7_MODE3);
|
||||
#endif
|
||||
default:
|
||||
reset_state = 0;
|
||||
|
|
|
@ -8,16 +8,18 @@
|
|||
volatile uint8_t *terminal_page = terminal_memory;
|
||||
|
||||
void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
||||
// Shadow parts of the Apple's memory by observing the bus write cycles
|
||||
if((address < 0xC000) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
// Apple IIgs: CARD_SELECT is pulled low by our CPLD when M2B0 is active and addr < $C000
|
||||
#ifdef ANALOG_GS
|
||||
if(CARD_SELECT) {
|
||||
// Apple IIgs: Bit 27 is GS jumper closed, Bit 26 is M2B0
|
||||
if(value & 0x4000000) {
|
||||
if(ACCESS_WRITE) {
|
||||
private_memory[address] = value & 0xff;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Shadow parts of the Apple's memory by observing the bus write cycles
|
||||
if(ACCESS_WRITE) {
|
||||
// Mirror Video Memory from MAIN & AUX banks
|
||||
if(soft_switches & SOFTSW_80STORE) {
|
||||
if(soft_switches & SOFTSW_PAGE_2) {
|
||||
|
@ -46,57 +48,57 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
|||
if((address & 0xff80) == 0xc000) {
|
||||
switch(address & 0x7f) {
|
||||
case 0x00:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches &= ~SOFTSW_80STORE;
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches |= SOFTSW_80STORE;
|
||||
}
|
||||
break;
|
||||
case 0x04:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches &= ~SOFTSW_AUX_WRITE;
|
||||
}
|
||||
break;
|
||||
case 0x05:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches |= SOFTSW_AUX_WRITE;
|
||||
}
|
||||
break;
|
||||
case 0x08:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches &= ~SOFTSW_AUXZP;
|
||||
}
|
||||
break;
|
||||
case 0x09:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches |= SOFTSW_AUXZP;
|
||||
}
|
||||
break;
|
||||
case 0x0c:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches &= ~SOFTSW_80COL;
|
||||
}
|
||||
break;
|
||||
case 0x0d:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches |= SOFTSW_80COL;
|
||||
}
|
||||
break;
|
||||
case 0x0e:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches &= ~SOFTSW_ALTCHAR;
|
||||
}
|
||||
break;
|
||||
case 0x0f:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
soft_switches |= SOFTSW_ALTCHAR;
|
||||
}
|
||||
break;
|
||||
case 0x21:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
|
||||
if(value & 0x80) {
|
||||
soft_switches |= SOFTSW_MONOCHROME;
|
||||
} else {
|
||||
|
@ -105,22 +107,22 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
|||
}
|
||||
break;
|
||||
case 0x22:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ACCESS_WRITE) {
|
||||
apple_tbcolor = value & 0xff;
|
||||
}
|
||||
break;
|
||||
case 0x29:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ACCESS_WRITE) {
|
||||
soft_switches = (soft_switches & ~(SOFTSW_NEWVID_MASK << SOFTSW_NEWVID_SHIFT)) | ((value & SOFTSW_NEWVID_MASK) << SOFTSW_NEWVID_SHIFT);
|
||||
}
|
||||
break;
|
||||
case 0x34:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ACCESS_WRITE) {
|
||||
apple_border = value & 0x0f;
|
||||
}
|
||||
break;
|
||||
case 0x35:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ACCESS_WRITE) {
|
||||
soft_switches = (soft_switches & ~(SOFTSW_SHADOW_MASK << SOFTSW_SHADOW_SHIFT)) | ((value & SOFTSW_SHADOW_MASK) << SOFTSW_SHADOW_SHIFT);
|
||||
}
|
||||
break;
|
||||
|
@ -154,17 +156,22 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
|||
}
|
||||
break;
|
||||
case 0x5f:
|
||||
// Video 7 shift register
|
||||
if(!soft_switches & SOFTSW_DGR) {
|
||||
internal_flags = (internal_flags & 0xfffffffc) | ((internal_flags & 0x1) << 1) | ((soft_switches & SOFTSW_80COL) ? 1 : 0);
|
||||
}
|
||||
|
||||
if(internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) {
|
||||
soft_switches &= ~SOFTSW_DGR;
|
||||
}
|
||||
break;
|
||||
case 0x7e:
|
||||
if((internal_flags & IFLAGS_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & IFLAGS_IIE_REGS) && ACCESS_WRITE) {
|
||||
soft_switches |= SOFTSW_IOUDIS;
|
||||
}
|
||||
break;
|
||||
case 0x7f:
|
||||
if((internal_flags & IFLAGS_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if((internal_flags & IFLAGS_IIE_REGS) && ACCESS_WRITE) {
|
||||
soft_switches &= ~SOFTSW_IOUDIS;
|
||||
}
|
||||
break;
|
||||
|
@ -173,24 +180,24 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
|||
}
|
||||
|
||||
// Control sequences used by ROMX and ROMXe
|
||||
if(value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) {
|
||||
if(((address >> 8) == 0xCA) || ((address >> 8) == 0xFA)) {
|
||||
switch(address & 0xFF) {
|
||||
case 0xCA:
|
||||
romx_unlocked = (romx_unlocked == 1) ? 2 : 1;
|
||||
break;
|
||||
case 0xFE:
|
||||
romx_unlocked = (romx_unlocked == 2) ? 3 : 0;
|
||||
if(romx_unlocked == 3)
|
||||
romx_type = address >> 8;
|
||||
break;
|
||||
default:
|
||||
if(romx_unlocked != 3)
|
||||
romx_unlocked = 0;
|
||||
break;
|
||||
}
|
||||
} else if(romx_unlocked == 3) {
|
||||
if(romx_type == 0xFA) {
|
||||
switch(current_machine) {
|
||||
case MACHINE_IIE:
|
||||
// Trigger on read sequence FACA FACA FAFE
|
||||
if(ACCESS_READ) {
|
||||
if((address >> 8) == 0xFA) {
|
||||
switch(address & 0xFF) {
|
||||
case 0xCA:
|
||||
romx_unlocked = (romx_unlocked == 1) ? 2 : 1;
|
||||
break;
|
||||
case 0xFE:
|
||||
romx_unlocked = (romx_unlocked == 2) ? 3 : 0;
|
||||
break;
|
||||
default:
|
||||
if(romx_unlocked != 3)
|
||||
romx_unlocked = 0;
|
||||
break;
|
||||
}
|
||||
} else if(romx_unlocked == 3) {
|
||||
if((address & 0xFFF0) == 0xF810) {
|
||||
romx_textbank = address & 0xF;
|
||||
}
|
||||
|
@ -198,7 +205,26 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
|||
romx_changed = 1;
|
||||
romx_unlocked = 0;
|
||||
}
|
||||
} else if(romx_type == 0xCA) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MACHINE_II:
|
||||
// Trigger on read sequence CACA CACA CAFE
|
||||
if(ACCESS_READ) {
|
||||
if((address >> 8) == 0xCA) {
|
||||
switch(address & 0xFF) {
|
||||
case 0xCA:
|
||||
romx_unlocked = (romx_unlocked == 1) ? 2 : 1;
|
||||
break;
|
||||
case 0xFE:
|
||||
romx_unlocked = (romx_unlocked == 2) ? 3 : 0;
|
||||
break;
|
||||
default:
|
||||
if(romx_unlocked != 3)
|
||||
romx_unlocked = 0;
|
||||
break;
|
||||
}
|
||||
} else if(romx_unlocked == 3) {
|
||||
if((address & 0xFFF0) == 0xCFD0) {
|
||||
romx_textbank = address & 0xF;
|
||||
}
|
||||
|
@ -208,20 +234,26 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
|||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Card Registers
|
||||
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
|
||||
if(ACCESS_WRITE) {
|
||||
if(CARD_SELECT && CARD_DEVSEL) {
|
||||
cardslot = (address >> 4) & 0x7;
|
||||
switch(address & 0x0F) {
|
||||
case 0x01:
|
||||
mono_palette = (value >> 4) & 0xF;
|
||||
if(value & 0x8) {
|
||||
if(value & 8) {
|
||||
internal_flags |= IFLAGS_OLDCOLOR;
|
||||
} else {
|
||||
internal_flags &= ~IFLAGS_OLDCOLOR;
|
||||
}
|
||||
if(value & 4) {
|
||||
internal_flags |= IFLAGS_VIDEO7;
|
||||
} else {
|
||||
internal_flags &= ~IFLAGS_VIDEO7;
|
||||
}
|
||||
apple_memory[address] = value;
|
||||
break;
|
||||
case 0x02:
|
||||
|
@ -233,10 +265,10 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
|||
apple_memory[address] = terminal_border;
|
||||
break;
|
||||
case 0x08:
|
||||
soft_switches &= ~SOFTSW_TERMINAL;
|
||||
internal_flags &= ~IFLAGS_TERMINAL;
|
||||
break;
|
||||
case 0x09:
|
||||
soft_switches |= SOFTSW_TERMINAL;
|
||||
internal_flags |= IFLAGS_TERMINAL;
|
||||
break;
|
||||
case 0x0A:
|
||||
terminal_fifo[terminal_fifo_wrptr++] = (value & 0xFF);
|
||||
|
|
|
@ -213,7 +213,7 @@ void DELAYED_COPY_CODE(render_loop)() {
|
|||
vga_prepare_frame();
|
||||
render_shr();
|
||||
#endif
|
||||
} else if(soft_switches & SOFTSW_TERMINAL) {
|
||||
} else if(internal_flags & IFLAGS_TERMINAL) {
|
||||
vga_prepare_frame();
|
||||
render_terminal();
|
||||
} else {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define RENDER_TEST_PATTERN
|
||||
|
||||
extern uint16_t lores_palette[16];
|
||||
extern uint16_t dhgr_palette[16];
|
||||
|
||||
extern uint16_t text_fore, text_back, text_border;
|
||||
extern uint8_t status_line[81];
|
||||
extern bool mono_rendering;
|
||||
|
@ -25,8 +27,11 @@ extern void render_test_sleep();
|
|||
|
||||
extern void update_text_flasher();
|
||||
extern void render_text();
|
||||
extern void render_mixed_text();
|
||||
extern void render_text40_line(bool p2, unsigned int line);
|
||||
extern void render_text80_line(bool p2, unsigned int line);
|
||||
extern void render_color_text40_line(unsigned int line);
|
||||
extern void render_color_text80_line(unsigned int line);
|
||||
extern void render_status_line();
|
||||
|
||||
extern void render_terminal();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
uint8_t terminal_jsoffset = 0;
|
||||
uint8_t terminal_ssoffset = 0;
|
||||
bool terminal_inverse = 0;
|
||||
bool terminal_esc = 0;
|
||||
bool terminal_esc_crz = 0;
|
||||
int terminal_esc_pos = 0;
|
||||
|
@ -26,15 +27,19 @@ static inline uint_fast8_t char_terminal_bits(uint_fast8_t ch, uint_fast8_t glyp
|
|||
return (bits & 0x7f);
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(terminal_scroll)() {
|
||||
// Clear the next text buffer line (using dma if possible)
|
||||
memset((void*)(terminal_memory+(((terminal_height+terminal_jsoffset) * 128) & 0xFFF)), ' ', 128);
|
||||
|
||||
// Smooth scroll then increment jsoffset
|
||||
terminal_ssoffset = 1;
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(terminal_linefeed)() {
|
||||
if(terminal_row < (terminal_height-1)) {
|
||||
terminal_row++;
|
||||
} else {
|
||||
// Clear the next text buffer line (using dma if possible)
|
||||
memset((void*)(terminal_memory+(((terminal_row+1+terminal_jsoffset) * 128) & 0xFFF)), ' ', 128);
|
||||
|
||||
// Smooth scroll then increment jsoffset
|
||||
terminal_ssoffset = 1;
|
||||
terminal_scroll();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +94,7 @@ void DELAYED_COPY_CODE(terminal_process_input)() {
|
|||
terminal_clear_screen();
|
||||
break;
|
||||
case '1':
|
||||
soft_switches &= ~SOFTSW_TERMINAL;
|
||||
internal_flags &= ~IFLAGS_TERMINAL;
|
||||
break;
|
||||
case '2':
|
||||
terminal_charset = 0;
|
||||
|
@ -104,17 +109,30 @@ void DELAYED_COPY_CODE(terminal_process_input)() {
|
|||
}
|
||||
terminal_esc_crz = false;
|
||||
} else if(terminal_esc) {
|
||||
terminal_esc = false;
|
||||
switch(ch) {
|
||||
case 'K':
|
||||
case '>':
|
||||
terminal_esc = true;
|
||||
case 'A':
|
||||
terminal_advance_cursor();
|
||||
break;
|
||||
case 'J':
|
||||
case '<':
|
||||
terminal_esc = true;
|
||||
case 'B':
|
||||
if(terminal_col > 0)
|
||||
terminal_col--;
|
||||
break;
|
||||
case 'M':
|
||||
case 'v':
|
||||
terminal_esc = true;
|
||||
case 'C':
|
||||
terminal_linefeed();
|
||||
break;
|
||||
case 'I':
|
||||
case '^':
|
||||
terminal_esc = true;
|
||||
case 'D': // Reverse Linefeed
|
||||
if(terminal_row > 0)
|
||||
terminal_row--;
|
||||
|
@ -128,14 +146,25 @@ void DELAYED_COPY_CODE(terminal_process_input)() {
|
|||
case '@': // Clear screen
|
||||
terminal_clear_screen();
|
||||
break;
|
||||
case '4':
|
||||
internal_flags &= ~IFLAGS_TERMINAL;
|
||||
break;
|
||||
case '8':
|
||||
internal_flags |= IFLAGS_TERMINAL;
|
||||
break;
|
||||
default:
|
||||
terminal_memory[(((terminal_row+terminal_jsoffset) * 128) + terminal_col) & 0xFFF] = ch;
|
||||
terminal_advance_cursor();
|
||||
break;
|
||||
}
|
||||
terminal_esc = false;
|
||||
} else
|
||||
switch(ch) {
|
||||
case 0x07:
|
||||
break;
|
||||
case 0x08:
|
||||
if(terminal_col > 0)
|
||||
terminal_col--;
|
||||
break;
|
||||
case 0x0A: // Line Feed
|
||||
terminal_linefeed();
|
||||
break;
|
||||
|
@ -148,10 +177,25 @@ void DELAYED_COPY_CODE(terminal_process_input)() {
|
|||
case 0x0D: // Ctrl-M: Carriage Return
|
||||
terminal_col = 0;
|
||||
break;
|
||||
case 0x0E: // Normal Text
|
||||
terminal_inverse = false;
|
||||
break;
|
||||
case 0x0F: // Inverse Text
|
||||
terminal_inverse = true;
|
||||
break;
|
||||
case 0x11:
|
||||
internal_flags &= ~IFLAGS_TERMINAL;
|
||||
break;
|
||||
case 0x12:
|
||||
internal_flags |= IFLAGS_TERMINAL;
|
||||
break;
|
||||
case 0x13: // Ctrl-S: Xon/Xoff (unimplemented)
|
||||
break;
|
||||
case 0x15: // Ctrl-U: Copy (unimplemented)
|
||||
break;
|
||||
case 0x17: // Ctrl-W: Scroll one line without moving cursor
|
||||
terminal_scroll();
|
||||
break;
|
||||
case 0x19: // Ctrl-Y: Home Cursor
|
||||
terminal_row = 0;
|
||||
terminal_col = 0;
|
||||
|
@ -176,7 +220,7 @@ void DELAYED_COPY_CODE(terminal_process_input)() {
|
|||
terminal_row--;
|
||||
break;
|
||||
default:
|
||||
terminal_memory[(((terminal_row+terminal_jsoffset) * 128) + terminal_col) & 0xFFF] = ch;
|
||||
terminal_memory[(((terminal_row+terminal_jsoffset) * 128) + terminal_col) & 0xFFF] = ch ^ (terminal_inverse ? 0x80 : 0x00);
|
||||
terminal_advance_cursor();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -30,13 +30,7 @@ void DELAYED_COPY_CODE(render_mixed_dgr)() {
|
|||
render_dgr_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
render_mixed_text();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,27 +25,25 @@ static inline uint dhgr_line_to_mem_offset(uint line) {
|
|||
|
||||
|
||||
void DELAYED_COPY_CODE(render_dhgr)() {
|
||||
if((internal_flags & IFLAGS_VIDEO7) && (internal_flags & IFLAGS_V7_MODE3 == IFLAGS_V7_MODE3)) {
|
||||
mono_rendering = true;
|
||||
}
|
||||
for(uint line=0; line < 192; line++) {
|
||||
render_dhgr_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_mixed_dhgr)() {
|
||||
if((internal_flags & IFLAGS_VIDEO7) && (internal_flags & IFLAGS_V7_MODE3 == IFLAGS_V7_MODE3)) {
|
||||
mono_rendering = true;
|
||||
}
|
||||
for(uint line=0; line < 160; line++) {
|
||||
render_dhgr_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
render_mixed_text();
|
||||
}
|
||||
|
||||
|
||||
static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
|
@ -54,10 +52,17 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint 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
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word
|
||||
if((internal_flags & IFLAGS_VIDEO7) && ((internal_flags & IFLAGS_V7_MODE3) == IFLAGS_V7_MODE1)) {
|
||||
// Pad 30 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_3) | ((text_border|THEN_EXTEND_7) << 16); // 12 pixels per word
|
||||
sl->data[sl_pos++] = (text_border) | ((text_border) << 16); // 2 pixels per word
|
||||
} else {
|
||||
// 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); // 16 pixels per word
|
||||
}
|
||||
|
||||
// DHGR is weird. Nuff said.
|
||||
uint32_t dots = 0;
|
||||
|
@ -86,6 +91,27 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line) {
|
|||
dotc -= 2;
|
||||
}
|
||||
}
|
||||
} else if((internal_flags & IFLAGS_VIDEO7) && ((internal_flags & IFLAGS_V7_MODE3) == IFLAGS_V7_MODE1)) {
|
||||
while(i < 40) {
|
||||
// Load in as many subpixels as possible
|
||||
while((dotc <= 18) && (i < 40)) {
|
||||
dots |= (line_memb[i] & 0xff) << dotc;
|
||||
dotc += 8;
|
||||
dots |= (line_mema[i] & 0xff) << dotc;
|
||||
dotc += 8;
|
||||
i++;
|
||||
}
|
||||
|
||||
// Consume pixels
|
||||
while(dotc >= 8) {
|
||||
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;
|
||||
dotc -= 8;
|
||||
}
|
||||
}
|
||||
} else if(internal_flags & IFLAGS_OLDCOLOR) {
|
||||
while(i < 40) {
|
||||
// Load in as many subpixels as possible
|
||||
|
@ -149,10 +175,17 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line) {
|
|||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
|
||||
// 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); // 16 pixels per word
|
||||
if((internal_flags & IFLAGS_VIDEO7) && ((internal_flags & IFLAGS_V7_MODE3) == IFLAGS_V7_MODE1)) {
|
||||
// Pad 30 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_3) | ((text_border|THEN_EXTEND_7) << 16); // 12 pixels per word
|
||||
sl->data[sl_pos++] = (text_border) | ((text_border) << 16); // 2 pixels per word
|
||||
} else {
|
||||
// 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); // 16 pixels per word
|
||||
}
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
|
|
|
@ -29,13 +29,7 @@ void DELAYED_COPY_CODE(render_mixed_hires)() {
|
|||
render_hires_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
render_mixed_text();
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) {
|
||||
|
|
|
@ -48,13 +48,7 @@ void DELAYED_COPY_CODE(render_mixed_lores)() {
|
|||
render_lores_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
render_mixed_text();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
extern uint16_t lores_palette[16];
|
||||
|
||||
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
|
||||
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
|
||||
|
||||
|
@ -48,11 +50,53 @@ static inline uint_fast8_t char_text_bits(uint_fast8_t ch, uint_fast8_t glyph_li
|
|||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_text)() {
|
||||
for(uint line=0; line < 24; line++) {
|
||||
uint line;
|
||||
|
||||
if((internal_flags & IFLAGS_VIDEO7) && !(soft_switches & SOFTSW_DGR)) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
for(line=0; line < 24; line++) {
|
||||
render_color_text80_line(line);
|
||||
}
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
for(line=0; line < 24; line++) {
|
||||
render_color_text40_line(line);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
for(line=0; line < 24; line++) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
}
|
||||
} else {
|
||||
for(line=0; line < 24; line++) {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_mixed_text)() {
|
||||
uint line;
|
||||
|
||||
if((internal_flags & IFLAGS_VIDEO7) && !(soft_switches & SOFTSW_DGR)) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
for(line=20; line < 24; line++) {
|
||||
render_color_text80_line(line);
|
||||
}
|
||||
} else {
|
||||
for(line=20; line < 24; line++) {
|
||||
render_color_text40_line(line);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
for(line=20; line < 24; line++) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
}
|
||||
} else {
|
||||
for(line=20; line < 24; line++) {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,3 +194,146 @@ void DELAYED_COPY_CODE(render_text80_line)(bool p2, unsigned int line) {
|
|||
}
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_color_text40_line)(unsigned int line) {
|
||||
const uint8_t *line_buf = (const uint8_t *)(text_p1 + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
const uint8_t *color_buf = (const uint8_t *)(text_p3 + ((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 two characters
|
||||
uint32_t bits_a = char_text_bits(line_buf[col], glyph_line);
|
||||
uint16_t color1 = lores_palette[(color_buf[col] >> 4) & 0xf];
|
||||
uint16_t color2 = lores_palette[color_buf[col] & 0xf];
|
||||
col++;
|
||||
uint32_t bits_b = char_text_bits(line_buf[col], glyph_line);
|
||||
uint16_t color3 = lores_palette[(color_buf[col] >> 4) & 0xf];
|
||||
uint16_t color4 = lores_palette[color_buf[col] & 0xf];
|
||||
col++;
|
||||
|
||||
uint32_t bits = (bits_a << 7) | bits_b;
|
||||
uint32_t pixeldata;
|
||||
|
||||
// Translate each pair of bits into a pair of pixels
|
||||
for(int i=0; i < 3; i++) {
|
||||
pixeldata = (bits & 0x2000) ? (color2|THEN_EXTEND_1) : (color1|THEN_EXTEND_1);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
(uint32_t)(color2|THEN_EXTEND_1) << 16 :
|
||||
(uint32_t)(color1|THEN_EXTEND_1) << 16;
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
}
|
||||
|
||||
pixeldata = (bits & 0x2000) ? (color2|THEN_EXTEND_1) : (color1|THEN_EXTEND_1);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
(uint32_t)(color4|THEN_EXTEND_1) << 16 :
|
||||
(uint32_t)(color3|THEN_EXTEND_1) << 16;
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
|
||||
for(int i=4; i < 7; i++) {
|
||||
pixeldata = (bits & 0x2000) ? (color4|THEN_EXTEND_1) : (color3|THEN_EXTEND_1);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
(uint32_t)(color4|THEN_EXTEND_1) << 16 :
|
||||
(uint32_t)(color3|THEN_EXTEND_1) << 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;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_color_text80_line)(unsigned int line) {
|
||||
const uint8_t *line_buf_a = (const uint8_t *)(text_p1 + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
const uint8_t *line_buf_b = (const uint8_t *)(text_p3 + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
const uint8_t *color_buf_a = (const uint8_t *)(text_p2 + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
const uint8_t *color_buf_b = (const uint8_t *)(text_p4 + ((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 two 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);
|
||||
uint16_t color1 = lores_palette[color_buf_a[col] >> 4];
|
||||
uint16_t color2 = lores_palette[color_buf_a[col] & 0xF];
|
||||
uint16_t color3 = lores_palette[color_buf_b[col] >> 4];
|
||||
uint16_t color4 = lores_palette[color_buf_b[col] & 0xF];
|
||||
col++;
|
||||
|
||||
uint32_t bits = (bits_b << 7) | bits_a;
|
||||
uint32_t pixeldata;
|
||||
|
||||
// Translate each pair of bits into a pair of pixels
|
||||
for(int i=0; i < 3; i++) {
|
||||
pixeldata = (bits & 0x2000) ? (color2) : (color1);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
(uint32_t)(color2) << 16 :
|
||||
(uint32_t)(color1) << 16;
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
}
|
||||
|
||||
pixeldata = (bits & 0x2000) ? (color2) : (color1);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
(uint32_t)(color4) << 16 :
|
||||
(uint32_t)(color3) << 16;
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
|
||||
for(int i=4; i < 7; i++) {
|
||||
pixeldata = (bits & 0x2000) ? (color4) : (color3);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
(uint32_t)(color4) << 16 :
|
||||
(uint32_t)(color3) << 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;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue