mirror of
https://github.com/V2RetroComputing/analog.git
synced 2024-11-28 19:49:45 +00:00
0835003caa
Progress on PCPI mode bug fixes. PCPI mode is now working again, but the config interface is still broken enough to prevent the use of the config utility while in this mode.. Sending the FORMAT command from the monitor rom returns the card to defaults. Replace n with the slot number the card is installed in: ]CALL -151 *CnF0:46 4F 52 4D 41 54 00 00 Correction of mousetext / inverse / flashing handling on IIe see https://github.com/V2RetroComputing/analog/issues/3 Monochrome mode & color palettes are now implemented. $C0n1: Monochrome mode & palette $80: B&W $90: Inverse $A0: Amber $B0: Inverse Amber $C0: Green $D0: Inverse Green $E0: Commodore 64 Theme $F0: Use IIgs palette $C0n2: Mirror of IIgs TBCOLOR register $C0n3: Mirror of IIgs BORDER register
258 lines
7.3 KiB
C
258 lines
7.3 KiB
C
#include <string.h>
|
|
#include <pico/stdlib.h>
|
|
#include <hardware/timer.h>
|
|
#include "common/config.h"
|
|
#include "vga/vgabuf.h"
|
|
#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 = MACHINE_II;
|
|
bool userfont = false;
|
|
|
|
uint16_t mono_colors[14] = {
|
|
_RGB333(0x00, 0x00, 0x00), _RGB333(0xFF, 0xFF, 0xFF), // White Normal
|
|
_RGB333(0xFF, 0xFF, 0xFF), _RGB333(0x00, 0x00, 0x00), // White Inverse
|
|
_RGB333(0x00, 0x00, 0x00), _RGB333(0xFE, 0x7F, 0x00), // Amber Normal
|
|
_RGB333(0xFE, 0x7F, 0x00), _RGB333(0x00, 0x00, 0x00), // Amber Inverse
|
|
_RGB333(0x00, 0x00, 0x00), _RGB333(0x00, 0xBF, 0x00), // Green Normal
|
|
_RGB333(0x00, 0xBF, 0x00), _RGB333(0x00, 0x00, 0x00), // Green Inverse
|
|
_RGB333(0x35, 0x28, 0x79), _RGB333(0x6C, 0x5E, 0xB5), // Commodore
|
|
};
|
|
|
|
// Initialize the character generator ROM
|
|
void switch_font() {
|
|
switch(current_machine) {
|
|
default:
|
|
case MACHINE_II:
|
|
memcpy(character_rom, default_character_rom, 2048);
|
|
break;
|
|
case MACHINE_PRAVETZ:
|
|
memcpy(character_rom, pravetz_character_rom, 2048);
|
|
break;
|
|
case MACHINE_IIE:
|
|
memcpy(character_rom, appleiie_character_rom, 2048);
|
|
break;
|
|
case MACHINE_IIGS:
|
|
memcpy(character_rom, appleiigs_character_rom, 2048);
|
|
break;
|
|
}
|
|
machinefont = current_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;
|
|
}
|
|
|
|
uint16_t status_timeout = 900;
|
|
uint8_t status_line[81];
|
|
|
|
void 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 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 render_init() {
|
|
int i;
|
|
|
|
load_font();
|
|
if(!userfont)
|
|
switch_font();
|
|
|
|
if((soft_switches & SOFTSW_MODE_MASK) == 0)
|
|
internal_flags |= IFLAGS_TEST;
|
|
terminal_tbcolor = 0xf0;
|
|
terminal_border = 0x00;
|
|
|
|
memcpy(terminal_character_rom, appleiie_character_rom, 2048);
|
|
memset(status_line, 0, sizeof(status_line));
|
|
|
|
render_test_init();
|
|
}
|
|
|
|
// Skip 48 lines to center vertically
|
|
void __time_critical_func(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); // 8 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 __noinline __time_critical_func(render_loop)() {
|
|
while(current_mode == MODE_VGACARD) {
|
|
config_handler();
|
|
|
|
if((busactive == 0) && (screentimeout > (15 * 60))) {
|
|
vga_prepare_frame();
|
|
render_border(480);
|
|
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 == 5) {
|
|
update_status_right("Going to sleep...");
|
|
}
|
|
} else {
|
|
if(screentimeout >= 5) {
|
|
// Clear the sleep mode message
|
|
memset(status_line, 0, sizeof(status_line));
|
|
status_timeout = 0;
|
|
}
|
|
screentimeout = 0;
|
|
}
|
|
busactive = 0;
|
|
|
|
if(!userfont && (machinefont != current_machine)) {
|
|
switch_font();
|
|
}
|
|
|
|
update_text_flasher();
|
|
|
|
if((soft_switches & SOFTSW_MONOCHROME) && (mono_palette != 0x7)) {
|
|
text_fore = mono_colors[mono_palette*2+1];
|
|
text_back = mono_colors[mono_palette*2];
|
|
text_border = (mono_palette == 0x6) ? text_fore : text_back;
|
|
} else {
|
|
text_fore = lores_palette[TERMINAL_FORE];
|
|
text_back = lores_palette[TERMINAL_BACK];
|
|
text_border = lores_palette[TERMINAL_BORDER];
|
|
}
|
|
|
|
if(internal_flags & IFLAGS_TEST) {
|
|
render_testpattern();
|
|
// Automatically dismiss the test pattern when the Apple II is seen.
|
|
if(((soft_switches & SOFTSW_MODE_MASK) != 0) && (testdone == 0)) {
|
|
internal_flags &= ~IFLAGS_TEST;
|
|
testdone = 1;
|
|
render_about_init();
|
|
}
|
|
#if 0
|
|
} else if(soft_switches & SOFTSW_TERMINAL) {
|
|
render_terminal();
|
|
} else if(soft_switches & SOFTSW_SHR) {
|
|
render_shr();
|
|
#endif
|
|
} else {
|
|
vga_prepare_frame();
|
|
|
|
render_border(24);
|
|
if(status_line[0] != 0) {
|
|
render_status_line();
|
|
render_border(16);
|
|
} 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);
|
|
}
|
|
}
|
|
}
|
|
}
|