OSDN Git Service

[VM][FMTOWNS] Add VRAM.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 16 Jan 2017 07:41:54 +0000 (16:41 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 16 Jan 2017 07:41:54 +0000 (16:41 +0900)
source/src/vm/fmtowns/towns_crtc.cpp
source/src/vm/fmtowns/towns_crtc.h
source/src/vm/fmtowns/towns_vram.cpp [new file with mode: 0644]
source/src/vm/fmtowns/towns_vram.h

index 114f37f..a04f3f1 100644 (file)
@@ -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
 
index 6129bfa..399ddee 100644 (file)
@@ -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 (file)
index 0000000..f161823
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+       Skelton for retropc emulator
+
+       Author : Kyuma Ohta <whatisthis.sowhat _at_ gmail.com>
+       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
+
index 199ad90..6cb60bb 100644 (file)
 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;
        };
 };