2 #ifndef _TOWNS_SPRITE_H_
3 #define _TOWNS_SPRITE_H_
9 #define SIG_FMTOWNS_SPRITE_RENDER 256
10 #define SIG_FMTOWNS_SPRITE_UPDATE_FRAMEBUFFER 257
11 #define SIG_FMTOWNS_RENDER_SPRITE_CHANGE_BANK 258
12 #define SIG_FMTOWNS_RENDER_SPRITE_ENABLED 259
13 #define SIG_FMTOWNS_RENDER_SPRITE_RESET 260
14 #define SIG_FMTOWNS_RENDER_SPRITE_SET_LIMIT 261
15 #define SIG_FMTOWNS_RENDER_SPRITE_SET_NUM 262
16 #define SIG_FMTOWNS_RENDER_SPRITE_CLEAR_VRAM 263
20 ROT_FMTOWNS_SPRITE_0 = 0,
21 ROT_FMTOWNS_SPRITE_90,
22 ROT_FMTOWNS_SPRITE_180,
23 ROT_FMTOWNS_SPRITE_270
29 #define TOWNS_SPRITE_CACHE_NUM 512
31 class TOWNS_SPRITE : public DEVICE
35 TOWNS_VRAM *vram_head;
51 uint16_t index_ram[4096]; // 1024 * 4
52 uint16_t color_ram[4096]; // 16 * 256
53 uint8_t pattern_ram[(65536 - (4096 * 2)) * 2];
55 bool pattern_cached[((65536 - (4096 * 2)) * 2) / (8 * 16)];
56 bool color_cached[256];
60 inline void take_data_32768(uint16_t* src, uint16_t* dst, uint16_t* mask);
61 inline void take_data_32768_mirror(uint16_t* src, uint16_t* dst, uint16_t* mask);
62 inline void take_data_16(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask);
63 inline void take_data_16_mirror(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask);
64 inline void zoom_data(uint16_t* cache, uint16_t* maskcache, bool is_halfx, bool is_halfy, uint16_t* dstcache, uint16_t* dstmask);
66 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);
67 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);
68 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);
69 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);
73 TOWNS_SPRITE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
74 set_device_name(_T("SPRITE"));
82 void write_data8(uint32_t addr, uint32_t data);
83 void write_data16(uint32_t addr, uint32_t data);
84 void write_data32(uint32_t addr, uint32_t data);
86 uint32_t read_data8(uint32_t addr);
87 uint32_t read_data16(uint32_t addr);
88 uint32_t read_data32(uint32_t addr);
90 void write_signal(int id, uint32_t data, uint32_t mask);
94 void set_context_vram(TOWNS_VRAM *p)
98 void save_state(FILEIO *fio);
99 bool load_stste(FILEIO *fio);
102 inline void TOWNS_SPRITE::take_data_32768(uint16_t* src, uint16_t* dst, uint16_t* mask)
107 for(int y = 0; y < 16; y++) {
108 for(int x = 0; x < 16; x++) {
111 for(int x = 0; x < 16; x++) {
112 r[x] = ((q[x] & 0x8000) != 0) ? 0 : 0xffff;
120 inline void TOWNS_SPRITE::take_data_32768_mirror(uint16_t* src, uint16_t* dst, uint16_t* mask)
125 for(int y = 0; y < 16; y++) {
126 for(int x = 0; x < 16; x++) {
129 for(int x = 0; x < 16; x++) {
130 r[x] = ((q[x] & 0x8000) != 0) ? 0 : 0xffff;
139 inline void TOWNS_SPRITE::take_data_16(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask)
145 for(int y = 0; y < 16; y++) {
146 for(int x = 0; x < 16; x += 2) {
147 cache[x] = p[x >> 1];
148 cache[x + 1] = cache[x];
150 for(int x = 0; x < 16; x += 2) {
151 cache[x] = cache[x] >> 4;
153 for(int x = 0; x < 16; x++) {
154 cache[x] = cache[x] & 0x0f;
155 r[x] = (cache[x] == 0) ? 0x0000 : 0xffff;
156 q[x] = color_table[cache[x]];
164 inline void TOWNS_SPRITE::take_data_16_mirror(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask)
170 for(int y = 0; y < 16; y++) {
171 for(int x = 0; x < 16; x += 2) {
172 cache[x] = p[(15 - x) >> 1];
173 cache[x + 1] = cache[x];
175 for(int x = 1; x < 16; x += 2) {
176 cache[x] = cache[x] >> 4;
178 for(int x = 0; x < 16; x++) {
179 cache[x] = cache[x] & 0x0f;
180 r[x] = (cache[x] == 0) ? 0x0000 : 0xffff;
181 q[x] = color_table[cache[x]];
190 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)
192 uint16_t cache[16 * 16];
195 take_data_16_mirror(src, color_table, cache, mask);
197 take_data_16(src, color_table, cache, mask);
202 take_data_32768_mirror((uint16_t*)src, cache, mask);
204 take_data_16((uint16_t*)src, cache, mask);
209 uint16_t maskcache[16 * 16];
210 memcpy(maskcache, mask, sizeof(maskcache));
211 zoom_data(cache, maskcache, is_halfx, is_halfy, dstcache, mask);
214 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)
216 uint16_t cache[16 * 16];
219 take_data_16_mirror(src, color_table, cache, mask);
221 take_data_16(src, color_table, cache, mask);
226 take_data_32768_mirror((uint16_t*)src, cache, mask);
228 take_data_16((uint16_t*)src, cache, mask);
232 uint16_t maskcache[16][16];
233 uint16_t cache2[16][16];
235 // q[x][y] = p[15 - y][15 - x]
236 __DECL_VECTORIZED_LOOP
237 for(y = 0; y < 16; y++) {
238 uint16_t* p = &(cache[15 - y]);
239 uint16_t* q = &(mask[15 - y]);
240 for(x = 0; x < 16; x++) {
241 cache2[y][x] = p[(15 - x) << 4];
242 maskcache[y][x] = q[(15 - x) << 4];
246 // q[x][y] = p[15 - y][x]
247 for(y = 0; y < 16; y++) {
248 uint16_t* p = &(cache[15 - y]);
249 uint16_t* q = &(mask[15 - y]);
250 __DECL_VECTORIZED_LOOP
251 for(x = 0; x < 16; x++) {
252 cache2[y][x] = p[x << 4];
253 maskcache[y][x] = q[x << 4];
257 zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
260 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)
262 uint16_t cache[16 * 16];
265 take_data_16_mirror(src, color_table, cache, mask);
267 take_data_16(src, color_table, cache, mask);
272 take_data_32768_mirror((uint16_t*)src, cache, mask);
274 take_data_16((uint16_t*)src, cache, mask);
278 uint16_t maskcache[16][16];
279 uint16_t cache2[16][16];
281 // q[x][y] = p[x][15 - y]
282 for(y = 0; y < 16; y++) {
283 uint16_t* p = &(cache[(15 - y) << 4]);
284 uint16_t* q = &(mask[(15 - y) << 4]);
285 __DECL_VECTORIZED_LOOP
286 for(x = 0; x < 16; x++) {
288 maskcache[y][x] = q[x];
292 // q[x][y] = p[15 - x][15 - y]
293 for(y = 0; y < 16; y++) {
294 uint16_t* p = &(cache[15 - y] << 4);
295 uint16_t* q = &(mask[15 - y] << 4);
296 __DECL_VECTORIZED_LOOP
297 for(x = 0; x < 16; x++) {
298 cache2[y][x] = p[15 - x];
299 maskcache[y][x] = q[15 - x];
303 zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
306 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)
308 uint16_t cache[16 * 16];
311 take_data_16_mirror(src, color_table, cache, mask);
313 take_data_16(src, color_table, cache, mask);
318 take_data_32768_mirror((uint16_t*)src, cache, mask);
320 take_data_16((uint16_t*)src, cache, mask);
324 uint16_t maskcache[16][16];
325 uint16_t cache2[16][16];
329 for(y = 0; y < 16; y++) {
330 uint16_t* p = &(cache[y]);
331 uint16_t* q = &(mask[y]);
332 __DECL_VECTORIZED_LOOP
333 for(x = 0; x < 16; x++) {
334 cache2[y][x] = p[x << 4];
335 maskcache[y][x] = q[x << 4];
339 // q[x][y] = p[y][15 - x]
340 for(y = 0; y < 16; y++) {
341 uint16_t* p = &(cache[15 - y]);
342 uint16_t* q = &(mask[15 - y]);
343 __DECL_VECTORIZED_LOOP
344 for(x = 0; x < 16; x++) {
345 cache2[y][x] = p[x << 4];
346 maskcache[y][x] = q[x << 4];
350 zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
353 inline void TOWNS_SPRITE::zoom_data(uint16_t* cache, uint16_t* maskcache, bool is_halfx, bool is_halfy, uint16_t* dstcache, uint16_t* dstmask)
357 uint16_t cache2[8][8];
358 uint16_t maskcache2[8][8];
359 for(int y = 0; y < 16; y += 2) {
360 uint16_t cacheline[8];
361 uint16_t *pp = &(cache[y << 4]);
362 uint16_t maskcacheline[8];
363 uint16_t *pq = &(maskcache[y << 4]);
364 __DECL_VECTORIZED_LOOP
365 for(int x = 0; x < 8; x++) {
366 cacheline[x] = pp[x << 1];
367 maskcacheline[x] = pq[x << 1];
369 __DECL_VECTORIZED_LOOP
370 for(int x = 0; x < 8; x++) {
371 cache2[y >> 1][x] = cacheline[x];
372 maskcache2[y >> 1][x] = maskcacheline[x];
375 memcpy(dstcache, &(cache2[0][0]), 8 * 8 * sizeof(uint16_t));
376 memcpy(dstmask, &(maskcache2[0][0]), 8 * 8 * sizeof(uint16_t));
377 } else { // halfx only, not halfy
378 uint16_t cache2[16][8];
379 uint16_t maskcache2[16][8];
380 for(int y = 0; y < 16; y++) {
381 uint16_t cacheline[8];
382 uint16_t *pp = &(cache[y << 4]);
383 uint16_t maskcacheline[8];
384 uint16_t *pq = &(maskcache[y << 4]);
385 __DECL_VECTORIZED_LOOP
386 for(int x = 0; x < 8; x++) {
387 cacheline[x] = pp[x << 1];
388 maskcacheline[x] = pq[x << 1];
390 __DECL_VECTORIZED_LOOP
391 for(int x = 0; x < 8; x++) {
392 cache2[y][x] = cacheline[x];
393 maskcache2[y][x] = maskcacheline[x];
396 memcpy(dstcache, &(cache2[0][0]), 16 * 8 * sizeof(uint16_t));
397 memcpy(mask, &(maskcache2[0][0]), 16 * 8 * sizeof(uint16_t));
400 if(is_halfy) { // halfx only, not halfx
401 uint16_t cache2[16][8];
402 uint16_t maskcache2[16][8];
403 for(int y = 0; y < 16; y += 2) {
404 uint16_t cacheline[16];
405 uint16_t *pp = &(cache[y << 4]);
406 uint16_t maskcacheline[16];
407 uint16_t *pq = &(maskcache[y << 4]);
408 __DECL_VECTORIZED_LOOP
409 for(int x = 0; x < 16; x++) {
410 cacheline[x] = pp[x];
411 maskcacheline[x] = pq[x];
413 __DECL_VECTORIZED_LOOP
414 for(int x = 0; x < 16; x++) {
415 cache2[y >> 1][x] = cacheline[x];
416 maskcache2[y >> 1][x] = maskcacheline[x];
419 memcpy(dstcache, &(cache2[0][0]), 8 * 16 * sizeof(uint16_t));
420 memcpy(dstmask, &(maskcache2[0][0]), 8 * 16 * sizeof(uint16_t));
422 memcpy(dstcache, cache, 16 * 16 * sizeof(uint16_t));
423 memcpy(dstmask, maskcache, 16 * 16 * sizeof(uint16_t));
428 #endif /* _TOWNS_SPRITE_H */