From: K.Ohta Date: Mon, 16 Jan 2017 07:41:54 +0000 (+0900) Subject: [VM][FMTOWNS] Add VRAM. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=344fd040a13761ad59586abbf542b2401fe62175;p=csp-qt%2Fcommon_source_project-fm7.git [VM][FMTOWNS] Add VRAM. --- diff --git a/source/src/vm/fmtowns/towns_crtc.cpp b/source/src/vm/fmtowns/towns_crtc.cpp index 114f37f52..a04f3f113 100644 --- a/source/src/vm/fmtowns/towns_crtc.cpp +++ b/source/src/vm/fmtowns/towns_crtc.cpp @@ -21,34 +21,16 @@ enum { EVENT_CRTC_HSW = 14, }; -#define CLEAR_COLOR RGBA_COLOR(0,0,0,0) - -#if defined(_RGB888) -#define _USE_ALPHA_CHANNEL -#endif void TOWNS_CRTC::initialize() { memset(regs, 0, sizeof(regs)); memset(regs_written, 0, sizeof(regs_written)); -#ifdef _USE_ALPHA_CHANNEL - for(int i = 0; i < 32768; i++) { - uint8_t g = (i / (32 * 32)) & 0x1f; - uint8_t r = (i / 32) & 0x1f; - uint8_t b = i & 0x1f; - table_32768c[i] = RGBA_COLOR(r << 3, g << 3, b << 3, 0xff); - } - for(int i = 32768; i < 65536; i++) { - table_32768c[i] = _CLEAR_COLOR; - } -#endif line_count[0] = line_count[1] = 0; for(int i = 0; i < TOWNS_CRTC_MAX_LINES; i++) { line_changed[0][i] = true; - line_rendered[0][i] = false; line_changed[1][i] = true; - line_rendered[1][i] = false; } event_id_hsync = -1; event_id_hsw = -1; @@ -200,74 +182,6 @@ uint32_t TOWNS_CRTC::read_io8(uint32_t addr) } } -// I/Os -// Palette. -void TOWNS_CRTC::calc_apalette16(int layer, int index) -{ - if(index < 0) return; - if(index > 15) return; - apalette_16_rgb[layer][index] = - ((uint16_t)(apalette_b & 0x0f)) | - ((uint16_t)(apalette_r & 0x0f) << 4) | - ((uint16_t)(apalette_g & 0x0f) << 8); - if(index == 0) { - apalette_16_pixel[layer][index] = _CLEAR_COLOR; // ?? - } else { - apalette_16_pixel[layer][index] = RGBA_COLOR((apalette_r & 0x0f) << 4, (apalette_g & 0x0f) << 4, (apalette_b & 0x0f) << 4, 0xff); - } -} - -void TOWNS_CRTC::calc_apalette256(int index) -{ - if(index < 0) return; - if(index > 255) return; - apalette_256_rgb[layer][index] = - ((uint32_t)apalette_b) | - ((uint32_t)apalette_r << 8) | - ((uint32_t)apalette_g << 16); - if(index == 0) { - apalette_256_pixel[index] = _CLEAR_COLOR; // ?? - } else { - apalette_256_pixel[index] = RGBA_COLOR(apalette_r, apalette_g, apalette_b, 0xff); - } -} - -void TOWNS_CRTC::set_apalette_r(int layer, uint8_t val) -{ - apalette_r = val; - if(apalette_code < 16) { - calc_apalette16(layer, (int)apalette_code); - } - // if layer == 0 ? - calc_apalette256((int)apalette_code % 256); -} - -void TOWNS_CRTC::set_apalette_g(int layer, uint8_t val) -{ - apalette_g = val; - if(apalette_code < 16) { - calc_apalette16(layer, (int)apalette_code); - } - // if layer == 0 ? - calc_apalette256((int)apalette_code % 256); -} - -void TOWNS_CRTC::set_apalette_b(int layer, uint8_t val) -{ - apalette_b = val; - if(apalette_code < 16) { - calc_apalette16(layer, (int)apalette_code); - } - // if layer == 0 ? - calc_apalette256((int)apalette_code % 256); -} - -void TOWNS_CRTC::set_apalette_num(int layer, uint8_t val) -{ - apalette_code = ((int)val) % 256; -} - - void TOWNS_CRTC::event_pre_frame() { @@ -457,181 +371,6 @@ void TOWNS_CRTC::set_vblank(bool val) } -// Renderers -void TOWNS_CRTC::render_line_16(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words) -{ - uint32_t wordptr = 0; - int nwords = (int)words / 8; - int ip; - uint32_t src; - uint32_t src1, src2; - uint8_t srcdat1[4], srcdat2[1]; - scrntype_t *pdst = framebuffer; - uint32_t *pp = (uint32_t *)vramptr; - - if(framebuffer == NULL) return; - if(vramptr == NULL) return; - for(ip = 0; ip < nwords; ip++) { - src = pp[ip]; - src1 = (src & 0xf0f0f0f0) >> 4; - src2 = src & 0x0f0f0f0f; - - srcdat1[0] = (uint8_t)(src1 >> 24); - srcdat1[1] = (uint8_t)(src1 >> 16); - srcdat1[2] = (uint8_t)(src1 >> 8); - srcdat1[3] = (uint8_t)(src1 >> 0); - - srcdat2[0] = (uint8_t)(src2 >> 24); - srcdat2[1] = (uint8_t)(src2 >> 16); - srcdat2[2] = (uint8_t)(src2 >> 8); - srcdat2[3] = (uint8_t)(src2 >> 0); - /* - srcdat[0] = (uint8_t)((src & 0xf0000000) >> 28); - srcdat[1] = (uint8_t)((src & 0x0f000000) >> 24); - srcdat[2] = (uint8_t)((src & 0x00f00000) >> 20); - srcdat[3] = (uint8_t)((src & 0x000f0000) >> 16); - srcdat[4] = (uint8_t)((src & 0x0000f000) >> 12); - srcdat[5] = (uint8_t)((src & 0x00000f00) >> 8); - srcdat[6] = (uint8_t)((src & 0x000000f0) >> 4); - srcdat[7] = (uint8_t)(src & 0x0f); - for(int i = 0; i < 8; i++) { - pdst[i] = apalette_16_pixel[layer][srcdat[i]]; - } - pdst += 8; - */ - for(int i = 0; i < 4; i++) { - pdst[0] = apalette_16_pixel[layer][srcdat1[i]]; - pdst[1] = apalette_16_pixel[layer][srcdat2[i]]; - pdst += 2; - } - } - int mod_words = words - (nwords * 8); - if(mod_words > 0) { - uint8_t *ppp = (uint8_t *)(&pp[ip]); - uint8_t hi, lo; - for(int i = 0; i < mod_words / 2; i++) { - uint8_t d = ppp[i]; - hi = (d & 0xf0) >> 4; - lo = d & 0x0f; - *pdst++ = apalette_16_pixel[layer][hi]; - *pdst++ = apalette_16_pixel[layer][lo]; - } - if((mod_words & 1) != 0) { - hi = (ppp[mod_words / 2] & 0xf0) >> 4; - *pdst++ = apalette_16_pixel[layer][hi]; - } - } -} - -void TOWNS_CRTC::render_line_256(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words) -{ - uint32_t wordptr = 0; - int nwords = (int)words / 4; - int ip; - uint32_t src; - uint8_t srcdat[4]; - scrntype_t *pdst = framebuffer; - uint32_t *pp = (uint32_t *)vramptr; - - if(framebuffer == NULL) return; - if(vramptr == NULL) return; - for(ip = 0; ip < nwords; ip++) { - src = pp[ip]; - srcdat[0] = (uint8_t)((src & 0xff000000) >> 24); - srcdat[1] = (uint8_t)((src & 0x00ff0000) >> 16); - srcdat[2] = (uint8_t)((src & 0x0000ff00) >> 8); - srcdat[3] = (uint8_t) (src & 0x000000ff); - for(int i = 0; i < 4; i++) { - pdst[i] = apalette_256_pixel[srcdat[i]]; - } - pdst += 4; - } - int mod_words = words - (nwords * 4); - if(mod_words > 0) { - uint8_t src8; - uint8_t *p8 = (uint8_t *)(&pp[ip]); - for(int i = 0; i < mod_words; i++) { - src8 = p8[i]; - pdst[i] = apalette_256_pixel[src8]; - } - } -} - -// To be used table?? -void TOWNS_CRTC::render_line_32768(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words) -{ - uint32_t wordptr = 0; - int nwords = (int)words / 8; - int ip; - uint16_t src16; - uint32_t srcdat[4]; - scrntype_t *pdst = framebuffer; - uint32_t *pp = (uint32_t *)vramptr; - uint16_t *cachep = (uint16_t *)srcdat; - int i = 0; - - if(framebuffer == NULL) return; - if(vramptr == NULL) return; - - for(ip = 0; ip < nwords; ip++) { - for(int i = 0; i < 4; i++) { - srcdat[i] = pp[i]; - } - pp = pp + 4; - scrntype_t dcache[8]; - for(int i = 0; i < 8; i++) { - dcache[i] = _CLEAR_COLOR; - } - for(int i = 0; i < 8; i++) { - uint16_t v = cachep[i]; -#ifdef _USE_ALPHA_CHANNEL -#ifdef __BIG_ENDIAN__ - pair_t n; - n.d = 0; - n.b.l = v & 0xff; - n.b.h = (v & 0xff00) >> 8; - dcache[i] = table_32768c[n.sw.l]; -#else - dcache[i] = table_32768c[v]; -#endif -#else - if((v & 0x8000) == 0) { - dcache[i] = RGBA_COLOR((v & 0x03e0) >> 2, (v & 0x7c00) >> 7, (v & 0x001f) << 3, 0xff); // RGB555 -> PIXEL - } -#endif - } - for(int i = 0; i < 8; i++) { - pdst[i] = dcache[i]; - } - pdst += 8; - } - int mod_words = words - nwords * 8; - if(mod_words > 0) { - uint16_t *vp = (uint16_t *)pp; - scrntype_t dc; - for(int i = 0; i < mod_words; i++) { - src16 = vp[i]; -#ifdef _USE_ALPHA_CHANNEL -#ifdef __BIG_ENDIAN__ - pair_t n; - n.d = 0; - n.b.l = src16 & 0xff; - n.b.h = (src16 & 0xff00) >> 8; - dc = table_32768c[n.sw.l]; -#else - dc = table_32768c[src16]; -#endif -#else - dc = _CLEAR_COLOR; - if((src16 & 0x8000) == 0) { - dc = RGBA_COLOR((src16 & 0x03e0) >> 2, (src16 & 0x7c00) >> 7, (src16 & 0x001f) << 3, 0xff); // RGB555 -> PIXEL - } -#endif - pdst[i] = dc; - } - } -} -#undef _CLEAR_COLOR #define STATE_VERSION 1 diff --git a/source/src/vm/fmtowns/towns_crtc.h b/source/src/vm/fmtowns/towns_crtc.h index 6129bfa3a..399ddeec5 100644 --- a/source/src/vm/fmtowns/towns_crtc.h +++ b/source/src/vm/fmtowns/towns_crtc.h @@ -136,7 +136,6 @@ private: // Not include around video input/dizitize features yet. bool line_changed[2][TOWNS_CRTC_MAX_LINES]; - bool line_rendered[2][TOWNS_CRTC_MAX_LINES]; double crtc_clock; // // They are not saved.Must be calculate when loading. @@ -168,19 +167,12 @@ private: // 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. - scrntype_t *framebuffer0[2]; // Frame Buffer Layer 0. Not saved. - scrntype_t *framebuffer1[2]; // Frame Buffer Layer 1. Not saved. - - int framebuffer_width[2]; - int framebuffer_height[2]; + // Not Saved?. + uint8_t layer_colors[2]; uint16_t *vram_ptr[2]; // Layer [01] address. uint32_t vram_size[2]; // Layer [01] size [bytes]. uint32_t vram_offset[2]; // Layer [01] address offset. - - scrntype_t table_32768c[65536]; - // Not Saved?. - uint8_t layer_colors[2]; uint32_t layer_virtual_width[2]; uint32_t layer_virtual_height[2]; @@ -202,8 +194,6 @@ private: // Video output registers. May be split to separate files? // FMR50 Compatible registers. They are mostly dummy. - // Digital paletts. I/O FD98H - FD9FH. - uint8_t r50_digital_palette[8]; // MMIO? 000C:FF80H uint8_t r50_mix_reg; @@ -218,51 +208,13 @@ private: // I/O FDA0H Not Dummy? //uint8_t r50_sub_statreg; - // Around Analog palette. - uint8_t apalette_code; // I/O FD90H (RW). 16 or 256 colors. - uint8_t apalette_b; // I/O FD92H (RW). - uint8_t apalette_r; // I/O FD94H (RW). - uint8_t apalette_g; // I/O FD96H (RW). - uint16_t apalette_16_rgb[2][16]; // R * 256 + G * 16 + B - scrntype_t apalette_16_pixel[2][16]; // Not saved. Must be calculated. - uint32_t apalette_256_rgb[256]; // R * 65536 + G * 256 + B - scrntype_t apalette_256_pixel[256]; // Not saved. Must be calculated. // Others. uint8_t video_out_reg_addr; // I/O 0448H uint8_t video_out_reg_data; // I/O 044AH uint8_t video_out_regs[2]; - bool layer_display_flags[2]; // I/O FDA0H (WO) : bit3-2 (Layer1) or bit1-0 (Layer0).Not 0 is true. - bool r50_dpalette_updated; // I/O 044CH (RO) : bit7 - bool sprite_busy; // I/O 044CH (RO) : bit1. Must update from write_signal(). - bool splite_disp_page; // I/O 044CH (RO) : bit0. Must update from write_signal(). - // End. - - // Accessing VRAM. Will be separated. - // Memory description: - // All of accessing must be little endian. - // 000C:00000 - 000C:07fff : Plane accessing window(->FM-R50 features?). Access to Layer #0 (8000:00000). - // 000C:08000 - 000C:0ffff : I/O CVRAM - // 000D:00000 - 000E:0ffff : Reserved (Window for KANJI, DIC etc). - // 8000:00000 - 8000:3ffff : Plane accessing Layer #0. - // 8000:40000 - 8000:7ffff : Plane accessing Layer #1. - // 8010:00000 - 8010:7ffff : Plane accessing with one layer. - // 8100:00000 - 8100:1ffff : Sprite (and text vram). - // I/O 0458H (RW) : VRAM ACCESS CONTROLLER reg address. - // I/O 045AH (RW) : VRAM ACCESS CONTROLLER reg data (LOW). - // I/O 045BH (RW) : VRAM ACCESS CONTROLLER reg data (HIGH). - pair_t packed_pixel_mask_reg; // '1' = Write. I/O 0458H - 045BH. - uint8_t *vram_addr; - uint32_t vram_bytes; - uint32_t layer_offset[4]; - uint8_t *text_vram; // 4096bytes - uint8_t *kanji_vram; // 4096bytes // End. - // Flags related by host renderer. Not saved. - bool has_hardware_rendering; - bool has_hardware_blending; - // End. // // Event IDs. Saved. @@ -315,17 +267,6 @@ public: void write_data8(uint32_t addr, uint32_t data); void write_data16(uint32_t addr, uint32_t data); void write_data32(uint32_t addr, uint32_t data); - // New APIs? - void set_frame_buffer(int layer, bool buffer1, scrntype_t *framebuffer, int width, int height); - scrntype_t *get_frame_buffer_ptr(int layer); - int get_frame_buffer_width(int layer); - int get_frame_buffer_height(int layer); - bool is_display(int layer); - bool is_updated(int layer, int line_num); - void lock_frame_buffer(int layer); - void unlock_frame_buffer(int layer); - void set_render_features(bool blending_from_buffer, bool rendering_framebuffer); - // End. void event_callback(int event_id, int err); //void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame); void save_state(FILEIO* state_fio); diff --git a/source/src/vm/fmtowns/towns_vram.cpp b/source/src/vm/fmtowns/towns_vram.cpp new file mode 100644 index 000000000..f161823b8 --- /dev/null +++ b/source/src/vm/fmtowns/towns_vram.cpp @@ -0,0 +1,443 @@ +/* + Skelton for retropc emulator + + Author : Kyuma Ohta + Date : 2016.12.28 - + + [ FM-Towns VRAM ] + History: 2017.01.16 Initial. +*/ + +#include "common.h" +#include "./towns_vram.h" + +#define CLEAR_COLOR RGBA_COLOR(0,0,0,0) + +#if defined(_RGB888) +#define _USE_ALPHA_CHANNEL +#endif + +void TOWNS_VRAM::initialize() +{ +#ifdef _USE_ALPHA_CHANNEL + for(int i = 0; i < 32768; i++) { + uint8_t g = (i / (32 * 32)) & 0x1f; + uint8_t r = (i / 32) & 0x1f; + uint8_t b = i & 0x1f; + table_32768c[i] = RGBA_COLOR(r << 3, g << 3, b << 3, 0xff); + } + for(int i = 32768; i < 65536; i++) { + table_32768c[i] = _CLEAR_COLOR; + } +#endif + for(int i = 0; i < TOWNS_CRTC_MAX_LINES; i++) { + line_rendered[0][i] = false; + line_rendered[1][i] = false; + } + +} +uint32_t TOWNS_VRAM::read_data8(uint32_t addr) +{ + uint8_t *p; + uint8_t tmp_m, tmp_d; + uint8_t mask; + + if((addr & 1) == 0) { + mask = packed_access_mask_lo; + } else { + mask = packed_access_mask_hi; + } + p = &(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xffffffff]); + tmp_m = *p; + //tmp_m = tmp_m & ~mask; + tmp_d = tmp_m & mask; // Is unreaderble bits are '0'? + return (uint32_t) tmp_d; +} + +uint32_t TOWNS_VRAM::read_data16(uint32_t addr) +{ + uint16_t *p; + uint16_t tmp_m, tmp_d; + uint16_t mask; + pair_t n; + + n.b.l = packed_access_mask_lo; + n.b.h = packed_access_mask_hi; + mask = n.w.l; + + p = &(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xfffffffe]); + tmp_m = *p; + //tmp_m = tmp_m & ~mask; + tmp_d = tmp_m & mask; // Is unreaderble bits are '0'? + return (uint32_t) tmp_d; +} + +uint32_t TOWNS_VRAM::read_data32(uint32_t addr) +{ + uint32_t *p; + uint32_t tmp_m, tmp_d; + uint32_t mask; + pair_t n; + + n.b.l = packed_access_mask_lo; + n.b.h = packed_access_mask_hi; + n.b.h2 = packed_access_mask_lo; + n.b.h3 = = packed_access_mask_hi; + + mask = n.d; + p = &(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xfffffffc]); + tmp_m = *p; + //tmp_m = tmp_m & ~mask; + tmp_d = tmp_m & mask; // Is unreaderble bits are '0'? + return tmp_d; +} + +void TOWNS_VRAM::write_data8(uint32_t addr, uint32_t data) +{ + uint8_t *p; + uint8_t tmp_m, tmp_d; + uint8_t mask; + + if((addr & 1) == 0) { + mask = packed_access_mask_lo; + } else { + mask = packed_access_mask_hi; + } + p = &(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xffffffff]); + tmp_m = *p; + tmp_m = tmp_m & ~mask; + tmp_d = data & mask; + *p = tmp_d | tmp_m; +} + +void TOWNS_VRAM::write_data16(uint32_t addr, uint32_t data) +{ + uint16_t *p; + uint16_t tmp_m, tmp_d; + uint16_t mask; + pair_t n; + + n.b.l = packed_access_mask_lo; + n.b.h = packed_access_mask_hi; + mask = n.w.l; + p = (uint16_t *)(&(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xfffffffe])); + tmp_m = *p; + tmp_m = tmp_m & ~mask; + tmp_d = data & mask; + *p = tmp_d | tmp_m; +} + +void TOWNS_VRAM::write_data32(uint32_t addr, uint32_t data) +{ + uint32_t *p; + uint32_t tmp_m, tmp_d; + uint32_t mask; + pair_t n; + + n.b.l = packed_access_mask_lo; + n.b.h = packed_access_mask_hi; + n.b.h2 = packed_access_mask_lo; + n.b.h3 = = packed_access_mask_hi; + + mask = n.d; + p = (uint32_t *)(&(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xfffffffc])); + tmp_m = *p; + tmp_m = tmp_m & ~mask; + tmp_d = data & mask; + *p = tmp_d | tmp_m; +} + +void TOWNS_VRAM::write_plane_data8(uint32_t addr, uint32_t data) +{ + // Plane Access + pair_t data_p; + uint32_t x_addr = 0; + uint8_t *p; + uint32_t mod_pos; + + if(access_page1) x_addr = 0x20000; //? + p = &(vram[x_addr]); + + // 8bit -> 32bit + uint32_t *pp = (uint32_t *)p; + uint32_t tmp = 0; + uint32_t tmp_d = data & 0xff; + uint32_t tmp_m = 0xf0000000 & write_plane_mask; + uint32_t tmp_r; + + for(int i = 0; i < 8; i++) { + if((tmp_d & 0x80)) tmp |= tmp_m; + tmp_d << 1; + tmp_m >>= 4; + } + tmp_r = pp[addr]; + tmp_r = tmp_r & ~write_plane_mask; + tmp_r = tmp_d | tmp_r; + pp[addr] = tmp_r; +} + +void TOWNS_VRAM::write_plane_data16(uint32_t addr, uint32_t data) +{ + pair_t d; + d.d = data; + write_plane_data8(addr, d.b.l); + write_plane_data8(addr + 1, d.b.h); +} + +void TOWNS_VRAM::write_plane_data16(uint32_t addr, uint32_t data) +{ + write_plane_data8(addr, data & 0xff); + write_plane_data8(addr + 1, (data >> 8) & 0xff); +} + +void TOWNS_VRAM::write_plane_data32(uint32_t addr, uint32_t data) +{ + write_plane_data8(addr, data & 0xff); + write_plane_data8(addr + 1, (data >> 8) & 0xff); + write_plane_data8(addr + 2, (data >> 16) & 0xff); + write_plane_data8(addr + 3, (data >> 24) & 0xff); +} + +// I/Os +// Palette. +void TOWNS_CRTC::calc_apalette16(int layer, int index) +{ + if(index < 0) return; + if(index > 15) return; + apalette_16_rgb[layer][index] = + ((uint16_t)(apalette_b & 0x0f)) | + ((uint16_t)(apalette_r & 0x0f) << 4) | + ((uint16_t)(apalette_g & 0x0f) << 8); + if(index == 0) { + apalette_16_pixel[layer][index] = _CLEAR_COLOR; // ?? + } else { + apalette_16_pixel[layer][index] = RGBA_COLOR((apalette_r & 0x0f) << 4, (apalette_g & 0x0f) << 4, (apalette_b & 0x0f) << 4, 0xff); + } +} + +void TOWNS_CRTC::calc_apalette256(int index) +{ + if(index < 0) return; + if(index > 255) return; + apalette_256_rgb[layer][index] = + ((uint32_t)apalette_b) | + ((uint32_t)apalette_r << 8) | + ((uint32_t)apalette_g << 16); + if(index == 0) { + apalette_256_pixel[index] = _CLEAR_COLOR; // ?? + } else { + apalette_256_pixel[index] = RGBA_COLOR(apalette_r, apalette_g, apalette_b, 0xff); + } +} + +void TOWNS_CRTC::set_apalette_r(int layer, uint8_t val) +{ + apalette_r = val; + if(apalette_code < 16) { + calc_apalette16(layer, (int)apalette_code); + } + // if layer == 0 ? + calc_apalette256((int)apalette_code % 256); +} + +void TOWNS_CRTC::set_apalette_g(int layer, uint8_t val) +{ + apalette_g = val; + if(apalette_code < 16) { + calc_apalette16(layer, (int)apalette_code); + } + // if layer == 0 ? + calc_apalette256((int)apalette_code % 256); +} + +void TOWNS_CRTC::set_apalette_b(int layer, uint8_t val) +{ + apalette_b = val; + if(apalette_code < 16) { + calc_apalette16(layer, (int)apalette_code); + } + // if layer == 0 ? + calc_apalette256((int)apalette_code % 256); +} + +void TOWNS_CRTC::set_apalette_num(int layer, uint8_t val) +{ + apalette_code = ((int)val) % 256; +} + +// Renderers +void TOWNS_CRTC::render_line_16(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words) +{ + uint32_t wordptr = 0; + int nwords = (int)words / 8; + int ip; + uint32_t src; + uint32_t src1, src2; + uint8_t srcdat1[4], srcdat2[1]; + scrntype_t *pdst = framebuffer; + uint32_t *pp = (uint32_t *)vramptr; + + if(framebuffer == NULL) return; + if(vramptr == NULL) return; + for(ip = 0; ip < nwords; ip++) { + src = pp[ip]; + src1 = (src & 0xf0f0f0f0) >> 4; + src2 = src & 0x0f0f0f0f; + + srcdat1[0] = (uint8_t)(src1 >> 24); + srcdat1[1] = (uint8_t)(src1 >> 16); + srcdat1[2] = (uint8_t)(src1 >> 8); + srcdat1[3] = (uint8_t)(src1 >> 0); + + srcdat2[0] = (uint8_t)(src2 >> 24); + srcdat2[1] = (uint8_t)(src2 >> 16); + srcdat2[2] = (uint8_t)(src2 >> 8); + srcdat2[3] = (uint8_t)(src2 >> 0); + /* + srcdat[0] = (uint8_t)((src & 0xf0000000) >> 28); + srcdat[1] = (uint8_t)((src & 0x0f000000) >> 24); + srcdat[2] = (uint8_t)((src & 0x00f00000) >> 20); + srcdat[3] = (uint8_t)((src & 0x000f0000) >> 16); + srcdat[4] = (uint8_t)((src & 0x0000f000) >> 12); + srcdat[5] = (uint8_t)((src & 0x00000f00) >> 8); + srcdat[6] = (uint8_t)((src & 0x000000f0) >> 4); + srcdat[7] = (uint8_t)(src & 0x0f); + for(int i = 0; i < 8; i++) { + pdst[i] = apalette_16_pixel[layer][srcdat[i]]; + } + pdst += 8; + */ + for(int i = 0; i < 4; i++) { + pdst[0] = apalette_16_pixel[layer][srcdat1[i]]; + pdst[1] = apalette_16_pixel[layer][srcdat2[i]]; + pdst += 2; + } + } + int mod_words = words - (nwords * 8); + if(mod_words > 0) { + uint8_t *ppp = (uint8_t *)(&pp[ip]); + uint8_t hi, lo; + for(int i = 0; i < mod_words / 2; i++) { + uint8_t d = ppp[i]; + hi = (d & 0xf0) >> 4; + lo = d & 0x0f; + *pdst++ = apalette_16_pixel[layer][hi]; + *pdst++ = apalette_16_pixel[layer][lo]; + } + if((mod_words & 1) != 0) { + hi = (ppp[mod_words / 2] & 0xf0) >> 4; + *pdst++ = apalette_16_pixel[layer][hi]; + } + } +} + +void TOWNS_CRTC::render_line_256(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words) +{ + uint32_t wordptr = 0; + int nwords = (int)words / 4; + int ip; + uint32_t src; + uint8_t srcdat[4]; + scrntype_t *pdst = framebuffer; + uint32_t *pp = (uint32_t *)vramptr; + + if(framebuffer == NULL) return; + if(vramptr == NULL) return; + for(ip = 0; ip < nwords; ip++) { + src = pp[ip]; + srcdat[0] = (uint8_t)((src & 0xff000000) >> 24); + srcdat[1] = (uint8_t)((src & 0x00ff0000) >> 16); + srcdat[2] = (uint8_t)((src & 0x0000ff00) >> 8); + srcdat[3] = (uint8_t) (src & 0x000000ff); + for(int i = 0; i < 4; i++) { + pdst[i] = apalette_256_pixel[srcdat[i]]; + } + pdst += 4; + } + int mod_words = words - (nwords * 4); + if(mod_words > 0) { + uint8_t src8; + uint8_t *p8 = (uint8_t *)(&pp[ip]); + for(int i = 0; i < mod_words; i++) { + src8 = p8[i]; + pdst[i] = apalette_256_pixel[src8]; + } + } +} + +// To be used table?? +void TOWNS_CRTC::render_line_32768(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words) +{ + uint32_t wordptr = 0; + int nwords = (int)words / 8; + int ip; + uint16_t src16; + uint32_t srcdat[4]; + scrntype_t *pdst = framebuffer; + uint32_t *pp = (uint32_t *)vramptr; + uint16_t *cachep = (uint16_t *)srcdat; + int i = 0; + + if(framebuffer == NULL) return; + if(vramptr == NULL) return; + + for(ip = 0; ip < nwords; ip++) { + for(int i = 0; i < 4; i++) { + srcdat[i] = pp[i]; + } + pp = pp + 4; + scrntype_t dcache[8]; + for(int i = 0; i < 8; i++) { + dcache[i] = _CLEAR_COLOR; + } + for(int i = 0; i < 8; i++) { + uint16_t v = cachep[i]; +#ifdef _USE_ALPHA_CHANNEL +#ifdef __BIG_ENDIAN__ + pair_t n; + n.d = 0; + n.b.l = v & 0xff; + n.b.h = (v & 0xff00) >> 8; + dcache[i] = table_32768c[n.sw.l]; +#else + dcache[i] = table_32768c[v]; +#endif +#else + if((v & 0x8000) == 0) { + dcache[i] = RGBA_COLOR((v & 0x03e0) >> 2, (v & 0x7c00) >> 7, (v & 0x001f) << 3, 0xff); // RGB555 -> PIXEL + } +#endif + } + for(int i = 0; i < 8; i++) { + pdst[i] = dcache[i]; + } + pdst += 8; + } + int mod_words = words - nwords * 8; + if(mod_words > 0) { + uint16_t *vp = (uint16_t *)pp; + scrntype_t dc; + for(int i = 0; i < mod_words; i++) { + src16 = vp[i]; +#ifdef _USE_ALPHA_CHANNEL +#ifdef __BIG_ENDIAN__ + pair_t n; + n.d = 0; + n.b.l = src16 & 0xff; + n.b.h = (src16 & 0xff00) >> 8; + dc = table_32768c[n.sw.l]; +#else + dc = table_32768c[src16]; +#endif +#else + dc = _CLEAR_COLOR; + if((src16 & 0x8000) == 0) { + dc = RGBA_COLOR((src16 & 0x03e0) >> 2, (src16 & 0x7c00) >> 7, (src16 & 0x001f) << 3, 0xff); // RGB555 -> PIXEL + } +#endif + pdst[i] = dc; + } + } +} +#undef _CLEAR_COLOR + diff --git a/source/src/vm/fmtowns/towns_vram.h b/source/src/vm/fmtowns/towns_vram.h index 199ad9000..6cb60bb7d 100644 --- a/source/src/vm/fmtowns/towns_vram.h +++ b/source/src/vm/fmtowns/towns_vram.h @@ -35,169 +35,121 @@ class TOWNS_VRAM : public DEVICE { protected: - scrntype_t *render_buffer; uint32_t page_modes[4]; - uint32_t masks; + bool line_rendered[2][TOWNS_CRTC_MAX_LINES]; + + scrntype_t *framebuffer0[2]; // Frame Buffer Layer 0. Not saved. + scrntype_t *framebuffer1[2]; // Frame Buffer Layer 1. Not saved. + + int framebuffer_width[2]; + int framebuffer_height[2]; + + uint16_t *vram_ptr[2]; // Layer [01] address. + uint32_t vram_size[2]; // Layer [01] size [bytes]. + uint32_t vram_offset[2]; // Layer [01] address offset. + + scrntype_t table_32768c[65536]; + + uint32_t layer_virtual_width[2]; + uint32_t layer_virtual_height[2]; + uint32_t layer_display_width[2]; + uint32_t layer_display_height[2]; + + bool access_page1; + uint32_t write_plane_mask; // for plane-access. + uint8_t packed_access_mask_lo; + uint8_t packed_access_mask_hi; + + uint8_t vram[0x80000]; // Related by machine. + // FMR50 Compatible registers. They are mostly dummy. + // Digital paletts. I/O FD98H - FD9FH. + uint8_t r50_digital_palette[8]; + bool layer_display_flags[2]; // I/O FDA0H (WO) : bit3-2 (Layer1) or bit1-0 (Layer0).Not 0 is true. + + bool r50_dpalette_updated; // I/O 044CH (RO) : bit7 + + bool sprite_busy; // I/O 044CH (RO) : bit1. Must update from write_signal(). + bool splite_disp_page; // I/O 044CH (RO) : bit0. Must update from write_signal(). + + // Around Analog palette. + uint8_t apalette_code; // I/O FD90H (RW). 16 or 256 colors. + uint8_t apalette_b; // I/O FD92H (RW). + uint8_t apalette_r; // I/O FD94H (RW). + uint8_t apalette_g; // I/O FD96H (RW). + uint16_t apalette_16_rgb[2][16]; // R * 256 + G * 16 + B + scrntype_t apalette_16_pixel[2][16]; // Not saved. Must be calculated. + uint32_t apalette_256_rgb[256]; // R * 65536 + G * 256 + B + scrntype_t apalette_256_pixel[256]; // Not saved. Must be calculated. + // Accessing VRAM. Will be separated. + // Memory description: + // All of accessing must be little endian. + // 000C:00000 - 000C:07fff : Plane accessing window(->FM-R50 features?). Access to Layer #0 (8000:00000). + // 000C:08000 - 000C:0ffff : I/O CVRAM + // 000D:00000 - 000E:0ffff : Reserved (Window for KANJI, DIC etc). + // 8000:00000 - 8000:3ffff : Plane accessing Layer #0. + // 8000:40000 - 8000:7ffff : Plane accessing Layer #1. + // 8010:00000 - 8010:7ffff : Plane accessing with one layer. + // 8100:00000 - 8100:1ffff : Sprite (and text vram). + // I/O 0458H (RW) : VRAM ACCESS CONTROLLER reg address. + // I/O 045AH (RW) : VRAM ACCESS CONTROLLER reg data (LOW). + // I/O 045BH (RW) : VRAM ACCESS CONTROLLER reg data (HIGH). + pair_t packed_pixel_mask_reg; // '1' = Write. I/O 0458H - 045BH. + //uint8_t *vram_addr; + uint32_t vram_bytes; + uint32_t layer_offset[4]; + uint8_t text_vram[4096]; // 4096bytes + uint8_t kanji_vram[4096]; // 4096bytes + // End. + + // Flags related by host renderer. Not saved. + bool has_hardware_rendering; + bool has_hardware_blending; + // End. public: TOWNS_VRAM(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) { memset(vram, 0x00, sizeof(vram)); render_buffer = NULL; page_modes[0] = page_modes[1] = page_modes[2] = page_modes[3] = 0; - masks = 0; + packed_access_mask_hi = packed_access_mask_lo = 0xff; + write_plane_mask = 0xffffffff; } ~TOWNS_VRAM() {} - uint32_t read_data8(uint32_t addr) - { - if(addr < 0x80000000) { - // Plane Access - uint32_t data32; - uint8_t data8; - uint32_t n_plane = (addr & 0x18000) / 0x8000; - uint32_t n_addr = addr & 0x7fff; - uint32_t x_addr = n_addr << 2; - uint32_t *p; - if(plane_page1) x_addr += 0x20000; - p = (uint32_t *)(&(vram[x_addr])); - data32 = *p; - data32 >>= (3 - n_plane); - data8 = - ((data32 & 0x10000000) ? 0x80 : 0) | - ((data32 & 0x01000000) ? 0x40 : 0) | - ((data32 & 0x00100000) ? 0x20 : 0) | - ((data32 & 0x00010000) ? 0x10 : 0) | - ((data32 & 0x00001000) ? 0x08 : 0) | - ((data32 & 0x00000100) ? 0x04 : 0) | - ((data32 & 0x00000010) ? 0x02 : 0) | - ((data32 & 0x00000001) ? 0x01 : 0); - return (uint32_t) data8; - } else { - return vram[addr & TOWNS_VRAM_ADDR_MASK]; - } - }; - - uint32_t read_data16(uint32_t addr) - { - pair_t n; - n.d = 0; - if(addr < 0x80000000) { - addr = addr & 0x1fffe; - n.b.h = read_data8(addr + 1); - n.b.l = read_data8(addr); - } else { - addr = addr & (TOWNS_VRAM_ADDR_MASK & 0xfffffffe); - n.b.h = vram[addr + 1]; - n.b.l = vram[addr]; - } - return n.d; - } - - uint32_t read_data32(uint32_t addr) - { - if(addr < 0x80000000) { - addr = addr & 0x1fffc; - n.b.h3 = read_data8(addr + 3); - n.b.h2 = read_data8(addr + 2); - n.b.h = read_data8(addr + 1); - n.b.l = read_data8(addr); - } else { - addr = addr & (TOWNS_VRAM_ADDR_MASK & 0xfffffffc); - n.b.h3 = vram[addr + 3]; - n.b.h2 = vram[addr + 2]; - n.b.h = vram[addr + 1]; - n.b.l = vram[addr]; - } - return n.d; - } - - void write_data8(uint32_t addr, uint32_t data) - { - if(addr < 0x80000000) { - // Plane Access - pair_t data_p; - uint32_t n_plane = (addr & 0x18000) / 0x8000; - uint32_t n_addr = addr & 0x7fff; - uint32_t x_addr = n_addr << 2; - - pair_t *p; - if(plane_page1) x_addr += 0x20000; - p = (pair_t *)(&(vram[x_addr])); - data_p.d = *p; - // ToDo - } else { - // ToDo: Scroll - uint32_t mask2 = (masks >> ((3 - (addr & 3)) * 8)) & 0xff; - uint32_t d_s = vram[addr & TOWNS_VRAM_ADDR_MASK] & ~mask2; - uint32_t d_d = data & mask2; - vram[addr & TOWNS_VRAM_ADDR_MASK] = d_s | d_d; - } - } - - void write_data16(uint32_t addr, uint32_t data) - { - if(addr < 0x80000000) { - // Plane Access - pair_t data_p; - uint32_t n_plane = (addr & 0x18000) / 0x8000; - uint32_t n_addr = addr & 0x7fff; - uint32_t x_addr = n_addr << 2; - - pair_t *p; - if(plane_page1) x_addr += 0x20000; - p = (pair_t *)(&(vram[x_addr])); - data_p.d = *p; - // ToDo - } else { - pair_t n; - uint16_t *p; - n.d = 0; - p = (uint16_t *)(&(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xfffffffe])); - n.sw.l = *p; - uint32_t mask2 = (masks >> ((2 - (addr & 2)) * 16)) & 0xffff; - uint32_t d_s = n.d & ~mask2; - uint32_t d_d = data & mask2; - // ToDo: Scroll - n.d = d_s | d_d; - *p = n.sw.l; - } - } - - void write_data32(uint32_t addr, uint32_t data) - { - if(addr < 0x80000000) { - // Plane Access - pair_t data_p; - uint32_t n_plane = (addr & 0x18000) / 0x8000; - uint32_t n_addr = addr & 0x7fff; - uint32_t x_addr = n_addr << 2; - - pair_t *p; - if(plane_page1) x_addr += 0x20000; - p = (pair_t *)(&(vram[x_addr])); - data_p.d = *p; - // ToDo - } else { - uint32_t n; - uint32_t *p; - - p = (uint32_t *)(&(vram[addr & TOWNS_VRAM_ADDR_MASK & 0xfffffffc])); - n = *p; - uint32_t mask2 = masks; - uint32_t d_s = n & ~mask2; - uint32_t d_d = data & mask2; - // ToDo: Scroll - *p = d_s | d_d; - } - } + uint32_t read_data8(uint32_t addr); + uint32_t read_data16(uint32_t addr); + uint32_t read_data32(uint32_t addr); + void write_data8(uint32_t addr, uint32_t data); + void write_data16(uint32_t addr, uint32_t data); + void write_data32(uint32_t addr, uint32_t data); uint32_t read_io8(uint32_t addr); void write_io8(uint32_t addr, uint32_t data); void draw_screen(); void write_signal(int id, uint32_t data, uint32_t mask); // Do render - void set_context_renderbuffer(scrntype_t *p){ + // Unique Functions + uint32_t read_plane_data8(uint32_t addr); + uint32_t read_plane_data16(uint32_t addr); + uint32_t read_plane_data32(uint32_t addr); + // New APIs? + void write_plane_data8(uint32_t addr, uint32_t data); + void write_plane_data16(uint32_t addr, uint32_t data); + void write_plane_data32(uint32_t addr, uint32_t data); + + void set_frame_buffer(int layer, bool buffer1, scrntype_t *framebuffer, int width, int height); + scrntype_t *get_frame_buffer_ptr(int layer); + int get_frame_buffer_width(int layer); + int get_frame_buffer_height(int layer); + bool is_display(int layer); + bool is_updated(int layer, int line_num); + void lock_frame_buffer(int layer); + void unlock_frame_buffer(int layer); + void set_render_features(bool blending_from_buffer, bool rendering_framebuffer); + // End. + + void set_context_renderbuffer(scrntype_t *p, uint32_t size){ render_buffer = p; }; };