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;
}
}
-// 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()
{
}
-// 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
// 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.
// 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];
// 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;
// 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.
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);
--- /dev/null
+/*
+ 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
+
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;
};
};