#include #include #include #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); } } } }