From: K.Ohta Date: Sat, 15 Jul 2023 10:50:05 +0000 (+0900) Subject: [VM][FMTOWNS][CRTC] More accuracy frame transfer.Fix text issues of A4(Ayayo 4). X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=0eda4f21dd0155e312046bfb1b9260621e4a99fb;p=csp-qt%2Fcommon_source_project-fm7.git [VM][FMTOWNS][CRTC] More accuracy frame transfer.Fix text issues of A4(Ayayo 4). - Fix around address offset by layer. - For layer 0, address offset is decided by FMR's address offset register. - For layer 1, address offset is decided by SPRITE. - These effect to ALL display MODE. - This is referred by Tsugaru, commit 1a442831.Thanks to YAMAKAWA-SAN. - Render before frame until the end of this frame. --- diff --git a/source/src/vm/fmtowns/crtc.cpp b/source/src/vm/fmtowns/crtc.cpp index d4b23e9cb..a83029e22 100644 --- a/source/src/vm/fmtowns/crtc.cpp +++ b/source/src/vm/fmtowns/crtc.cpp @@ -96,6 +96,7 @@ void TOWNS_CRTC::reset() line_count[0] = line_count[1] = 0; vert_line_count = -1; display_linebuf = 0; + render_linebuf = 0; r50_planemask = 0x0f; r50_pagesel = 0; @@ -853,7 +854,7 @@ bool TOWNS_CRTC::render_32768(scrntype_t* dst, scrntype_t *mask, int y, int laye { __UNLIKELY_IF(dst == nullptr) return false; - int trans = (display_linebuf == 0) ? display_linebuf_mask : ((display_linebuf - 1) & display_linebuf_mask); + int trans = display_linebuf & display_linebuf_mask; // int trans = display_linebuf & 3; int magx = linebuffers[trans][y].mag[layer]; int pwidth = linebuffers[trans][y].pixels[layer]; @@ -1128,7 +1129,7 @@ bool TOWNS_CRTC::render_256(scrntype_t* dst, int y) { // 256 colors __UNLIKELY_IF(dst == nullptr) return false; - int trans = (display_linebuf == 0) ? display_linebuf_mask : ((display_linebuf - 1) & display_linebuf_mask); + int trans = display_linebuf & display_linebuf_mask; // int trans = display_linebuf & 3; int magx = linebuffers[trans][y].mag[0]; int pwidth = linebuffers[trans][y].pixels[0]; @@ -1277,7 +1278,7 @@ bool TOWNS_CRTC::render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, i { __UNLIKELY_IF(dst == nullptr) return false; - int trans = (display_linebuf == 0) ? display_linebuf_mask : ((display_linebuf - 1) & display_linebuf_mask); + int trans = display_linebuf & display_linebuf_mask; // int trans = display_linebuf & 3; int magx = linebuffers[trans][y].mag[layer]; int pwidth = linebuffers[trans][y].pixels[layer]; @@ -1597,7 +1598,7 @@ void TOWNS_CRTC::mix_screen(int y, int width, bool do_mix0, bool do_mix1) __UNLIKELY_IF(width > TOWNS_CRTC_MAX_PIXELS) width = TOWNS_CRTC_MAX_PIXELS; __UNLIKELY_IF(width <= 0) return; - int trans = (display_linebuf == 0) ? display_linebuf_mask : ((display_linebuf - 1) & display_linebuf_mask); + int trans = display_linebuf & display_linebuf_mask; int bitshift0 = linebuffers[trans][y].bitshift[0]; int bitshift1 = linebuffers[trans][y].bitshift[1]; @@ -1722,7 +1723,7 @@ __DECL_VECTORIZED_LOOP void TOWNS_CRTC::draw_screen() { - int trans = (display_linebuf == 0) ? display_linebuf_mask : ((display_linebuf - 1) & display_linebuf_mask); + int trans = display_linebuf & display_linebuf_mask; //int trans2 = ((display_linebuf - 2) & display_linebuf_mask); bool do_alpha = false; // ToDo: Hardware alpha rendaring. __UNLIKELY_IF(d_vram == nullptr) { @@ -1805,8 +1806,6 @@ void TOWNS_CRTC::draw_screen() // } mix_screen(y, width, do_mix0, do_mix1); } - - //display_linebuf = (display_linebuf + 1) & 3; return; } @@ -1941,7 +1940,7 @@ void TOWNS_CRTC::transfer_line(int line) prio = voutreg_prio; //int trans = (display_linebuf - 1) & 3; - int trans = display_linebuf & display_linebuf_mask; + int trans = render_linebuf & display_linebuf_mask; __UNLIKELY_IF(linebuffers[trans] == nullptr) return; __DECL_VECTORIZED_LOOP @@ -2100,18 +2099,20 @@ __DECL_VECTORIZED_LOOP offset = (offset + ((-bit_shift) >> ashift)) & (((ctrl & 0x10) == 0) ? 0x7ffff : 0x3ffff); offset = offset + (int)head_address[l]; offset <<= ashift; -// bit_shift = _x >> ashift; - if((trans & 1) != 0) offset = offset + (frame_offset_bak[l] <<= ashift); + if((trans & 1) != 0) offset = offset + (frame_offset_bak[l] << ashift); +// if((trans & 1) != 0) offset = offset + (frame_offset[l] << ashift); if(l == 1) { - offset = offset + (fo1_offset_value <<= ashift); - } - if(linebuffers[trans][line].mode[l] == DISPMODE_16) { + offset = offset + (fo1_offset_value << ashift); + } + //! Note: + //! - Below is from Tsugaru, commit 1a442831 . + //! - I wonder sprite offset effects every display mode at page1, + //! and FMR's address offset register effects every display mode at page0 + //! - -- 20230715 K.O + if(l == 0) { offset += ((page_16mode != 0) ? 0x20000 : 0); - } - if(l == 1) { - if((is_sprite) && (linebuffers[trans][line].mode[l] == DISPMODE_32768)) { - offset += sprite_offset; - } + } else { + offset += sprite_offset; } offset = offset & address_mask[l]; // OK? offset += address_add[l]; @@ -2170,7 +2171,8 @@ __DECL_VECTORIZED_LOOP zoom_count_vert[l] = zoom_factor_vert[l]; // ToDo: Interlace if(to_disp[l]) { - head_address[l] += line_offset_bak[l]; + //head_address[l] += line_offset_bak[l]; + head_address[l] += line_offset[l]; } } } @@ -2190,6 +2192,7 @@ void TOWNS_CRTC::update_timing(int new_clocks, double new_frames_per_sec, int ne void TOWNS_CRTC::event_pre_frame() { + display_linebuf = render_linebuf & display_linebuf_mask; // Incremant per vstart interlace_field = !interlace_field; for(int i = 0; i < 2; i++) { crtout_top[i] = crtout[i]; @@ -2249,22 +2252,22 @@ void TOWNS_CRTC::event_pre_frame() void TOWNS_CRTC::event_frame() { - display_linebuf = (display_linebuf + 1) & display_linebuf_mask; // Incremant per vstart - hst[display_linebuf] = hst_tmp; - vst[display_linebuf] = vst_tmp; + render_linebuf = (render_linebuf + 1) & display_linebuf_mask; // Incremant per vstart + hst[render_linebuf] = hst_tmp; + vst[render_linebuf] = vst_tmp; lines_per_frame = max_lines; line_count[0] = line_count[1] = 0; vert_line_count = -1; hsync = false; - //! @note at event_pre_frame() at SPRITE, clear VRAM if enabled. + //! @note Every event_pre_frame() at SPRITE, clear VRAM if enabled. is_sprite = (d_sprite->read_signal(SIG_TOWNS_SPRITE_ENABLED) != 0) ? true : false; - if(is_sprite) { - sprite_offset = (d_sprite->read_signal(SIG_TOWNS_SPRITE_DISP_PAGE1) != 0) ? 0x20000 : 0x00000; - } else { - sprite_offset = 0x00000; - } + //! Note: + //! - Below is from Tsugaru, commit 1a442831 . + //! - I wonder sprite offset effects every display mode at page1. + //! - -- 20230715 K.O + sprite_offset = (d_sprite->read_signal(SIG_TOWNS_SPRITE_DISP_PAGE1) != 0) ? 0x20000 : 0x00000; // ToDo: EET //register_event(this, EVENT_CRTC_VSTART, frame_us, false, &event_id_frame); // EVENT_VSTART MOVED TO event_frame(). cancel_event_by_id(event_id_vst1); @@ -2666,6 +2669,7 @@ bool TOWNS_CRTC::process_state(FILEIO* state_fio, bool loading) hst[i] = hst_tmp; } display_linebuf = 0; + render_linebuf = 0; req_recalc = false; force_recalc_crtc_param(); } diff --git a/source/src/vm/fmtowns/crtc.h b/source/src/vm/fmtowns/crtc.h index 6341a2d14..30ace85ce 100644 --- a/source/src/vm/fmtowns/crtc.h +++ b/source/src/vm/fmtowns/crtc.h @@ -11,8 +11,8 @@ #ifndef _TOWNS_CRTC_H_ #define _TOWNS_CRTC_H_ +#include #include "device.h" - #include "towns_common.h" /* * I/O Address : @@ -28,7 +28,7 @@ * #28 has bit 15,14 and 7 to 0. * #29 has 4bit. * #31 has bit15 and bit 8 to 0. - * + * * #00 / bit 7 - 1 : HSW1 (Bit 10 to 8 and 0 must be '0') * #01 / bit 7 - 1 : HSW2 (Bit 10 to 8 and 0 must be '0') * #02 / ?? @@ -46,13 +46,13 @@ * #14 / bit10 - 0 : VDE0 (Layer 0) * #15 / bit10 - 0 : VDS1 (Layer 1) * #16 / bit10 - 0 : VDE1 (Layer 1) - * #17 / bit15 - 0 : FA0 (Layer 0) - * #18 / bit10 - 0 : HAJ0 (Layer 0) - * #19 / bit15 - 0 : FO0 (Layer 0) - * #20 / bit15 - 0 : LO0 (Layer 0) - * #21 / bit15 - 0 : FA1 (Layer 1) - * #22 / bit10 - 0 : HAJ1 (Layer 1) - * #23 / bit15 - 0 : FO1 (Layer 1) + * #17 / bit15 - 0 : FA0 (Layer 0) + * #18 / bit10 - 0 : HAJ0 (Layer 0) + * #19 / bit15 - 0 : FO0 (Layer 0) + * #20 / bit15 - 0 : LO0 (Layer 0) + * #21 / bit15 - 0 : FA1 (Layer 1) + * #22 / bit10 - 0 : HAJ1 (Layer 1) + * #23 / bit15 - 0 : FO1 (Layer 1) * #24 / bit15 - 0 : LO1 (Layer 1) * #25 / bit10 - 0 : EHAJ (External horizonal sync adjusting) * #26 / bit10 - 0 : EVAJ (External horizonal sync adjusting) @@ -64,7 +64,7 @@ * bit1-0 : CL0 * #29 / bit3-2 : SCSEL (Clock divide = 2 * (SCSEL + 1)). * bit1-0 : CLKSEL (00 = 28.6363MHz / 01 = 24.5454MHz / 10 = 25.175MHz / 11 = 21.0525MHz) - * #30 / Status register (RO): + * #30 / Status register (RO): * bit15 : DSPTV1 / bit14 : DSPTV0 (VDISP = '1') * bit13 : DSPTH1 / bit12 : DSPTH0 (HDISP = '1') * bit11 : FIELD (Field number) @@ -116,7 +116,7 @@ namespace FMTOWNS { TOWNS_CRTC_REG_VST1, TOWNS_CRTC_REG_VST2, TOWNS_CRTC_REG_EET, - + TOWNS_CRTC_REG_VST, // 8 TOWNS_CRTC_REG_HDS0, TOWNS_CRTC_REG_HDE0, @@ -125,7 +125,7 @@ namespace FMTOWNS { TOWNS_CRTC_REG_VDS0, TOWNS_CRTC_REG_VDE0, TOWNS_CRTC_REG_VDS1, - + TOWNS_CRTC_REG_VDE1, TOWNS_CRTC_REG_FA0, TOWNS_CRTC_REG_HAJ0, @@ -134,7 +134,7 @@ namespace FMTOWNS { TOWNS_CRTC_REG_FA1, TOWNS_CRTC_REG_HAJ1, TOWNS_CRTC_REG_FO1, - + TOWNS_CRTC_REG_LO1, TOWNS_CRTC_REG_EHAJ, TOWNS_CRTC_REG_EVAJ, @@ -166,7 +166,7 @@ typedef struct { #pragma pack(push, 1) uint8_t r50_planemask; // MMIO 000CF882h : BIT 5(C0) and BIT2 to 0 uint8_t crtout[2]; - uint8_t r50_pad; + uint8_t r50_pad; #pragma pack(pop) int32_t bitshift[2]; uint32_t pad; @@ -185,7 +185,7 @@ protected: TOWNS_VRAM* d_vram; TOWNS_SPRITE* d_sprite; FONT_ROMS* d_font; - + uint16_t machine_id; uint8_t cpu_id; bool is_compatible; @@ -198,14 +198,14 @@ protected: bool address_changed[2]; bool mode_changed[2]; uint32_t fo1_offset_value; - + uint8_t display_mode[2]; bool line_changed[2][TOWNS_CRTC_MAX_LINES]; bool display_enabled; - + double crtc_clock; // int cpu_clocks; - + // They are not saved.Must be calculate when loading. double horiz_us; // (HST + 1) * clock double horiz_width_posi_us, horiz_width_nega_us; // HSW1, HSW2 @@ -217,12 +217,12 @@ protected: double vst2_us; int hst[4], vst[4]; int vst_tmp, hst_tmp; - + double vert_start_us[2]; double vert_end_us[2]; double horiz_start_us[2]; double horiz_end_us[2]; - + bool req_recalc; // End @@ -233,10 +233,10 @@ protected: uint32_t hend_words[2]; // HEND ((HDE[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0. uint32_t frame_offset[2]; // FOx. uint32_t line_offset[2]; // LOx. - + uint32_t frame_offset_bak[2]; // FOx(Backup). uint32_t line_offset_bak[2]; // LOx(Backup). - + uint32_t head_address[2]; int horiz_offset_tmp[2]; int vert_offset_tmp[2]; @@ -245,7 +245,7 @@ protected: bool is_sprite; uint32_t sprite_offset; - + uint8_t zoom_factor_vert[2]; // Related display resolutions of two layers and zoom factors. uint8_t zoom_factor_horiz[2]; // Related display resolutions of two layers and zoom factors. uint8_t zoom_count_vert[2]; @@ -253,24 +253,24 @@ protected: uint8_t scsel; uint8_t clksel; - + int pixels_per_line; int lines_per_frame; int max_lines; - + int vert_line_count; // Not separate per layer.Total count. // Note: To display to real screen, use blending of OpenGL/DirectX // from below framebuffers per layer if you can. // And, recommand to use (hardware) shader to rendering (= not to use framebuffer of below) if enabled. // Not recommanded to use draw_screen() type rendering. // Rendering precesses may be heavily to use only CPU (I think). 20170107 K.Ohta. - + // Not Saved?. // End. bool vsync, hsync, hdisp[2], frame_in[2]; bool interlace_field; - - + + // Around Analog palette. uint8_t apalette_code; // I/O FD90H (RW). 16 or 256 colors. uint8_t apalette_b; // I/O FD92H (RW). @@ -282,18 +282,18 @@ protected: scrntype_t apalette_256_pixel[256]; // Not saved. Must be calculated. uint8_t tvram_snapshot[0x4000]; - + // FM-R50 emulation uint8_t r50_planemask; // MMIO 000CF882h : BIT 5(C0) and BIT2 to 0 uint8_t r50_pagesel; // MMIO 000CF882h : BIT 4 uint8_t dpalette_regs[8]; // I/O FD98H - FD9FH bool dpalette_changed; - + // Video output controller (I/O 0448H, 044AH) // Register 00 : Display mode. // Register 11: Priority mode. bool video_brightness; // false = high. - + // Others. // VRAM CONTROL REGISTER. uint8_t voutreg_num; // I/O 0448h @@ -305,8 +305,8 @@ protected: uint8_t crtout_reg; // End. - - // + + // // Event IDs. Saved. int event_id_hsync; int event_id_hsw; @@ -322,9 +322,10 @@ protected: int event_id_hds[2]; int event_id_hde[2]; - int display_linebuf; + std::atomic display_linebuf; + std::atomic render_linebuf; int display_linebuf_mask; - + __DECL_ALIGNED(32) linebuffer_t linebuffers[4][TOWNS_CRTC_MAX_LINES]; // Render buffer @@ -339,17 +340,17 @@ protected: void restart_display(); void stop_display(); void notify_mode_changed(int layer, uint8_t mode); - + void cancel_event_by_id(int& event_num); - + void set_crtc_clock(uint16_t val); uint16_t read_reg30(); uint32_t __FASTCALL get_font_address(uint32_t c, uint8_t &attr); - + virtual void __FASTCALL calc_apalette16(int layer, int index); virtual void __FASTCALL calc_apalette256(int index); virtual void __FASTCALL calc_apalette(int index); - + virtual void __FASTCALL set_apalette_r(uint8_t val); virtual void __FASTCALL set_apalette_g(uint8_t val); virtual void __FASTCALL set_apalette_b(uint8_t val); @@ -357,7 +358,7 @@ protected: virtual uint8_t __FASTCALL get_apalette_b(); virtual uint8_t __FASTCALL get_apalette_r(); virtual uint8_t __FASTCALL get_apalette_g(); - + bool __FASTCALL render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, int y, int layer, bool do_alpha); bool __FASTCALL render_256(scrntype_t* dst, int y); bool __FASTCALL render_32768(scrntype_t* dst, scrntype_t *mask, int y, int layer, bool do_alpha); @@ -387,7 +388,7 @@ public: void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame); void event_pre_frame(); void event_frame(); - + void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask); uint32_t __FASTCALL read_signal(int ch); void __FASTCALL write_io8(uint32_t addr, uint32_t data); @@ -395,7 +396,7 @@ public: void __FASTCALL write_io16(uint32_t addr, uint32_t data); uint32_t __FASTCALL read_io16(uint32_t addr); - + void __FASTCALL event_callback(int event_id, int err); bool process_state(FILEIO* state_fio, bool loading); @@ -418,7 +419,7 @@ public: __UNLIKELY_IF(line >= TOWNS_CRTC_MAX_LINES) return NULL; return &(linebuffers[page][line]); } - + void set_context_sprite(DEVICE* dev) { d_sprite = (TOWNS_SPRITE*)dev; @@ -439,7 +440,7 @@ public: { cpu_id = val & 0x07; } - + void set_context_vsync(DEVICE* device, int id, uint32_t mask) { register_output_signal(&outputs_int_vsync, device, id, mask); @@ -453,4 +454,3 @@ public: } #endif -