2 Skelton for retropc emulator
4 Author : Kyuma Ohta <whatisthis.sowhat _at_ gmail.com>
8 History: 2017.01.16 Initial.
12 #include "./towns_vram.h"
14 #define CLEAR_COLOR RGBA_COLOR(0,0,0,0)
17 #define _USE_ALPHA_CHANNEL
22 void TOWNS_VRAM::initialize()
24 for(int i = 0; i < 32768; i++) {
25 uint8_t g = (i / (32 * 32)) & 0x1f;
26 uint8_t r = (i / 32) & 0x1f;
28 table_32768c[i] = RGBA_COLOR(r << 3, g << 3, b << 3, 0xff);
29 table_32768c[i + 32768] = table_32768c[i];
30 alpha_32768c[i] = RGBA_COLOR(255, 255, 255, 255);
31 alpha_32768c[i + 32768] = RGBA_COLOR(0, 0, 0, 0);
32 mask_32768c[i] = 0xffff;
33 mask_32768c[i + 32768] = 0x0000;
35 for(int i = 0; i < 256; i++) {
39 alpha_16c[ i << 2 ] = (chigh == 0) ? RGBA_COLOR(0, 0, 0, 0) : RGBA_COLOR(255, 255, 255, 255);
40 alpha_16c[(i << 2) + 1] = (clow == 0) ? RGBA_COLOR(0, 0, 0, 0) : RGBA_COLOR(255, 255, 255, 255);
41 mask_16c[i] = ((chigh == 0) ? 0x00: 0xf0) | ((clow == 0) ? 0x00 : 0x0f);
43 for(int i = 0; i < TOWNS_CRTC_MAX_LINES; i++) {
44 line_rendered[0][i] = false;
45 line_rendered[1][i] = false;
49 uint32_t TOWNS_VRAM::read_data8(uint32_t addr)
53 #ifdef __LITTLE_ENDIAN__
54 uint8_t*p = (uint8_t*)vram;
55 return (uint32_t)(p[addr & 0x7ffff]);
58 d.w= vram[(addr & 0x7ffff) >> 1];
59 if((addr & 0x01) == 0) { // Hi
60 return (uint32_t)(d.b.h);
62 return (uint32_t)(d.b.l);
69 uint32_t TOWNS_VRAM::read_data16(uint32_t addr)
73 // Host: Little endian
74 // ToDo: Mask Register.
75 uint32_t naddr = (addr & 0x7fffe) >> 1;
76 #ifdef __LITTLE_ENDIAN__
77 uint16_t w = vram[naddr];
79 #else // __BIG_ENDIAN__
82 return (uint32_t)(nw.w);
86 uint32_t TOWNS_VRAM::read_data32(uint32_t addr)
89 // ToDo: Mask Register.
90 #ifdef __LITTLE_ENDIAN__
91 uint32_t*p = (uint32_t*)vram;
92 uint32_t naddr = (addr & 0x7ffff) >> 2;
93 uint32_t w = p[naddr];
95 #else // __BIG_ENDIAN__
97 uint32_t naddr = (addr & 0x7ffff) >> 1;
99 nd.w.h = vram[naddr + 1];;
104 void TOWNS_VRAM::write_data8(uint32_t addr, uint32_t data)
108 // ToDo: Mask Register.
110 uint32_t naddr = addr & 0x7ffff;
112 #ifdef __LITTLE_ENDIAN__
113 uint8_t* p = (uint8_t*)vram;
117 // ToDo: Mask register
118 d.w = vram[naddr >> 1];
119 if((addr & 0x01) != 0) { // Hi
127 // ToDo: Mask register
129 dirty = ((uint8_t)data != n) ? true : false;
132 dirty_flag[naddr >> 3] = true;
133 // ToDo: Mask register
134 #ifdef __LITTLE_ENDIAN__
137 vram[naddr >> 1] = d.w;
142 void TOWNS_VRAM::write_data16(uint32_t addr, uint32_t data)
147 uint32_t naddr = (addr & 0x7fffe) >> 1;
149 // ToDo: Mask register
151 dirty = ((uint16_t)data != d) ? true : false;
154 dirty_flag[naddr >> 3] = true;
155 // ToDo: Mask register
160 void TOWNS_VRAM::write_data32(uint32_t addr, uint32_t data)
165 uint32_t naddr = (addr & 0x7fffc) >> 1;
166 uint32_t *p = (uint32_t*)vram;
169 // ToDo: Mask register
170 #ifdef __LITTLE_ENDIAN__
171 nw.d = p[naddr >> 1];
173 nw.w.l = vram[naddr + 0];
174 nw.w.h = vram[naddr + 1];
176 // ToDo: Mask register
177 dirty = (data != nw.d) ? true : false;
180 // ToDo: Mask register
181 dirty_flag[naddr >> 3] = true;
183 #ifdef __LITTLE_ENDIAN__
184 p[naddr >> 1] = data;
187 vram[naddr + 0] = nw.w.l;
188 vram[naddr + 1] = nw.w.h;
193 // Check dirty and calc alpha by 8 bytes.
194 bool TOWNS_VRAM::check_dirty_and_calc_alpha(uint32_t addr)
196 __DECL_ALIGNED(16) uint16_t pix_cache_16[4];
197 __DECL_ALIGNED(16) uint8_t pix_cache_8[8];
198 __DECL_ALIGNED(16) uint8_t pix_cache_4[16];
200 __DECL_ALIGNED(4 * sizeof(scrntype_t)) scrntype_t alpha_cache_16[4];
201 __DECL_ALIGNED(16) uint16_t mask_cache_16[4];
202 __DECL_ALIGNED(16) uint16_t mask_cache_16_neg[4];
203 __DECL_ALIGNED(16) uint8_t mask_cache_4[8];
204 __DECL_ALIGNED(16) uint8_t mask_cache_4_neg[8];
205 __DECL_ALIGNED(16) scrntype_t alpha_cache_4[16];
206 bool dirty = dirty_flag[addr >> 3];
207 // If Not dirty, alpha/mask already calced.
209 uint32_t layer = (addr >= 0x40000) ? 1 : 0;
210 uint32_t naddr = addr & 0x3ffff;
212 uint16_t *vptr = vram_ptr[layer];
213 uint16_t *vptr8 = (uint8_t*)vptr;
214 for(int i = 0; i < 4; i++) {
215 pix_cache_16[i] = vptr[naddr >> 1];
217 for(int i = 0; i < 4; i++) {
218 alpha_cache_16[i] = alpha_32768c[pix_cache_16[i]];
219 mask_cache_16[i] = mask_32768c[pix_cache_16[i]];
220 mask_cache_16_neg[i] = ~mask_cache_16[i];
222 scrntype_t* palpha = &(alpha_buffer_32768[addr >> 1]);
223 uint16_t* pmask16 = &(mask_buffer_32768[addr >> 1]);
224 uint16_t* pmask16_neg = &(mask_buffer_32768_neg[addr >> 1]);
225 for(int i = 0; i < 4; i++) {
226 palpha[i] = alpha_cache_16[i];
227 pmask16[i] = mask_cache_16[i];
228 pmask16_neg[i] = mask_cache_16_neg[i];
231 for(int i = 0; i < 8; i++) {
232 pix_cache_8[i] = vptr8[naddr];
236 for(int i = 0; i < 8; i++) {
237 alpha_cache_4[i << 1] = alpha_16c[pix_cache_8[i] << 1];
238 alpha_cache_4[(i << 1) + 1] = alpha_16c[(pix_cache_8[i] << 1) + 1];
240 for(int i = 0; i < 8; i++) {
241 mask_cache_4[i] = mask_16c[pix_cache_8[i]];
242 mask_cache_4_neg[i] = ~mask_cache_4[i];
244 palpha = &(alpha_buffer_16[addr << 1]);
245 uint16_t* pmask4 = &(mask_buffer_16[addr]);
246 uint16_t* pmask4_neg = &(mask_buffer_16_neg[addr]);
247 for(int i = 0; i < 16; i++) {
248 palpha[i] = alpha_cache_4[i];
250 for(int i = 0; i < 8; i++) {
251 pmask4[i] = mask_cache_4[i];
252 pmask4_neg[i] = mask_cache_4_neg[i];
259 uint32_t TOWNS_VRAM::read_plane_data8(uint32_t addr)
264 uint8_t *p = (uint8_t*)vram;
267 // ToDo: Writing plane.
268 if(access_page1) x_addr = 0x40000; //?
269 addr = (addr & 0x7fff) << 3;
270 p = &(p[x_addr + addr]);
273 uint32_t *pp = (uint32_t *)p;
275 uint32_t tmp_d = *pp;
277 #ifdef __LITTLE_ENDIAN__
278 uint32_t tmp_m1 = 0x000000f0;
279 uint32_t tmp_m2 = 0x0000000f;
281 uint32_t tmp_m1 = 0xf0000000;
282 uint32_t tmp_m2 = 0x0f000000;
285 tmp_d = tmp_d & write_plane_mask;
287 for(int i = 0; i < 4; i++) {
289 tmp = tmp | (((tmp_d & tmp_m1) != 0) ? 0x02 : 0x00);
290 tmp = tmp | (((tmp_d & tmp_m2) != 0) ? 0x01 : 0x00);
292 #ifdef __LITTLE_ENDIAN__
301 uint32_t TOWNS_VRAM::read_plane_data16(uint32_t addr)
304 d.b.l = (uint8_t)(read_plane_data8(addr + 0));
305 d.b.h = (uint8_t)(read_plane_data8(addr + 1));
306 return (uint32_t)(d.w);
309 uint32_t TOWNS_VRAM::read_plane_data32(uint32_t addr)
312 d.b.l = (uint8_t)(read_plane_data8(addr + 0));
313 d.b.h = (uint8_t)(read_plane_data8(addr + 1));
314 d.b.h2 = (uint8_t)(read_plane_data8(addr + 2));
315 d.b.h3 = (uint8_t)(read_plane_data8(addr + 3));
319 void TOWNS_VRAM::write_plane_data8(uint32_t addr, uint32_t data)
324 uint8_t *p = (uint8_t*)vram;
327 // ToDo: Writing plane.
328 if(access_page1) x_addr = 0x40000; //?
329 addr = (addr & 0x7fff) << 3;
330 x_addr = x_addr + addr;
334 uint32_t *pp = (uint32_t *)p;
336 uint32_t tmp_d = data & 0xff;
337 #ifdef __LITTLE_ENDIAN__
338 uint32_t tmp_m1 = 0xf0000000 & write_plane_mask;
339 uint32_t tmp_m2 = 0x0f000000 & write_plane_mask;
341 uint32_t tmp_m1 = 0x000000f0 & write_plane_mask;
342 uint32_t tmp_m2 = 0x0000000f & write_plane_mask;
347 for(int i = 0; i < 4; i++) {
348 #ifdef __LITTLE_ENDIAN__
353 tmp = tmp | (((tmp_d & 0x02) != 0) ? tmp_m1 : 0x00);
354 tmp = tmp | (((tmp_d & 0x01) != 0) ? tmp_m2 : 0x00);
359 tmp_r1 = tmp_r1 & ~write_plane_mask;
360 tmp_r1 = tmp_d | tmp_r1;
361 if(tmp_r2 != tmp_r1) {
363 dirty_flag[x_addr >> 3] = true;
367 void TOWNS_VRAM::write_plane_data16(uint32_t addr, uint32_t data)
370 d.w = (uint16_t)data;
371 write_plane_data8(addr + 0, d.b.l);
372 write_plane_data8(addr + 1, d.b.h);
376 void TOWNS_VRAM::write_plane_data32(uint32_t addr, uint32_t data)
380 write_plane_data8(addr + 0, d.b.l);
381 write_plane_data8(addr + 1, d.b.h);
382 write_plane_data8(addr + 2, d.b.h2);
383 write_plane_data8(addr + 3, d.b.h3);
389 void TOWNS_CRTC::calc_apalette16(int layer, int index)
391 if(index < 0) return;
392 if(index > 15) return;
393 apalette_16_rgb[layer][index] =
394 ((uint16_t)(apalette_b & 0x0f)) |
395 ((uint16_t)(apalette_r & 0x0f) << 4) |
396 ((uint16_t)(apalette_g & 0x0f) << 8);
398 apalette_16_pixel[layer][index] = _CLEAR_COLOR; // ??
400 apalette_16_pixel[layer][index] = RGBA_COLOR((apalette_r & 0x0f) << 4, (apalette_g & 0x0f) << 4, (apalette_b & 0x0f) << 4, 0xff);
404 void TOWNS_CRTC::calc_apalette256(int index)
406 if(index < 0) return;
407 if(index > 255) return;
408 apalette_256_rgb[layer][index] =
409 ((uint32_t)apalette_b) |
410 ((uint32_t)apalette_r << 8) |
411 ((uint32_t)apalette_g << 16);
413 apalette_256_pixel[index] = _CLEAR_COLOR; // ??
415 apalette_256_pixel[index] = RGBA_COLOR(apalette_r, apalette_g, apalette_b, 0xff);
419 void TOWNS_CRTC::set_apalette_r(int layer, uint8_t val)
422 if(apalette_code < 16) {
423 calc_apalette16(layer, (int)apalette_code);
426 calc_apalette256((int)apalette_code % 256);
429 void TOWNS_CRTC::set_apalette_g(int layer, uint8_t val)
432 if(apalette_code < 16) {
433 calc_apalette16(layer, (int)apalette_code);
436 calc_apalette256((int)apalette_code % 256);
439 void TOWNS_CRTC::set_apalette_b(int layer, uint8_t val)
442 if(apalette_code < 16) {
443 calc_apalette16(layer, (int)apalette_code);
446 calc_apalette256((int)apalette_code % 256);
449 void TOWNS_CRTC::set_apalette_num(int layer, uint8_t val)
451 apalette_code = ((int)val) % 256;
455 void TOWNS_CRTC::render_line_16_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
457 // Simplify render: Must set 16pixels
458 uint32_t wordptr = 0;
459 int nwords = (int)words / 16;
463 __DECL_ALIGNED(8) uint8_t srcdat[8];
464 __DECL_ALIGNED(sizeof(scrntype_t) * 16) scrntype_t data_cache_16[16];
466 scrntype_t *pdst = framebuffer;
467 uint8_t *pp = (uint8_t *)vramptr;
468 if(framebuffer == NULL) return;
469 if(vramptr == NULL) return;
471 uintptr_t offset_base = (uintptr_t)startaddr;
472 uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
474 // offet_base = (offset_base + [value_of_offset_register]) & mask.
475 offset_base = (offet_base & 0x3ffff) + base;
476 pp = &(pp[offset_base]);
478 for(ip = 0; ip < nwords; ip++) {
479 if(!check_dirty_and_calc_alpha(offset_base)) {
485 dirty_flag[(offset_base >> 3)] = false;
486 for(int ii = 0; ii < 8; ii++) {
487 srcdat[ii << 1] = pp[ii];
488 srcdat[(ii << 1) + 1] = srcdat[ii << 1] & 0x0f;
489 srcdat[ii << 1] = (srcdat[ii << 1] & 0x0f) >> 4;
491 scrntype_t* aptr = alpha_buffer_16[offset_base << 1];
492 for(int ii = 0; ii < 16; ii++) {
493 data_cache_16[ii] = apalette_16[layer][srcdat1[ii]];
495 // ToDo: For hadrdware that does not support alpha blending(not RGBA32).
496 for(int ii = 0; ii < 16; ii++) {
497 pdst[ii] = data_cache_16[ii];
505 void TOWNS_CRTC::render_line_16_not_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
507 // Simplify render: Must set 32pixels
508 uint32_t wordptr = 0;
512 scrntype_t *pdst = framebuffer;
513 uint8_t *pp = (uint8_t *)vramptr;
514 if(framebuffer == NULL) return;
515 if(vramptr == NULL) return;
517 uintptr_t offset_base = (uintptr_t)startaddr;
518 uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
520 // offet_base = (offset_base + [value_of_offset_register]) & mask.
521 offset_base = (offet_base & 0x3ffff) + base;
522 pp = &(pp[offset_base]);
524 if(check_dirty_and_calc_alpha(offset_base)) {
525 //dirty_flag[(offset_base >> 3)] = false; // OK?
526 for(ip = 0; ip < words; ip++) {
527 uint8_t sdat = pp[ip];
528 scrntype_t pdat = apalette_16[layer][sdat];
534 void TOWNS_CRTC::render_line_256_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
536 uint32_t wordptr = 0;
537 int nwords = (int)words / 8;
539 __DECL_ALIGNED(16) uint8_t src[8];
540 scrntype_t *pdst = __builtin_assume_aligned(framebuffer, sizeof(scrntype_t));
541 uint8_t *pp = (uint8_t *)vramptr;
543 if(framebuffer == NULL) return;
544 if(vramptr == NULL) return;
546 uintptr_t offset_base = (uintptr_t)startaddr;
547 uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
548 // offet_base = (offset_base + [value_of_offset_register]) & mask.
549 offset_base = (offet_base & 0x3ffff) + base;
550 pp = &(pp[offset_base >> 2]);
552 for(ip = 0; ip < nwords; ip++) {
553 if(check_dirty_and_calc_alpha(offset_base)) {
554 dirty_flag[offset_base >> 3] = false;
555 for(int i = 0; i < 8; i++) {
558 // ToDo: Super Impose.
559 for(int i = 0; i < 8; i++) {
560 pdst[i] = apalette_256_pixel[src[i]];
569 void TOWNS_CRTC::render_line_256_not_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
571 uint32_t wordptr = 0;
572 int nwords = (int)words / 8;
574 uint8_t *pp = (uint8_t *)vramptr;
576 if(framebuffer == NULL) return;
577 if(vramptr == NULL) return;
579 uintptr_t offset_base = (uintptr_t)startaddr;
580 uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
581 // offet_base = (offset_base + [value_of_offset_register]) & mask.
582 offset_base = (offet_base & 0x3ffff) + base;
583 pp = &(pp[offset_base >> 2]);
585 for(ip = 0; ip < nwords; ip++) {
586 if(check_dirty_and_calc_alpha(offset_base + ip)) {
589 // ToDo: Super Impose.
590 pdst[ip] = apalette_256_pixel[src];
596 // To be used table??
597 void TOWNS_CRTC::render_line_32768_boundary(int layer, scrntype_t *pixcache, uint16_t *vramptr, uint32_t words)
599 uint32_t wordptr = 0;
600 int nwords = (int)words / 4;
603 scrntype_t *pdst = pixcache;
604 uint16_t *pp = (uint16_t *)vramptr;
605 uint16_t *cachep = (uint16_t *)srcdat;
606 __DECL_ALIGNED(16) uint16_t rgb[4];
607 __DECL_ALIGNED(sizeof(scrntype_t) * 4) scrntype_t dcache[4];
610 if(framebuffer == NULL) return;
611 if(vramptr == NULL) return;
613 uintptr_t offset_base = (uintptr_t)startaddr;
614 uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
615 // offet_base = (offset_base + [value_of_offset_register]) & mask.
616 offset_base = (offet_base & 0x3ffff) + base;
617 pp = &(pp[offset_base >> 1]);
619 for(ip = 0; ip < nwords; ip++) {
620 if(check_dirty_and_calc_alpha(offset_base)) {
621 dirty_flag[(offset_base >> 3)] = false;
622 for(int i = 0; i < 4; i++) {
625 for(int ii = 0; ii < 4; ii++) {
626 dcache[ii] = table_32768c[rgb[ii]];
628 for(int ii = 0; ii < 4; ii++) {
629 pdst[ii] = dcache[ii];
638 void TOWNS_CRTC::render_line_32768_not_boundary(int layer, scrntype_t *pixcache, uint16_t *vramptr, uint32_t words)
640 uint32_t wordptr = 0;
641 int nwords = (int)words / 4;
644 scrntype_t *pdst = pixcache;
645 uint16_t *pp = (uint16_t *)vramptr;
646 uint16_t *cachep = (uint16_t *)srcdat;
649 if(framebuffer == NULL) return;
650 if(vramptr == NULL) return;
652 uintptr_t offset_base = (uintptr_t)startaddr;
653 uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
654 // offet_base = (offset_base + [value_of_offset_register]) & mask.
655 offset_base = (offet_base & 0x3ffff) + base;
656 pp = &(pp[offset_base >> 1]);
658 for(ip = 0; ip < words; ip++) {
659 if(check_dirty_and_calc_alpha(offset_base)) {
661 pdst[ip] = table_32768c[pp[ip]];
666 // ToDo: Super impose.
667 void TOWNS_CRTC::mix_layers(scrntype* dst, scrntype_t* upper, scrntype_t *upper_alpha, scrntype_t* lower, int width)
669 scrntype_t* src1 = upper;
670 scrntype_t* src2 = lower;
672 __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t dcache1[8];
673 __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t dcache2[8];
674 __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t dcache3[8];
675 __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t acache1[8];
676 __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t acache2[8];
679 for(int i = 0; i < width; i++) {
680 dst[i] = RGBA_COLOR(0, 0, 0, 255);
683 // Upper don't display, lower displayed.
684 int iwidth = width / 8;
685 for(int i = 0; i < iwidth; i++) {
686 for(int ii = 0; ii < 8; ii++) {
687 dcache2[ii] = src2[ii];
689 for(int ii = 0; ii < 8; ii++) {
690 dst[ii] = dcache2[ii];
695 width = width - (iwidth * 8);
697 for(int i = 0; i < width; i++) {
703 if(src2 == NULL) { // upper only
704 int iwidth = width / 8;
705 for(int i = 0; i < iwidth; i++) {
706 for(int ii = 0; ii < 8; ii++) {
707 dcache1[ii] = src1[ii];
709 for(int ii = 0; ii < 8; ii++) {
710 dst[ii] = dcache1[ii];
715 width = width - (iwidth * 8);
717 for(int i = 0; i < width; i++) {
721 } else { // Both lives
722 if(upper_alpha == NULL) {
723 for(int i = 0; i < 8; i++) {
724 acache1[i] = RGBA_COLOR(255, 255, 255, 255);
727 int iwidth = width / 8;
728 for(int i = 0; i < iwidth; i++) {
729 if(upper_alpha != NULL) {
730 for(int ii = 0; ii < 8; i++) {
731 acache1[ii] = upper_alpha[ii];
735 for(int ii = 0; ii < 8; i++) {
736 acache2[ii] = ~acache1[ii];
738 for(int ii = 0; ii < 8; ii++) {
739 dcache1[ii] = src1[ii];
740 dcache2[ii] = src2[ii];
742 for(int ii = 0; ii < 8; ii++) {
743 dcache2[ii] = dcache2[ii] * acache1[ii]; // Mask Upper
744 //dcache3[ii] = (dcache2[ii] == RGBA_COLOR(0, 0, 0, 0)) ? dcache1[ii] : dcache2[ii];
745 dcache1[ii] = dcache1[ii] * acache2[ii]; // Mask Lower.
746 dcache3[ii] = dcache1[ii] | dcache2[ii];
748 for(int ii = 0; ii < 8; ii++) {
749 dst[ii] = dcache3[ii];
755 width = width - (iwidth * 8) ;
756 scrntype_t d1, d2, a1, a2;
757 for(int i = 0; i < width; i++) {
758 if(upper_alpha != NULL) {
761 a1 = RGBA_COLOR(255, 255, 255, 255);
774 void TOWNS_CRTC::vzoom_pixel(scrntype_t*src, int width, int srclines, scrntype_t* dst, int stride, int dstlines, float vzoom)
776 if(src == dst) return;
777 if(vzoom <= 0.0f) return;
778 if((src == NULL) || (dst == NULL)) return;
779 if(width <= 0) return;
780 if(srclines <= 0) return;
781 if(dstlines <= 0) return;
783 scrntype_t *psrc = src;
784 scrntype_t *pdst = dst;
786 float vzoom_int = floor(vzoom);
787 float vzoom_mod = vzoom - vzoom_int;
789 int nint = (int)vzoom_int;
792 for(srcline = 0; srcline < srclines; srcline++) {
798 for(int ii = 0; ii < ifactor; ii++) {
799 // ToDo: Mask, blend.
800 memcpy(pdst, psrc, width * sizeof(scrntype_t));
802 if(linecount >= dstlines) goto _exit0;;
806 nmod = nmod + vzoom_mod;
812 void TOWNS_CRTC::hzoom_pixel(scrntype_t* src, int width, scrntype_t* dst, int dst_width, float hzoom)
814 if(src == dst) return;
815 if(hzoom <= 0.0f) return;
816 if((src == NULL) || (dst == NULL)) return;
817 if(width <= 0) return;
818 if(dst_width <= 0) return;
820 scrntype_t* pdst = dst;
821 float hzoom_int = floor(hzoom);
822 float hzoom_mod = hzoom - hzoom_int;
824 int nint = (int)hzoom_int;
825 if((nint == 1) && (hzoom_mod <= 0.0f)) {
827 scrntype_t *sp = src;
828 scrntype_t pcache[4];
832 for(int ii = 0; ii < nw; ii++) {
833 if((dx + 3) >= dst_width) break;
834 for(int j = 0; j < 4; j++) {
838 for(int j = 0; j < 4; j++) {
846 if(dx >= dst_width) return;
847 for(int ii = 0; ii < nw; ii++) {
848 if(dx >= dst_width) goto __exit_0;
851 pdst[ii] = pcache[ii];
855 scrntype_t *sp = src;
858 for(int i = 0; i < width; i++) {
859 // ToDo : Storage via SIMD.
860 if(dx >= dst_width) goto __exit_0;
867 scrntype_t pix = *sp++;
868 scrntype_t pcache[4];
871 int jfactor = ifactor / 4;
873 for(int k = 0; k < 4; k++) {
876 for(int j = 0; j < jfactor; j++) {
877 if((dx + 3) >= dst_width) break;
878 for(int k = 0; k < 4; k++) {
885 ifactor = ifactor - xcount;
886 if(ifactor < 0) ifactor = 0;
887 for(int k = 0; k < ifactor; k++) {
888 if(dx >= dst_width) goto __exit_0;
892 nmod = nmod + hzoom_mod;
901 void TOWNS_VRAM::draw_screen()
903 // Note: This renderer will contain three types (at least:)
904 // 1. Software Zoom, Hardware stack (Using GPU for stack, Using CPU for zoom)
905 // 2. Softare Zoom, Software stack (Using only host-CPU).
906 // 3. Hardware Zoom, Hardware stack (Using GPU and compute shader?).
907 // To implement 1., Zooming all screen don't wish to use CPU, per raster Zooming wish to use GPU.
908 // At first, will implement 2.As of CSP platform implement only single frame buffer area.
910 // Answer values(excepts 2.):
911 // Note: Upper layer = layer1, lower layer = layer2.
912 // a. Pixel Layers of 1/2.
913 // b. Alpha Layers of 1.
914 // c. Layer using flags both layer1, layer2.
915 // d. Data of Layers (1/2).
916 // e. Source screen width and height per layer.
917 // f. Offset sourcfe-pixel-address per raster.
918 // g. Source raster width per layer and scanline.
919 // h. Offset dst-pixel-position in raster per layer.
920 // - 20190110 K.Ohta.