From 9c3f13a8b9c9b51e247e35047ac76410a0f72d66 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Mon, 24 Sep 2018 05:02:54 +0900 Subject: [PATCH] [VM][FMTOWNS][WIP] Implementing.Still WIP. --- source/src/vm/fmtowns/towns_sprite.cpp | 442 ++++++---- source/src/vm/fmtowns/towns_sprite.h | 1464 ++++++-------------------------- 2 files changed, 539 insertions(+), 1367 deletions(-) diff --git a/source/src/vm/fmtowns/towns_sprite.cpp b/source/src/vm/fmtowns/towns_sprite.cpp index b27495e66..e3b0a9156 100644 --- a/source/src/vm/fmtowns/towns_sprite.cpp +++ b/source/src/vm/fmtowns/towns_sprite.cpp @@ -35,6 +35,7 @@ void TOWNS_SPRITE::initialize(void) for(int i = 0; i < 256; i++) { color_cached[i] = false; } + use_cache = false; // ToDo: Enable cache. } void TOWNS_SPRITE::reset() @@ -66,6 +67,7 @@ void TOWNS_SPRITE::set_sprite_attribute(int table_num, uint16_t num_attr) 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; @@ -83,124 +85,26 @@ void TOWNS_SPRITE::set_sprite_color(int table_num, uint16_t color_table_num) sprite_table[table_num].is_disp = ((color_table_num & 0x2000) != 0); } -void TOWNS_SPRITE::render_not_rotate(int num, uint16* dst_pixel, int width, int height, int stride) -{ - uint16_t* qp = (uint16_t*)(sprite_table[num].pixels); - uint8_t* addr; - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - if(sprite_table[num].is_32768) { - } else { - addr = &(pattern_ram[(sprite_table[num].num - 128) << 3]); - int ystep = (cache_index[num].is_halfy) ? 2 : 1; - int xstep = (cache_index[num].is_halfx) ? 2 : 1; - int w = (cache_index[num].is_halfy) ? 8 : 16; - int h = (cache_index[num].is_halfx) ? 8 : 16; - int color = sprite_table[num].color; - if(color < 256) return; - if(color > 511) return; - color = color - 256; - uint16_t* p; - uint16_t* m; - uint16_t* q; - uint16_t* dp; - int yy = 0; - uint8_t pixels[16]; - uint8_t pixels_lo[16]; - uint8_t pixels_hi[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t t2pixels[16]; - uint16_t* color_index = (uint16_t*)(&color_index_ram[color << 5]); - for(int y = 0; y < 16; y += ystep) { - p = &(cache_pixel[yy << 4]); - m = &(cache_mask[yy << 4]); - q = (uint8_t*)qp; - q = &q[y << 3]; - dp = &(dst_pixel[yy * stride]); - if(cache_index[num].is_halfx) { - for(int x = 0; x < 8; x++) { - pixels[x] = q[x]; - } - for(int x = 0; x < 8; x++) { - pixels[x] = pixels[x] & 0xf0; - } - - for(int x = 0; x < 8; x++) { - masks[x] = (pixels[x] == 0) ? 0xffff : 0x0000; - } - for(int x = 0; x < 8; x++) { - p[x] = color_index[pixels[x]]; - } - for(int x = 0; x < 8; x++) { - m[x] = masks[x]; - } - // Draw to buffer - for(int x = 0; x < 8; x++) { - tpixels[x] = dp[x] & masks[x]; - } - for(int x = 0; x < 8; x++) { - pixels[x] = p[x] & ~masks[x]; - } - for(int x = 0; x < 8; x++) { - dp[x] = pixels[x] | tpixels[x]; - } - } else { - for(int x = 0; x < 8; x++) { - pixels[x] = q[x]; - } - for(int x = 0; x < 8; x++) { - pixels_hi[x] = pixels[x] & 0xf0; - } - for(int x = 0; x < 8; x++) { - pixels_lo[x] = pixels[x] & 0x0f; - } - - for(int x = 0; x < 8; x++) { - masks[x << 1] = (pixels_hi[x] == 0) ? 0xffff : 0x0000; - } - for(int x = 0; x < 8; x++) { - masks[(x << 1) + 1] = (pixels_lo[x] == 0) ? 0xffff : 0x0000; - } - for(int x = 0; x < 8; x++) { - p[x << 1] = color_index[pixels_hi[x]]; - p[(x << 1) + 1] = color_index[pixels_lo[x]]; - } - for(int x = 0; x < 16; x++) { - m[x] = masks[x]; - } - // Draw to buffer - for(int x = 0; x < 16; x++) { - tpixels[x] = dp[x] & masks[x]; - } - for(int x = 0; x < 16; x++) { - t2pixels[x] = p[x] & ~masks[x]; - } - for(int x = 0; x < 16; x++) { - dp[x] = t2pixels[x] | tpixels[x]; - } - } - yy++; - } - } -} - void TOWNS_SPRITE::render_sprite(int num, uint16* dst_pixel, int width, int height, int stride) { + uint16_t sprite_limit = reg_index & 0x3ff; + if(sprite_limit == 0) sprite_limit = 1024; if(num < 0) return; if(num >= sprite_limit) return; if(num >= 1024) return; if(stride <= 0) return; if(stride > 512) return; if(!(sprite_table[num].is_disp)) return; - + + if(use_cache) { for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) { if(!(cache_index[i].is_use)) continue; if(cache_index[i].attribute == sprite_table[num].attribute) { if(cache_index[i].is_32768 == sprite_table[num].is_32768) { if(cache_index[i].is_32768) { // + // ToDo: Integrate to not hitting cache. int h = (cache_index[i].is_halfy) ? 8 : 16; int w = (cache_index[i].is_halfx) ? 8 : 16; if(height < h) h = height; @@ -246,6 +150,7 @@ void TOWNS_SPRITE::render_sprite(int num, uint16* dst_pixel, int width, int heig uint16_t* rp = &qp[y << 4]; uint16_t* rm = &qm[y << 4]; ppp = pp; +__DECL_VECTORIZED_LOOP for(x = 0; x < w; x++) { uint16_t pixel = *rp; uint16_t dpixel = *ppp; @@ -262,6 +167,7 @@ void TOWNS_SPRITE::render_sprite(int num, uint16* dst_pixel, int width, int heig } } } + } // Cache Not hit int target_num = -1; for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) { @@ -284,12 +190,158 @@ void TOWNS_SPRITE::render_sprite(int num, uint16* dst_pixel, int width, int heig cache_index[target_num].masks = (uint16_t*)(&(cache_masks[target_num][0])); cache_index[target_num].color = sprite_table[num].color; cache_index[target_num].num = sprite_table[num].num; - color_cached[(cache_index[target_num].color) & 0xff] = true; + if(!(cache_index[target_num].is_32768)) { + color_cached[(cache_index[target_num].color) & 0xff] = true; + } pattern_cached[sprite_table[num].num] = true; // OK? - render_base(num, dst_pixel, width, height, stride); + switch((sprite_table[num].rotate) & 7) { + case 0: + rot_type = ROT_FMTOWNS_SPRITE_0; + is_mirror = false; + break; + case 1: + rot_type = ROT_FMTOWNS_SPRITE_180; + is_mirror = true; + break; + case 2: + rot_type = ROT_FMTOWNS_SPRITE_180; + is_mirror = false; + break; + case 3: + rot_type = ROT_FMTOWNS_SPRITE_0; + is_mirror = true; + break; + case 4: + rot_type = ROT_FMTOWNS_SPRITE_270; + is_mirror = true; + break; + case 5: + rot_type = ROT_FMTOWNS_SPRITE_90; + is_mirror = false; + break; + case 6: + rotate = false; + rot_type = ROT_FMTOWNS_SPRITE_270; + is_mirror = false; + break; + case 7: + rot_type = ROT_FMTOWNS_SPRITE_90; + is_mirror = true; + break; + } + uint32_t index_num = cache_index[target_num].attribute & 0x3ff; + if(index_num < 128) return; + + uint8_t* src = &(pattern_ram[index_num << 7]); + bool is_32768 = cache_index[target_num].is_32768; + bool is_halfx = cache_index[target_num].is_halfx; + bool is_halfy = cache_index[target_num].is_halfy; + + switch(rot_type) { + case ROT_FMTOWNS_SPRITE_00: + rot_data_0(src, is_mirror, cache_index[target_num].pixels, cache_index[target_num].masks, is_32768, is_halfx, is_halfy); + break; + case ROT_FMTOWNS_SPRITE_90: + rot_data_0(src, is_mirror, cache_index[target_num].pixels, cache_index[target_num].masks, is_32768, is_halfx, is_halfy); + break; + case ROT_FMTOWNS_SPRITE_180: + rot_data_0(src, is_mirror, cache_index[target_num].pixels, cache_index[target_num].masks, is_32768, is_halfx, is_halfy); + break; + case ROT_FMTOWNS_SPRITE_270: + rot_data_0(src, is_mirror, cache_index[target_num].pixels, cache_index[target_num].masks, is_32768, is_halfx, is_halfy); + break; + } + // ToDo: wrap round.This is still bogus implement. + // ToDo: Separate writing buffer and integrate cache. + // copy cache to buffer + uint16_t* pp = cache_index[target_num].pixels; + uint16_t* pq = cache_index[target_num].masks; + uint16_t* pd = dst_pixel; + if(is_halfx) { + uint16_t cacheline[8]; + uint16_t mcacheline[8]; + uint16_t pcacheline[8]; + int ysize = 16; + if(is_halfy) { + ysize = 8; + } + for(int y = 0; y < ysize; y++) { +__DECL_VECTORIZED_LOOP + for(int x = 0; x < 8; x++) { + cacheline[x] = pp[x]; + mcacheline[x] = pq[x]; + } +__DECL_VECTORIZED_LOOP + for(int x = 0; x < 8; x++) { + pcacheline[x] = pd[x] & mcacheline[x]; + mcacheline[x] = ~mcacheline[x]; + cacheline[x] = cacheline[x] & mcacheline[x]; + } +__DECL_VECTORIZED_LOOP + for(int x = 0; x < 8; x++) { + pd[x] = pcacheline[x] | mcacheline[x]; + } + pd = pd + stride; + pp += 8; + pq += 8; + } + } else { // Not halfx + uint16_t cacheline[16]; + uint16_t mcacheline[16]; + uint16_t pcacheline[16]; + int ysize = 16; + if(is_halfy) { + ysize = 8; + } + for(int y = 0; y < ysize; y++) { +__DECL_VECTORIZED_LOOP + for(int x = 0; x < 16; x++) { + cacheline[x] = pp[x]; + mcacheline[x] = pq[x]; + } +__DECL_VECTORIZED_LOOP + for(int x = 0; x < 16; x++) { + pcacheline[x] = pd[x] & mcacheline[x]; + mcacheline[x] = ~mcacheline[x]; + cacheline[x] = cacheline[x] & mcacheline[x]; + } +__DECL_VECTORIZED_LOOP + for(int x = 0; x < 16; x++) { + pd[x] = pcacheline[x] | mcacheline[x]; + } + pd = pd + stride; + pp += 8; + pq += 8; + } + } } +void TOWNS_SPRITE::render(uint16_t *buffer, int w, int h, int stride) +{ + // ToDo: Implement Register #2-5 + uint16_t lot = reg_index & 0x3ff; + if(lot == 0) lot = 1024; + if((w <= 0) || (h <= 0)) return; + if(stride <= 0) return; + // Clear buffer? + memset(buffer, 0x00, w * h * sizeof(uint16_t)); + + if(reg_spen) { + for(int i = 0; i < (int)lot; i++) { + uint16_t* index_base = &(index_ram[i << 2]); + uint16_t xaddr = index_base[0] & 0x1ff; + uint16_t yaddr = index_base[1] & 0x1ff; + if((xaddr < (uint16_t)w) && (yaddr < (uint16_t)h)) { + // ToDo: wrap round.This is still bogus implement. + uint16_t* addr = &(buffer[yaddr * w + xaddr]); + render_sprite(i, addr, width, height, stride); + } + } + } +} +// ToDo: Discard cache(s) if dirty color index and if used this cache at 16 colors. +// ToDo: Discard cache(s) if dirty void TOWNS_SPRITE::write_io8(uint32_t addr, uint32_t data) { reg_addr = addr & 7; @@ -440,6 +492,9 @@ uint32_t TOWNS_SPRITE::read_data32(uint32_t addr) void TOWNS_SPRITE::write_data8(uint32_t addr, uint32_t data) { uint32_t nbank; + uint32_t uaddr; + uint16_t tmp16; + uint8_t tmp8; uint8_t* p8; pair_t tval; if((addr >= 0x81000000) && (addr < 0x81020000)) { @@ -447,54 +502,107 @@ void TOWNS_SPRITE::write_data8(uint32_t addr, uint32_t data) } else { nbank = 0; // OK? } + switch(nbank) { case 0: case 1: - tval.w.l = index_ram[(addr & 0x1ffe) >> 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); } - index_ram[(addr & 0x1ffe) >> 1] = tval.w.l; + 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; break; case 2: case 3: // ToDO: Discard cache - tval.w.l = color_ram[(addr & 0x1ffe) >> 1]; + 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); } - color_ram[(addr & 0x1ffe) >> 1] = tval.w.l; - if(color_cached[(addr & 0x1ffe) >> 5]) { - uint32_t nnum = (addr & 0x1ffe) >> 5; - 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) { - clear_cache(i); + 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; + } - color_cached[nnum] = false; + } else { + color_ram[uaddr] = tval.w.l; } break; default: // ToDO: Discard cache - p8 = &(pattern_ram[(addr & 0x1ffff) - 0x4000]); - *p8 = (uint8_t)(data & 0xff); - if(pattern_cached[((addr & 0x1fffe) - 0x4000) >> 7]) { - uint32_t nnum = ((addr & 0x1fffe) - 0x4000) >> 7; - for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) { - if(cache_index[i].num == (uint16_t)nnum) { - if(cache_index[i].is_use) { - clear_cache(i); + 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; + } } - pattern_cached[((addr & 0x1fffe) - 0x4000) >> 7] = false; - } + } else { + *p8 = (uint8_t)(data & 0xff); + } break; } return; @@ -502,65 +610,38 @@ void TOWNS_SPRITE::write_data8(uint32_t addr, uint32_t data) void TOWNS_SPRITE::write_data16(uint32_t addr, uint32_t data) { - uint32_t nbank; - uint16_t* p; - pair_t tval; - if((addr >= 0x81000000) && (addr < 0x81020000)) { - nbank = (addr & 0x1e000) >> 12; - } else { - nbank = 0; // OK? - } - switch(nbank) { - case 0: - case 1: - index_ram[(addr & 0x1ffe) >> 1] = (uint16_t)(data & 0xffff); - break; - case 2: - case 3: - // ToDO: Discard cache - color_ram[(addr & 0x1ffe) >> 1] = (uint16_t)(data & 0xffff); - if(color_cached[(addr & 0x1ffe) >> 5]) { - uint32_t nnum = (addr & 0x1ffe) >> 5; - 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) { - clear_cache(i); - } - } - } - color_cached[nnum] = false; - } - break; - default: - // ToDO: Discard cache - tval.w.l = (uint16_t)data; - pattern_ram[(addr & 0x1fffe) - 0x4000] = tval.b.l; - pattern_ram[(addr & 0x1fffe) - 0x4000 + 1] = tval.b.h; - if(pattern_cached[((addr & 0x1fffe) - 0x4000) >> 7]) { - uint32_t nnum = ((addr & 0x1fffe) - 0x4000) >> 7; - for(int i = 0; i < TOWNS_SPRITE_CACHE_NUM; i++) { - if(cache_index[i].num == (uint16_t)nnum) { - if(cache_index[i].is_use) { - clear_cache(i); - } - } - } - pattern_cached[((addr & 0x1fffe) - 0x4000) >> 7] = false; - } - break; - } - return; + 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_data16(addr, (uint32_t)(t.w.l)); - if(addr < 0x8101fffe) write_data16(addr + 2, (uint32_t)(t.w.h)); + 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)); + } } - +// 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; + display_page = (displae_page + 1) & 1; + } else if(id == SIG_FMTOWNS_SPRITE_SET_DATA_VRAM) { + } else if(id == SIG_FMTOWNS_SPRITE_SET_MASK_VRAM) { + } + +} #define STATE_VERSION 1 #include "../../statesub.h" @@ -578,8 +659,9 @@ void TOWNS_SPRITE::decl_state() DECL_STATE_ENTRY_UINT16(reg_hoffset); DECL_STATE_ENTRY_BOOL(disp_page0); DECL_STATE_ENTRY_BOOL(disp_page1); - - DECL_STATE_ENTRY_INT32(sprite_limit); + + DECL_STATE_ENTRY_BOOL(use_cache); + 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)); diff --git a/source/src/vm/fmtowns/towns_sprite.h b/source/src/vm/fmtowns/towns_sprite.h index 26d072260..5c862bda5 100644 --- a/source/src/vm/fmtowns/towns_sprite.h +++ b/source/src/vm/fmtowns/towns_sprite.h @@ -30,7 +30,8 @@ class TOWNS_VRAM; class TOWNS_SPRITE : public DEVICE { -private: + +protected: TOWNS_VRAM *vram_head; // REGISTERS @@ -53,7 +54,19 @@ private: bool pattern_cached[((65536 - (4096 * 2)) * 2) / (8 * 16)]; bool color_cached[256]; -protected: + + bool sprite_enabled; + bool use_cache; + 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); public: @@ -86,1252 +99,329 @@ public: bool load_stste(FILEIO *fio); }; -inline void TOWNS_SPRITE::render_32768_x1_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +inline void TOWNS_SPRITE::take_data_32768(uint16_t* src, uint16_t* dst, uint16_t* mask) { - uint16_t* qp = (uint16_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; - } - uint16_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint16_t* yaddr; - uint16_t*p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(y - 15) << 5]); // 1 line is 4 bytes (16pixels) - } else { - yaddr = &(qp[y << 5]); // 1 line is 4 bytes (16pixels) - } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 15; i >= 0; i--) { - pixels[i] = p[15 - i]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int i = 0; i <= 15; i++) { - pixels[i] = p[i]; - } - } - } else { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[15 - y]); - } else { - yaddr = &(qp[y]); - } - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int x = 15; x >= 0; x--) { - p = &(yaddr[x << 5]); - pixels[x] = p[15 - y]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int x = 0; x <= 15; x++) { - p = &(yaddr[x << 5]); - pixels[x] = p[y]; - } - } + 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]; } -__DECL_VECTORIZED_LOOP for(int x = 0; x < 16; x++) { - masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000; - cp[x] = pixels[x]; - cm[x] = masks[x]; - // Draw to buffer - tpixels[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - pixels[x] = pixels[x] & masks[x]; - dp[x] = pixels[x] | tpixels[x]; + r[x] = ((q[x] & 0x8000) != 0) ? 0 : 0xffff; } + r += 16; + q += 16; + p += 16; } } -inline void TOWNS_SPRITE::render_32768_x05_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +inline void TOWNS_SPRITE::take_data_32768_mirror(uint16_t* src, uint16_t* dst, uint16_t* mask) { - uint16_t* qp = (uint16_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; - } - uint16_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint16_t* yaddr; - uint16_t*p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(y - 15) << 5]); // 1 line is 4 bytes (16pixels) - } else { - yaddr = &(qp[y << 5]); // 1 line is 4 bytes (16pixels) - } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 7; i >= 0; i--) { - pixels[i] = p[15 - (i << 1)]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int i = 0; i <= 7; i++) { - pixels[i] = p[i << 1]; - } - } - } else { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[15 - y]); - } else { - yaddr = &(qp[y]); - } - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int x = 7; x >= 0; x--) { - p = &(yaddr[x << 6]); - pixels[x] = p[15 - y]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int x = 0; x <= 7; x++) { - p = &(yaddr[x << 6]); - pixels[x] = p[y]; - } - } + 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]; } -__DECL_VECTORIZED_LOOP - for(int x = 0; x < 8; x++) { - masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000; - cp[x] = pixels[x]; - cm[x] = masks[x]; - // Draw to buffer - tpixels[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - pixels[x] = pixels[x] & masks[x]; - dp[x] = pixels[x] | tpixels[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::render_32768_x1_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +inline void TOWNS_SPRITE::take_data_16(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask) { - uint16_t* qp = (uint16_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; - } - uint16_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint16_t* yaddr; - uint16_t*p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels) - } else { - yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels) - } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 15; i >= 0; i--) { - pixels[i] = p[15 - i]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int i = 0; i <= 15; i++) { - pixels[i] = p[i]; - } - } - } else { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[15 - (y << 1)]); - } else { - yaddr = &(qp[y << 1]); - } - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int x = 7; x >= 0; x--) { - p = &(yaddr[x << 6]); - pixels[x] = p[7 - y]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int x = 0; x <= 7; x++) { - p = &(yaddr[x << 6]); - pixels[x] = p[y]; - } - } + 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; } -__DECL_VECTORIZED_LOOP - for(int x = 0; x < 8; x++) { - masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000; - cp[x] = pixels[x]; - cm[x] = masks[x]; - // Draw to buffer - tpixels[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - pixels[x] = pixels[x] & masks[x]; - dp[x] = pixels[x] | tpixels[x]; + 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::render_32768_x05_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +inline void TOWNS_SPRITE::take_data_16_mirror(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask) { - uint16_t* qp = (uint16_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; - } - uint16_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint16_t* yaddr; - uint16_t*p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(7 - y) << 6]); // 1 line is 8 bytes (16pixels) - } else { - yaddr = &(qp[y << 6]); // 1 line is 8 bytes (16pixels) - } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 7; i >= 0; i--) { - pixels[i] = p[15 - (i << 1)]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int i = 0; i <= 7; i++) { - pixels[i] = p[i << 1]; - } - } - } else { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[15 - (y << 1)]); - } else { - yaddr = &(qp[y << 1]); - } - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int x = 7; x >= 0; x--) { - p = &(yaddr[x << 6]); - pixels[x] = p[7 - (y >> 1)]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int x = 0; x <= 7; x++) { - p = &(yaddr[x << 6]); - pixels[x] = p[y]; - } - } + 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; } -__DECL_VECTORIZED_LOOP - for(int x = 0; x < 8; x++) { - masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000; - cp[x] = pixels[x]; - cm[x] = masks[x]; - // Draw to buffer - tpixels[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - pixels[x] = pixels[x] & masks[x]; - dp[x] = pixels[x] | tpixels[x]; + 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::render_16_x1_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +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) { - uint8_t* qp = (uint8_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; - } - uint8_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t tpixels2[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint8_t* yaddr; - uint8_t* p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(y - 15) << 3]); // 1 line is 4 bytes (16pixels) - } else { - yaddr = &(qp[y << 3]); // 1 line is 4 bytes (16pixels) - } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 15; i >= 0; i--) { - pixels[i] = p[(15 - i) >> 1]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int i = 0; i <= 15; i++) { - pixels[i] = p[i]; - } - } -__DECL_VECTORIZED_LOOP - for(int i = 0; i < 16; i+= 2) { - pixels[i] = pixels[i] >> 4; - } -__DECL_VECTORIZED_LOOP - for(int i = 0; i < 16; i++) { - pixels[i] = pixels[i] & 0x0f; - } + uint16_t cache[16 * 16]; + if(!is_32768) { + if(is_mirror) { + take_data_16_mirror(src, color_table, cache, mask); } else { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[(15 - y) >> 1]); - } else { - yaddr = &(qp[(y >> 1)]); - } - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int x = 15; x >= 0; x--) { - p = &(yaddr[x << 3]); - pixels[x] = p[(15 - y) >> 1]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int x = 0; x <= 15; x++) { - p = &(yaddr[x << 3]); - pixels[x] = p[y >> 1]; - } - } -__DECL_VECTORIZED_LOOP - for(int i = 0; i < 16; i++) { - pixels[i] = pixels[i] >> 4; - pixels[i] = pixels[i] & 0x0f; - } - + take_data_16(src, color_table, cache, mask); } -__DECL_VECTORIZED_LOOP - for(int x = 0; x < 16; x++) { - masks[x] = (pixels[x] == 0) ? 0xffff : 0x0000 - tpixel[x] = color_index[pixels[x]]; - cp[x] = tpixel; - cm[x] = masks[x]; - // Draw to buffer - tpixels2[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - tpixels[x] = tpixels[x] & masks[x]; - dp[x] = tpixels[x] | tpixels2[x]; + + } 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); } -inline void TOWNS_SPRITE::render_16_x05_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +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* qp = (uint16_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 16; - xstep = 2; - ybegin = 0; - yend = 16; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; - } - uint16_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint8_t* yaddr; - uint8_t*p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(y - 15) << 3]); // 1 line is 4 bytes (16pixels) - } else { - yaddr = &(qp[y << 3]); // 1 line is 4 bytes (16pixels) - } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 7; i >= 0; i--) { - pixels[i] = p[7 - i]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int i = 0; i <= 7; i++) { - pixels[i] = p[i]; - } - } -__DECL_VECTORIZED_LOOP - for(int i = 0; i < 8; i+= 2) { - pixels[i] = pixels[i] >> 4; - pixels[i] = pixels[i] & 0x0f; - } + uint16_t cache[16 * 16]; + if(!is_32768) { + if(is_mirror) { + take_data_16_mirror(src, color_table, cache, mask); } else { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[(15 - y) >> 1]); - } else { - yaddr = &(qp[y >> 1]); - } - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int x = 7; x >= 0; x--) { - p = &(yaddr[x << 4]); - pixels[x] = p[15 - y]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int x = 0; x <= 7; x++) { - p = &(yaddr[x << 4]); - pixels[x] = p[y]; - } - } -__DECL_VECTORIZED_LOOP - for(int i = 0; i < 8; i++) { - pixels[i] = pixels[i] >> 4; - pixels[i] = pixels[i] & 0x0f; - } + take_data_16(src, color_table, cache, mask); } -__DECL_VECTORIZED_LOOP - for(int x = 0; x < 8; x++) { - masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000; - cp[x] = pixels[x]; - cm[x] = masks[x]; - // Draw to buffer - tpixels[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - pixels[x] = pixels[x] & masks[x]; - dp[x] = pixels[x] | tpixels[x]; + + } 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); } - -inline void TOWNS_SPRITE::render_16_x1_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +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* qp = (uint16_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 16; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; + 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); + } } - uint16_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint16_t* yaddr; - uint16_t*p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels) - } else { - yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels) + // 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]; } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 15; i >= 0; i--) { - pixels[i] = p[15 - i]; - } - } else { + } + } 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(int i = 0; i <= 15; i++) { - pixels[i] = p[i]; - } + 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 { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[15 - (y << 1)]); - } else { - yaddr = &(qp[y << 1]); - } - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int x = 7; x >= 0; x--) { - p = &(yaddr[x << 6]); - pixels[x] = p[7 - y]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int x = 0; x <= 7; x++) { - p = &(yaddr[x << 6]); - pixels[x] = p[y]; - } - } + take_data_16(src, color_table, cache, mask); } -__DECL_VECTORIZED_LOOP - for(int x = 0; x < 8; x++) { - masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000; - cp[x] = pixels[x]; - cm[x] = masks[x]; - // Draw to buffer - tpixels[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - pixels[x] = pixels[x] & masks[x]; - dp[x] = pixels[x] | tpixels[x]; + + } 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::render_16_x05_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride) +inline void TOWNS_SPRITE::zoom_data(uint16_t* cache, uint16_t* maskcache, bool is_halfx, bool is_halfy, uint16_t* dstcache, uint16_t* dstmask) { - uint16_t* qp = (uint16_t*)(sprite_table[num].pixels); - uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]); - uint16_t *cache_mask = cache_masks[last_put_cache_num][0]; - int xbegin; - int xend; - int xstep; - int ybegin; - int yend; - int ystep; - int addr_base; - int addr_inc; - bool xreverse; - bool yreverse; - bool rotate = false; - switch(rot_type) { - case ROT_FMTOWNS_SPRITE_0: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = false; - rotate = false; - if(is_mirror) { - xreverse = true; - } - } - break; - case ROT_FMTOWNS_SPRITE_90: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = false; - yreverse = true; - rotate = true; - if(is_mirror) { - yreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_180: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = true; - rotate = false; - if(is_mirror) { - xreverse = false; - } - } - break; - case ROT_FMTOWNS_SPRITE_270: - xbegin = 0; - xend = 8; - xstep = 1; - ybegin = 0; - yend = 8; - ystep = 1; - xreverse = true; - yreverse = false; - rotate = true; - if(is_mirror) { - yreverse = true; - } - } - break; - } - uint16_t pixels[16]; - uint16_t masks[16]; - uint16_t tpixels[16]; - uint16_t* cp; - uint16_t* cm; - uint16* dp; - uint16_t* yaddr; - uint16_t*p; - for(y = ybegin; y != yend; y += ystep) { - cp = &(cache_pixel[y << 5]); - cm = &(cache_mask[y << 5]); - dp = &(dst[stride * y]); - if(!rotate) { - if(yreverse) { - yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels) - } else { - yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels) - } - p = &(yaddr[0]); - if(xreverse) { -__DECL_VECTORIZED_LOOP - for(int i = 7; i >= 0; i--) { - pixels[i] = p[15 - (i << 1)]; - } - } else { -__DECL_VECTORIZED_LOOP - for(int i = 0; i <= 7; i++) { - pixels[i] = p[i << 1]; + 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]; } - } - } else { - // Rotate: Swap x, y - if(yreverse) { - yaddr = &(qp[15 - (y << 1)]); - } else { - yaddr = &(qp[y << 1]); - } - if(xreverse) { __DECL_VECTORIZED_LOOP - for(int x = 7; x >= 0; x--) { - p = &(yaddr[x << 6]); - pixels[x] = p[7 - x]; + 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]; } - } else { __DECL_VECTORIZED_LOOP - for(int x = 0; x <= 7; x++) { - p = &(yaddr[x << 6]); - pixels[x] = p[x]; + 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)); } -__DECL_VECTORIZED_LOOP - for(int x = 0; x < 8; x++) { - masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000; - cp[x] = pixels[x]; - cm[x] = masks[x]; - // Draw to buffer - tpixels[x] = dp[x] & masks[x]; - masks[x] = ~masks[x]; - pixels[x] = pixels[x] & masks[x]; - dp[x] = pixels[x] | tpixels[x]; - } - } -} - - -inline void TOWNS_SPRITE::render_base(int num, uint16* dst_pixel, int width, int height, int stride) -{ - int half_type = 0; - int rot_type; - half_type = half_type | ((cache_index[num].is_halfx) ? 1 : 0); - half_type = half_type | ((cache_index[num].is_halfy) ? 2 : 0); - - switch((sprite_table[num].rotate) & 7) { - case 0: - rot_type = ROT_FMTOWNS_SPRITE_0; - is_mirror = false; - break; - case 1: - rot_type = ROT_FMTOWNS_SPRITE_180; - is_mirror = true; - break; - case 2: - rot_type = ROT_FMTOWNS_SPRITE_180; - is_mirror = false; - break; - case 3: - rot_type = ROT_FMTOWNS_SPRITE_0; - is_mirror = true; - break; - case 4: - rot_type = ROT_FMTOWNS_SPRITE_270; - is_mirror = true; - break; - case 5: - rot_type = ROT_FMTOWNS_SPRITE_90; - is_mirror = false; - break; - case 6: - rotate = false; - rot_type = ROT_FMTOWNS_SPRITE_270; - is_mirror = false; - break; - case 7: - rot_type = ROT_FMTOWNS_SPRITE_90; - is_mirror = true; - break; - } - if(sprite_table[num].is_32768) { - switch(half_type & 3) { - case 0: // not rotate - render_32768_x1_x1(num, dst, rot_type, mirror, stride); - break; - case 1: - render_32768_x05_x1(num, dst, rot_type, mirror, stride); - break; - case 2: - render_32768_x1_x05(num, dst, rot_type, mirror, stride); - break; - case 3: - render_32768_x05_x05(num, dst, rot_type, mirror, stride); - break; - } } else { - switch(half_type & 3) { - case 0: // not rotate - render_16_x1_x1(num, dst, rot_type, mirror, stride); - break; - case 1: - render_16_x05_x1(num, dst, rot_type, mirror, stride); - break; - case 2: - render_16_x1_x05(num, dst, rot_type, mirror, stride); - break; - case 3: - render_16_x05_x05(num, dst, rot_type, mirror, stride); - break; - } + 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)); + } } } -- 2.11.0