From d28a8b5ec1d5489851b88628fafcf17bbfbe1ea0 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Thu, 1 Nov 2018 05:40:46 +0900 Subject: [PATCH] [VM][FMTOWNS][VRAM][WIP] Implementing vram and renderer. --- source/src/vm/fmtowns/towns_vram.cpp | 482 ++++++++++++++++++++++------------- 1 file changed, 306 insertions(+), 176 deletions(-) diff --git a/source/src/vm/fmtowns/towns_vram.cpp b/source/src/vm/fmtowns/towns_vram.cpp index f161823b8..73981d566 100644 --- a/source/src/vm/fmtowns/towns_vram.cpp +++ b/source/src/vm/fmtowns/towns_vram.cpp @@ -38,115 +38,88 @@ void TOWNS_VRAM::initialize() } 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; + // ToDo:Offset. + // ToDo: Wait. + return vram[addr & 0x7ffff]; } + + 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; + // ToDo:Offset. + // ToDo: Wait. + uint32_t naddr = addr & 0x7fffe; + pair16_t nw; + nw.l = vram[naddr + 0]; + nw.h = vram[naddr + 1]; + return (uint32_t)(nw.w); } 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; + // ToDo: Wait. + pair32_t nd; + uint32_t naddr = addr & 0x7fffc; + nd.w.l = read_data16(naddr + 0); + nd.w.h = read_data16(naddr + 2); + return nd.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; + // ToDo:Offset. + // ToDo: Wait. + bool dirty; + uint32_t naddr = addr & 0x7ffff; + uint8_t n = vram[naddr]; + dirty = ((uint8_t)data != n) ? true : false; + dirty_flag[naddr] = dirty; + if(dirty) { + vram[naddr] = n; + if((naddr & 1) != 0) { + uint16_t nd = (n < 0x80) ? 0xffff : 0x0000; + alpha_32768_byte[naddr >> 1] = (uint8_t)nd; + alpha_32768_word[naddr >> 1] = nd; + mask_32768_word[naddr >> 1] = ~nd; + } + // ToDo: Mask/alpha16. } - 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; + // ToDo:Offset. + // ToDo: Wait. + bool dirty; + uint32_t naddr = addr & 0x7fffe; + uint16_t *vp = (uint16_t*)(&(vram[naddr])); + pair16_t nw; + nw.b.l = vram[naddr + 0]; + nw.b.h = vram[naddr + 1]; + + dirty = ((uint16_t)data != nw.w) ? true : false; + dirty_flag[naddr] = dirty; + dirty_flag[naddr + 1] = dirty; + + if(dirty) { + uint16_t alphaw = (nw.w < 0x8000) ? 0xffff : 0x0000; + alpha_32768_byte[naddr >> 1] = (uint8_t)alphaw; + alpha_32768_word[naddr >> 1] = alphaw; + mask_32768_word[naddr >> 1] = ~alphaw; + *vp = (uint16_t)data; + } } 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; + uint32_t naddr = addr & 0x7fffc; // OK? + write_data16(naddr + 0, (uint16_t)data); + write_data16(naddr + 2, (uint16_t)(data >> 16)); } + + void TOWNS_VRAM::write_plane_data8(uint32_t addr, uint32_t data) { // Plane Access @@ -198,6 +171,7 @@ void TOWNS_VRAM::write_plane_data32(uint32_t addr, uint32_t data) write_plane_data8(addr + 3, (data >> 24) & 0xff); } + // I/Os // Palette. void TOWNS_CRTC::calc_apalette16(int layer, int index) @@ -269,64 +243,85 @@ void TOWNS_CRTC::set_apalette_num(int layer, uint8_t val) 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 nwords = (int)words / 16; int ip; uint32_t src; uint32_t src1, src2; - uint8_t srcdat1[4], srcdat2[1]; + uint8_t srcdat[16]; + scrntype_t tmpdat[16]; scrntype_t *pdst = framebuffer; - uint32_t *pp = (uint32_t *)vramptr; - + uint8_t *pp = (uint8_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); + for(int ii = 0; ii < 8; ii++) { + srcdat[ii << 1] = pp[ii]; + srcdat[(ii << 1) + 1] = srcdat[ii << 1] & 0x0f; + srcdat[ii << 1] = (srcdat[ii << 1] & 0x0f) >> 4; + } - 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]]; + for(int ii = 0; ii < 16; ii++) { + uint16_t c = (srcdat[ii] == 0) ? 0x0000 : 0xffff; + alpha_cache_16_word[ii] = c; + alpha_cache_16_byte[ii] = (uint8_t)c; + mask_cache_16_word[ii] = ~c; } - 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; + if(upper_layer) { + for(int ii = 0; ii < 16; i++) { + tmpdat[ii] = (alpha_cache_16_byte[ii] != 0) ? apalette_16[layer][srcdat1[ii]] : RGBA_COLOR(0, 0, 0, 0); + } + } else { + for(int ii = 0; ii < 16; i++) { + tmpdat[ii] = (alpha_cache_16_byte[ii] != 0) ? apalette_16[layer][srcdat1[ii]] : RGBA_COLOR(0, 0, 0, 255); + } + } + for(int ii = 0; ii < 16; ii++) { + pdst[ii] = tmpdat[ii]; } + pdst += 16; + pp += 8; } - int mod_words = words - (nwords * 8); + int mod_words = words - (nwords * 16); + uint8_t sdat1, sdat2; + uint16_t c1 = 0xffff; + uint16_t c2 = 0xffff; + 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]; + for(int ii = 0; ii < mod_words; i++) { + if((ii & 1) == 0) { + sdat1 = *pp; + sdat2 = sdat1 & 0x0f; + sdat1 = (sdat1 & 0xf0) >> 4; + c1 = (sdat1 == 0) ? 0x0000 : 0xffff; + c2 = (sdat2 == 0) ? 0x0000 : 0xffff; + } + if((ii & 1) == 0) { + alpha_cache_16_word[ii] = c1; + alpha_cache_16_byte[ii] = (uint8_t)c1; + mask_cache_16_word[ii] = ~c1; + } else { + alpha_cache_16_word[ii] = c2; + alpha_cache_16_byte[ii] = (uint8_t)c2; + mask_cache_16_word[ii] = ~c2; + } + + if((ii & 1) == 0) { + if(upper_layer) { + tmpdat[ii] = (c1 != 0) ? apalette_16_pixel[layer][sdat1] : RGBA_COLOR(0, 0, 0, 0); + } else { + tmpdat[ii] = (c1 != 0) ? apalette_16_pixel[layer][sdat1] : RGBA_COLOR(0, 0, 0, 255); + } + } else { + if(upper_layer) { + tmpdat[ii] = (c2 != 0) ? apalette_16_pixel[layer][sdat2] : RGBA_COLOR(0, 0, 0, 0); + } else { + tmpdat[ii] = (c2 != 0) ? apalette_16_pixel[layer][sdat2] : RGBA_COLOR(0, 0, 0, 255); + } + } + pp++; } - if((mod_words & 1) != 0) { - hi = (ppp[mod_words / 2] & 0xf0) >> 4; - *pdst++ = apalette_16_pixel[layer][hi]; + for(int ii = 0; ii < mod_words; i++) { + pdst[ii] = tmpdat[ii]; } } } @@ -366,78 +361,213 @@ void TOWNS_CRTC::render_line_256(int layer, scrntype_t *framebuffer, uint8_t *vr } // To be used table?? -void TOWNS_CRTC::render_line_32768(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words) +void TOWNS_CRTC::render_line_32768(int layer, scrntype_t *pixcache, 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; + scrntype_t *pdst = pixcache; + uint8_t *pp = (uint8_t *)vramptr; uint16_t *cachep = (uint16_t *)srcdat; + pair16_t rgb[8]; + uint8_t a[8], r[8], g[8], b[8]; + scrntype_t dcache[8]; + int i = 0; if(framebuffer == NULL) return; if(vramptr == NULL) return; - + + union { + uint16_t u16[8]; + pair16_t p16[8]; + uint8_t u8[16]; + } srcdat; for(ip = 0; ip < nwords; ip++) { - for(int i = 0; i < 4; i++) { - srcdat[i] = pp[i]; + for(int i = 0; i < 16; i++) { + srcdat.u8[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 + + for(int ii = 0; ii < 8; ii++) { +#if defined(__LITTLE_ENDIAN__) + rgb[ii].w = srcdat.w[ii]; #else - if((v & 0x8000) == 0) { - dcache[i] = RGBA_COLOR((v & 0x03e0) >> 2, (v & 0x7c00) >> 7, (v & 0x001f) << 3, 0xff); // RGB555 -> PIXEL - } + rgb[ii].b.l = srcdat.u8[ii << 1]; + rgb[ii].b.h = srcdat.u8[(ii << 1) + 1]; #endif } - for(int i = 0; i < 8; i++) { - pdst[i] = dcache[i]; + for(int ii = 0; ii < 8; ii++) { + //g5r5b5 + g[ii] = (rgb[ii].w & 0x7c00) >> 10; + r[ii] = (rgb[ii].w & 0x03e0) >> 5; + b[ii] = (rgb[ii].w & 0x001f); + a[ii] = (rgb[ii].w < 0x8000) ? 0xff : 0x00; + } + for(int ii = 0; ii < 8; ii++) { + dcache[ii] = RGBA_COLOR(r[ii], g[ii], b[ii], a[ii]); + } + for(int ii = 0; ii < 8; ii++) { + pdst[ii] = dcache[ii]; } pdst += 8; + pp += 16; + } + for(int i = 0; i < 8; i++) { + dcache[i] = _CLEAR_COLOR; } 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]; + for(ip = 0; ip < mod_words; ip++) { + srcdat.u8[ip << 1] = pp[ip << 1]; + srcdat.u8[(ip << 1) + 1] = pp[(ip << 1) + 1]; +#if defined(__LITTLE_ENDIAN__) + rgb[ip].w = srcdat.w[ip]; #else - dc = table_32768c[src16]; + rgb[ip].b.l = srcdat.u8[ip << 1]; + rgb[ip].b.h = srcdat.u8[(ip << 1) + 1]; #endif -#else - dc = _CLEAR_COLOR; - if((src16 & 0x8000) == 0) { - dc = RGBA_COLOR((src16 & 0x03e0) >> 2, (src16 & 0x7c00) >> 7, (src16 & 0x001f) << 3, 0xff); // RGB555 -> PIXEL + //g5r5b5 + g[ip] = (rgb[ip].w & 0x7c00) >> 10; + r[ip] = (rgb[ip].w & 0x03e0) >> 5; + b[ip] = (rgb[ip].w & 0x001f); + a[ip] = (rgb[ip].w < 0x8000) ? 0xff : 0x00; + dcache[ip] = RGBA_COLOR(r[ip], g[ip], b[ip], a[ip]); + } + for(ip = 0; ip < mod_words; ip++) { + pdst[ip] = dcache[ip]; + } +} + +void TOWNS_CRTC::vzoom_pixel(scrntype_t*src, int width, int srclines, scrntype_t* dst, int stride, int dstlines, float vzoom) +{ + if(src == dst) return; + if(vzoom <= 0.0f) return; + if((src == NULL) || (dst == NULL)) return; + if(width <= 0) return; + if(srclines <= 0) return; + if(dstlines <= 0) return; + + scrntype_t *psrc = src; + scrntype_t *pdst = dst; + + float vzoom_int = floor(vzoom); + float vzoom_mod = vzoom - vzoom_int; + float nmod = 0.0f; + int nint = (int)vzoom_int; + int srcline = 0; + int linecount = 0; + for(srcline = 0; srcline < srclines; srcline++) { + int ifactor = nint; + if(nmod >= 1.0f) { + nmod = nmod - 1.0f; + ifactor++; + } + for(int ii = 0; ii < ifactor; ii++) { + // ToDo: Mask, blend. + memcpy(pdst, psrc, width * sizeof(scrntype_t)); + linecount++; + if(linecount >= dstlines) goto _exit0;; + pdst += stride; + } + psrc += stride; + nmod = nmod + vzoom_mod; + } +_exit0: + return; +} + +void TOWNS_CRTC::hzoom_pixel(scrntype_t* src, int width, scrntype_t* dst, int dst_width, float hzoom) +{ + if(src == dst) return; + if(hzoom <= 0.0f) return; + if((src == NULL) || (dst == NULL)) return; + if(width <= 0) return; + if(dst_width <= 0) return; + + scrntype_t* pdst = dst; + float hzoom_int = floor(hzoom); + float hzoom_mod = hzoom - hzoom_int; + float nmod = 0.0f; + int nint = (int)hzoom_int; + if((nint == 1) && (hzoom_mod <= 0.0f)) { + // x1.0 + scrntype_t *sp = src; + scrntype_t pcache[4]; + int nw = width / 4; + int dx = 0; + int ycount = 0; + for(int ii = 0; ii < nw; ii++) { + if((dx + 3) >= dst_width) break; + for(int j = 0; j < 4; j++) { + pcache[j] = sp[j]; } -#endif - pdst[i] = dc; + // ToDo: Mask/Alpha + for(int j = 0; j < 4; j++) { + pdst[j] = pcache[j]; + } + dx += 4; + pdst += 4; + sp += 4; } + nw = width - dx; + if(dx >= dst_width) return; + for(int ii = 0; ii < nw; ii++) { + if(dx >= dst_width) goto __exit_0; + // ToDo: Mask/Alpha + pcache[ii] = sp[ii]; + pdst[ii] = pcache[ii]; + dx++; + } + } else { + scrntype_t *sp = src; + int dx = 0; + int xcount = 0; + for(int i = 0; i < width; i++) { + // ToDo : Storage via SIMD. + if(dx >= dst_width) goto __exit_0; + + int ifactor = nint; + if(nmod >= 1.0f) { + ifactor++; + nmod = nmod - 1.0f; + } + scrntype_t pix = *sp++; + scrntype_t pcache[4]; + // ToDo: MASK/ALPHA + + int jfactor = ifactor / 4; + xcount = 0; + for(int k = 0; k < 4; k++) { + pcache[k] = pix; + } + for(int j = 0; j < jfactor; j++) { + if((dx + 3) >= dst_width) break; + for(int k = 0; k < 4; k++) { + pdst[k] = pcache[k]; + } + xcount += 4; + pdst += 4; + dx += 4; + } + ifactor = ifactor - xcount; + if(ifactor < 0) ifactor = 0; + for(int k = 0; k < ifactor; k++) { + if(dx >= dst_width) goto __exit_0; + pdst[k] = pcache[k]; + dx++; + } + nmod = nmod + hzoom_mod; + + pdst += ifactor; + } } +__exit_0: + return; } + + #undef _CLEAR_COLOR -- 2.11.0