OSDN Git Service

26d072260de28b49041dff7f51f5e51174b3f4ba
[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 private:
34         TOWNS_VRAM *vram_head;
35
36         // REGISTERS
37         uint8_t reg_addr;
38         uint8_t reg_data[8];
39         // #0, #1
40         bool reg_spen;
41         uint16_t reg_index;
42
43         uint16_t reg_voffset;
44         uint16_t reg_hoffset;
45         bool disp_page0;
46         bool disp_page1;
47         
48         int32_t splite_limit;
49
50         uint16_t index_ram[4096]; // 1024 * 4
51         uint16_t color_ram[4096]; // 16 * 256
52         uint8_t pattern_ram[(65536 - (4096 * 2)) * 2];
53
54         bool pattern_cached[((65536 - (4096 * 2)) * 2) / (8 * 16)];
55         bool color_cached[256];
56 protected:
57
58         
59 public:
60         TOWNS_SPRITE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
61                 set_device_name(_T("SPRITE"));
62                 vram_head = NULL;
63                 framebuffer = NULL;
64                 
65         }
66         ~TOWNS_SPRITE() {}
67         
68
69         void write_data8(uint32_t addr, uint32_t data);
70         void write_data16(uint32_t addr, uint32_t data);
71         void write_data32(uint32_t addr, uint32_t data);
72         
73         uint32_t read_data8(uint32_t addr);
74         uint32_t read_data16(uint32_t addr);
75         uint32_t read_data32(uint32_t addr);
76
77         void write_signal(int id, uint32_t data, uint32_t mask);
78         
79         void initialize();
80
81         void set_context_vram(TOWNS_VRAM *p)
82         {
83                 vram_head = p;
84         }
85         void save_state(FILEIO *fio);
86         bool load_stste(FILEIO *fio);
87 };
88
89 inline void TOWNS_SPRITE::render_32768_x1_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
90 {
91         uint16_t* qp = (uint16_t*)(sprite_table[num].pixels);
92         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
93         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
94         int xbegin;
95         int xend;
96         int xstep;
97         int ybegin;
98         int yend;
99         int ystep;
100         int addr_base;
101         int addr_inc;
102         bool xreverse;
103         bool yreverse;
104         bool rotate = false;
105         switch(rot_type) {
106         case ROT_FMTOWNS_SPRITE_0:
107                         xbegin = 0;
108                         xend = 16;
109                         xstep = 1;
110                         ybegin = 0;
111                         yend = 16;
112                         ystep = 1;
113                         xreverse = false;
114                         yreverse = false;
115                         rotate = false;
116                         if(is_mirror) {
117                                 xreverse = true;
118                         }
119                 }                       
120                 break;
121         case ROT_FMTOWNS_SPRITE_90:
122                         xbegin = 0;
123                         xend = 16;
124                         xstep = 1;
125                         ybegin = 0;
126                         yend = 16;
127                         ystep = 1;
128                         xreverse = false;
129                         yreverse = true;
130                         rotate = true;
131                         if(is_mirror) {
132                                 yreverse = false;
133                         }
134                 }                       
135                 break;
136         case ROT_FMTOWNS_SPRITE_180:
137                         xbegin = 0;
138                         xend = 16;
139                         xstep = 1;
140                         ybegin = 0;
141                         yend = 16;
142                         ystep = 1;
143                         xreverse = true;
144                         yreverse = true;
145                         rotate = false;
146                         if(is_mirror) {
147                                 xreverse = false;
148                         }
149                 }                       
150                 break;
151         case ROT_FMTOWNS_SPRITE_270:
152                         xbegin = 0;
153                         xend = 16;
154                         xstep = 1;
155                         ybegin = 0;
156                         yend = 16;
157                         ystep = 1;
158                         xreverse = true;
159                         yreverse = false;
160                         rotate = true;
161                         if(is_mirror) {
162                                 yreverse = true;
163                         }
164                 }                       
165                 break;
166         }
167         uint16_t pixels[16];
168         uint16_t masks[16];
169         uint16_t tpixels[16];
170         uint16_t* cp;
171         uint16_t* cm;
172         uint16* dp;
173         uint16_t* yaddr;
174         uint16_t*p;
175         for(y = ybegin; y != yend; y += ystep) {
176                 cp = &(cache_pixel[y << 5]);
177                 cm = &(cache_mask[y << 5]);
178                 dp =  &(dst[stride * y]);
179                 if(!rotate) {
180                         if(yreverse) {
181                                 yaddr = &(qp[(y - 15) << 5]); // 1 line is 4 bytes (16pixels)
182                         } else {
183                                 yaddr = &(qp[y << 5]); // 1 line is 4 bytes (16pixels)
184                         }
185                         p = &(yaddr[0]);
186                         if(xreverse) {
187 __DECL_VECTORIZED_LOOP
188                                 for(int i = 15; i >= 0; i--) {
189                                         pixels[i] = p[15 - i];
190                                 }
191                         } else {
192 __DECL_VECTORIZED_LOOP
193                                 for(int i = 0; i <= 15; i++) {
194                                         pixels[i] = p[i];
195                                 }
196                         }
197                 } else {
198                         // Rotate: Swap x, y
199                         if(yreverse) {
200                                 yaddr = &(qp[15 - y]);
201                         } else {
202                                 yaddr = &(qp[y]);
203                         }                       
204                         if(xreverse) {
205 __DECL_VECTORIZED_LOOP                          
206                                 for(int x = 15; x >= 0; x--) {
207                                         p = &(yaddr[x << 5]);
208                                         pixels[x] = p[15 - y];
209                                 }
210                         } else {
211 __DECL_VECTORIZED_LOOP                          
212                                 for(int x = 0; x <= 15; x++) {
213                                         p = &(yaddr[x << 5]);
214                                         pixels[x] = p[y];
215                                 }
216                         }
217                 }
218 __DECL_VECTORIZED_LOOP          
219                 for(int x = 0; x < 16; x++) {
220                         masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
221                         cp[x] = pixels[x];
222                         cm[x] = masks[x];
223                         // Draw to buffer
224                         tpixels[x] = dp[x] & masks[x];
225                         masks[x] = ~masks[x];
226                         pixels[x] = pixels[x] & masks[x];
227                         dp[x] = pixels[x] | tpixels[x];
228                 }
229         }
230 }
231
232 inline void TOWNS_SPRITE::render_32768_x05_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
233 {
234         uint16_t* qp = (uint16_t*)(sprite_table[num].pixels);
235         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
236         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
237         int xbegin;
238         int xend;
239         int xstep;
240         int ybegin;
241         int yend;
242         int ystep;
243         int addr_base;
244         int addr_inc;
245         bool xreverse;
246         bool yreverse;
247         bool rotate = false;
248         switch(rot_type) {
249         case ROT_FMTOWNS_SPRITE_0:
250                         xbegin = 0;
251                         xend = 16;
252                         xstep = 2;
253                         ybegin = 0;
254                         yend = 16;
255                         ystep = 1;
256                         xreverse = false;
257                         yreverse = false;
258                         rotate = false;
259                         if(is_mirror) {
260                                 xreverse = true;
261                         }
262                 }                       
263                 break;
264         case ROT_FMTOWNS_SPRITE_90:
265                         xbegin = 0;
266                         xend = 16;
267                         xstep = 2;
268                         ybegin = 0;
269                         yend = 16;
270                         ystep = 1;
271                         xreverse = false;
272                         yreverse = true;
273                         rotate = true;
274                         if(is_mirror) {
275                                 yreverse = false;
276                         }
277                 }                       
278                 break;
279         case ROT_FMTOWNS_SPRITE_180:
280                         xbegin = 0;
281                         xend = 16;
282                         xstep = 2;
283                         ybegin = 0;
284                         yend = 16;
285                         ystep = 1;
286                         xreverse = true;
287                         yreverse = true;
288                         rotate = false;
289                         if(is_mirror) {
290                                 xreverse = false;
291                         }
292                 }                       
293                 break;
294         case ROT_FMTOWNS_SPRITE_270:
295                         xbegin = 0;
296                         xend = 16;
297                         xstep = 2;
298                         ybegin = 0;
299                         yend = 16;
300                         ystep = 1;
301                         xreverse = true;
302                         yreverse = false;
303                         rotate = true;
304                         if(is_mirror) {
305                                 yreverse = true;
306                         }
307                 }                       
308                 break;
309         }
310         uint16_t pixels[16];
311         uint16_t masks[16];
312         uint16_t tpixels[16];
313         uint16_t* cp;
314         uint16_t* cm;
315         uint16* dp;
316         uint16_t* yaddr;
317         uint16_t*p;
318         for(y = ybegin; y != yend; y += ystep) {
319                 cp = &(cache_pixel[y << 5]);
320                 cm = &(cache_mask[y << 5]);
321                 dp =  &(dst[stride * y]);
322                 if(!rotate) {
323                         if(yreverse) {
324                                 yaddr = &(qp[(y - 15) << 5]); // 1 line is 4 bytes (16pixels)
325                         } else {
326                                 yaddr = &(qp[y << 5]); // 1 line is 4 bytes (16pixels)
327                         }
328                         p = &(yaddr[0]);
329                         if(xreverse) {
330 __DECL_VECTORIZED_LOOP
331                                 for(int i = 7; i >= 0; i--) {
332                                         pixels[i] = p[15 - (i << 1)];
333                                 }
334                         } else {
335 __DECL_VECTORIZED_LOOP
336                                 for(int i = 0; i <= 7; i++) {
337                                         pixels[i] = p[i << 1];
338                                 }
339                         }
340                 } else {
341                         // Rotate: Swap x, y
342                         if(yreverse) {
343                                 yaddr = &(qp[15 - y]);
344                         } else {
345                                 yaddr = &(qp[y]);
346                         }                       
347                         if(xreverse) {
348 __DECL_VECTORIZED_LOOP                          
349                                 for(int x = 7; x >= 0; x--) {
350                                         p = &(yaddr[x << 6]);
351                                         pixels[x] = p[15 - y];
352                                 }
353                         } else {
354 __DECL_VECTORIZED_LOOP                          
355                                 for(int x = 0; x <= 7; x++) {
356                                         p = &(yaddr[x << 6]);
357                                         pixels[x] = p[y];
358                                 }
359                         }
360                 }
361 __DECL_VECTORIZED_LOOP          
362                 for(int x = 0; x < 8; x++) {
363                         masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
364                         cp[x] = pixels[x];
365                         cm[x] = masks[x];
366                         // Draw to buffer
367                         tpixels[x] = dp[x] & masks[x];
368                         masks[x] = ~masks[x];
369                         pixels[x] = pixels[x] & masks[x];
370                         dp[x] = pixels[x] | tpixels[x];
371                 }
372         }
373 }
374
375
376 inline void TOWNS_SPRITE::render_32768_x1_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
377 {
378         uint16_t* qp = (uint16_t*)(sprite_table[num].pixels);
379         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
380         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
381         int xbegin;
382         int xend;
383         int xstep;
384         int ybegin;
385         int yend;
386         int ystep;
387         int addr_base;
388         int addr_inc;
389         bool xreverse;
390         bool yreverse;
391         bool rotate = false;
392         switch(rot_type) {
393         case ROT_FMTOWNS_SPRITE_0:
394                         xbegin = 0;
395                         xend = 16;
396                         xstep = 1;
397                         ybegin = 0;
398                         yend = 8;
399                         ystep = 1;
400                         xreverse = false;
401                         yreverse = false;
402                         rotate = false;
403                         if(is_mirror) {
404                                 xreverse = true;
405                         }
406                 }                       
407                 break;
408         case ROT_FMTOWNS_SPRITE_90:
409                         xbegin = 0;
410                         xend = 16;
411                         xstep = 1;
412                         ybegin = 0;
413                         yend = 8;
414                         ystep = 1;
415                         xreverse = false;
416                         yreverse = true;
417                         rotate = true;
418                         if(is_mirror) {
419                                 yreverse = false;
420                         }
421                 }                       
422                 break;
423         case ROT_FMTOWNS_SPRITE_180:
424                         xbegin = 0;
425                         xend = 16;
426                         xstep = 1;
427                         ybegin = 0;
428                         yend = 8;
429                         ystep = 1;
430                         xreverse = true;
431                         yreverse = true;
432                         rotate = false;
433                         if(is_mirror) {
434                                 xreverse = false;
435                         }
436                 }                       
437                 break;
438         case ROT_FMTOWNS_SPRITE_270:
439                         xbegin = 0;
440                         xend = 16;
441                         xstep = 1;
442                         ybegin = 0;
443                         yend = 8;
444                         ystep = 1;
445                         xreverse = true;
446                         yreverse = false;
447                         rotate = true;
448                         if(is_mirror) {
449                                 yreverse = true;
450                         }
451                 }                       
452                 break;
453         }
454         uint16_t pixels[16];
455         uint16_t masks[16];
456         uint16_t tpixels[16];
457         uint16_t* cp;
458         uint16_t* cm;
459         uint16* dp;
460         uint16_t* yaddr;
461         uint16_t*p;
462         for(y = ybegin; y != yend; y += ystep) {
463                 cp = &(cache_pixel[y << 5]);
464                 cm = &(cache_mask[y << 5]);
465                 dp =  &(dst[stride * y]);
466                 if(!rotate) {
467                         if(yreverse) {
468                                 yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels)
469                         } else {
470                                 yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels)
471                         }
472                         p = &(yaddr[0]);
473                         if(xreverse) {
474 __DECL_VECTORIZED_LOOP
475                                 for(int i = 15; i >= 0; i--) {
476                                         pixels[i] = p[15 - i];
477                                 }
478                         } else {
479 __DECL_VECTORIZED_LOOP
480                                 for(int i = 0; i <= 15; i++) {
481                                         pixels[i] = p[i];
482                                 }
483                         }
484                 } else {
485                         // Rotate: Swap x, y
486                         if(yreverse) {
487                                 yaddr = &(qp[15 - (y << 1)]);
488                         } else {
489                                 yaddr = &(qp[y << 1]);
490                         }                       
491                         if(xreverse) {
492 __DECL_VECTORIZED_LOOP                          
493                                 for(int x = 7; x >= 0; x--) {
494                                         p = &(yaddr[x << 6]);
495                                         pixels[x] = p[7 - y];
496                                 }
497                         } else {
498 __DECL_VECTORIZED_LOOP                          
499                                 for(int x = 0; x <= 7; x++) {
500                                         p = &(yaddr[x << 6]);
501                                         pixels[x] = p[y];
502                                 }
503                         }
504                 }
505 __DECL_VECTORIZED_LOOP          
506                 for(int x = 0; x < 8; x++) {
507                         masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
508                         cp[x] = pixels[x];
509                         cm[x] = masks[x];
510                         // Draw to buffer
511                         tpixels[x] = dp[x] & masks[x];
512                         masks[x] = ~masks[x];
513                         pixels[x] = pixels[x] & masks[x];
514                         dp[x] = pixels[x] | tpixels[x];
515                 }
516         }
517 }
518
519 inline void TOWNS_SPRITE::render_32768_x05_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
520 {
521         uint16_t* qp = (uint16_t*)(sprite_table[num].pixels);
522         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
523         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
524         int xbegin;
525         int xend;
526         int xstep;
527         int ybegin;
528         int yend;
529         int ystep;
530         int addr_base;
531         int addr_inc;
532         bool xreverse;
533         bool yreverse;
534         bool rotate = false;
535         switch(rot_type) {
536         case ROT_FMTOWNS_SPRITE_0:
537                         xbegin = 0;
538                         xend = 8;
539                         xstep = 1;
540                         ybegin = 0;
541                         yend = 8;
542                         ystep = 1;
543                         xreverse = false;
544                         yreverse = false;
545                         rotate = false;
546                         if(is_mirror) {
547                                 xreverse = true;
548                         }
549                 }                       
550                 break;
551         case ROT_FMTOWNS_SPRITE_90:
552                         xbegin = 0;
553                         xend = 8;
554                         xstep = 1;
555                         ybegin = 0;
556                         yend = 8;
557                         ystep = 1;
558                         xreverse = false;
559                         yreverse = true;
560                         rotate = true;
561                         if(is_mirror) {
562                                 yreverse = false;
563                         }
564                 }                       
565                 break;
566         case ROT_FMTOWNS_SPRITE_180:
567                         xbegin = 0;
568                         xend = 8;
569                         xstep = 1;
570                         ybegin = 0;
571                         yend = 8;
572                         ystep = 1;
573                         xreverse = true;
574                         yreverse = true;
575                         rotate = false;
576                         if(is_mirror) {
577                                 xreverse = false;
578                         }
579                 }                       
580                 break;
581         case ROT_FMTOWNS_SPRITE_270:
582                         xbegin = 0;
583                         xend = 8;
584                         xstep = 1;
585                         ybegin = 0;
586                         yend = 8;
587                         ystep = 1;
588                         xreverse = true;
589                         yreverse = false;
590                         rotate = true;
591                         if(is_mirror) {
592                                 yreverse = true;
593                         }
594                 }                       
595                 break;
596         }
597         uint16_t pixels[16];
598         uint16_t masks[16];
599         uint16_t tpixels[16];
600         uint16_t* cp;
601         uint16_t* cm;
602         uint16* dp;
603         uint16_t* yaddr;
604         uint16_t*p;
605         for(y = ybegin; y != yend; y += ystep) {
606                 cp = &(cache_pixel[y << 5]);
607                 cm = &(cache_mask[y << 5]);
608                 dp =  &(dst[stride * y]);
609                 if(!rotate) {
610                         if(yreverse) {
611                                 yaddr = &(qp[(7 - y) << 6]); // 1 line is 8 bytes (16pixels)
612                         } else {
613                                 yaddr = &(qp[y << 6]); // 1 line is 8 bytes (16pixels)
614                         }
615                         p = &(yaddr[0]);
616                         if(xreverse) {
617 __DECL_VECTORIZED_LOOP
618                                 for(int i = 7; i >= 0; i--) {
619                                         pixels[i] = p[15 - (i << 1)];
620                                 }
621                         } else {
622 __DECL_VECTORIZED_LOOP
623                                 for(int i = 0; i <= 7; i++) {
624                                         pixels[i] = p[i << 1];
625                                 }
626                         }
627                 } else {
628                         // Rotate: Swap x, y
629                         if(yreverse) {
630                                 yaddr = &(qp[15 - (y << 1)]);
631                         } else {
632                                 yaddr = &(qp[y << 1]);
633                         }                       
634                         if(xreverse) {
635 __DECL_VECTORIZED_LOOP                          
636                                 for(int x = 7; x >= 0; x--) {
637                                         p = &(yaddr[x << 6]);
638                                         pixels[x] = p[7 - (y >> 1)];
639                                 }
640                         } else {
641 __DECL_VECTORIZED_LOOP                          
642                                 for(int x = 0; x <= 7; x++) {
643                                         p = &(yaddr[x << 6]);
644                                         pixels[x] = p[y];
645                                 }
646                         }
647                 }
648 __DECL_VECTORIZED_LOOP          
649                 for(int x = 0; x < 8; x++) {
650                         masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
651                         cp[x] = pixels[x];
652                         cm[x] = masks[x];
653                         // Draw to buffer
654                         tpixels[x] = dp[x] & masks[x];
655                         masks[x] = ~masks[x];
656                         pixels[x] = pixels[x] & masks[x];
657                         dp[x] = pixels[x] | tpixels[x];
658                 }
659         }
660 }
661
662
663 inline void TOWNS_SPRITE::render_16_x1_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
664 {
665         uint8_t* qp = (uint8_t*)(sprite_table[num].pixels);
666         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
667         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
668         int xbegin;
669         int xend;
670         int xstep;
671         int ybegin;
672         int yend;
673         int ystep;
674         int addr_base;
675         int addr_inc;
676         bool xreverse;
677         bool yreverse;
678         bool rotate = false;
679         switch(rot_type) {
680         case ROT_FMTOWNS_SPRITE_0:
681                         xbegin = 0;
682                         xend = 16;
683                         xstep = 1;
684                         ybegin = 0;
685                         yend = 16;
686                         ystep = 1;
687                         xreverse = false;
688                         yreverse = false;
689                         rotate = false;
690                         if(is_mirror) {
691                                 xreverse = true;
692                         }
693                 }                       
694                 break;
695         case ROT_FMTOWNS_SPRITE_90:
696                         xbegin = 0;
697                         xend = 16;
698                         xstep = 1;
699                         ybegin = 0;
700                         yend = 16;
701                         ystep = 1;
702                         xreverse = false;
703                         yreverse = true;
704                         rotate = true;
705                         if(is_mirror) {
706                                 yreverse = false;
707                         }
708                 }                       
709                 break;
710         case ROT_FMTOWNS_SPRITE_180:
711                         xbegin = 0;
712                         xend = 16;
713                         xstep = 1;
714                         ybegin = 0;
715                         yend = 16;
716                         ystep = 1;
717                         xreverse = true;
718                         yreverse = true;
719                         rotate = false;
720                         if(is_mirror) {
721                                 xreverse = false;
722                         }
723                 }                       
724                 break;
725         case ROT_FMTOWNS_SPRITE_270:
726                         xbegin = 0;
727                         xend = 16;
728                         xstep = 1;
729                         ybegin = 0;
730                         yend = 16;
731                         ystep = 1;
732                         xreverse = true;
733                         yreverse = false;
734                         rotate = true;
735                         if(is_mirror) {
736                                 yreverse = true;
737                         }
738                 }                       
739                 break;
740         }
741         uint8_t pixels[16];
742         uint16_t masks[16];
743         uint16_t tpixels[16];
744         uint16_t tpixels2[16];
745         uint16_t* cp;
746         uint16_t* cm;
747         uint16* dp;
748         uint8_t* yaddr;
749         uint8_t* p;
750         for(y = ybegin; y != yend; y += ystep) {
751                 cp = &(cache_pixel[y << 5]);
752                 cm = &(cache_mask[y << 5]);
753                 dp =  &(dst[stride * y]);
754                 if(!rotate) {
755                         if(yreverse) {
756                                 yaddr = &(qp[(y - 15) << 3]); // 1 line is 4 bytes (16pixels)
757                         } else {
758                                 yaddr = &(qp[y << 3]); // 1 line is 4 bytes (16pixels)
759                         }
760                         p = &(yaddr[0]);
761                         if(xreverse) {
762 __DECL_VECTORIZED_LOOP
763                                 for(int i = 15; i >= 0; i--) {
764                                         pixels[i] = p[(15 - i) >> 1];
765                                 }
766                         } else {
767 __DECL_VECTORIZED_LOOP
768                                 for(int i = 0; i <= 15; i++) {
769                                         pixels[i] = p[i];
770                                 }
771                         }
772 __DECL_VECTORIZED_LOOP
773                         for(int i = 0; i < 16; i+= 2) {
774                                 pixels[i] = pixels[i] >> 4;
775                         }
776 __DECL_VECTORIZED_LOOP
777                         for(int i = 0; i < 16; i++) {
778                                 pixels[i] = pixels[i] & 0x0f;
779                         }
780                 } else {
781                         // Rotate: Swap x, y
782                         if(yreverse) {
783                                 yaddr = &(qp[(15 - y) >> 1]);
784                         } else {
785                                 yaddr = &(qp[(y >> 1)]);
786                         }                       
787                         if(xreverse) {
788 __DECL_VECTORIZED_LOOP                          
789                                 for(int x = 15; x >= 0; x--) {
790                                         p = &(yaddr[x << 3]);
791                                         pixels[x] = p[(15 - y) >> 1];
792                                 }
793                         } else {
794 __DECL_VECTORIZED_LOOP                          
795                                 for(int x = 0; x <= 15; x++) {
796                                         p = &(yaddr[x << 3]);
797                                         pixels[x] = p[y >> 1];
798                                 }
799                         }
800 __DECL_VECTORIZED_LOOP
801                         for(int i = 0; i < 16; i++) {
802                                 pixels[i] = pixels[i] >> 4;
803                                 pixels[i] = pixels[i] & 0x0f;
804                         }
805                         
806                 }
807 __DECL_VECTORIZED_LOOP          
808                 for(int x = 0; x < 16; x++) {
809                         masks[x] = (pixels[x] == 0) ? 0xffff : 0x0000
810                         tpixel[x] = color_index[pixels[x]];
811                         cp[x] = tpixel;
812                         cm[x] = masks[x];
813                         // Draw to buffer
814                         tpixels2[x] = dp[x] & masks[x];
815                         masks[x] = ~masks[x];
816                         tpixels[x] = tpixels[x] & masks[x];
817                         dp[x] = tpixels[x] | tpixels2[x];
818                 }
819         }
820 }
821
822 inline void TOWNS_SPRITE::render_16_x05_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
823 {
824         uint16_t* qp = (uint16_t*)(sprite_table[num].pixels);
825         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
826         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
827         int xbegin;
828         int xend;
829         int xstep;
830         int ybegin;
831         int yend;
832         int ystep;
833         int addr_base;
834         int addr_inc;
835         bool xreverse;
836         bool yreverse;
837         bool rotate = false;
838         switch(rot_type) {
839         case ROT_FMTOWNS_SPRITE_0:
840                         xbegin = 0;
841                         xend = 16;
842                         xstep = 2;
843                         ybegin = 0;
844                         yend = 16;
845                         ystep = 1;
846                         xreverse = false;
847                         yreverse = false;
848                         rotate = false;
849                         if(is_mirror) {
850                                 xreverse = true;
851                         }
852                 }                       
853                 break;
854         case ROT_FMTOWNS_SPRITE_90:
855                         xbegin = 0;
856                         xend = 16;
857                         xstep = 2;
858                         ybegin = 0;
859                         yend = 16;
860                         ystep = 1;
861                         xreverse = false;
862                         yreverse = true;
863                         rotate = true;
864                         if(is_mirror) {
865                                 yreverse = false;
866                         }
867                 }                       
868                 break;
869         case ROT_FMTOWNS_SPRITE_180:
870                         xbegin = 0;
871                         xend = 16;
872                         xstep = 2;
873                         ybegin = 0;
874                         yend = 16;
875                         ystep = 1;
876                         xreverse = true;
877                         yreverse = true;
878                         rotate = false;
879                         if(is_mirror) {
880                                 xreverse = false;
881                         }
882                 }                       
883                 break;
884         case ROT_FMTOWNS_SPRITE_270:
885                         xbegin = 0;
886                         xend = 16;
887                         xstep = 2;
888                         ybegin = 0;
889                         yend = 16;
890                         ystep = 1;
891                         xreverse = true;
892                         yreverse = false;
893                         rotate = true;
894                         if(is_mirror) {
895                                 yreverse = true;
896                         }
897                 }                       
898                 break;
899         }
900         uint16_t pixels[16];
901         uint16_t masks[16];
902         uint16_t tpixels[16];
903         uint16_t* cp;
904         uint16_t* cm;
905         uint16* dp;
906         uint8_t* yaddr;
907         uint8_t*p;
908         for(y = ybegin; y != yend; y += ystep) {
909                 cp = &(cache_pixel[y << 5]);
910                 cm = &(cache_mask[y << 5]);
911                 dp =  &(dst[stride * y]);
912                 if(!rotate) {
913                         if(yreverse) {
914                                 yaddr = &(qp[(y - 15) << 3]); // 1 line is 4 bytes (16pixels)
915                         } else {
916                                 yaddr = &(qp[y << 3]); // 1 line is 4 bytes (16pixels)
917                         }
918                         p = &(yaddr[0]);
919                         if(xreverse) {
920 __DECL_VECTORIZED_LOOP
921                                 for(int i = 7; i >= 0; i--) {
922                                         pixels[i] = p[7 - i];
923                                 }
924                         } else {
925 __DECL_VECTORIZED_LOOP
926                                 for(int i = 0; i <= 7; i++) {
927                                         pixels[i] = p[i];
928                                 }
929                         }
930 __DECL_VECTORIZED_LOOP
931                         for(int i = 0; i < 8; i+= 2) {
932                                 pixels[i] = pixels[i] >> 4;
933                                 pixels[i] = pixels[i] & 0x0f;
934                         }
935                 } else {
936                         // Rotate: Swap x, y
937                         if(yreverse) {
938                                 yaddr = &(qp[(15 - y) >> 1]);
939                         } else {
940                                 yaddr = &(qp[y >> 1]);
941                         }                       
942                         if(xreverse) {
943 __DECL_VECTORIZED_LOOP                          
944                                 for(int x = 7; x >= 0; x--) {
945                                         p = &(yaddr[x << 4]);
946                                         pixels[x] = p[15 - y];
947                                 }
948                         } else {
949 __DECL_VECTORIZED_LOOP                          
950                                 for(int x = 0; x <= 7; x++) {
951                                         p = &(yaddr[x << 4]);
952                                         pixels[x] = p[y];
953                                 }
954                         }
955 __DECL_VECTORIZED_LOOP
956                         for(int i = 0; i < 8; i++) {
957                                 pixels[i] = pixels[i] >> 4;
958                                 pixels[i] = pixels[i] & 0x0f;
959                         }
960                 }
961 __DECL_VECTORIZED_LOOP          
962                 for(int x = 0; x < 8; x++) {
963                         masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
964                         cp[x] = pixels[x];
965                         cm[x] = masks[x];
966                         // Draw to buffer
967                         tpixels[x] = dp[x] & masks[x];
968                         masks[x] = ~masks[x];
969                         pixels[x] = pixels[x] & masks[x];
970                         dp[x] = pixels[x] | tpixels[x];
971                 }
972         }
973 }
974
975
976 inline void TOWNS_SPRITE::render_16_x1_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
977 {
978         uint16_t* qp = (uint16_t*)(sprite_table[num].pixels);
979         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
980         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
981         int xbegin;
982         int xend;
983         int xstep;
984         int ybegin;
985         int yend;
986         int ystep;
987         int addr_base;
988         int addr_inc;
989         bool xreverse;
990         bool yreverse;
991         bool rotate = false;
992         switch(rot_type) {
993         case ROT_FMTOWNS_SPRITE_0:
994                         xbegin = 0;
995                         xend = 16;
996                         xstep = 1;
997                         ybegin = 0;
998                         yend = 8;
999                         ystep = 1;
1000                         xreverse = false;
1001                         yreverse = false;
1002                         rotate = false;
1003                         if(is_mirror) {
1004                                 xreverse = true;
1005                         }
1006                 }                       
1007                 break;
1008         case ROT_FMTOWNS_SPRITE_90:
1009                         xbegin = 0;
1010                         xend = 16;
1011                         xstep = 1;
1012                         ybegin = 0;
1013                         yend = 8;
1014                         ystep = 1;
1015                         xreverse = false;
1016                         yreverse = true;
1017                         rotate = true;
1018                         if(is_mirror) {
1019                                 yreverse = false;
1020                         }
1021                 }                       
1022                 break;
1023         case ROT_FMTOWNS_SPRITE_180:
1024                         xbegin = 0;
1025                         xend = 16;
1026                         xstep = 1;
1027                         ybegin = 0;
1028                         yend = 8;
1029                         ystep = 1;
1030                         xreverse = true;
1031                         yreverse = true;
1032                         rotate = false;
1033                         if(is_mirror) {
1034                                 xreverse = false;
1035                         }
1036                 }                       
1037                 break;
1038         case ROT_FMTOWNS_SPRITE_270:
1039                         xbegin = 0;
1040                         xend = 16;
1041                         xstep = 1;
1042                         ybegin = 0;
1043                         yend = 8;
1044                         ystep = 1;
1045                         xreverse = true;
1046                         yreverse = false;
1047                         rotate = true;
1048                         if(is_mirror) {
1049                                 yreverse = true;
1050                         }
1051                 }                       
1052                 break;
1053         }
1054         uint16_t pixels[16];
1055         uint16_t masks[16];
1056         uint16_t tpixels[16];
1057         uint16_t* cp;
1058         uint16_t* cm;
1059         uint16* dp;
1060         uint16_t* yaddr;
1061         uint16_t*p;
1062         for(y = ybegin; y != yend; y += ystep) {
1063                 cp = &(cache_pixel[y << 5]);
1064                 cm = &(cache_mask[y << 5]);
1065                 dp =  &(dst[stride * y]);
1066                 if(!rotate) {
1067                         if(yreverse) {
1068                                 yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels)
1069                         } else {
1070                                 yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels)
1071                         }
1072                         p = &(yaddr[0]);
1073                         if(xreverse) {
1074 __DECL_VECTORIZED_LOOP
1075                                 for(int i = 15; i >= 0; i--) {
1076                                         pixels[i] = p[15 - i];
1077                                 }
1078                         } else {
1079 __DECL_VECTORIZED_LOOP
1080                                 for(int i = 0; i <= 15; i++) {
1081                                         pixels[i] = p[i];
1082                                 }
1083                         }
1084                 } else {
1085                         // Rotate: Swap x, y
1086                         if(yreverse) {
1087                                 yaddr = &(qp[15 - (y << 1)]);
1088                         } else {
1089                                 yaddr = &(qp[y << 1]);
1090                         }                       
1091                         if(xreverse) {
1092 __DECL_VECTORIZED_LOOP                          
1093                                 for(int x = 7; x >= 0; x--) {
1094                                         p = &(yaddr[x << 6]);
1095                                         pixels[x] = p[7 - y];
1096                                 }
1097                         } else {
1098 __DECL_VECTORIZED_LOOP                          
1099                                 for(int x = 0; x <= 7; x++) {
1100                                         p = &(yaddr[x << 6]);
1101                                         pixels[x] = p[y];
1102                                 }
1103                         }
1104                 }
1105 __DECL_VECTORIZED_LOOP          
1106                 for(int x = 0; x < 8; x++) {
1107                         masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
1108                         cp[x] = pixels[x];
1109                         cm[x] = masks[x];
1110                         // Draw to buffer
1111                         tpixels[x] = dp[x] & masks[x];
1112                         masks[x] = ~masks[x];
1113                         pixels[x] = pixels[x] & masks[x];
1114                         dp[x] = pixels[x] | tpixels[x];
1115                 }
1116         }
1117 }
1118
1119 inline void TOWNS_SPRITE::render_16_x05_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
1120 {
1121         uint16_t* qp = (uint16_t*)(sprite_table[num].pixels);
1122         uint16_t *cache_pixel = &(cache_pixels[last_put_cache_num][0]);
1123         uint16_t *cache_mask = cache_masks[last_put_cache_num][0];
1124         int xbegin;
1125         int xend;
1126         int xstep;
1127         int ybegin;
1128         int yend;
1129         int ystep;
1130         int addr_base;
1131         int addr_inc;
1132         bool xreverse;
1133         bool yreverse;
1134         bool rotate = false;
1135         switch(rot_type) {
1136         case ROT_FMTOWNS_SPRITE_0:
1137                         xbegin = 0;
1138                         xend = 8;
1139                         xstep = 1;
1140                         ybegin = 0;
1141                         yend = 8;
1142                         ystep = 1;
1143                         xreverse = false;
1144                         yreverse = false;
1145                         rotate = false;
1146                         if(is_mirror) {
1147                                 xreverse = true;
1148                         }
1149                 }                       
1150                 break;
1151         case ROT_FMTOWNS_SPRITE_90:
1152                         xbegin = 0;
1153                         xend = 8;
1154                         xstep = 1;
1155                         ybegin = 0;
1156                         yend = 8;
1157                         ystep = 1;
1158                         xreverse = false;
1159                         yreverse = true;
1160                         rotate = true;
1161                         if(is_mirror) {
1162                                 yreverse = false;
1163                         }
1164                 }                       
1165                 break;
1166         case ROT_FMTOWNS_SPRITE_180:
1167                         xbegin = 0;
1168                         xend = 8;
1169                         xstep = 1;
1170                         ybegin = 0;
1171                         yend = 8;
1172                         ystep = 1;
1173                         xreverse = true;
1174                         yreverse = true;
1175                         rotate = false;
1176                         if(is_mirror) {
1177                                 xreverse = false;
1178                         }
1179                 }                       
1180                 break;
1181         case ROT_FMTOWNS_SPRITE_270:
1182                         xbegin = 0;
1183                         xend = 8;
1184                         xstep = 1;
1185                         ybegin = 0;
1186                         yend = 8;
1187                         ystep = 1;
1188                         xreverse = true;
1189                         yreverse = false;
1190                         rotate = true;
1191                         if(is_mirror) {
1192                                 yreverse = true;
1193                         }
1194                 }                       
1195                 break;
1196         }
1197         uint16_t pixels[16];
1198         uint16_t masks[16];
1199         uint16_t tpixels[16];
1200         uint16_t* cp;
1201         uint16_t* cm;
1202         uint16* dp;
1203         uint16_t* yaddr;
1204         uint16_t*p;
1205         for(y = ybegin; y != yend; y += ystep) {
1206                 cp = &(cache_pixel[y << 5]);
1207                 cm = &(cache_mask[y << 5]);
1208                 dp =  &(dst[stride * y]);
1209                 if(!rotate) {
1210                         if(yreverse) {
1211                                 yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels)
1212                         } else {
1213                                 yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels)
1214                         }
1215                         p = &(yaddr[0]);
1216                         if(xreverse) {
1217 __DECL_VECTORIZED_LOOP
1218                                 for(int i = 7; i >= 0; i--) {
1219                                         pixels[i] = p[15 - (i << 1)];
1220                                 }
1221                         } else {
1222 __DECL_VECTORIZED_LOOP
1223                                 for(int i = 0; i <= 7; i++) {
1224                                         pixels[i] = p[i << 1];
1225                                 }
1226                         }
1227                 } else {
1228                         // Rotate: Swap x, y
1229                         if(yreverse) {
1230                                 yaddr = &(qp[15 - (y << 1)]);
1231                         } else {
1232                                 yaddr = &(qp[y << 1]);
1233                         }                       
1234                         if(xreverse) {
1235 __DECL_VECTORIZED_LOOP                          
1236                                 for(int x = 7; x >= 0; x--) {
1237                                         p = &(yaddr[x << 6]);
1238                                         pixels[x] = p[7 - x];
1239                                 }
1240                         } else {
1241 __DECL_VECTORIZED_LOOP                          
1242                                 for(int x = 0; x <= 7; x++) {
1243                                         p = &(yaddr[x << 6]);
1244                                         pixels[x] = p[x];
1245                                 }
1246                         }
1247                 }
1248 __DECL_VECTORIZED_LOOP          
1249                 for(int x = 0; x < 8; x++) {
1250                         masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
1251                         cp[x] = pixels[x];
1252                         cm[x] = masks[x];
1253                         // Draw to buffer
1254                         tpixels[x] = dp[x] & masks[x];
1255                         masks[x] = ~masks[x];
1256                         pixels[x] = pixels[x] & masks[x];
1257                         dp[x] = pixels[x] | tpixels[x];
1258                 }
1259         }
1260 }
1261
1262
1263 inline void TOWNS_SPRITE::render_base(int num, uint16* dst_pixel, int width, int height, int stride)
1264 {
1265         int half_type = 0;
1266         int rot_type;
1267         half_type = half_type | ((cache_index[num].is_halfx) ? 1 : 0);
1268         half_type = half_type | ((cache_index[num].is_halfy) ? 2 : 0);
1269
1270         switch((sprite_table[num].rotate) & 7) {
1271         case 0:
1272                 rot_type = ROT_FMTOWNS_SPRITE_0;
1273                 is_mirror = false;
1274                 break;
1275         case 1:
1276                 rot_type = ROT_FMTOWNS_SPRITE_180;
1277                 is_mirror = true;
1278                 break;
1279         case 2:
1280                 rot_type = ROT_FMTOWNS_SPRITE_180;
1281                 is_mirror = false;
1282                 break;
1283         case 3:
1284                 rot_type = ROT_FMTOWNS_SPRITE_0;
1285                 is_mirror = true;
1286                 break;
1287         case 4:
1288                 rot_type = ROT_FMTOWNS_SPRITE_270;
1289                 is_mirror = true;
1290                 break;
1291         case 5:
1292                 rot_type = ROT_FMTOWNS_SPRITE_90;
1293                 is_mirror = false;
1294                 break;
1295         case 6:
1296                 rotate = false;
1297                 rot_type = ROT_FMTOWNS_SPRITE_270;
1298                 is_mirror = false;
1299                 break;
1300         case 7:
1301                 rot_type = ROT_FMTOWNS_SPRITE_90;
1302                 is_mirror = true;
1303                 break;
1304         }
1305         if(sprite_table[num].is_32768) {
1306         switch(half_type & 3) {
1307         case 0: // not rotate
1308                 render_32768_x1_x1(num, dst, rot_type, mirror, stride);
1309                 break;
1310         case 1:
1311                 render_32768_x05_x1(num, dst, rot_type, mirror, stride);
1312                 break;
1313         case 2:
1314                 render_32768_x1_x05(num, dst, rot_type, mirror, stride);
1315                 break;
1316         case 3:
1317                 render_32768_x05_x05(num, dst, rot_type, mirror, stride);
1318                 break;
1319         }
1320         } else {
1321         switch(half_type & 3) {
1322         case 0: // not rotate
1323                 render_16_x1_x1(num, dst, rot_type, mirror, stride);
1324                 break;
1325         case 1:
1326                 render_16_x05_x1(num, dst, rot_type, mirror, stride);
1327                 break;
1328         case 2:
1329                 render_16_x1_x05(num, dst, rot_type, mirror, stride);
1330                 break;
1331         case 3:
1332                 render_16_x05_x05(num, dst, rot_type, mirror, stride);
1333                 break;
1334         }
1335         }
1336 }
1337
1338 #endif /* _TOWNS_SPRITE_H */