From 492790cb81a4928915d45310a8f498b968058783 Mon Sep 17 00:00:00 2001 From: Randy Rossi Date: Thu, 13 Feb 2020 21:22:01 -0500 Subject: [PATCH] Add raster_skip option to cmdline.txt --- README.md | 15 +++++++++++++++ emulatorcore.h | 4 +++- plus4emulatorcore.cpp | 5 +++-- plus4emulatorcore.h | 3 ++- third_party/common/circle.h | 2 +- third_party/common/menu_switch.c | 15 ++++++++++++++- third_party/plus4emu/main.c | 10 ++++++++-- third_party/vice-3.3/src/arch/raspi/vice_api.c | 9 ++++++--- third_party/vice-3.3/src/arch/raspi/videoarch.c | 16 +++++++++++++++- third_party/vice-3.3/src/arch/raspi/videoarch.h | 1 + viceapp.cpp | 2 +- viceemulatorcore.cpp | 5 +++-- viceemulatorcore.h | 3 ++- viceoptions.cpp | 13 +++++++++++-- viceoptions.h | 4 +++- 15 files changed, 88 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 59b31894..b33d0364 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,21 @@ NOTE: This mode has a 15khz horizontal refresh rate which many monitors don't su Many thanks goes out to Alessio Scanderebech and Andrea Mazzoleni for their assistance with getting this working. +# VGA Display without 15khz hsync support + +If you have a VGA monitor that doesn't support 15khz hsync, you can try using a 1920x1080 resolution and add raster_skip=true to the machine config. The 'raster_skip' option doubles the vertical height of the frame buffer and draws the emulated display into every other line. When this is integer scaled up to 1080, you can achieve more or less the same effect you would get with a monitor that could do 15khz. That is, there will be gaps between each 'scanline' as though there were only ~270 lines. This looks pretty decent on a Trinitron tube because there are no horizontal gaps in the phosphor bars and the 2 real scanlines that resulted from doubling the one line from the frame buffer looks like one solid scanline (...at least that's what I think is happening) + + [C64/PAL/DPI/VGA666:1920x1080@50hz] + enable_dpi=true + machine_timing=pal-custom + cycles_per_second=985257 + enable_dpi_lcd=1 + display_default_lcd=1 + dpi_group=1 + dpi_mode=31 + raster_skip=true + scaling_params=1920,540,1920,1080 + # Video Scaling Algorithm The emulated resolutions are small and must be scaled up to the video mode's resolution. You can tell the Pi to change the way it scales the video using the 'scaling_kernel' option in config.txt: diff --git a/emulatorcore.h b/emulatorcore.h index c4384f8a..12c72e1d 100644 --- a/emulatorcore.h +++ b/emulatorcore.h @@ -16,12 +16,14 @@ #ifndef emualtorcore_h #define emulatorcore_h +#include "viceoptions.h" + class EmulatorCore { public: EmulatorCore(void) = default; ~EmulatorCore(void) = default; - virtual bool Init() = 0; + virtual bool Init(ViceOptions *options) = 0; virtual void LaunchEmulator(char *timing_option) = 0; }; diff --git a/plus4emulatorcore.cpp b/plus4emulatorcore.cpp index 0bc6228d..c0dbf1f7 100644 --- a/plus4emulatorcore.cpp +++ b/plus4emulatorcore.cpp @@ -51,7 +51,7 @@ void Plus4EmulatorCore::RunMainPlus4(bool wait) { printf("Starting emulator main loop\n"); int argc = 0; char *argv[] = {}; - emu_machine_init(); + emu_machine_init(m_options->GetRasterSkip()); main_program(argc, argv); emu_exit(); } @@ -89,7 +89,8 @@ void Plus4EmulatorCore::Run(unsigned nCore) { #endif } -bool Plus4EmulatorCore::Init(void) { +bool Plus4EmulatorCore::Init(ViceOptions* options) { + m_options = options; return Initialize(); } diff --git a/plus4emulatorcore.h b/plus4emulatorcore.h index d248019e..2b59747e 100644 --- a/plus4emulatorcore.h +++ b/plus4emulatorcore.h @@ -45,7 +45,7 @@ class Plus4EmulatorCore bool Initialize() { return true; } #endif - bool Init(void) override; + bool Init(ViceOptions* options) override; void LaunchEmulator(char *timing_option) override; private: @@ -53,6 +53,7 @@ class Plus4EmulatorCore int cyclesPerSecond_; char timing_option_[8]; CSpinLock m_Lock; + ViceOptions *m_options; void RunMainPlus4(bool wait); void ComputeResidFilter(int model); diff --git a/third_party/common/circle.h b/third_party/common/circle.h index 100e77a9..d4f4d4cd 100644 --- a/third_party/common/circle.h +++ b/third_party/common/circle.h @@ -248,7 +248,7 @@ extern void circle_set_interpolation(int enable); // Init some common layer stuff about the machine being emulated. // Must be called before launching emulator's main_program func. -extern void emu_machine_init(void); +extern void emu_machine_init(int raster_skip_enabled); // Compares the previous button state for 'button_num' with // the current state and will return a press or release event diff --git a/third_party/common/menu_switch.c b/third_party/common/menu_switch.c index 63e22755..06b05bc0 100644 --- a/third_party/common/menu_switch.c +++ b/third_party/common/menu_switch.c @@ -58,6 +58,7 @@ struct s_cfg_flags { int have_enable_dpi; int have_scaling_params; int have_scaling_params2; + int have_raster_skip; // Have flags for config.txt int have_kernel; @@ -278,7 +279,8 @@ void free_machines(struct machine_entry* head) { } } -static struct machine_option* find_option(char *key, struct machine_option *head) { +static struct machine_option* find_option(const char *key, + struct machine_option *head) { struct machine_option* opt = head; while (opt) { if(strcmp(opt->key, key) == 0) { @@ -441,6 +443,7 @@ static int apply_override_m(char *line, struct machine_entry *head, if (strcmp(key,"enable_dpi") == 0) { cfg_flags->have_enable_dpi = 1; } if (strcmp(key,"scaling_params") == 0) { cfg_flags->have_scaling_params = 1; } if (strcmp(key,"scaling_params2") == 0) { cfg_flags->have_scaling_params2 = 1; } + if (strcmp(key,"raster_skip") == 0) { cfg_flags->have_raster_skip = 1; } struct machine_option* found = find_option(key, head->options); if (found) { @@ -458,6 +461,7 @@ static int apply_override_m(char *line, struct machine_entry *head, strcmp(key,"audio_out")!=0 && strcmp(key,"disk_partition")!=0 && strcmp(key,"enable_dpi")!=0 && + strcmp(key,"raster_skip")!=0 && strcmp(key,"scaling_params")!=0 && strcmp(key,"scaling_params2")!=0) { if (need_space) { strcat(replacement," "); } @@ -552,6 +556,15 @@ static int apply_override_m(char *line, struct machine_entry *head, need_space=1; } } + if (!cfg_flags->have_raster_skip) { + struct machine_option* found = find_option("raster_skip", head->options); + if (found) { + if (need_space) { strcat(replacement," "); } + snprintf(new_option, OPTION_SCRATCH_LEN, "%s=%s", found->key, found->value); + strcat(replacement, new_option); + need_space=1; + } + } strcat(replacement, "\n"); strcpy(line, replacement); diff --git a/third_party/plus4emu/main.c b/third_party/plus4emu/main.c index d72fafb7..b4044d71 100644 --- a/third_party/plus4emu/main.c +++ b/third_party/plus4emu/main.c @@ -76,7 +76,7 @@ int color_brightness = 1000; int color_contrast = 666; int color_gamma = 800; int color_tint = 1000; -int raster_skip = 1; // Never going to change. +int raster_skip = 1; static struct menu_item *sid_model_item; static struct menu_item *sid_write_access_item; @@ -784,8 +784,14 @@ int main_program(int argc, char **argv) // Begin emu_api impl. -void emu_machine_init() { +void emu_machine_init(int raster_skip_enabled) { emux_machine_class = BMC64_MACHINE_CLASS_PLUS4EMU; + + raster_skip = raster_skip_enabled ? 2 : 1; + + // For plus4emu, raster_skip can't be turned off + // at runtime. There's no line dupe like in our + // VICE mod. } void emux_trap_main_loop_ui(void) { diff --git a/third_party/vice-3.3/src/arch/raspi/vice_api.c b/third_party/vice-3.3/src/arch/raspi/vice_api.c index 27291741..33a1b319 100644 --- a/third_party/vice-3.3/src/arch/raspi/vice_api.c +++ b/third_party/vice-3.3/src/arch/raspi/vice_api.c @@ -132,7 +132,7 @@ static void check_sid_options() { } } -void emu_machine_init(void) { +void emu_machine_init(int raster_skip_enabled) { switch (machine_class) { case VICE_MACHINE_C64: emux_machine_class = BMC64_MACHINE_CLASS_C64; @@ -160,9 +160,12 @@ void emu_machine_init(void) { // frame buffer so we can do our 'cheap' scanlines effect. canvas_state[VIC_INDEX].raster_skip = 2; } else { - canvas_state[VIC_INDEX].raster_skip = 1; - canvas_state[VDC_INDEX].raster_skip = 1; + canvas_state[VIC_INDEX].raster_skip = raster_skip_enabled ? 2 : 1; + canvas_state[VDC_INDEX].raster_skip = raster_skip_enabled ? 2 : 1; } + + // If raster skip enabled via kernel params, enable lines. + set_raster_lines(raster_skip_enabled); } static int vice_keymap_index_to_bmc(int value) { diff --git a/third_party/vice-3.3/src/arch/raspi/videoarch.c b/third_party/vice-3.3/src/arch/raspi/videoarch.c index d907c226..cceaa3fa 100644 --- a/third_party/vice-3.3/src/arch/raspi/videoarch.c +++ b/third_party/vice-3.3/src/arch/raspi/videoarch.c @@ -83,11 +83,15 @@ const unsigned long video_tick_inc = 10000; unsigned long video_freq; unsigned long video_frame_count; -int raspi_warp = 0; +int raspi_warp; static int raspi_boot_warp = 1; static int vdc_map[] = {0, 12, 6, 14, 5, 13, 11, 3, 2, 10, 8, 4, 9, 7, 15, 1}; +// Should be set only when raster_skip=true is present +// in the kernel args. +int raster_lines; + #define COLOR16(r,g,b) (((r)>>3)<<11 | ((g)>>2)<<5 | (b)>>3) int is_vic(struct video_canvas_s *canvas) { @@ -179,6 +183,9 @@ static void check_dimensions(struct video_canvas_s* canvas, canvas_state[canvas_index].max_padding_w = max_padding_w; canvas_state[canvas_index].max_padding_h = max_padding_h; + + // If config says raster lines, do it here. + canvas->raster_lines |= raster_lines; } // Draw buffer bridge functions back to kernel @@ -496,3 +503,10 @@ palette_t *raspi_video_load_palette(int num_entries, char *name) { } return palette; } + +void set_raster_lines(int v) { + vic_canvas->raster_lines = v; + if (vdc_canvas) { + vdc_canvas->raster_lines = v; + } +} diff --git a/third_party/vice-3.3/src/arch/raspi/videoarch.h b/third_party/vice-3.3/src/arch/raspi/videoarch.h index 63e03c84..7fc77004 100644 --- a/third_party/vice-3.3/src/arch/raspi/videoarch.h +++ b/third_party/vice-3.3/src/arch/raspi/videoarch.h @@ -100,4 +100,5 @@ void main_exit(void); // holding the lock. void key_interrupt_locked(long key, int pressed); +void set_raster_lines(int v); #endif diff --git a/viceapp.cpp b/viceapp.cpp index 92be675f..0285e829 100644 --- a/viceapp.cpp +++ b/viceapp.cpp @@ -190,7 +190,7 @@ bool ViceScreenApp::Initialize(void) { } } - if (!mEmulatorCore->Init()) { + if (!mEmulatorCore->Init(&mViceOptions)) { return false; } diff --git a/viceemulatorcore.cpp b/viceemulatorcore.cpp index d24f7e97..1c11578d 100644 --- a/viceemulatorcore.cpp +++ b/viceemulatorcore.cpp @@ -140,7 +140,7 @@ void ViceEmulatorCore::RunMainVice(bool wait) { #else #error "RASPI_[model] NOT DEFINED" #endif - emu_machine_init(); + emu_machine_init(m_options->GetRasterSkip()); main_program(argc, argv); emu_exit(); } @@ -213,7 +213,8 @@ void ViceEmulatorCore::Run(unsigned nCore) { #endif } -bool ViceEmulatorCore::Init(void) { +bool ViceEmulatorCore::Init(ViceOptions* options) { + m_options = options; return Initialize(); } diff --git a/viceemulatorcore.h b/viceemulatorcore.h index c7f108fa..d31e1a9d 100644 --- a/viceemulatorcore.h +++ b/viceemulatorcore.h @@ -45,7 +45,7 @@ class ViceEmulatorCore bool Initialize() { return true; } #endif - bool Init(void) override; + bool Init(ViceOptions* options) override; void LaunchEmulator(char *timing_option) override; private: @@ -54,6 +54,7 @@ class ViceEmulatorCore int passBandFreq_; char timing_option_[8]; CSpinLock m_Lock; + ViceOptions *m_options; void RunMainVice(bool wait); void ComputeResidFilter(int model); diff --git a/viceoptions.cpp b/viceoptions.cpp index 5a357259..677e052d 100644 --- a/viceoptions.cpp +++ b/viceoptions.cpp @@ -37,7 +37,8 @@ ViceOptions::ViceOptions(void) m_bGPIOOutputsEnabled(false), m_nCyclesPerSecond(0), m_audioOut(VCHIQSoundDestinationAuto), m_bDPIEnabled(false), m_scaling_param_fbw{0,0}, m_scaling_param_fbh{0,0}, - m_scaling_param_sx{0,0}, m_scaling_param_sy{0,0} { + m_scaling_param_sx{0,0}, m_scaling_param_sy{0,0}, + m_raster_skip(false) { s_pThis = this; CBcmPropertyTags Tags; @@ -140,6 +141,12 @@ ViceOptions::ViceOptions(void) m_scaling_param_fbh[num] = atoi(fbh_s); m_scaling_param_sx[num] = atoi(sx_s); m_scaling_param_sy[num] = atoi(sy_s); + } else if (strcmp(pOption, "raster_skip") == 0) { + if (strcmp(pValue, "true") == 0 || strcmp(pValue, "1") == 0) { + m_raster_skip = true; + } else { + m_raster_skip = false; + } } } @@ -186,7 +193,7 @@ bool ViceOptions::DPIEnabled(void) const { return m_bDPIEnabled; } int ViceOptions::GetDiskPartition(void) const { return m_disk_partition; } -void ViceOptions::GetScalingParams(int display, int *fbw, int *fbh, int *sx, int *sy) { +void ViceOptions::GetScalingParams(int display, int *fbw, int *fbh, int *sx, int *sy) const { if (display >=0 && display < 2) { *fbw = m_scaling_param_fbw[display]; *fbh = m_scaling_param_fbh[display]; @@ -195,6 +202,8 @@ void ViceOptions::GetScalingParams(int display, int *fbw, int *fbh, int *sx, int } } +bool ViceOptions::GetRasterSkip(void) const { return m_raster_skip; } + const char *ViceOptions::GetDiskVolume(void) const { return m_disk_volume; } unsigned long ViceOptions::GetCyclesPerSecond(void) const { diff --git a/viceoptions.h b/viceoptions.h index d0ed88e3..2227f888 100644 --- a/viceoptions.h +++ b/viceoptions.h @@ -36,7 +36,8 @@ class ViceOptions { unsigned long GetCyclesPerSecond(void) const; TVCHIQSoundDestination GetAudioOut(void) const; bool DPIEnabled(void) const; - void GetScalingParams(int display, int *fbw, int *fbh, int *sx, int *sy); + void GetScalingParams(int display, int *fbw, int *fbh, int *sx, int *sy) const; + bool GetRasterSkip(void) const; static ViceOptions *Get(void); @@ -67,6 +68,7 @@ class ViceOptions { int m_scaling_param_fbh[2]; int m_scaling_param_sx[2]; int m_scaling_param_sy[2]; + bool m_raster_skip; static ViceOptions *s_pThis; };