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
34 TOWNS_VRAM *vram_head;
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];
54 bool pattern_cached[((65536 - (4096 * 2)) * 2) / (8 * 16)];
55 bool color_cached[256];
60 TOWNS_SPRITE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
61 set_device_name(_T("SPRITE"));
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);
73 uint32_t read_data8(uint32_t addr);
74 uint32_t read_data16(uint32_t addr);
75 uint32_t read_data32(uint32_t addr);
77 void write_signal(int id, uint32_t data, uint32_t mask);
81 void set_context_vram(TOWNS_VRAM *p)
85 void save_state(FILEIO *fio);
86 bool load_stste(FILEIO *fio);
89 inline void TOWNS_SPRITE::render_32768_x1_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
106 case ROT_FMTOWNS_SPRITE_0:
121 case ROT_FMTOWNS_SPRITE_90:
136 case ROT_FMTOWNS_SPRITE_180:
151 case ROT_FMTOWNS_SPRITE_270:
169 uint16_t tpixels[16];
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]);
181 yaddr = &(qp[(y - 15) << 5]); // 1 line is 4 bytes (16pixels)
183 yaddr = &(qp[y << 5]); // 1 line is 4 bytes (16pixels)
187 __DECL_VECTORIZED_LOOP
188 for(int i = 15; i >= 0; i--) {
189 pixels[i] = p[15 - i];
192 __DECL_VECTORIZED_LOOP
193 for(int i = 0; i <= 15; i++) {
200 yaddr = &(qp[15 - y]);
205 __DECL_VECTORIZED_LOOP
206 for(int x = 15; x >= 0; x--) {
207 p = &(yaddr[x << 5]);
208 pixels[x] = p[15 - y];
211 __DECL_VECTORIZED_LOOP
212 for(int x = 0; x <= 15; x++) {
213 p = &(yaddr[x << 5]);
218 __DECL_VECTORIZED_LOOP
219 for(int x = 0; x < 16; x++) {
220 masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
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];
232 inline void TOWNS_SPRITE::render_32768_x05_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
249 case ROT_FMTOWNS_SPRITE_0:
264 case ROT_FMTOWNS_SPRITE_90:
279 case ROT_FMTOWNS_SPRITE_180:
294 case ROT_FMTOWNS_SPRITE_270:
312 uint16_t tpixels[16];
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]);
324 yaddr = &(qp[(y - 15) << 5]); // 1 line is 4 bytes (16pixels)
326 yaddr = &(qp[y << 5]); // 1 line is 4 bytes (16pixels)
330 __DECL_VECTORIZED_LOOP
331 for(int i = 7; i >= 0; i--) {
332 pixels[i] = p[15 - (i << 1)];
335 __DECL_VECTORIZED_LOOP
336 for(int i = 0; i <= 7; i++) {
337 pixels[i] = p[i << 1];
343 yaddr = &(qp[15 - y]);
348 __DECL_VECTORIZED_LOOP
349 for(int x = 7; x >= 0; x--) {
350 p = &(yaddr[x << 6]);
351 pixels[x] = p[15 - y];
354 __DECL_VECTORIZED_LOOP
355 for(int x = 0; x <= 7; x++) {
356 p = &(yaddr[x << 6]);
361 __DECL_VECTORIZED_LOOP
362 for(int x = 0; x < 8; x++) {
363 masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
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];
376 inline void TOWNS_SPRITE::render_32768_x1_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
393 case ROT_FMTOWNS_SPRITE_0:
408 case ROT_FMTOWNS_SPRITE_90:
423 case ROT_FMTOWNS_SPRITE_180:
438 case ROT_FMTOWNS_SPRITE_270:
456 uint16_t tpixels[16];
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]);
468 yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels)
470 yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels)
474 __DECL_VECTORIZED_LOOP
475 for(int i = 15; i >= 0; i--) {
476 pixels[i] = p[15 - i];
479 __DECL_VECTORIZED_LOOP
480 for(int i = 0; i <= 15; i++) {
487 yaddr = &(qp[15 - (y << 1)]);
489 yaddr = &(qp[y << 1]);
492 __DECL_VECTORIZED_LOOP
493 for(int x = 7; x >= 0; x--) {
494 p = &(yaddr[x << 6]);
495 pixels[x] = p[7 - y];
498 __DECL_VECTORIZED_LOOP
499 for(int x = 0; x <= 7; x++) {
500 p = &(yaddr[x << 6]);
505 __DECL_VECTORIZED_LOOP
506 for(int x = 0; x < 8; x++) {
507 masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
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];
519 inline void TOWNS_SPRITE::render_32768_x05_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
536 case ROT_FMTOWNS_SPRITE_0:
551 case ROT_FMTOWNS_SPRITE_90:
566 case ROT_FMTOWNS_SPRITE_180:
581 case ROT_FMTOWNS_SPRITE_270:
599 uint16_t tpixels[16];
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]);
611 yaddr = &(qp[(7 - y) << 6]); // 1 line is 8 bytes (16pixels)
613 yaddr = &(qp[y << 6]); // 1 line is 8 bytes (16pixels)
617 __DECL_VECTORIZED_LOOP
618 for(int i = 7; i >= 0; i--) {
619 pixels[i] = p[15 - (i << 1)];
622 __DECL_VECTORIZED_LOOP
623 for(int i = 0; i <= 7; i++) {
624 pixels[i] = p[i << 1];
630 yaddr = &(qp[15 - (y << 1)]);
632 yaddr = &(qp[y << 1]);
635 __DECL_VECTORIZED_LOOP
636 for(int x = 7; x >= 0; x--) {
637 p = &(yaddr[x << 6]);
638 pixels[x] = p[7 - (y >> 1)];
641 __DECL_VECTORIZED_LOOP
642 for(int x = 0; x <= 7; x++) {
643 p = &(yaddr[x << 6]);
648 __DECL_VECTORIZED_LOOP
649 for(int x = 0; x < 8; x++) {
650 masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
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];
663 inline void TOWNS_SPRITE::render_16_x1_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
680 case ROT_FMTOWNS_SPRITE_0:
695 case ROT_FMTOWNS_SPRITE_90:
710 case ROT_FMTOWNS_SPRITE_180:
725 case ROT_FMTOWNS_SPRITE_270:
743 uint16_t tpixels[16];
744 uint16_t tpixels2[16];
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]);
756 yaddr = &(qp[(y - 15) << 3]); // 1 line is 4 bytes (16pixels)
758 yaddr = &(qp[y << 3]); // 1 line is 4 bytes (16pixels)
762 __DECL_VECTORIZED_LOOP
763 for(int i = 15; i >= 0; i--) {
764 pixels[i] = p[(15 - i) >> 1];
767 __DECL_VECTORIZED_LOOP
768 for(int i = 0; i <= 15; i++) {
772 __DECL_VECTORIZED_LOOP
773 for(int i = 0; i < 16; i+= 2) {
774 pixels[i] = pixels[i] >> 4;
776 __DECL_VECTORIZED_LOOP
777 for(int i = 0; i < 16; i++) {
778 pixels[i] = pixels[i] & 0x0f;
783 yaddr = &(qp[(15 - y) >> 1]);
785 yaddr = &(qp[(y >> 1)]);
788 __DECL_VECTORIZED_LOOP
789 for(int x = 15; x >= 0; x--) {
790 p = &(yaddr[x << 3]);
791 pixels[x] = p[(15 - y) >> 1];
794 __DECL_VECTORIZED_LOOP
795 for(int x = 0; x <= 15; x++) {
796 p = &(yaddr[x << 3]);
797 pixels[x] = p[y >> 1];
800 __DECL_VECTORIZED_LOOP
801 for(int i = 0; i < 16; i++) {
802 pixels[i] = pixels[i] >> 4;
803 pixels[i] = pixels[i] & 0x0f;
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]];
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];
822 inline void TOWNS_SPRITE::render_16_x05_x1(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
839 case ROT_FMTOWNS_SPRITE_0:
854 case ROT_FMTOWNS_SPRITE_90:
869 case ROT_FMTOWNS_SPRITE_180:
884 case ROT_FMTOWNS_SPRITE_270:
902 uint16_t tpixels[16];
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]);
914 yaddr = &(qp[(y - 15) << 3]); // 1 line is 4 bytes (16pixels)
916 yaddr = &(qp[y << 3]); // 1 line is 4 bytes (16pixels)
920 __DECL_VECTORIZED_LOOP
921 for(int i = 7; i >= 0; i--) {
922 pixels[i] = p[7 - i];
925 __DECL_VECTORIZED_LOOP
926 for(int i = 0; i <= 7; i++) {
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;
938 yaddr = &(qp[(15 - y) >> 1]);
940 yaddr = &(qp[y >> 1]);
943 __DECL_VECTORIZED_LOOP
944 for(int x = 7; x >= 0; x--) {
945 p = &(yaddr[x << 4]);
946 pixels[x] = p[15 - y];
949 __DECL_VECTORIZED_LOOP
950 for(int x = 0; x <= 7; x++) {
951 p = &(yaddr[x << 4]);
955 __DECL_VECTORIZED_LOOP
956 for(int i = 0; i < 8; i++) {
957 pixels[i] = pixels[i] >> 4;
958 pixels[i] = pixels[i] & 0x0f;
961 __DECL_VECTORIZED_LOOP
962 for(int x = 0; x < 8; x++) {
963 masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
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];
976 inline void TOWNS_SPRITE::render_16_x1_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
993 case ROT_FMTOWNS_SPRITE_0:
1008 case ROT_FMTOWNS_SPRITE_90:
1023 case ROT_FMTOWNS_SPRITE_180:
1038 case ROT_FMTOWNS_SPRITE_270:
1054 uint16_t pixels[16];
1056 uint16_t tpixels[16];
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]);
1068 yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels)
1070 yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels)
1074 __DECL_VECTORIZED_LOOP
1075 for(int i = 15; i >= 0; i--) {
1076 pixels[i] = p[15 - i];
1079 __DECL_VECTORIZED_LOOP
1080 for(int i = 0; i <= 15; i++) {
1085 // Rotate: Swap x, y
1087 yaddr = &(qp[15 - (y << 1)]);
1089 yaddr = &(qp[y << 1]);
1092 __DECL_VECTORIZED_LOOP
1093 for(int x = 7; x >= 0; x--) {
1094 p = &(yaddr[x << 6]);
1095 pixels[x] = p[7 - y];
1098 __DECL_VECTORIZED_LOOP
1099 for(int x = 0; x <= 7; x++) {
1100 p = &(yaddr[x << 6]);
1105 __DECL_VECTORIZED_LOOP
1106 for(int x = 0; x < 8; x++) {
1107 masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
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];
1119 inline void TOWNS_SPRITE::render_16_x05_x05(int num, uint16_t* dst, int rot_type, bool is_mirror, int stride)
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];
1134 bool rotate = false;
1136 case ROT_FMTOWNS_SPRITE_0:
1151 case ROT_FMTOWNS_SPRITE_90:
1166 case ROT_FMTOWNS_SPRITE_180:
1181 case ROT_FMTOWNS_SPRITE_270:
1197 uint16_t pixels[16];
1199 uint16_t tpixels[16];
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]);
1211 yaddr = &(qp[(7 - y) << 6]); // 1 line is 4 bytes (16pixels)
1213 yaddr = &(qp[y << 6]); // 1 line is 4 bytes (16pixels)
1217 __DECL_VECTORIZED_LOOP
1218 for(int i = 7; i >= 0; i--) {
1219 pixels[i] = p[15 - (i << 1)];
1222 __DECL_VECTORIZED_LOOP
1223 for(int i = 0; i <= 7; i++) {
1224 pixels[i] = p[i << 1];
1228 // Rotate: Swap x, y
1230 yaddr = &(qp[15 - (y << 1)]);
1232 yaddr = &(qp[y << 1]);
1235 __DECL_VECTORIZED_LOOP
1236 for(int x = 7; x >= 0; x--) {
1237 p = &(yaddr[x << 6]);
1238 pixels[x] = p[7 - x];
1241 __DECL_VECTORIZED_LOOP
1242 for(int x = 0; x <= 7; x++) {
1243 p = &(yaddr[x << 6]);
1248 __DECL_VECTORIZED_LOOP
1249 for(int x = 0; x < 8; x++) {
1250 masks[x] = ((pixels[x] & 0x8000) == 0) ? 0xffff : 0x0000;
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];
1263 inline void TOWNS_SPRITE::render_base(int num, uint16* dst_pixel, int width, int height, int stride)
1267 half_type = half_type | ((cache_index[num].is_halfx) ? 1 : 0);
1268 half_type = half_type | ((cache_index[num].is_halfy) ? 2 : 0);
1270 switch((sprite_table[num].rotate) & 7) {
1272 rot_type = ROT_FMTOWNS_SPRITE_0;
1276 rot_type = ROT_FMTOWNS_SPRITE_180;
1280 rot_type = ROT_FMTOWNS_SPRITE_180;
1284 rot_type = ROT_FMTOWNS_SPRITE_0;
1288 rot_type = ROT_FMTOWNS_SPRITE_270;
1292 rot_type = ROT_FMTOWNS_SPRITE_90;
1297 rot_type = ROT_FMTOWNS_SPRITE_270;
1301 rot_type = ROT_FMTOWNS_SPRITE_90;
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);
1311 render_32768_x05_x1(num, dst, rot_type, mirror, stride);
1314 render_32768_x1_x05(num, dst, rot_type, mirror, stride);
1317 render_32768_x05_x05(num, dst, rot_type, mirror, stride);
1321 switch(half_type & 3) {
1322 case 0: // not rotate
1323 render_16_x1_x1(num, dst, rot_type, mirror, stride);
1326 render_16_x05_x1(num, dst, rot_type, mirror, stride);
1329 render_16_x1_x05(num, dst, rot_type, mirror, stride);
1332 render_16_x05_x05(num, dst, rot_type, mirror, stride);
1338 #endif /* _TOWNS_SPRITE_H */