diff --git a/CMakeLists.txt b/CMakeLists.txt index 75bd97a..1e9c5c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,11 +19,11 @@ set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR}/boards ) #set(PICO_PLATFORM "rp2040" CACHE STRING "Chip type") set(PICO_PLATFORM "rp2350" CACHE STRING "Chip type") -#set(PICO_BOARD "murmulator" CACHE STRING "Board type") +set(PICO_BOARD "murmulator" CACHE STRING "Board type") #set(PICO_BOARD "murmulator2" CACHE STRING "Board type") #set(PICO_BOARD "olimex-pico-pc" CACHE STRING "Board type") #set(PICO_BOARD "waveshare_rp2040_pizero" CACHE STRING "Board type") -set(PICO_BOARD "waveshare_rp2350_pizero" CACHE STRING "Board type") +#set(PICO_BOARD "waveshare_rp2350_pizero" CACHE STRING "Board type") include(pico_sdk_import.cmake) @@ -48,7 +48,7 @@ set(I2S ON) #set(TFT ON) #set(ILI9341 ON) -set(HDMI ON) +#set(HDMI ON) #set(TV ON) #set(SOFTTV ON) diff --git a/src/main.cpp b/src/main.cpp index e1e5efe..e802576 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,7 +62,7 @@ SETTINGS settings = { .version = 1, .swap_ab = false, .aspect_ratio = false, - .ghosting = 8, + .ghosting = 4, .palette = SV_COLOR_SCHEME_WATAROO, .save_slot = 0, .rgb0 = 0xCCFFFF, @@ -187,8 +187,6 @@ Ps2Kbd_Mrmltr ps2kbd( process_kbd_report ); - - static const uint8 palettes[SV_COLOR_SCHEME_COUNT][12] = { { /* SV_COLOR_SCHEME_DEFAULT */ 252, 252, 252, @@ -813,7 +811,6 @@ void load_config() { FIL file; char pathname[256]; sprintf(pathname, "%s\\emulator.cfg", HOME_DIR); - if (FR_OK == f_mount(&fs, "", 1) && FR_OK == f_open(&file, pathname, FA_READ)) { UINT bytes_read; f_read(&file, &settings, sizeof(settings), &bytes_read); @@ -823,6 +820,7 @@ void load_config() { rgb1 = settings.rgb1; rgb2 = settings.rgb2; rgb3 = settings.rgb3; + if (settings.ghosting > 6) settings.ghosting = 4; } void save_config() { @@ -864,7 +862,7 @@ bool toggle_color() { const MenuItem menu_items[] = { {"Swap AB <> BA: %s", ARRAY, &settings.swap_ab, nullptr, 1, {"NO ", "YES"}}, {}, - { "Ghosting pix: %i ", INT, &settings.ghosting, nullptr, 8 }, + { "Ghosting pix: %i ", INT, &settings.ghosting, nullptr, 6 }, { "Palette: %s ", ARRAY, &settings.palette, nullptr, SV_COLOR_SCHEME_COUNT, { "DEFAULT " , "AMBER " @@ -968,16 +966,19 @@ void menu() { uint32_t vc = *value; vc &= ~(0xF << (5 - hex_digit) * 4); vc |= ((uint32_t)h_code << (5 - hex_digit) * 4); + if (vc < item->max_value) *value = vc; if (++hex_digit == 6) { - hex_digit = 0; + h_code = -1; + hex_digit = -1; + keyboard.h_code = -1; current_item++; } - if (vc < item->max_value) *value = vc; settings.rgb0 = rgb0; settings.rgb1 = rgb1; settings.rgb2 = rgb2; settings.rgb3 = rgb3; update_palette(); + sleep_ms(125); break; } if (gamepad1.bits.right && hex_digit == 5) { @@ -1064,18 +1065,16 @@ void menu() { draw_text(result, x, y, color, bg_color); } - if (gamepad1.bits.b) + if (gamepad1.bits.b || (gamepad1.bits.select && !gamepad1.bits.start)) exit = true; - if (gamepad1.bits.down) { + if (gamepad1.bits.down && hex_digit < 0) { current_item = (current_item + 1) % MENU_ITEMS_NUMBER; - if (menu_items[current_item].type == NONE) current_item++; } - if (gamepad1.bits.up) { + if (gamepad1.bits.up && hex_digit < 0) { current_item = (current_item - 1 + MENU_ITEMS_NUMBER) % MENU_ITEMS_NUMBER; - if (menu_items[current_item].type == NONE) current_item--; } @@ -1083,7 +1082,6 @@ void menu() { sleep_ms(125); } - update_palette(); #if VGA if (settings.aspect_ratio) { graphics_set_offset(40, 20); @@ -1101,7 +1099,6 @@ void menu() { graphics_set_mode(GRAPHICSMODE_DEFAULT); memcpy(SCREEN, (void *)bezel, sizeof(bezel)); #endif - supervision_set_ghosting(settings.ghosting); if (count_of(palettes) <= settings.palette) { settings.rgb0 = rgb0; settings.rgb1 = rgb1; @@ -1212,7 +1209,6 @@ int __time_critical_func(main)() { if (supervision_load((uint8_t *)rom, rom_size) ) { update_palette(); - supervision_set_ghosting(settings.ghosting); } #if VGA @@ -1249,12 +1245,14 @@ int __time_critical_func(main)() { } #if VGA if (settings.aspect_ratio) { - supervision_exec_ex((uint8_t *) SCREEN + 240 * 20 + 40, 240, 0); + uint32_t sw_w = 240; + supervision_exec_ex((uint8_t *) SCREEN + sw_w * 20 + 40, sw_w, 0, settings.ghosting); } else { - supervision_exec_ex((uint8_t *) SCREEN, SV_W, 0); + supervision_exec_ex((uint8_t *) SCREEN, SV_W, 0, settings.ghosting); } #else - supervision_exec_ex((uint8_t *) SCREEN + 240 * 20 + 40, 240, 0); + uint32_t sw_w = 240; + supervision_exec_ex((uint8_t *) SCREEN + sw_w * 20 + 40, sw_w, 0, settings.ghosting); #endif // for(int x = 0; x <64; x++) graphics_set_palette(x, RGB888(bitmap.pal.color[x][0], bitmap.pal.color[x][1], bitmap.pal.color[x][2])); diff --git a/src/potator/gpu.c b/src/potator/gpu.c index ef743f6..eac3637 100644 --- a/src/potator/gpu.c +++ b/src/potator/gpu.c @@ -24,8 +24,6 @@ static SV_MapRGBFunc mapRGB = rgb555; //uint32 watara_palette[4]; -int ghostCount = 8; - /* static uint8 screenBuffer8[SV_H][SV_W] = { 0 }; @@ -51,12 +49,10 @@ void gpu_init(void) { void gpu_reset(void) { gpu_set_map_func(NULL); - // gpu_set_ghosting(0); } void gpu_done(void) { // free(watara_palette); watara_palette = NULL; - // gpu_set_ghosting(0); } void gpu_set_map_func(SV_MapRGBFunc func) { @@ -64,110 +60,3 @@ void gpu_set_map_func(SV_MapRGBFunc func) { // if (mapRGB == NULL) // mapRGB = rgb555; } - -/* - -void __time_critical_func(gpu_render_scanline2)(uint32 scanline, uint8 *backbuffer, uint8 innerx, uint8 size) { - uint8 *vram_line = memorymap_getUpperRamPointer() + scanline; - uint8 x, j = innerx, b = 0; - - // #1 - if (j & 3) { - b = *vram_line++; - b >>= (j & 3) * 2; - } -//#pragma GCC unroll 320 - if (ghostCount) { - for (x = 0; x < size; x++, j++) { - if (!(j & 3)) { - b = *(vram_line++); - } - //int color = (b & 3); // curr. state in 2 bits format - { - int c8 = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - int c8n = (b & 3) << 4; // new state in 8 bit format - if (c8n < c8) c8n = c8; - backbuffer[x] = c8n; - - // save it to next step - b >>= 2; - } - } - } else { - for (x = 0; x < size; x++, j++) { - if (!(j & 3)) { - b = *(vram_line++); - } - backbuffer[x] = (b & 3) << 4; - // save it to next step - b >>= 2; - } - } - -} - -*/ -void __time_critical_func(gpu_render_scanline)(uint32 scanline, uint8 *backbuffer, uint8 innerx, uint8 size) { - uint8 *vram_line = memorymap_getUpperRamPointer() + scanline; - uint8 x = 0, j = innerx & 3; - static int previous_color, current_color = 0; - - uint8 b = *vram_line++; - - if (j) { - b >>= j * 2; - } - - if (ghostCount) { -#pragma GCC unroll 4 - while (x < size) { - backbuffer[x++] = (b & 3) << 4; - b >>= 2; - backbuffer[x++] = (b & 3) << 4; - b >>= 2; - backbuffer[x++] = (b & 3) << 4; - b >>= 2; - backbuffer[x++] = (b & 3) << 4; - - b = *vram_line++; - } - } else { -#pragma GCC unroll 4 - while (x < size) { - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - if (current_color < previous_color) current_color = previous_color; - backbuffer[x++] = current_color; - b >>= 2; - - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - if (current_color < previous_color) current_color = previous_color; - backbuffer[x++] = current_color; - b >>= 2; - - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - if (current_color < previous_color) current_color = previous_color; - backbuffer[x++] = current_color; - b >>= 2; - - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - if (current_color < previous_color) current_color = previous_color; - backbuffer[x++] = current_color; - - b = *vram_line++; - } - } -} - -void gpu_set_ghosting(int frameCount) { - int i; - if (frameCount < 0) - ghostCount = 0; - else if (frameCount > SV_GHOSTING_MAX) - ghostCount = SV_GHOSTING_MAX; - else - ghostCount = frameCount; -} diff --git a/src/potator/gpu.h b/src/potator/gpu.h index ffe77b2..93456a5 100644 --- a/src/potator/gpu.h +++ b/src/potator/gpu.h @@ -8,7 +8,5 @@ void gpu_init(void); void gpu_reset(void); void gpu_done(void); void gpu_set_map_func(SV_MapRGBFunc func); -void gpu_render_scanline(uint32 scanline, uint8 *backbuffer, uint8 innerx, uint8 size); -void gpu_set_ghosting(int frameCount); #endif diff --git a/src/potator/supervision.h b/src/potator/supervision.h index 4d08f4c..73f9cf5 100644 --- a/src/potator/supervision.h +++ b/src/potator/supervision.h @@ -61,10 +61,6 @@ enum SV_COLOR { , SV_COLOR_SCHEME_COUNT }; -/*! - * \sa supervision_set_ghosting() - */ -#define SV_GHOSTING_MAX 8 /*! * \sa supervision_update_sound() */ @@ -77,7 +73,7 @@ void supervision_done(void); * \return TRUE - success, FALSE - error */ BOOL supervision_load(const uint8 *rom, uint32 romSize); -void supervision_exec_ex(uint8 *backbuffer, int16 backbufferWidth, BOOL skipFrame); +void supervision_exec_ex(uint8 *backbuffer, uint32 backbufferWidth, BOOL skipFrame, uint8_t ghosting); /*! * \param data Bits 0-7: Right, Left, Down, Up, B, A, Select, Start. @@ -87,11 +83,6 @@ void supervision_set_input(uint8 data); * \param func Default: RGB888 -> RGB555 (RGBA5551), R - least significant. */ void supervision_set_map_func(SV_MapRGBFunc func); -/*! - * Add ghosting (blur). It reduces flickering. - * \param frameCount in range [0, SV_GHOSTING_MAX]. 0 - disable. - */ -void supervision_set_ghosting(int frameCount); uint32 supervision_save_state_buf_size(void); BOOL supervision_save_state_buf(uint8 *data, uint32 size); diff --git a/src/potator/watara.c b/src/potator/watara.c index 0d5025b..83e32a6 100644 --- a/src/potator/watara.c +++ b/src/potator/watara.c @@ -76,84 +76,97 @@ BOOL supervision_load(const uint8 *rom, uint32 romSize) return TRUE; } -void __time_critical_func(supervision_exec_ex)(uint8 *backbuffer, int16 backbufferWidth, BOOL skipFrame) -{ - uint32 i, scanline; - uint8 innerx, size; - int previous_color, current_color; +static uint8_t rich_screen[200*240] = { 0 }; // current extended value + +static inline uint8_t __time_critical_func(convert_to_rich_format)(uint8_t v) { + return ((v & 1) ? 0b1111 : 0) | (((v >> 1) & 1) ? 0b11110000: 0); +} +void __time_critical_func(supervision_exec_ex)(uint8 *backbuffer, uint32 backbufferWidth, BOOL skipFrame, uint8_t ghosting) +{ // Number of iterations = 256 * 256 / m6502_registers.IPeriod - for (i = 0; i < 256; i++) { + for (uint32 i = 0; i < 256; ++i) { Run6502(&m6502_registers); timer_exec(m6502_registers.IPeriod); } - if (!skipFrame) { - scanline = regs[XPOS] / 4 + regs[YPOS] * 0x30; - innerx = regs[XPOS] & 3; - size = regs[XSIZE]; // regs[XSIZE] <= SV_W + uint32 scanline = regs[XPOS] / 4 + regs[YPOS] * 0x30; + uint8 innerx = regs[XPOS] & 3; + uint8 size = regs[XSIZE]; // regs[XSIZE] <= SV_W if (size > SV_W) size = SV_W; // 192: Chimera, Matta Blatta, Tennis Pro '92 - for (i = 0; i < SV_H; i++) { - if (scanline >= 0x1fe0) + uint8_t ghost_speed = ghosting < 7 ? (7 - ghosting) : 1; + ghosting = (0xFF >> (ghosting + 1)); // mask to extend values + uint8_t* p_out = backbuffer; + uint8_t* p_rich = rich_screen; + for (uint32 i = 0; i < SV_H; ++i) { + if (scanline >= 0x1fe0) { scanline -= 0x1fe0; // SSSnake -// gpu_render_scanline(scanline, backbuffer, innerx, SV_W); - + } uint8 *vram_line = upperRam + scanline; uint8 x = 0; - - uint8 b = *vram_line++; - if (innerx) { b >>= innerx * 2; } - - if (!ghostCount) { #pragma GCC unroll 4 - while (x < size) { - backbuffer[x++] = (b & 3) << 4; - b >>= 2; - backbuffer[x++] = (b & 3) << 4; - b >>= 2; - backbuffer[x++] = (b & 3) << 4; - b >>= 2; - backbuffer[x++] = (b & 3) << 4; - - b = *vram_line++; + while (x < size) { + uint8_t new_v = convert_to_rich_format(b); b >>= 2; + uint8_t pre_v = p_rich[x]; + uint8_t v; + if (new_v > pre_v) { + v = (pre_v << ghost_speed) | ghosting; + if (v > new_v) v = new_v; + } else { + v = pre_v >> ghost_speed; + if (v < new_v) v = new_v; } - } else { -#pragma GCC unroll 4 - while (x < size) { - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - backbuffer[x++] = current_color < previous_color ? previous_color : current_color; - b >>= 2; - - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - backbuffer[x++] = current_color < previous_color ? previous_color : current_color; - b >>= 2; - - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - backbuffer[x++] = current_color < previous_color ? previous_color : current_color; - b >>= 2; - - previous_color = backbuffer[x] - 4; // prev. state in 8 bit format (reduced to 1/gh) - current_color = (b & 3) << 4; // new state in 8 bit format - backbuffer[x++] = current_color < previous_color ? previous_color : current_color; - - b = *vram_line++; + p_rich[x] = v; + // back to output style format -> 0bxy0000 + p_out[x++] = (((v >> 4) ? 0b10 : 0) | ((v & 0b1111) ? 0b01 : 0)) << 4; + + new_v = convert_to_rich_format(b); b >>= 2; + pre_v = p_rich[x]; + if (new_v > pre_v) { + v = (pre_v << ghost_speed) | ghosting; + if (v > new_v) v = new_v; + } else { + v = pre_v >> ghost_speed; + if (v < new_v) v = new_v; + } + p_rich[x] = v; + p_out[x++] = (((v >> 4) ? 0b10 : 0) | ((v & 0b1111) ? 0b01 : 0)) << 4; + + new_v = convert_to_rich_format(b); b >>= 2; + pre_v = p_rich[x]; + if (new_v > pre_v) { + v = (pre_v << ghost_speed) | ghosting; + if (v > new_v) v = new_v; + } else { + v = pre_v >> ghost_speed; + if (v < new_v) v = new_v; } + p_rich[x] = v; + p_out[x++] = (((v >> 4) ? 0b10 : 0) | ((v & 0b1111) ? 0b01 : 0)) << 4; + + new_v = convert_to_rich_format(b); b = *vram_line++; + pre_v = p_rich[x]; + if (new_v > pre_v) { + v = (pre_v << ghost_speed) | ghosting; + if (v > new_v) v = new_v; + } else { + v = pre_v >> ghost_speed; + if (v < new_v) v = new_v; + } + p_rich[x] = v; + p_out[x++] = (((v >> 4) ? 0b10 : 0) | ((v & 0b1111) ? 0b01 : 0)) << 4; } - - backbuffer += backbufferWidth; + p_rich += backbufferWidth; + p_out += backbufferWidth; scanline += 0x30; } } - if (Rd6502(0x2026) & 0x01) Int6502(&m6502_registers, INT_NMI); @@ -165,11 +178,6 @@ void supervision_set_map_func(SV_MapRGBFunc func) gpu_set_map_func(func); } -void supervision_set_ghosting(int frameCount) -{ - gpu_set_ghosting(frameCount); -} - void supervision_set_input(uint8 data) { controls_state_write(data);