void TOWNS_SPRITE::initialize(void)
{
- memset(index_ram, 0x00, sizeof(index_ram));
memset(pattern_ram, 0x00, sizeof(pattern_ram));
- memset(color_ram, 0x00, sizeof(color_ram));
-
- for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) {
- memset(&(cache_pixels[i][0]) , 0x00, sizeof(uint16_t) * 16 * 16);
- memset(&(cache_masks[i][0]) , 0x00, sizeof(uint16_t) * 16 * 16);
- memset(&(cache_index[i]), 0x00, sizeof(sprite_cache_t));
- cache_index[i].is_use = false;
- cache_index[i].pixels = &(cache_pixels[i][0]);
- cache_index[i].masks = &(cache_masks[i][0]);
- }
- last_put_cache_num = 0;
reg_ctrl = 0x0000; // REG#00, #01
reg_voffset = 0x0000; // REG#02, #03
reg_hoffset = 0x0000; // REG#04, #05
reg_spen = false;
reg_addr = 0;
memset(reg_data, 0x00, sizeof(reg_data));
- for(int i = 0; i < (sizeof(pattern_cached) / sizeof(bool)); i++) {
- pattern_cached[i] = false;
- }
- for(int i = 0; i < 256; i++) {
- color_cached[i] = false;
- }
- use_cache = false; // ToDo: Enable cache.
render_num = 0;
render_mod = 0;
render_lines = 0;
- split_rendering = false;
+ split_rendering = true;
+
+ max_sprite_per_frame = 224;
+ frame_sprite_count = 0;
+
vram_buffer = NULL;
mask_buffer = NULL;
}
reg_addr = 0;
render_num = 0;
render_mod = 0;
- render_lines = 0;
+// render_lines = 0;
+ sprite_enabled = false;
+ now_transferring = false;
+ max_sprite_per_frame = 224;
+ frame_sprite_count = 0;
+
memset(reg_data, 0x00, sizeof(reg_data)); // OK?
- // ToDo: Is these right?
- write_page = 1;
- display_page = 0;
- // Is clear cache?
- // Is clear buffers?
}
+#if 0
void TOWNS_SPRITE::clear_cache(int num)
{
if(num >= TOWNS_SPRITE_CACHE_NUM) return;
cache_index[num].masks = &(cache_masks[num][0]);
}
-void TOWNS_SPRITE::set_sprite_attribute(int table_num, uint16_t num_attr)
-{
- if((table_num < 0) || (table_num > 1023)) return;
- uint16_t num = num_attr & 0x3ff;
- uint8_t rotate_type = (uint8_t)((num_attr & 0x7000) >> 12);
- bool halfx = ((num_attr & 0x0400) != 0);
- bool halfy = ((num_attr & 0x0800) != 0);
- bool enable_offset = ((num_attr & 0x8000) != 0);
-
- sprite_table[table_num].num = num;
- sprite_table[table_num].rotate_type = rotate_type;
- sprite_table[table_num].is_halfx = halfx;
- sprite_table[table_num].is_halfy = halfy;
- sprite_table[table_num].offset = enable_offset;
- sprite_table[table_num].attribute = num_attr & 0x7fff;
-}
-
-void TOWNS_SPRITE::set_sprite_color(int table_num, uint16_t color_table_num)
-{
- if((table_num < 0) || (table_num > 1023)) return;
- sprite_table[table_num].color = color_table_num & 0x0fff;
- sprite_table[table_num].is_32768 = ((color_table_num & 0x8000) == 0);
- sprite_table[table_num].is_impose = ((color_table_num & 0x4000) != 0);
- sprite_table[table_num].is_disp = ((color_table_num & 0x2000) != 0);
-}
-
-void TOWNS_SPRITE::build_sprite_table(void)
-{
- uint16_t* p = index_ram;
- for(int i = 0; i < 1024; i++) {
- set_sprite_attribute(i, p[3]);
- set_sprite_color(i, p[3]);
- p = p + 4;
- }
-}
-
bool TOWNS_SPRITE::check_cache(int num, sprite_cache_t** p)
{
sprite_cache_t* q;
return false;
}
-void TOWNS_SPRITE::render_sprite(int num, uint16* dst_pixel, uint16_t* dst_mask, int x, int y)
+void TOWNS_SPRITE::render_sprite(int num, int x, int y, uint16_t attr, uint16_t color)
{
uint16_t sprite_limit = reg_index & 0x3ff;
if(sprite_limit == 0) sprite_limit = 1024;
}
}
+#else
+ // Still don't use cache.
+void TOWNS_SPRITE::render_sprite(int num, int x, int y, uint16_t attr, uint16_t color)
+{
+ uint16_t lot = reg_index & 0x3ff;
+ if(lot == 0) lot = 1024;
+ if(num < 0) return;
+ if(num >= lot) return;
+ if(!(reg_spen) || !(sprite_enabled)) return;
+
+ bool is_32768 = ((color & 0x8000) == 0); // CTEN
+ // ToDo: SPYS
+ if((color & 0x2000) != 0) return; // DISP
+ uint32_t color_offset = ((uint32_t)((color & 0xfff) << 5)) & 0x1ffff; // COL11 - COL0
+
+ int xoffset = 0;
+ int yoffset = 0;
+ if((attr & 0x8000) != 0) { // OFFS
+ xoffset = reg_hoffset & 0x1ff;
+ yoffset = reg_voffset & 0x1ff;
+ }
+ bool swap_v_h = false;
+ if((attr & 0x4000) != 0) { // ROT2
+ swap_v_h = true;
+ }
+ uint8_t rot = attr >> 12;
+ bool is_halfy = ((attr & 0x0800) != 0);
+ bool is_halfx = ((attr & 0x0400) != 0); // SUX
+ // From MAME 0.209, mame/drivers/video/fmtowns.cpp
+ uint32_t ram_offset = ((uint32_t)(attr & 0x3ff) << 7) & 0x1ffff; // PAT9 - PAT0
+
+ int xbegin, xend;
+ int ybegin, yend;
+ int xinc, yinc;
+ switch(rot & 3) { // ROT1, ROT0
+ case 0:
+ // 0deg, not mirror
+ xbegin = 0;
+ xend = 15;
+ ybegin = 0;
+ yend = 15;
+ xinc = 1;
+ yinc = 1;
+ break;
+ case 1:
+ // 180deg, mirror
+ xbegin = 0;
+ xend = 15;
+ ybegin = 15;
+ yend = 0;
+ xinc = 1;
+ yinc = -1;
+ break;
+ case 2:
+ // 0deg, mirror
+ xbegin = 15;
+ xend = 0;
+ ybegin = 0;
+ yend = 15;
+ xinc = -1;
+ yinc = 1;
+ break;
+ case 3:
+ // 180deg, not mirror
+ xbegin = 15;
+ xend = 0;
+ ybegin = 15;
+ yend = 0;
+ xinc = -1;
+ yinc = -1;
+ break;
+ /*
+ case 4:
+ // 270deg, mirror
+ xbegin = 0;
+ xend = 15;
+ ybegin = 0;
+ yend = 15;
+ xinc = 1;
+ yinc = 1;
+ swap_v_h = true;
+ break;
+ case 5:
+ // 90deg, not mirror
+ xbegin = 0;
+ xend = 15;
+ ybegin = 15;
+ yend = 0;
+ xinc = 1;
+ yinc = -1;
+ swap_v_h = true;
+ break;
+ case 6:
+ // 270deg, not mirror
+ xbegin = 15;
+ xend = 0;
+ ybegin = 0;
+ yend = 15;
+ xinc = -1;
+ yinc = 1;
+ swap_v_h = true;
+ break;
+ case 7:
+ // 90deg, mirror
+ xbegin = 15;
+ xend = 0;
+ ybegin = 15;
+ yend = 0;
+ xinc = -1;
+ yinc = -1;
+ swap_v_h = true;
+ break;
+ */
+ }
+ now_transferring = true;
+ __DECL_ALIGNED(32) uint16_t sbuf[16][16];
+ __DECL_ALIGNED(32) uint32_t lbuf[16];
+ __DECL_ALIGNED(32) uint32_t mbuf[16];
+ __DECL_ALIGNED(16) uint16_t pixel_h[8];
+ __DECL_ALIGNED(16) uint16_t pixel_l[8];
+ __DECL_ALIGNED(16) uint16_t color_table[16] = {0};
+ if(!(swap_v_h)) {
+ if(is_32768) {
+ // get from ram.
+ for(int yy = 0; yy < 16; yy++) {
+ uint32_t addr = ((ybegin + yy * yinc) << 5) + (xbegin << 1) + ram_offset;
+ pair16_t nn;
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ nn.b.l = pattern_ram[(addr + 0) & 0x1ffff];
+ nn.b.h = pattern_ram[(addr + 1) & 0x1ffff];
+ sbuf[yy][xx] = nn.w;
+ addr = (addr + (xinc << 1)) & 0x1ffff;
+ }
+ }
+ } else { // 16 colors
+ pair16_t nn;
+__DECL_VECTORIZED_LOOP
+ for(int i = 0; i < 16; i++) {
+ nn.b.l = pattern_ram[(color_offset + 0) & 0x1ffff];
+ nn.b.h = pattern_ram[(color_offset + 1) & 0x1ffff];
+ color_offset += 2;
+ color_table[i] = nn.w;
+ }
+ color_table[0] = 0x8000; // Clear color
+ for(int yy = 0; yy < 16; yy++) {
+ uint32_t addr = ((ybegin + yy * yinc) << 3) + (xbegin >> 1) + ram_offset;
+ uint8_t nnh, nnl;
+ uint8_t nn;
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 8; xx++ ) {
+ nn = pattern_ram[(addr + xx * xinc) & 0x1ffff];
+ nnh = nn >> 4;
+ nnl = nn & 0x0f;
+ pixel_h[xx] = color_table[nnh];
+ pixel_l[xx] = color_table[nnl];
+ }
+ if(yinc < 0) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx += 2 ) {
+ sbuf[yy][xx ] = pixel_l[xx >> 1];
+ sbuf[yy][xx + 1] = pixel_h[xx >> 1];
+ }
+ } else {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx += 2 ) {
+ sbuf[yy][xx ] = pixel_h[xx >> 1];
+ sbuf[yy][xx + 1] = pixel_l[xx >> 1];
+ }
+ }
+ }
+ }
+ } else { // swap v and h
+ if(is_32768) {
+ // get from ram.
+ for(int yy = 0; yy < 16; yy++) {
+ uint32_t addr = ((ybegin + yy * yinc) << 5) + (xbegin << 1) + ram_offset;
+ pair16_t nn;
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ nn.b.l = pattern_ram[(addr + 0) & 0x1ffff];
+ nn.b.h = pattern_ram[(addr + 1) & 0x1ffff];
+ sbuf[xx][yy] = nn.w;
+ addr = (addr + (xinc << 1)) & 0x1ffff;
+ }
+ }
+ } else { // 16 colors
+ pair16_t nn;
+__DECL_VECTORIZED_LOOP
+ for(int i = 0; i < 16; i++) {
+ nn.b.l = pattern_ram[(color_offset + 0) & 0x1ffff];
+ nn.b.h = pattern_ram[(color_offset + 1) & 0x1ffff];
+ color_offset += 2;
+ color_table[i] = nn.w;
+ }
+ color_table[0] = 0x8000; // Clear color
+ for(int yy = 0; yy < 16; yy++) {
+ uint32_t addr = ((ybegin + yy * yinc) << 3) + (xbegin >> 1) + ram_offset;
+ uint8_t nnh, nnl;
+ uint8_t nn;
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 8; xx++ ) {
+ nn = pattern_ram[(addr + xx * xinc) & 0x1ffff];
+ nnh = nn >> 4;
+ nnl = nn & 0x0f;
+ pixel_h[xx] = color_table[nnh];
+ pixel_l[xx] = color_table[nnl];
+ }
+ if(yinc < 0) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx += 2 ) {
+ sbuf[xx ][yy] = pixel_l[xx >> 1];
+ sbuf[xx + 1][yy] = pixel_h[xx >> 1];
+ }
+ } else {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx += 2 ) {
+ sbuf[xx ][yy] = pixel_h[xx >> 1];
+ sbuf[xx + 1][yy] = pixel_l[xx >> 1];
+ }
+ }
+ }
+ }
+ }
+
+ if(!(is_halfx) && !(is_halfy)) { // not halfed
+ for(int yy = 0; yy < 16; yy++) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ lbuf[xx] = 0;
+ mbuf[xx] = 0;
+ }
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ lbuf[xx] = sbuf[yy][xx];
+ }
+ // void __FASTCALL VRAM::write_sprite_data(int x, int y, int xoffset, int yoffset, uint16_t *ptr __assume_aligned(16), int width);
+ if(d_vram != NULL) {
+ d_vram->write_sprite_data(x, y + yy, xoffset, yoffset, lbuf, 16);
+ }
+ }
+ } else if(is_halfx) { // halfx only
+ for(int yy = 0; yy < 16; yy++) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ lbuf[xx] = 0;
+ mbuf[xx] = 0;
+ }
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx += 2) {
+ lbuf[xx >> 1] += (sbuf[yy][xx] & 0x7fff);
+ mbuf[xx >> 1] |= (sbuf[yy][xx] & 0x8000);
+ }
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 8; xx++) {
+ lbuf[xx] = ((lbuf[xx] >> 2) & 0x7fff) | mbuf[xx];
+ }
+ if(d_vram != NULL) {
+ d_vram->write_sprite_data(x, y + yy, xoffset, yoffset, lbuf, 8);
+ }
+ }
+ } else if(is_halfy) { // halfy only
+ for(int yy = 0; yy < 16; yy += 2) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ lbuf[xx] = 0;
+ mbuf[xx] = 0;
+ }
+ for(int yy2 = 0; yy2 < 2; yy2++) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ lbuf[xx] += (sbuf[yy + yy2][xx] & 0x7fff);
+ mbuf[xx] |= (sbuf[yy + yy2][xx] & 0x8000);
+ }
+ }
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ lbuf[xx] = ((lbuf[xx] >> 1) & 0x7fff) | mbuf[xx];
+ }
+ if(d_vram != NULL) {
+ d_vram->write_sprite_data(x, y + (yy >>1), xoffset, yoffset, lbuf, 16);
+ }
+ }
+ } else { //halfx &&halfy
+ for(int yy = 0; yy < 16; yy += 2) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx++) {
+ lbuf[xx] = 0;
+ mbuf[xx] = 0;
+ }
+ for(int yy2 = 0; yy2 < 2; yy2++) {
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 16; xx += 2) {
+ lbuf[xx >> 1] += (sbuf[yy + yy2][xx] & 0x7fff);
+ mbuf[xx >> 1] |= (sbuf[yy + yy2][xx] & 0x8000);
+ }
+ }
+__DECL_VECTORIZED_LOOP
+ for(int xx = 0; xx < 8; xx++) {
+ lbuf[xx] = ((lbuf[xx] >> 2) & 0x7fff) | mbuf[xx];
+ }
+ if(d_vram != NULL) {
+ d_vram->write_sprite_data(x, y + (yy >>1), xoffset, yoffset, lbuf, 8);
+ }
+ }
+ }
+ now_transferring = false;
+
+}
+
+#endif
// Q: Does split rendering per vline?
-void TOWNS_SPRITE::render(uint16_t *buffer, uint16_t* mask)
+void TOWNS_SPRITE::render_full()
{
// ToDo: Implement Register #2-5
uint16_t lot = reg_index & 0x3ff;
if(lot == 0) lot = 1024;
+
// Clear buffer?
- if((buffer == NULL) || (mask == NULL)) return;
//memset(buffer, 0x00, 256 * 256 * sizeof(uint16_t));
//memset(mask, 0x00, 256 * 256 * sizeof(uint16_t));
// ToDo: Implement registers.
if(reg_spen) {
- for(render_num = 0; render_num < (int)lot; render_num++) {
- uint16_t* index_base = &(index_ram[render_num << 2]);
- uint16_t xaddr = index_base[0] & 0x1ff;
- uint16_t yaddr = index_base[1] & 0x1ff;
+ if((frame_sprite_count >= max_sprite_per_frame) && (max_sprite_per_frame > 0)) return;
+ for(; render_num < (int)lot; render_num++) {
+
+ uint32_t addr = render_num << 3;
+ pair16_t _nx, _ny, _nattr, _ny;
+ _nx.b.l = pattern_ram[addr + 0];
+ _nx.b.h = pattern_ram[addr + 1];
+ _ny.b.l = pattern_ram[addr + 2];
+ _ny.b.h = pattern_ram[addr + 3];
+ _nattr.b.l = pattern_ram[addr + 4];
+ _nattr.b.h = pattern_ram[addr + 5];
+ _ncol.b.l = pattern_ram[addr + 6];
+ _ncol.b.h = pattern_ram[addr + 7];
+
+ int xaddr = _nx.w & 0x1ff;
+ int yaddr = _ny.w & 0x1ff;
// ToDo: wrap round.This is still bogus implement.
- render_sprite(render_num, buffer, mask, (int)xaddr, (int)yaddr);
+ render_sprite(render_num, xaddr, yaddr, _nattr.w, _ncol.w);
+ frame_sprite_count++;
+ if((frame_sprite_count >= max_sprite_per_frame) && (max_sprite_per_frame > 0)) break;
}
}
}
-void TOWNS_SPRITE::render_part(uint16_t *buffer, uint16_t* mask, int start, int end)
+void TOWNS_SPRITE::render_part(int start, int end)
{
// ToDo: Implement Register #2-5
uint16_t lot = reg_index & 0x3ff;
if((start < 0) || (end < 0)) return;
if(end > lot) end = lot;
if(start > end) return;
- // Clear buffer?
- if((buffer == NULL) || (mask == NULL)) return;
// ToDo: Implement registers.
if(reg_spen) {
+ if((frame_sprite_count >= max_sprite_per_frame) && (max_sprite_per_frame > 0)) return;
for(render_num = start; render_num < end; render_num++) {
- uint16_t* index_base = &(index_ram[render_num << 2]);
- uint16_t xaddr = index_base[0] & 0x1ff;
- uint16_t yaddr = index_base[1] & 0x1ff;
+ uint32_t addr = render_num << 3;
+ pair16_t _nx, _ny, _nattr, _ny;
+ _nx.b.l = pattern_ram[addr + 0];
+ _nx.b.h = pattern_ram[addr + 1];
+ _ny.b.l = pattern_ram[addr + 2];
+ _ny.b.h = pattern_ram[addr + 3];
+ _nattr.b.l = pattern_ram[addr + 4];
+ _nattr.b.h = pattern_ram[addr + 5];
+ _ncol.b.l = pattern_ram[addr + 6];
+ _ncol.b.h = pattern_ram[addr + 7];
+
+ int xaddr = _nx.w & 0x1ff;
+ int yaddr = _ny.w & 0x1ff;
+ // ToDo: wrap round.This is still bogus implement.
// ToDo: wrap round.This is still bogus implement.
- render_sprite(render_num, buffer, mask, (int)xaddr, (int)yaddr);
+ render_sprite(render_num, xaddr, yaddr, _nattr.w, _ncol.w);
+ frame_sprite_count++;
+ if((frame_sprite_count >= max_sprite_per_frame) && (max_sprite_per_frame > 0)) break;
}
}
}
reg_voffset = ((uint16_t)(reg_data[4]) + (((uint16_t)(reg_data[5] & 0x01)) << 8));
break;
case 6:
- disp_page0 = ((data & 0x01) != 0) ? true : false;
- disp_page1 = ((data & 0x10) != 0) ? true : false;
+ if(!(now_transferring)) {
+ disp_page0 = ((data & 0x01) != 0) ? true : false;
+ disp_page1 = ((data & 0x10) != 0) ? true : false;
+ if(d_vram != NULL) {
+ d_vram->write_signal(SIG_TOWNS_VRAM_DP0, (disp_page0) ? 0xffffffff : 0 , 0xffffffff);
+ d_vram->write_signal(SIG_TOWNS_VRAM_DP1, (disp_page1) ? 0xffffffff : 0 , 0xffffffff);
+ }
+ }
break;
default:
break;
uint32_t TOWNS_SPRITE::read_data8(uint32_t addr)
{
+ return pattern_ram[addr & 0x1ffff];
+}
+
+uint32_t TOWNS_SPRITE::read_data16(uint32_t addr)
+{
+ pair16_t tval;
+ tval.b.l = pattern_ram[addr & 0x1ffff];
+ tval.b.h = pattern_ram[(addr + 1) & 0x1ffff];
+ return (uint32_t)(tval.w);
+}
+
+uint32_t TOWNS_SPRITE::read_data32(uint32_t addr)
+{
+ pair32_t tval;
+ tval.b.l = pattern_ram[addr & 0x1ffff];
+ tval.b.h = pattern_ram[(addr + 1) & 0x1ffff];
+ tval.b.h2 = pattern_ram[(addr + 2) & 0x1ffff];
+ tval.b.h3 = pattern_ram[(addr + 3) & 0x1ffff];
+ return (uint32_t)(tval.d);
+}
+
+void TOWNS_SPRITE::write_data8(uint32_t addr, uint32_t data)
+{
uint32_t nbank;
- uint8_t* p8;
- uint16_t val;
- pair_t tval;
if((addr >= 0x81000000) && (addr < 0x81020000)) {
nbank = (addr & 0x1e000) >> 12;
} else {
nbank = 0; // OK?
}
+
switch(nbank) {
case 0:
case 1:
- tval.w.l = index_ram[(addr & 0x1ffe) >> 1];
- if((addr & 1) == 0) { // Lo
- val = (uint16_t)(tval.b.l);
- } else {
- val = (uint16_t)(tval.b.h);
- }
+ // ToDO: Discard cache
+ pattern_ram[addr & 0x1fff] = data;
break;
case 2:
case 3:
- tval.w.l = color_ram[(addr & 0x1ffe) >> 1];
- if((addr & 1) == 0) { // Lo
- val = (uint16_t)(tval.b.l);
- } else {
- val = (uint16_t)(tval.b.h);
- }
+ // ToDO: Discard cache
+ pattern_ram[(addr & 0x1fff) + 0x2000] = data;
break;
default:
- p8 = &(pattern_ram[(addr & 0x1fffe) - 0x4000]);
- if((addr & 1) == 0) { // Lo
- val = p8[0];
- } else {
- val = p8[1];
- }
+ // ToDO: Discard cache
+ pattern_ram[addr & 0x1ffff] = data;
break;
}
- return (uint32_t)val;
+ return;
}
-
-uint32_t TOWNS_SPRITE::read_data16(uint32_t addr)
+void TOWNS_SPRITE::write_data16(uint32_t addr, uint32_t data)
{
+ pair16_t t;
uint32_t nbank;
- uint8_t* p8;
- pair_t tval;
- uint16_t val;
if((addr >= 0x81000000) && (addr < 0x81020000)) {
nbank = (addr & 0x1e000) >> 12;
} else {
nbank = 0; // OK?
}
+
+ t.w = (uint16_t)data;
+
switch(nbank) {
case 0:
case 1:
- val = (uint32_t)(index_ram[(addr & 0x1ffe) >> 1]);
+ // ToDO: Discard cache
+ pattern_ram[(addr + 0) & 0x1fff] = t.b.l;
+ pattern_ram[(addr + 1) & 0x1fff] = t.b.h;
break;
case 2:
case 3:
- val = (uint32_t)(color_ram[(addr & 0x1ffe) >> 1]);
+ // ToDO: Discard cache
+ pattern_ram[((addr + 0) & 0x1fff) + 0x2000] = t.b.l;
+ pattern_ram[((addr + 1) & 0x1fff) + 0x2000] = t.b.h;
break;
default:
- p8 = &(pattern_ram[(addr & 0x1fffe) - 0x4000]);
- tval.b.l = p8[0];
- tval.b.h = p8[1];
- val = (uint32_t)(tval.w.l);
+ // ToDO: Discard cache
+ pattern_ram[(addr + 0) & 0x1ffff] = t.b.l;
+ pattern_ram[(addr + 1) & 0x1ffff] = t.b.h;
break;
}
- return (uint32_t)val;
-}
-
-uint32_t TOWNS_SPRITE::read_data32(uint32_t addr)
-{
- uint32_t hi, lo = 0;
- lo = read_data16(addr);
- if(addr < 0x8101fffe) hi = read_data16(addr + 2);
- return ((hi << 16) & 0xffff0000) | (lo & 0x0000ffff);
+ return;
}
-
-void TOWNS_SPRITE::write_data8(uint32_t addr, uint32_t data)
+
+void TOWNS_SPRITE::write_data32(uint32_t addr, uint32_t data)
{
+ pair32_t t;
uint32_t nbank;
- uint32_t uaddr;
- uint16_t tmp16;
- uint8_t tmp8;
- uint8_t* p8;
- pair_t tval;
if((addr >= 0x81000000) && (addr < 0x81020000)) {
nbank = (addr & 0x1e000) >> 12;
} else {
nbank = 0; // OK?
}
+
+ t.d = data;
switch(nbank) {
case 0:
case 1:
- uaddr = (addr & 0x1ffe) >> 1;
- tval.w.l = index_ram[uaddr];
- tmp16 = tval.w.l;
- if((addr & 1) == 0) { // Lo
- tval.b.l = (uint8_t)(data & 0xff);
- } else {
- tval.b.h = (uint8_t)(data & 0xff);
- }
- if(use_cache) {
- if(uaddr == 2) { // ATTR
- if((tmp16 & 0x7c00) != (tval.w.l & 0x7c00)) {
- // Search cache and Discard cache
- }
- } else if(uaddr == 3) {
- if((tmp16 & 0x8fff) != (tval.w.l & 0x8fff)) {
- // Search cache and Discard cache
- }
- }
- }
- index_ram[uaddr] = tval.w.l;
+ // ToDO: Discard cache
+ pattern_ram[(addr + 0) & 0x1fff] = t.b.l;
+ pattern_ram[(addr + 1) & 0x1fff] = t.b.h;
+ pattern_ram[(addr + 2) & 0x1fff] = t.b.h2;
+ pattern_ram[(addr + 3) & 0x1fff] = t.b.h3;
break;
case 2:
case 3:
// ToDO: Discard cache
- uaddr = (addr & 0x1ffe) >> 1;
- tval.w.l = color_ram[uaddr];
- tmp16 = tval.w.l;
- if((addr & 1) == 0) { // Lo
- tval.b.l = (uint8_t)(data & 0xff);
- } else {
- tval.b.h = (uint8_t)(data & 0xff);
- }
- if(use_cache) {
- if(tmp16 != tval.w.l) { // Dirty color table
- uint32_t nnum = uaddr >> 4;
- color_ram[uaddr] = tval.w.l;
- if(color_cached[nnum]) {
- for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) {
- if(cache_index[i].color == (uint16_t)(nnum + 256)) {
- if((cache_index[i].is_use) && !(cache_index[i].is_32768)) {
- clear_cache(i);
- }
- }
- }
- color_cached[nnum] = false;
-
- }
- } else {
- color_ram[uaddr] = tval.w.l;
- }
- break;
- default:
- // ToDO: Discard cache
- uaddr = (addr & 0x1ffff) - 0x4000;
- p8 = &(pattern_ram[uaddr]);
- tmp8 = *p8;
- if(use_cache) {
- if((uint8_t)(data & 0xff) != tmp8) { // Dirty pattern memory.
- *p8 = (uint8_t)(data & 0xff);
- uint32_t nnum = uaddr >> 7;
- uint32_t nnum_bak = nnum;
- if(pattern_cached[nnum]) { // ToDo: Search another number.
- for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) {
- if(cache_index[i].is_32768) {
- if(cache_index[i].num == (uint16_t)nnum) {
- if(cache_index[i].is_use) {
- clear_cache(i);
- }
- }
- } else {
- uint32_t begin;
- uint32_t end;
- uint32_t clen = 0;
- // OK?
- begin = (nnum <= (128 + 3)) ? (128 + 3) : nnum - 3;
- end = (nnum <= 128) ? 128 : nnum + 3;
- if(begin < 1024) {
- if(end > 1023) end = 1023;
- if((cache_index[i].num >= begin) && (cache_index[i].num <= end)) {
- clen = end - begin + 1;
- for(uint32_t j = 0; j < clen; j++) {
- if(cache_index[i].num == (uint16_t)(begin + j)) {
- if(cache_index[i].is_use) {
- clear_cache(i);
- }
- }
- }
- }
- }
- }
- }
- pattern_cached[nnum] = false;
- }
-
- }
- } else {
- *p8 = (uint8_t)(data & 0xff);
- }
- }
+ pattern_ram[((addr + 0) & 0x1fff) + 0x2000] = t.b.l;
+ pattern_ram[((addr + 1) & 0x1fff) + 0x2000] = t.b.h;
+ pattern_ram[((addr + 2) & 0x1fff) + 0x2000] = t.b.h2;
+ pattern_ram[((addr + 3) & 0x1fff) + 0x2000] = t.b.h3;
+ break;
+ default:
+ // ToDO: Discard cache
+ pattern_ram[(addr + 0) & 0x1ffff] = t.b.l;
+ pattern_ram[(addr + 1) & 0x1ffff] = t.b.h;
+ pattern_ram[(addr + 2) & 0x1ffff] = t.b.h2;
+ pattern_ram[(addr + 3) & 0x1ffff] = t.b.h3;
break;
}
return;
}
-void TOWNS_SPRITE::write_data16(uint32_t addr, uint32_t data)
-{
- pair_t t;
- t.d = data;
- write_data8(addr, (uint32_t)(t.b.l));
- write_data8(addr + 1, (uint32_t)(t.b.h));
-}
-
-void TOWNS_SPRITE::write_data32(uint32_t addr, uint32_t data)
-{
- pair_t t;
- t.d = data;
- write_data8(addr, (uint32_t)(t.b.l));
- write_data8(addr + 1, (uint32_t)(t.b.h));
- if(addr < 0x8101fffe) {
- write_data8(addr + 2, (uint32_t)(t.b.h2));
- write_data8(addr + 3, (uint32_t)(t.b.h3));
- }
-}
void FMTOWNS_SPRITE::event_frame()
{
- write_page = display_page & 1;
- display_page = (displae_page + 1) & 1;
- render_num = 0;
- render_mod = 0;
- render_lines = 0;
-
- // Set split_rendering from DIPSW.
- // Set cache_enabled from DIPSW.
- if(vram_head != NULL) {
- vram_buffer = vram_head->get_vram_buffer_sprite(write_page);
- mask_buffer = vram_head->get_mask_buffer_sprite(write_page);
- render_lines = vram_head->get_sprite_display_lines();
+ uint16_t lot = reg_index & 0x3ff;
+ if(reg_spen && !(sprite_enabled)) {
+ sprite_enabled = true;
+ render_num = 0;
+ }
+ if(lot == 0) lot = 1024;
+ frame_sprite_count = 0;
+ if(sprite_enabled){
+ if(d_vram != NULL) {
+ if(d_vram->read_signal(SIG_TOWNS_VRAM_FRAMEBUFFER_READY) != 0) {
+ if(render_num >= lot) {
+ d_vram->write_signal(SIG_TOWNS_VRAM_SWAP_FRAMEBUFFER, 0xffffffff, 0xffffffff);
+ render_num = 0;
+ render_mod = 0;
+ }
+ // Set split_rendering from DIPSW.
+ // Set cache_enabled from DIPSW.
+ if(!split_rendering) {
+ render_full();
+ }
+ } else {
+ render_num = 0;
+ render_mod = 0;
+ sprite_enabled = false;
+ }
+ } else {
+ render_num = 0;
+ render_mod = 0;
+ sprite_enabled = false;
+ }
}
- memset(vram_buffer, 0x00, w * h * sizeof(uint16_t));
- memset(vram_mask, 0x00, w * h * sizeof(uint16_t));
- if(!split_rendering) render(vram_buffer, mask_buffer);
}
-void FMTOWNS_SPRITE::event_vline(int v, int clock)
+void FMTOWNS_SPRITE::do_vline_hook(int line)
{
int lot = reg_index & 0x3ff;
if(!split_rendering) return;
if(lot == 0) lot = 1024;
+ if((max_sprite_per_frame > 0) && (max_sprite_per_frame < lot)) lot = max_sprite_per_frame;
+
if((sprite_enabled) && (render_lines > 0)) {
int nf = lot / render_lines;
int nm = lot % render_lines;
nf++;
render_mod -= render_lines;
}
- if((nf > 1) && (render_num < lot)) render_part(vram_buffer, mask_buffer, render_num, render_num + nf);
+ if((nf >= 1) && (render_num < lot)) render_part(render_num, render_num + nf);
}
}
// Q: Is changing pages syncing to Frame?
// ToDo: Implement VRAM.
void FMTOWNS_SPRITE::write_signal(int id, uint32_t data, uint32_t mask)
{
- if(id == SIG_FMTOWNS_SPRITE_CACHE_ENABLE) {
- cache_enabled = ((data & mask) != 0);
- } else if(id == SIG_FMTOWNS_SPRITE_SWAP_BUFFER) {
- write_page = display_page & 1;
- display_page = (displae_page + 1) & 1;
+ if(id == SIG_TOWNS_SPRITE_HOOK_VLINE) {
+ int line = data & 0x1ff;
+ do_vline_hook(line);
+ } else if(id == SIG_TOWNS_SPRITE_SET_LINES) {
+ int line = data & 0x7ff; // 2048 - 1
+ render_lines = line;
}
-
}
-#define STATE_VERSION 1
-
-#include "../../statesub.h"
-void TOWNS_SPRITE::decl_state()
+#define STATE_VERSION 1
+bool TOWNS_SPRITE::process_state(FILEIO* state_fio, bool loading)
{
- enter_decl_state(STATE_VERSION);
-
- DECL_STATE_ENTRY_UINT8(reg_addr);
- DECL_STATE_ENTRY_1D_ARRAY(reg_data, 8);
-
- DECL_STATE_ENTRY_BOOL(reg_spen);
- DECL_STATE_ENTRY_UINT16(reg_index);
- DECL_STATE_ENTRY_UINT16(reg_voffset);
- DECL_STATE_ENTRY_UINT16(reg_hoffset);
- DECL_STATE_ENTRY_BOOL(disp_page0);
- DECL_STATE_ENTRY_BOOL(disp_page1);
-
- DECL_STATE_ENTRY_BOOL(sprite_enabled);
- DECL_STATE_ENTRY_BOOL(use_cache);
- DECL_STATE_ENTRY_UINT8(write_page);
- DECL_STATE_ENTRY_UINT8(display_page);
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
- DECL_STATE_ENTRY_BOOL(split_rendering);
- DECL_STATE_ENTRY_INT32(render_num);
- DECL_STATE_ENTRY_INT32(render_mod);
- DECL_STATE_ENTRY_INT32(render_lines);
-
-
+ state_fio->StateValue(reg_addr);
+ state_fio->StateArray(reg_data, sizeof(reg_data), 1);
// RAMs
- DECL_STATE_ENTRY_1D_ARRAY(index_ram, sizeof(index_ram) / sizeof(uint16_t));
- DECL_STATE_ENTRY_1D_ARRAY(pattern_ram, sizeof(pattern_ram) / sizeof(uint8_t));
- DECL_STATE_ENTRY_1D_ARRAY(color_ram, sizeof(color_ram) / sizeof(uint16_t));
-
- // Q: Is save/load caches?
- // Flags around cache.
- DECL_STATE_ENTRY_1D_ARRAY(pattern_cached, (sizeof(pattern_cached) / sizeof(bool)));
- DECL_STATE_ENTRY_1D_ARRAY(color_cached, (sizeof(pattern_cached) / sizeof(bool)));
-
- // Around cache.
- DECL_STATE_ENTRY_INT32(last_put_cache_num);
+ state_fio->StateArray(pattern_ram, sizeof(pattern_ram), 1);
- DECL_STATE_ENTRY_2D_ARRAY(cache_pixels, TOWNS_SPRITE_CACHE_NUM, 16 * 16);
- DECL_STATE_ENTRY_2D_ARRAY(cache_masks, TOWNS_SPRITE_CACHE_NUM, 16 * 16);
+ state_fio->StateValue(reg_spen);
+ state_fio->StateValue(reg_index);
+ state_fio->StateValue(reg_voffset);
+ state_fio->StateValue(reg_hoffset);
+ state_fio->StateValue(disp_page0);
+ state_fio->StateValue(disp_page1);
+
+ state_fio->StateValue(sprite_enabled);
- DECL_STATE_ENTRY_BOOL_STRIDE((cache_index[0].is_use), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
- DECL_STATE_ENTRY_UINT16_STRIDE((cache_index[0].num), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
- DECL_STATE_ENTRY_UINT16_STRIDE((cache_index[0].attribute), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
- DECL_STATE_ENTRY_UINT8_STRIDE((cache_index[0].rotate_type), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
- DECL_STATE_ENTRY_BOOL_STRIDE((cache_index[0].is_32768), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
- DECL_STATE_ENTRY_BOOL_STRIDE((cache_index[0].is_halfx), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
- DECL_STATE_ENTRY_BOOL_STRIDE((cache_index[0].is_halfy), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
- DECL_STATE_ENTRY_UINT16_STRIDE((cache_index[0].color), TOWNS_SPRITE_CACHE_NUM, sizeof(sprite_cache_t));
+ state_fio->StateValue(render_num);
+ state_fio->StateValue(render_mod);
+ state_fio->StateValue(render_lines);
+ state_fio->StateValue(now_transferring);
- leave_decl_state();
-
-}
-bool TOWNS_SPRITE::save_state(FILEIO *state_fio)
-{
- if(state_entry != NULL) {
- state_entry->save_state(state_fio);
- }
-}
+ state_fio->StateValue(frame_sprite_count);
+ state_fio->StateValue(max_sprite_per_frame);
+
+ //state_fio->StateValue(split_rendering);
-bool TOWNS_SPRITE::load_state(FILEIO *state_fio)
-{
- bool mb = false;
- if(state_entry != NULL) {
- mb = state_entry->load_state(state_fio);
- this->out_debug_log(_T("Load State: SPRITE: id=%d stat=%s\n"), this_device_id, (mb) ? _T("OK") : _T("NG"));
- if(!mb) return false;
- }
- // Post Process
- build_sprite_table();
- // Render?
- if(vram_head != NULL) {
- write_page = vram_head->get_sprite_write_page();
- display_page = (write_page + 1) & 1;
- // Restore cache buffer.
- for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) {
- cache_index[i].pixels = &(cache_pixels[i][0]);
- cache_index[i].masks = &(cache_masks[i][0]);
- }
- vram_buffer = vram_head->get_vram_buffer_sprite(write_page);
- mask_buffer = vram_head->get_mask_buffer_sprite(write_page);
- render(vram_buffer, mask_buffer);
- }
return true;
}
-#ifndef _TOWNS_SPRITE_H_
-#define _TOWNS_SPRITE_H_
+#pragma once
#include "../vm.h"
#include "../../emu.h"
#include "../device.h"
-#define SIG_FMTOWNS_SPRITE_RENDER 256
-#define SIG_FMTOWNS_SPRITE_UPDATE_FRAMEBUFFER 257
-#define SIG_FMTOWNS_RENDER_SPRITE_CHANGE_BANK 258
-#define SIG_FMTOWNS_RENDER_SPRITE_ENABLED 259
-#define SIG_FMTOWNS_RENDER_SPRITE_RESET 260
-#define SIG_FMTOWNS_RENDER_SPRITE_SET_LIMIT 261
-#define SIG_FMTOWNS_RENDER_SPRITE_SET_NUM 262
-#define SIG_FMTOWNS_RENDER_SPRITE_CLEAR_VRAM 263
-
-
-namespace FMTOWNS {
- enum {
- ROT_FMTOWNS_SPRITE_0 = 0,
- ROT_FMTOWNS_SPRITE_90,
- ROT_FMTOWNS_SPRITE_180,
- ROT_FMTOWNS_SPRITE_270
- };
-}
-
-#define TOWNS_SPRITE_CACHE_NUM 512
-
-namespace FMTOWNS {
- typedef struct {
- uint16_t num;
- uint8_t rotate_type;
- uint16_t attribute;
- uint16_t color;
-
- bool is_halfx;
- bool is_halfy;
- bool enable_offset;
- bool is_32768;
- bool is_impose;
- bool is_disp;
- } sprite_table_t;
-
- typedef struct {
- bool is_use;
- uint16_t num;
- uint16_t attribute;
- uint8_t rotate_type;
- bool is_32768;
- bool is_halfx;
- bool is_halfy;
- uint16_t* pixels;
- uint16_t* masks;
- uint16_t color;
- } sprite_cache_t;
-}
+#define SIG_TOWNS_SPRITE_HOOK_VLINE 256
+#define SIG_TOWNS_SPRITE_SET_LINES 257
namespace FMTOWNS {
class TOWNS_VRAM;
{
protected:
- TOWNS_VRAM *vram_head;
- uint16_t* vram_buffer; // uint16_t[256][256]
- uint16_t* mask_buffer; // uint16_t[256][256]
+ TOWNS_VRAM *d_vram;
// REGISTERS
uint8_t reg_addr;
uint8_t reg_data[8];
// #0, #1
bool reg_spen;
uint16_t reg_index;
+ uint8_t pattern_ram[0x20000];
uint16_t reg_voffset;
uint16_t reg_hoffset;
bool disp_page0;
bool disp_page1;
- uint8_t display_page;
- uint8_t write_page;
+
+ bool now_transferring;
+
int render_num;
int render_mod;
int render_lines;
- bool split_rendering;
-
- uint16_t index_ram[4096]; // 1024 * 4
- uint16_t color_ram[4096]; // 16 * 256
- uint8_t pattern_ram[(65536 - (4096 * 2)) * 2];
-
- bool pattern_cached[((65536 - (4096 * 2)) * 2) / (8 * 16)];
- bool color_cached[256];
-
bool sprite_enabled;
- bool use_cache;
- int32_t last_put_cache_num;
- sprite_table_t sprite_table[1024];
- sprite_cache_t cache_index[TOWNS_SPRITE_CACHE_NUM];
- uint16_t cache_pixels[TOWNS_SPRITE_CACHE_NUM][16 * 16];
- uint16_t cache_masks[TOWNS_SPRITE_CACHE_NUM][16 * 16];
-
- inline void take_data_32768(uint16_t* src, uint16_t* dst, uint16_t* mask);
- inline void take_data_32768_mirror(uint16_t* src, uint16_t* dst, uint16_t* mask);
- inline void take_data_16(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask);
- inline void take_data_16_mirror(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask);
- inline void zoom_data(uint16_t* cache, uint16_t* maskcache, bool is_halfx, bool is_halfy, uint16_t* dstcache, uint16_t* dstmask);
-
- void rotate_data_0(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768, bool is_halfx, bool is_halfy);
- void rotate_data_90(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768, bool is_halfx, bool is_halfy);
- void rotate_data_180(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768, bool is_halfx, bool is_halfy);
- void rotate_data_270(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768, bool is_halfx, bool is_halfy);
+ bool split_rendering;
+ int max_sprite_per_frame;
- void clear_cache(int num);
- void build_sprite_table(void);
-
- void set_sprite_attribute(int table_num, uint16_t num_attr);
- void set_sprite_color(int table_num, uint16_t color_table_num);
- bool check_cache(int num, sprite_cache_t** p);
- void render_zoomed_pixels(int x, int y, int uint16_t* pixels, uint16_t* masks, bool is_halfx, bool is_halfy, uint16_t* dst_pixel, uint16_t* dst_mask);
- void render_sprite(int num, uint16* dst_pixel, uint16_t* dst_mask, int x, int y);
- void render(uint16_t *buffer, uint16_t* mask);
+ void __FASTCALL render_sprite(int num, int x, int y, uint16_t attr, uint16_t color);
+ void render_full();
+ void render_part(int start, int end);
+ void do_vline_hook(int line);
public:
- TOWNS_SPRITE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
+ TOWNS_SPRITE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ d_vram = NULL;
set_device_name(_T("SPRITE"));
- vram_head = NULL;
- framebuffer = NULL;
-
}
~TOWNS_SPRITE() {}
void write_signal(int id, uint32_t data, uint32_t mask);
void initialize();
void event_frame();
- void event_vline(int v, int clock);
+ bool process_state(FILEIO* state_fio, bool loading);
void set_context_vram(TOWNS_VRAM *p)
{
- vram_head = p;
+ d_vram = p;
}
- void save_state(FILEIO *fio);
- bool load_stste(FILEIO *fio);
};
-
-inline void TOWNS_SPRITE::take_data_32768(uint16_t* src, uint16_t* dst, uint16_t* mask)
-{
- uint16_t* p = src;
- uint16_t* q = dst;
- uint16_t* r = mask;
- for(int y = 0; y < 16; y++) {
- for(int x = 0; x < 16; x++) {
- q[x] = p[x];
- }
- for(int x = 0; x < 16; x++) {
- r[x] = ((q[x] & 0x8000) != 0) ? 0 : 0xffff;
- }
- r += 16;
- q += 16;
- p += 16;
- }
}
-
-inline void TOWNS_SPRITE::take_data_32768_mirror(uint16_t* src, uint16_t* dst, uint16_t* mask)
-{
- uint16_t* p = src;
- uint16_t* q = dst;
- uint16_t* r = mask;
- for(int y = 0; y < 16; y++) {
- for(int x = 0; x < 16; x++) {
- q[x] = p[15 - x];
- }
- for(int x = 0; x < 16; x++) {
- r[x] = ((q[x] & 0x8000) != 0) ? 0 : 0xffff;
- }
- r += 16;
- q += 16;
- p += 16;
- }
-}
-
-
-inline void TOWNS_SPRITE::take_data_16(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask)
-{
- uint8_t* p = src;
- uint16_t* q = dst;
- uint16_t* r = mask;
- uint8_t cache[16];
- for(int y = 0; y < 16; y++) {
- for(int x = 0; x < 16; x += 2) {
- cache[x] = p[x >> 1];
- cache[x + 1] = cache[x];
- }
- for(int x = 0; x < 16; x += 2) {
- cache[x] = cache[x] >> 4;
- }
- for(int x = 0; x < 16; x++) {
- cache[x] = cache[x] & 0x0f;
- r[x] = (cache[x] == 0) ? 0x0000 : 0xffff;
- q[x] = color_table[cache[x]];
- }
- r += 16;
- q += 16;
- p += 8;
- }
-}
-
-inline void TOWNS_SPRITE::take_data_16_mirror(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask)
-{
- uint8_t* p = src;
- uint16_t* q = dst;
- uint16_t* r = mask;
- uint8_t cache[16];
- for(int y = 0; y < 16; y++) {
- for(int x = 0; x < 16; x += 2) {
- cache[x] = p[(15 - x) >> 1];
- cache[x + 1] = cache[x];
- }
- for(int x = 1; x < 16; x += 2) {
- cache[x] = cache[x] >> 4;
- }
- for(int x = 0; x < 16; x++) {
- cache[x] = cache[x] & 0x0f;
- r[x] = (cache[x] == 0) ? 0x0000 : 0xffff;
- q[x] = color_table[cache[x]];
- }
- r += 16;
- q += 16;
- p += 8;
- }
-}
-
-
-void TOWNS_SPRITE::rotate_data_0(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768, bool is_halfx, bool is_halfy)
-{
- uint16_t cache[16 * 16];
- if(!is_32768) {
- if(is_mirror) {
- take_data_16_mirror(src, color_table, cache, mask);
- } else {
- take_data_16(src, color_table, cache, mask);
- }
-
- } else {
- if(is_mirror) {
- take_data_32768_mirror((uint16_t*)src, cache, mask);
- } else {
- take_data_16((uint16_t*)src, cache, mask);
- }
- }
- // Rotate
- // Zoom
- uint16_t maskcache[16 * 16];
- memcpy(maskcache, mask, sizeof(maskcache));
- zoom_data(cache, maskcache, is_halfx, is_halfy, dstcache, mask);
-}
-
-void TOWNS_SPRITE::rotate_data_90(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768, bool is_halfx, bool is_halfy)
-{
- uint16_t cache[16 * 16];
- if(!is_32768) {
- if(is_mirror) {
- take_data_16_mirror(src, color_table, cache, mask);
- } else {
- take_data_16(src, color_table, cache, mask);
- }
-
- } else {
- if(is_mirror) {
- take_data_32768_mirror((uint16_t*)src, cache, mask);
- } else {
- take_data_16((uint16_t*)src, cache, mask);
- }
- }
- // Rotate
- uint16_t maskcache[16][16];
- uint16_t cache2[16][16];
- if(is_mirror) {
- // q[x][y] = p[15 - y][15 - x]
-__DECL_VECTORIZED_LOOP
- for(y = 0; y < 16; y++) {
- uint16_t* p = &(cache[15 - y]);
- uint16_t* q = &(mask[15 - y]);
- for(x = 0; x < 16; x++) {
- cache2[y][x] = p[(15 - x) << 4];
- maskcache[y][x] = q[(15 - x) << 4];
- }
- }
- } else {
- // q[x][y] = p[15 - y][x]
- for(y = 0; y < 16; y++) {
- uint16_t* p = &(cache[15 - y]);
- uint16_t* q = &(mask[15 - y]);
-__DECL_VECTORIZED_LOOP
- for(x = 0; x < 16; x++) {
- cache2[y][x] = p[x << 4];
- maskcache[y][x] = q[x << 4];
- }
- }
- }
- zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
-}
-
-void TOWNS_SPRITE::rotate_data_180(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768, bool is_halfx, bool is_halfy)
-{
- uint16_t cache[16 * 16];
- if(!is_32768) {
- if(is_mirror) {
- take_data_16_mirror(src, color_table, cache, mask);
- } else {
- take_data_16(src, color_table, cache, mask);
- }
-
- } else {
- if(is_mirror) {
- take_data_32768_mirror((uint16_t*)src, cache, mask);
- } else {
- take_data_16((uint16_t*)src, cache, mask);
- }
- }
- // Rotate
- uint16_t maskcache[16][16];
- uint16_t cache2[16][16];
- if(is_mirror) {
- // q[x][y] = p[x][15 - y]
- for(y = 0; y < 16; y++) {
- uint16_t* p = &(cache[(15 - y) << 4]);
- uint16_t* q = &(mask[(15 - y) << 4]);
-__DECL_VECTORIZED_LOOP
- for(x = 0; x < 16; x++) {
- cache2[y][x] = p[x];
- maskcache[y][x] = q[x];
- }
- }
- } else {
- // q[x][y] = p[15 - x][15 - y]
- for(y = 0; y < 16; y++) {
- uint16_t* p = &(cache[15 - y] << 4);
- uint16_t* q = &(mask[15 - y] << 4);
-__DECL_VECTORIZED_LOOP
- for(x = 0; x < 16; x++) {
- cache2[y][x] = p[15 - x];
- maskcache[y][x] = q[15 - x];
- }
- }
- }
- zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
-}
-
-void TOWNS_SPRITE::rotate_data_270(uint16_t* src, bool is_mirror, uint16_t* color_table, uint16_t* dstcache, uint16_t* mask, bool is_32768,bool is_halfx, bool is_halfy)
-{
- uint16_t cache[16 * 16];
- if(!is_32768) {
- if(is_mirror) {
- take_data_16_mirror(src, color_table, cache, mask);
- } else {
- take_data_16(src, color_table, cache, mask);
- }
-
- } else {
- if(is_mirror) {
- take_data_32768_mirror((uint16_t*)src, cache, mask);
- } else {
- take_data_16((uint16_t*)src, cache, mask);
- }
- }
- // Rotate
- uint16_t maskcache[16][16];
- uint16_t cache2[16][16];
- if(is_mirror) {
- // q[x][y] = p[y][x]
-
- for(y = 0; y < 16; y++) {
- uint16_t* p = &(cache[y]);
- uint16_t* q = &(mask[y]);
-__DECL_VECTORIZED_LOOP
- for(x = 0; x < 16; x++) {
- cache2[y][x] = p[x << 4];
- maskcache[y][x] = q[x << 4];
- }
- }
- } else {
- // q[x][y] = p[y][15 - x]
- for(y = 0; y < 16; y++) {
- uint16_t* p = &(cache[15 - y]);
- uint16_t* q = &(mask[15 - y]);
-__DECL_VECTORIZED_LOOP
- for(x = 0; x < 16; x++) {
- cache2[y][x] = p[x << 4];
- maskcache[y][x] = q[x << 4];
- }
- }
- }
- zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
-}
-
-inline void TOWNS_SPRITE::zoom_data(uint16_t* cache, uint16_t* maskcache, bool is_halfx, bool is_halfy, uint16_t* dstcache, uint16_t* dstmask)
-{
- if(is_halfx) {
- if(is_halfy) {
- uint16_t cache2[8][8];
- uint16_t maskcache2[8][8];
- for(int y = 0; y < 16; y += 2) {
- uint16_t cacheline[8];
- uint16_t *pp = &(cache[y << 4]);
- uint16_t maskcacheline[8];
- uint16_t *pq = &(maskcache[y << 4]);
-__DECL_VECTORIZED_LOOP
- for(int x = 0; x < 8; x++) {
- cacheline[x] = pp[x << 1];
- maskcacheline[x] = pq[x << 1];
- }
-__DECL_VECTORIZED_LOOP
- for(int x = 0; x < 8; x++) {
- cache2[y >> 1][x] = cacheline[x];
- maskcache2[y >> 1][x] = maskcacheline[x];
- }
- }
- memcpy(dstcache, &(cache2[0][0]), 8 * 8 * sizeof(uint16_t));
- memcpy(dstmask, &(maskcache2[0][0]), 8 * 8 * sizeof(uint16_t));
- } else { // halfx only, not halfy
- uint16_t cache2[16][8];
- uint16_t maskcache2[16][8];
- for(int y = 0; y < 16; y++) {
- uint16_t cacheline[8];
- uint16_t *pp = &(cache[y << 4]);
- uint16_t maskcacheline[8];
- uint16_t *pq = &(maskcache[y << 4]);
-__DECL_VECTORIZED_LOOP
- for(int x = 0; x < 8; x++) {
- cacheline[x] = pp[x << 1];
- maskcacheline[x] = pq[x << 1];
- }
-__DECL_VECTORIZED_LOOP
- for(int x = 0; x < 8; x++) {
- cache2[y][x] = cacheline[x];
- maskcache2[y][x] = maskcacheline[x];
- }
- }
- memcpy(dstcache, &(cache2[0][0]), 16 * 8 * sizeof(uint16_t));
- memcpy(mask, &(maskcache2[0][0]), 16 * 8 * sizeof(uint16_t));
- }
- } else {
- if(is_halfy) { // halfx only, not halfx
- uint16_t cache2[16][8];
- uint16_t maskcache2[16][8];
- for(int y = 0; y < 16; y += 2) {
- uint16_t cacheline[16];
- uint16_t *pp = &(cache[y << 4]);
- uint16_t maskcacheline[16];
- uint16_t *pq = &(maskcache[y << 4]);
-__DECL_VECTORIZED_LOOP
- for(int x = 0; x < 16; x++) {
- cacheline[x] = pp[x];
- maskcacheline[x] = pq[x];
- }
-__DECL_VECTORIZED_LOOP
- for(int x = 0; x < 16; x++) {
- cache2[y >> 1][x] = cacheline[x];
- maskcache2[y >> 1][x] = maskcacheline[x];
- }
- }
- memcpy(dstcache, &(cache2[0][0]), 8 * 16 * sizeof(uint16_t));
- memcpy(dstmask, &(maskcache2[0][0]), 8 * 16 * sizeof(uint16_t));
- } else { // 1x1
- memcpy(dstcache, cache, 16 * 16 * sizeof(uint16_t));
- memcpy(dstmask, maskcache, 16 * 16 * sizeof(uint16_t));
- }
- }
-}
-}
-
-#endif /* _TOWNS_SPRITE_H */