OSDN Git Service

[VM][FMTOWNS][WIP] Implementing.Still WIP.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / towns_sprite.h
1
2 #ifndef _TOWNS_SPRITE_H_
3 #define _TOWNS_SPRITE_H_
4
5 #include "../vm.h"
6 #include "../../emu.h"
7 #include "../device.h"
8
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
17
18
19 enum {
20         ROT_FMTOWNS_SPRITE_0 = 0,
21         ROT_FMTOWNS_SPRITE_90,
22         ROT_FMTOWNS_SPRITE_180,
23         ROT_FMTOWNS_SPRITE_270
24 };
25
26
27 class TOWNS_VRAM;
28
29 #define TOWNS_SPRITE_CACHE_NUM 512
30
31 class TOWNS_SPRITE : public DEVICE
32 {
33
34 protected:
35         TOWNS_VRAM *vram_head;
36
37         // REGISTERS
38         uint8_t reg_addr;
39         uint8_t reg_data[8];
40         // #0, #1
41         bool reg_spen;
42         uint16_t reg_index;
43
44         uint16_t reg_voffset;
45         uint16_t reg_hoffset;
46         bool disp_page0;
47         bool disp_page1;
48         
49         int32_t splite_limit;
50
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];
54
55         bool pattern_cached[((65536 - (4096 * 2)) * 2) / (8 * 16)];
56         bool color_cached[256];
57         
58         bool sprite_enabled;
59         bool use_cache;
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);
65
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);
70
71         
72 public:
73         TOWNS_SPRITE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
74                 set_device_name(_T("SPRITE"));
75                 vram_head = NULL;
76                 framebuffer = NULL;
77                 
78         }
79         ~TOWNS_SPRITE() {}
80         
81
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);
85         
86         uint32_t read_data8(uint32_t addr);
87         uint32_t read_data16(uint32_t addr);
88         uint32_t read_data32(uint32_t addr);
89
90         void write_signal(int id, uint32_t data, uint32_t mask);
91         
92         void initialize();
93
94         void set_context_vram(TOWNS_VRAM *p)
95         {
96                 vram_head = p;
97         }
98         void save_state(FILEIO *fio);
99         bool load_stste(FILEIO *fio);
100 };
101
102 inline void TOWNS_SPRITE::take_data_32768(uint16_t* src, uint16_t* dst, uint16_t* mask)
103 {
104         uint16_t* p = src;
105         uint16_t* q = dst;
106         uint16_t* r = mask;
107         for(int y = 0; y < 16; y++) {
108                 for(int x = 0; x < 16; x++) {
109                         q[x] = p[x];
110                 }
111                 for(int x = 0; x < 16; x++) {
112                         r[x] = ((q[x] & 0x8000) != 0) ? 0 : 0xffff;
113                 }
114                 r += 16;
115                 q += 16;
116                 p += 16;
117         }
118 }
119
120 inline void TOWNS_SPRITE::take_data_32768_mirror(uint16_t* src, uint16_t* dst, uint16_t* mask)
121 {
122         uint16_t* p = src;
123         uint16_t* q = dst;
124         uint16_t* r = mask;
125         for(int y = 0; y < 16; y++) {
126                 for(int x = 0; x < 16; x++) {
127                         q[x] = p[15 - x];
128                 }
129                 for(int x = 0; x < 16; x++) {
130                         r[x] = ((q[x] & 0x8000) != 0) ? 0 : 0xffff;
131                 }
132                 r += 16;
133                 q += 16;
134                 p += 16;
135         }
136 }
137
138
139 inline void TOWNS_SPRITE::take_data_16(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask)
140 {
141         uint8_t* p = src;
142         uint16_t* q = dst;
143         uint16_t* r = mask;
144         uint8_t cache[16];
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];
149                 }
150                 for(int x = 0; x < 16; x += 2) {
151                         cache[x] = cache[x] >> 4;
152                 }
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]];
157                 }
158                 r += 16;
159                 q += 16;
160                 p += 8;
161         }
162 }
163
164 inline void TOWNS_SPRITE::take_data_16_mirror(uint8_t* src, uint16_t* color_table, uint16_t* dst, uint16_t* mask)
165 {
166         uint8_t* p = src;
167         uint16_t* q = dst;
168         uint16_t* r = mask;
169         uint8_t cache[16];
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];
174                 }
175                 for(int x = 1; x < 16; x += 2) {
176                         cache[x] = cache[x] >> 4;
177                 }
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]];
182                 }
183                 r += 16;
184                 q += 16;
185                 p += 8;
186         }
187 }
188
189
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)
191 {
192         uint16_t cache[16 * 16];
193         if(!is_32768) {
194                 if(is_mirror) {
195                         take_data_16_mirror(src, color_table, cache, mask);
196                 } else {
197                         take_data_16(src, color_table, cache, mask);
198                 }
199                 
200         } else {
201                 if(is_mirror) {
202                         take_data_32768_mirror((uint16_t*)src, cache, mask);
203                 } else {
204                         take_data_16((uint16_t*)src, cache, mask);
205                 }
206         }
207         // Rotate
208         // Zoom
209         uint16_t maskcache[16 * 16];
210         memcpy(maskcache, mask, sizeof(maskcache));
211         zoom_data(cache, maskcache, is_halfx, is_halfy, dstcache, mask);
212 }
213
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)
215 {
216         uint16_t cache[16 * 16];
217         if(!is_32768) {
218                 if(is_mirror) {
219                         take_data_16_mirror(src, color_table, cache, mask);
220                 } else {
221                         take_data_16(src, color_table, cache, mask);
222                 }
223                 
224         } else {
225                 if(is_mirror) {
226                         take_data_32768_mirror((uint16_t*)src, cache, mask);
227                 } else {
228                         take_data_16((uint16_t*)src, cache, mask);
229                 }
230         }
231         // Rotate
232         uint16_t maskcache[16][16];
233         uint16_t cache2[16][16];
234         if(is_mirror) {
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];
243                         }
244                 }                       
245         } else {
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];
254                         }
255                 }                       
256         }       
257         zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
258 }
259
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)
261 {
262         uint16_t cache[16 * 16];
263         if(!is_32768) {
264                 if(is_mirror) {
265                         take_data_16_mirror(src, color_table, cache, mask);
266                 } else {
267                         take_data_16(src, color_table, cache, mask);
268                 }
269                 
270         } else {
271                 if(is_mirror) {
272                         take_data_32768_mirror((uint16_t*)src, cache, mask);
273                 } else {
274                         take_data_16((uint16_t*)src, cache, mask);
275                 }
276         }
277         // Rotate
278         uint16_t maskcache[16][16];
279         uint16_t cache2[16][16];
280         if(is_mirror) {
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++) {
287                                 cache2[y][x] = p[x];
288                                 maskcache[y][x] = q[x];
289                         }
290                 }                       
291         } else {
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];
300                         }
301                 }                       
302         }       
303         zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
304 }
305
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)
307 {
308         uint16_t cache[16 * 16];
309         if(!is_32768) {
310                 if(is_mirror) {
311                         take_data_16_mirror(src, color_table, cache, mask);
312                 } else {
313                         take_data_16(src, color_table, cache, mask);
314                 }
315                 
316         } else {
317                 if(is_mirror) {
318                         take_data_32768_mirror((uint16_t*)src, cache, mask);
319                 } else {
320                         take_data_16((uint16_t*)src, cache, mask);
321                 }
322         }
323         // Rotate
324         uint16_t maskcache[16][16];
325         uint16_t cache2[16][16];
326         if(is_mirror) {
327                 // q[x][y] = p[y][x]
328                 
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];
336                         }
337                 }                       
338         } else {
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];
347                         }
348                 }                       
349         }       
350         zoom_data((uint16_t*)(&(cache2[0][0])), (uint16_t*)(&(maskcache[0][0])), is_halfx, is_halfy, dstcache, mask);
351 }
352
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)
354 {
355         if(is_halfx) {
356                 if(is_halfy) {
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];
368                                 }
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];
373                                 }
374                         }
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];
389                                 }
390 __DECL_VECTORIZED_LOOP                          
391                                 for(int x = 0; x < 8; x++) {
392                                         cache2[y][x] = cacheline[x];
393                                         maskcache2[y][x] = maskcacheline[x];
394                                 }
395                         }
396                         memcpy(dstcache, &(cache2[0][0]), 16 * 8 * sizeof(uint16_t));
397                         memcpy(mask, &(maskcache2[0][0]), 16 * 8 * sizeof(uint16_t));
398                 }
399         } else {
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];
412                                 }
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];
417                                 }
418                         }
419                         memcpy(dstcache, &(cache2[0][0]), 8 * 16 * sizeof(uint16_t));
420                         memcpy(dstmask, &(maskcache2[0][0]), 8 * 16 * sizeof(uint16_t));
421                 } else { // 1x1
422                         memcpy(dstcache, cache, 16 * 16 * sizeof(uint16_t));
423                         memcpy(dstmask, maskcache, 16 * 16 * sizeof(uint16_t));
424                 }
425         }
426 }
427
428 #endif /* _TOWNS_SPRITE_H */