Video 7 support

This commit is contained in:
David Kuder 2023-04-28 23:23:03 -04:00
parent d5e001f2c1
commit e94cfac000
12 changed files with 419 additions and 69 deletions

View File

@ -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

View File

@ -15,8 +15,10 @@ extern volatile uint8_t romx_changed;
#include <string.h>
#ifdef ANALOG_GS
volatile compat_t cfg_machine = MACHINE_AUTO;
volatile compat_t current_machine = MACHINE_AUTO;
#endif
#ifdef FUNCTION_Z80
volatile usbmux_t usbmux;
@ -68,21 +70,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 +108,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 +193,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 +308,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 +358,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 +374,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 +391,7 @@ bool DELAYED_COPY_CODE(read_config)() {
if(parse_config(FLASH_CONFIG_SECONDARY))
return true;
}
#endif
default_config();
return false;
@ -359,6 +407,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 +421,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 +453,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 +466,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 +628,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:

View File

@ -46,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;
@ -76,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;
@ -108,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;

View File

@ -8,14 +8,14 @@
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
@ -156,6 +156,11 @@ 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;
}
@ -239,11 +244,16 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
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:
@ -255,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);

View File

@ -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 {

View File

@ -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();

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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) {

View File

@ -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();
}

View File

@ -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);
}
}