analog-firmware/vga/render.c
David Kuder dd9fa40678 Disable the test screen on any bus activity
May need to make this on consistent bus activity.
The card was remaining in the test pattern if reset and no soft switches were toggled afterward.
2023-05-02 16:18:10 -04:00

271 lines
8.2 KiB
C

#include <string.h>
#include <pico/stdlib.h>
#include <hardware/timer.h>
#include "common/config.h"
#include "common/flash.h"
#include "common/dmacopy.h"
#include "vga/vgabuf.h"
#include "vga/render.h"
#include "vga/vgaout.h"
uint16_t text_fore;
uint16_t text_back;
uint16_t text_border;
compat_t machinefont = MACHINE_INVALID;
bool userfont = false;
bool mono_rendering = false;
uint16_t DELAYED_COPY_DATA(mono_colors)[14] = {
_RGB(0x00, 0x00, 0x00), _RGB(0xFF, 0xFF, 0xFF), // White Normal
_RGB(0xFF, 0xFF, 0xFF), _RGB(0x00, 0x00, 0x00), // White Inverse
_RGB(0x00, 0x00, 0x00), _RGB(0xFE, 0x7F, 0x00), // Amber Normal
_RGB(0xFE, 0x7F, 0x00), _RGB(0x00, 0x00, 0x00), // Amber Inverse
_RGB(0x00, 0x00, 0x00), _RGB(0x00, 0xBF, 0x00), // Green Normal
_RGB(0x00, 0xBF, 0x00), _RGB(0x00, 0x00, 0x00), // Green Inverse
_RGB(0x35, 0x28, 0x79), _RGB(0x6C, 0x5E, 0xB5), // Commodore
};
// Initialize the character generator ROM
static void DELAYED_COPY_CODE(switch_font)() {
if(romx_changed) {
memcpy32(character_rom, (void*)FLASH_FONT(romx_textbank), 4096);
} else if(userfont) {
return;
} else if(current_machine != machinefont) {
switch(current_machine) {
default:
case MACHINE_II:
memcpy32(character_rom, (void*)FLASH_FONT_APPLE_II, 4096);
break;
case MACHINE_IIE:
memcpy32(character_rom, (void*)FLASH_FONT_APPLE_IIE, 4096);
break;
case MACHINE_IIGS:
memcpy32(character_rom, (void*)FLASH_FONT_APPLE_IIGS, 4096);
break;
case MACHINE_PRAVETZ:
memcpy32(character_rom, (void*)FLASH_FONT_PRAVETZ, 4096);
break;
}
machinefont = current_machine;
}
}
uint16_t status_timeout = 900;
uint8_t status_line[81];
void DELAYED_COPY_CODE(update_status_right)(const char *str) {
uint i, len;
if(str != NULL) {
len = strlen(str);
} else {
len = 0;
}
if(len < 80) {
memset(status_line, ' ', 80 - len);
} else {
len = 80;
}
for(i = 0; i < len; i++) {
status_line[(80-len) + i] = str[i];
}
status_timeout = 900;
}
void DELAYED_COPY_CODE(update_status_left)(const char *str) {
uint i, len;
if(str != NULL) {
len = strlen(str);
} else {
len = 0;
}
if(len < 80) {
memset(status_line + len, ' ', 80 - len);
} else {
len = 80;
}
for(i = 0; i < len; i++) {
status_line[i] = str[i];
}
status_timeout = 900;
}
void DELAYED_COPY_CODE(render_init)() {
int i;
switch_font();
if((soft_switches & SOFTSW_MODE_MASK) == 0)
internal_flags |= IFLAGS_TEST;
apple_tbcolor = 0xf0;
apple_border = 0x00;
terminal_tbcolor = 0xf0;
terminal_border = 0x00;
memcpy(terminal_character_rom, (void*)FLASH_VIDEX_BASE, 4096);
memset(status_line, 0, sizeof(status_line));
terminal_clear_screen();
render_test_init();
}
// Skip lines to center vertically or blank the screen
void DELAYED_COPY_CODE(render_border)(uint count) {
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); // 16 pixels per word
sl_pos++;
}
sl->length = sl_pos;
sl->repeat_count = count - 1;
vga_submit_scanline(sl);
}
uint32_t screentimeout = 0;
uint32_t testdone = 0;
void DELAYED_COPY_CODE(render_loop)() {
for(;;) {
config_handler();
#if 0
if((busactive == 0) && (screentimeout > (15 * 60))) {
vga_prepare_frame();
render_border(VGA_HEIGHT);
memset(status_line, 0, sizeof(status_line));
status_timeout = 0;
vga_dpms_sleep();
while(busactive == 0);
vga_dpms_wake();
} else {
if(busactive == 0) {
screentimeout++;
if(screentimeout == 30) {
update_status_right("Going to sleep...");
}
} else {
if(screentimeout >= 30) {
// Clear the sleep mode message
memset(status_line, 0, sizeof(status_line));
status_timeout = 0;
}
screentimeout = 0;
}
busactive = 0;
#endif
if(romx_changed || (machinefont != current_machine)) {
switch_font();
romx_changed = 0;
machinefont = current_machine;
}
update_text_flasher();
if(!(mono_palette & 0x8)) {
if((current_machine == MACHINE_IIGS) && !(soft_switches & SOFTSW_MONOCHROME)) {
text_fore = lores_palette[APPLE_FORE];
text_back = lores_palette[APPLE_BACK];
text_border = lores_palette[APPLE_BORDER];
} else {
text_fore = mono_colors[1];
text_back = mono_colors[0];
text_border = mono_colors[0];
}
} else if(mono_palette == 0xF) {
text_fore = lores_palette[TERMINAL_FORE];
text_back = lores_palette[TERMINAL_BACK];
text_border = lores_palette[TERMINAL_BORDER];
} else {
int palette = mono_palette & 0x7;
text_fore = mono_colors[palette*2+1];
text_back = mono_colors[palette*2];
text_border = (palette == 0x6) ? text_fore : text_back;
}
mono_rendering = ((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8));
if(internal_flags & IFLAGS_TEST) {
render_testpattern();
// Assume the RP2040 has been hard reset and try to default to text display
if(busactive && (testdone == 0)) { // was ((soft_switches & SOFTSW_MODE_MASK) != 0)
soft_switches |= SOFTSW_TEXT_MODE;
internal_flags &= ~IFLAGS_TEST;
testdone = 1;
render_about_init();
}
#if defined(ANALOG_GS)
} else if(soft_switches & SOFTSW_SHR) {
vga_prepare_frame();
render_shr();
#endif
} else if(internal_flags & IFLAGS_TERMINAL) {
vga_prepare_frame();
render_terminal();
} else {
vga_prepare_frame();
render_border(16);
if(status_line[0] != 0) {
render_status_line();
} else {
render_border(32);
}
switch(soft_switches & SOFTSW_MODE_MASK) {
case 0:
if(soft_switches & SOFTSW_DGR) {
render_dgr();
} else {
render_lores();
}
break;
case SOFTSW_MIX_MODE:
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
render_mixed_dgr();
} else {
render_mixed_lores();
}
break;
case SOFTSW_HIRES_MODE:
if(soft_switches & SOFTSW_DGR) {
render_dhgr();
} else {
render_hires();
}
break;
case SOFTSW_HIRES_MODE|SOFTSW_MIX_MODE:
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
render_mixed_dhgr();
} else {
render_mixed_hires();
}
break;
default:
render_text();
break;
}
render_border(48);
}
#if 0
}
#endif
}
}