OSDN Git Service

[VM][FMTOWNS][VRAM] .
authorK.Ohta <whatisthis.sowhat@gmail.com>
Fri, 20 Sep 2019 20:34:09 +0000 (05:34 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Fri, 20 Sep 2019 20:34:09 +0000 (05:34 +0900)
source/src/vm/fmtowns/towns_vram.cpp

index 594c170..6ba3da6 100644 (file)
@@ -46,215 +46,439 @@ void TOWNS_VRAM::initialize()
        }
 
 }
-uint32_t TOWNS_VRAM::read_data8(uint32_t addr)
+
+void TOWNS_VRAM::write_memory_mapped_io8(uint32_t addr, uint32_t data)
 {
-       // ToDo:Offset.
-       // ToDo: Wait.
-#ifdef __LITTLE_ENDIAN__
-       uint8_t*p = (uint8_t*)vram;
-       return (uint32_t)(p[addr & 0x7ffff]);
-#else
-       pair16_t d;
-       d.w= vram[(addr & 0x7ffff) >> 1];
-       if((addr & 0x01) == 0) { // Hi
-               return (uint32_t)(d.b.h);
-       } else { // Lo
-               return (uint32_t)(d.b.l);
-       }
-#endif 
+       uint32_t naddr = addr & 0xfff00000;
+       switch(naddr) {
+       case 0x80000000:
+               // Main VRAM
+               write_raw_vram8(addr - 0x80000000, data);
+               return;
+               break;
+       case 0x80100000:
+               // Main VRAM
+               break;
+       case 0x00000000:
+               switch(addr & 0x000ff000) {
+               case 0xc0000:
+               case 0xc1000:
+               case 0xc2000:
+               case 0xc3000:
+               case 0xc4000:
+               case 0xc5000:
+               case 0xc6000:
+               case 0xc7000:
+                       write_plane_data8(addr, data);  // Plane access by I/O FF81h
+                       return;
+                       break;
+               case 0xc8000:
+                       // Text VRAM
+                       break;
+               case 0xc9000:
+                       // Reserved
+                       break;
+               case 0xca000:
+                       // ANKCG1 / IO / RAM
+                       break;
+               case 0xcb000:
+                       // CGROM
+                       break;
+               default:
+                       return;
+                       break;
+               }
+               break;
+       default:
+               return;
+               break;
+       }               
+       
 }
 
+void TOWNS_VRAM::write_memory_mapped_io16(uint32_t addr, uint32_t data)
+{
+       uint32_t naddr = addr & 0xfff00000;
+       switch(naddr) {
+       case 0x80000000:
+               // Main VRAM
+               write_raw_vram16(addr - 0x80000000, data);
+               return;
+               break;
+       case 0x80100000:
+               // Main VRAM
+               break;
+       case 0x00000000:
+               switch(addr & 0x000ff000) {
+               case 0xc0000:
+               case 0xc1000:
+               case 0xc2000:
+               case 0xc3000:
+               case 0xc4000:
+               case 0xc5000:
+               case 0xc6000:
+               case 0xc7000:
+                       write_plane_data16(addr, data); // Plane access by I/O FF81h
+                       return;
+                       break;
+               case 0xc8000:
+                       // Text VRAM
+                       break;
+               case 0xc9000:
+                       // Reserved
+                       break;
+               case 0xca000:
+                       // ANKCG1 / IO / RAM
+                       break;
+               case 0xcb000:
+                       // CGROM
+                       break;
+               default:
+                       return;
+                       break;
+               }
+               break;
+       default:
+               return;
+               break;
+       }               
+       
+}
+       
+void TOWNS_VRAM::write_memory_mapped_io8(uint32_t addr, uint32_t data)
+{
+       uint32_t naddr = addr & 0xfff00000;
+       switch(naddr) {
+       case 0x80000000:
+               // Main VRAM
+               write_raw_vram32(addr - 0x80000000, data);
+               return;
+               break;
+       case 0x80100000:
+               // Main VRAM
+               break;
+       case 0x00000000:
+               switch(addr & 0x000ff000) {
+               case 0xc0000:
+               case 0xc1000:
+               case 0xc2000:
+               case 0xc3000:
+               case 0xc4000:
+               case 0xc5000:
+               case 0xc6000:
+               case 0xc7000:
+                       write_plane_data32(addr, data); // Plane access by I/O FF81h
+                       return;
+                       break;
+               case 0xc8000:
+                       // Text VRAM
+                       break;
+               case 0xc9000:
+                       // Reserved
+                       break;
+               case 0xca000:
+                       // ANKCG1 / IO / RAM
+                       break;
+               case 0xcb000:
+                       // CGROM
+                       break;
+               default:
+                       return;
+                       break;
+               }
+               break;
+       default:
+               return;
+               break;
+       }               
+       
+}
 
+uint32_t TOWNS_VRAM::read_memory_mapped_io8(uint32_t addr)
+{
+       uint32_t naddr = addr & 0xfff00000;
+       switch(naddr) {
+       case 0x80000000:
+               // Main VRAM
+               return read_raw_vram8(addr - 0x80000000);
+               break;
+       case 0x80100000:
+               // Main VRAM
+               break;
+       case 0x00000000:
+               switch(addr & 0x000ff000) {
+               case 0xc0000:
+               case 0xc1000:
+               case 0xc2000:
+               case 0xc3000:
+               case 0xc4000:
+               case 0xc5000:
+               case 0xc6000:
+               case 0xc7000:
+                       // Plane access by I/O FF81h
+                       return read_plane_data8(addr);  // Plane access by I/O FF81h
+                       break;
+               case 0xc8000:
+                       // Text VRAM
+                       break;
+               case 0xc9000:
+                       // Reserved
+                       break;
+               case 0xca000:
+                       // ANKCG1 / IO / RAM
+                       break;
+               case 0xcb000:
+                       // CGROM
+                       break;
+               default:
+                       return 0xff;
+               }
+               break;
+       default:
+               return 0xff;
+               break;
+       }               
+}
 
-uint32_t TOWNS_VRAM::read_data16(uint32_t addr)
+uint32_t TOWNS_VRAM::read_memory_mapped_io16(uint32_t addr)
 {
-       // ToDo:Offset.
-       // ToDo: Wait.
-       // Host: Little endian
-       // ToDo: Mask Register.
-       uint32_t naddr = (addr & 0x7fffe) >> 1;
-#ifdef __LITTLE_ENDIAN__
-       uint16_t w = vram[naddr];
-       return (uint32_t)w;
-#else // __BIG_ENDIAN__        
-       pair16_t nw;
-       nw.w = vram[naddr];
-       return (uint32_t)(nw.w);
-#endif
+       uint32_t naddr = addr & 0xfff00000;
+       switch(naddr) {
+       case 0x80000000:
+               // Main VRAM
+               return read_raw_vram16(addr - 0x80000000);
+               break;
+       case 0x80100000:
+               // Main VRAM
+               break;
+       case 0x00000000:
+               switch(addr & 0x000ff000) {
+               case 0xc0000:
+               case 0xc1000:
+               case 0xc2000:
+               case 0xc3000:
+               case 0xc4000:
+               case 0xc5000:
+               case 0xc6000:
+               case 0xc7000:
+                       // Plane access by I/O FF81h
+                       return read_plane_data16(addr); // Plane access by I/O FF81h
+                       break;
+               case 0xc8000:
+                       // Text VRAM
+                       break;
+               case 0xc9000:
+                       // Reserved
+                       break;
+               case 0xca000:
+                       // ANKCG1 / IO / RAM
+                       break;
+               case 0xcb000:
+                       // CGROM
+                       break;
+               default:
+                       return 0xffff;
+               }
+               break;
+       default:
+               return 0xffff;
+               break;
+       }
+       return 0xffff;
 }
 
-uint32_t TOWNS_VRAM::read_data32(uint32_t addr)
+uint32_t TOWNS_VRAM::read_memory_mapped_io32(uint32_t addr)
 {
-       // ToDo: Wait.
-       // ToDo: Mask Register.
-#ifdef __LITTLE_ENDIAN__
-       uint32_t*p = (uint32_t*)vram;
-       uint32_t naddr = (addr & 0x7ffff) >> 2;
-       uint32_t w = p[naddr];
-       return w;
-#else // __BIG_ENDIAN__        
-       pair32_t nd;
-       uint32_t naddr = (addr & 0x7ffff) >> 1;
-       nd.w.l = vram[naddr];
-       nd.w.h = vram[naddr + 1];;
-       return nd.d;
-#endif
+       uint32_t naddr = addr & 0xfff00000;
+       switch(naddr) {
+       case 0x80000000:
+               // Main VRAM
+               return read_raw_vram32(addr - 0x80000000);
+               break;
+       case 0x80100000:
+               // Main VRAM
+               break;
+       case 0x00000000:
+               switch(addr & 0x000ff000) {
+               case 0xc0000:
+               case 0xc1000:
+               case 0xc2000:
+               case 0xc3000:
+               case 0xc4000:
+               case 0xc5000:
+               case 0xc6000:
+               case 0xc7000:
+                       // Plane access by I/O FF81h
+                       return read_plane_data32(addr); // Plane access by I/O FF81h
+                       break;
+               case 0xc8000:
+                       // Text VRAM
+                       break;
+               case 0xc9000:
+                       // Reserved
+                       break;
+               case 0xca000:
+                       // ANKCG1 / IO / RAM
+                       break;
+               case 0xcb000:
+                       // CGROM
+                       break;
+               default:
+                       return 0xffffffff;
+               }
+               break;
+       default:
+               return 0xffffffff;
+               break;
+       }               
+       return 0xffffffff;
 }
 
-void TOWNS_VRAM::write_data8(uint32_t addr, uint32_t data)
+uint32_t TOWNS_VRAM::read_raw_vram8(uint32_t addr)
 {
-       // ToDo:Offset.
-       // ToDo: Wait.
-       // ToDo: Mask Register.
-       bool dirty;
-       uint32_t naddr = addr & 0x7ffff;
+       return vram[addr];
+}
        
+uint32_t TOWNS_VRAM::read_raw_vram16(uint32_t addr)
+{
+       if(addr == 0x7ffff) {
+               pair16_t a;
+               a.b.l = vram[addr];
+               a.b.h = vram[0];
+               return (uint32_t)(a.w);
+       } else {
 #ifdef __LITTLE_ENDIAN__
-       uint8_t* p = (uint8_t*)vram;
-       n = p[naddr];
+               // SAME endian
+               uint16_t* p = (uint16_t *)(&vram[addr]);
+               return (uint32_t)(*p);
 #else
-       pair16_t d;
-       // ToDo: Mask register
-       d.w = vram[naddr >> 1];
-       if((addr & 0x01) != 0) { // Hi
-               n = d.b.h;
-               d.b.h = data;
-       } else { // Lo
-               n = d.b.l;
-               d.b.l = data;
-       }
+               pair16_t a;
+               a.b.l = vram[addr];
+               a.b.h = vram[addr + 1];
+               return (uint32_t)(a.w);
 #endif
-       // ToDo: Mask register
-       
-       dirty = ((uint8_t)data != n) ? true : false;
+       }
+}
 
-       if(dirty) {
-               dirty_flag[naddr >> 3] = true;
-       // ToDo: Mask register
+uint32_t TOWNS_VRAM::read_raw_vram32(uint32_t addr)
+{
+       if(addr > 0x7fffc) {
+               pair32_t a;
+               a.b.l  = vram[addr];
+               a.b.h  = vram[(addr + 1) & 0x7ffff];
+               a.b.h2 = vram[(addr + 2) & 0x7ffff];
+               a.b.h3 = vram[(addr + 3) & 0x7ffff];
+               return a.d;
+       } else {
 #ifdef __LITTLE_ENDIAN__
-               p[naddr] = data;
+               // SAME endian
+               uint32_t* p = (uint32_t *)(&vram[addr]);
+               return *p;
 #else
-               vram[naddr >> 1] = d.w; 
+               pair32_t a;
+               a.b.l  = vram[addr];
+               a.b.h  = vram[addr + 1];
+               a.b.h2 = vram[addr + 2];
+               a.b.h3 = vram[addr + 3];
 #endif
+               return a.d;
        }
 }
 
-void TOWNS_VRAM::write_data16(uint32_t addr, uint32_t data)
+void TOWNS_VRAM::write_raw_vram8(uint32_t addr, uint32_t data)
 {
-       // ToDo:Offset.
-       // ToDo: Wait.
-       bool dirty;
-       uint32_t naddr = (addr & 0x7fffe) >> 1;
-       uint16_t d;
-       // ToDo: Mask register
-       d = vram[naddr];
-    dirty = ((uint16_t)data != d) ? true : false;
-
-       if(dirty) {
-               dirty_flag[naddr >> 3] = true;
-               // ToDo: Mask register
-               vram[naddr] = data; 
+       if(vram[addr] != data) {
+               make_dirty_vram(addr, 1);
+               vram[addr] = data;
        }
 }
 
-void TOWNS_VRAM::write_data32(uint32_t addr, uint32_t data)
+void TOWNS_VRAM::write_raw_vram16(uint32_t addr, uint32_t data)
 {
-       // ToDo:Offset.
-       // ToDo: Wait.
-       bool dirty;
-       uint32_t naddr = (addr & 0x7fffc) >> 1;
-       uint32_t *p = (uint32_t*)vram; 
-       pair32_t nw;
-
-       // ToDo: Mask register
-#ifdef __LITTLE_ENDIAN__
-       nw.d = p[naddr >> 1];
-#else
-       nw.w.l = vram[naddr + 0];
-       nw.w.h = vram[naddr + 1];
-#endif
-       // ToDo: Mask register
-    dirty = (data != nw.d) ? true : false;
-
-       if(dirty) {
-               // ToDo: Mask register
-               dirty_flag[naddr >> 3] = true;
-
+       if(addr == 0x7ffff) {
+               pair16_t a;
+               a.w = data;
+               if(vram[addr] != a.b.l) {
+                       make_dirty_vram(addr, 1);
+                       vram[addr] = a.b.l;
+               }
+               if(vram[0] != a.b.h) {
+                       make_dirty_vram(0, 1);
+                       vram[0] = a.b.h;
+               }
+               return;
+       } else {
 #ifdef __LITTLE_ENDIAN__
-               p[naddr >> 1] = data;
+               // SAME endian
+               uint16_t* p = (uint16_t *)(&vram[addr]);
+               if(*p != (uint16_t)data) {
+                       make_dirty_vram(addr, 2);
+                       *p = data;
+               }
+               return;
 #else
-               nw.d = data;
-               vram[naddr + 0] = nw.w.l;
-               vram[naddr + 1] = nw.w.h;
+               pair16_t a;
+               a.w = data;
+               uint16_t* p = (uint16_t *)(&vram[addr]);
+               uint16_t b = *p;
+               if(a.w != b) {
+                       make_dirty_vram(addr, 2);
+                       vram[addr] = a.b.l;
+                       vram[addr + 1] = a.b.h;
+               }
 #endif
-       }       
+       }
 }
 
-// Check dirty and calc alpha by 8 bytes.
-bool TOWNS_VRAM::check_dirty_and_calc_alpha(uint32_t addr)
+void TOWNS_VRAM::write_raw_vram32(uint32_t addr, uint32_t data)
 {
-       __DECL_ALIGNED(16) uint16_t pix_cache_16[4];
-       __DECL_ALIGNED(16)  uint8_t pix_cache_8[8];
-       __DECL_ALIGNED(16)  uint8_t pix_cache_4[16];
-       
-       __DECL_ALIGNED(4 * sizeof(scrntype_t)) scrntype_t alpha_cache_16[4];
-       __DECL_ALIGNED(16) uint16_t mask_cache_16[4];
-       __DECL_ALIGNED(16) uint16_t mask_cache_16_neg[4];
-       __DECL_ALIGNED(16) uint8_t mask_cache_4[8];
-       __DECL_ALIGNED(16) uint8_t mask_cache_4_neg[8];
-       __DECL_ALIGNED(16) scrntype_t alpha_cache_4[16];
-       bool dirty = dirty_flag[addr >> 3];
-       // If Not dirty, alpha/mask already calced.
-       if(dirty) {
-               uint32_t layer = (addr >= 0x40000) ? 1 : 0;
-               uint32_t naddr = addr & 0x3ffff;
-               // alpha32768
-               uint16_t *vptr = vram_ptr[layer];
-               uint16_t *vptr8 = (uint8_t*)vptr;
-               for(int i = 0; i < 4; i++) {
-                       pix_cache_16[i] = vptr[naddr >> 1];
-               }
-               for(int i = 0; i < 4; i++) {
-                       alpha_cache_16[i] = alpha_32768c[pix_cache_16[i]];
-                       mask_cache_16[i] =  mask_32768c[pix_cache_16[i]];
-                       mask_cache_16_neg[i] = ~mask_cache_16[i];
+       if(addr > 0x7fffc) {
+               pair32_t a;
+               a.d = data;
+               if(vram[addr] != a.b.l) {
+                       make_dirty_vram(addr & 0x7ffff, 1);
+                       vram[addr & 0x7ffff] = a.b.l;
                }
-               scrntype_t* palpha = &(alpha_buffer_32768[addr >> 1]);
-               uint16_t* pmask16 = &(mask_buffer_32768[addr >> 1]);
-               uint16_t* pmask16_neg = &(mask_buffer_32768_neg[addr >> 1]);
-               for(int i = 0; i < 4; i++) {
-                       palpha[i]      = alpha_cache_16[i];
-                       pmask16[i]     = mask_cache_16[i];
-                       pmask16_neg[i] = mask_cache_16_neg[i];
+               if(vram[(addr + 1) & 0x7ffff] != a.b.h) {
+                       make_dirty_vram((addr + 1) & 0x7ffff, 1);
+                       vram[(addr + 1) & 0x7ffff] = a.b.h;
                }
-               
-               for(int i = 0; i < 8; i++) {
-                       pix_cache_8[i] = vptr8[naddr];
-               }
-               // Alpha8
-               
-               for(int i = 0; i < 8; i++) {
-                       alpha_cache_4[i << 1]       = alpha_16c[pix_cache_8[i] << 1];
-                       alpha_cache_4[(i << 1) + 1] = alpha_16c[(pix_cache_8[i] << 1) + 1];
+               if(vram[(addr + 2) & 0x7ffff] != a.b.h2) {
+                       make_dirty_vram((addr + 2) & 0x7ffff, 1);
+                       vram[(addr + 2) & 0x7ffff] = a.b.h2;
                }
-               for(int i = 0; i < 8; i++) {
-                       mask_cache_4[i] = mask_16c[pix_cache_8[i]];
-                       mask_cache_4_neg[i] = ~mask_cache_4[i];
+               if(vram[(addr + 3) & 0x7ffff] != a.b.h3) {
+                       make_dirty_vram((addr + 3) & 0x7ffff, 1);
+                       vram[(addr + 3) & 0x7ffff] = a.b.h3;
                }
-               palpha = &(alpha_buffer_16[addr << 1]);
-               uint16_t* pmask4 = &(mask_buffer_16[addr]);
-               uint16_t* pmask4_neg = &(mask_buffer_16_neg[addr]);
-               for(int i = 0; i < 16; i++) {
-                       palpha[i]     = alpha_cache_4[i];
+               return;
+       } else {
+#ifdef __LITTLE_ENDIAN__
+               // SAME endian
+               uint32_t* p = (uint32_t *)(&vram[addr]);
+               if(*p != data) {
+                       make_dirty_vram(addr, 4);
+                       *p = data;
                }
-               for(int i = 0; i < 8; i++) {
-                       pmask4[i]     = mask_cache_4[i];
-                       pmask4_neg[i] = mask_cache_4_neg[i];
+               return;
+#else
+               pair32_t a;
+               a.d = data;
+               uint32_t* p = (uint32_t *)(&vram[addr]);
+               uint32_t b = *p;
+               if(a.d != b) {
+                       make_dirty_vram(addr, 4);
+                       vram[addr] = a.b.l;
+                       vram[addr + 1] = a.b.h;
+                       vram[addr + 2] = a.b.h2;
+                       vram[addr + 3] = a.b.h3;
                }
+#endif
        }
-       return dirty;
 }
 
+
+
 void TOWNS_CRTC::write_io16(uint32_t addr, uint32_t data)
 {
        switch(addr) {
@@ -467,451 +691,6 @@ void TOWNS_CRTC::set_apalette_num(int layer, uint8_t val)
 }
 
 // Renderers
-void TOWNS_CRTC::render_line_16_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
-{
-       // Simplify render: Must set 16pixels
-       uint32_t wordptr = 0;
-       int nwords = (int)words / 16;
-       int ip;
-       uint32_t src;
-       uint32_t src1, src2;
-       __DECL_ALIGNED(8) uint8_t  srcdat[8];
-       __DECL_ALIGNED(sizeof(scrntype_t) * 16) scrntype_t data_cache_16[16];
-       
-       scrntype_t *pdst = framebuffer;
-       uint8_t *pp = (uint8_t *)vramptr;
-       if(framebuffer == NULL) return;
-       if(vramptr == NULL) return;
-
-       uintptr_t offset_base = (uintptr_t)startaddr;
-       uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
-       uintptr_t offset;
-       // offet_base = (offset_base + [value_of_offset_register]) & mask.
-       offset_base = (offet_base & 0x3ffff) + base;
-       pp = &(pp[offset_base]);
-       
-       for(ip = 0; ip < nwords; ip++) {
-               if(!check_dirty_and_calc_alpha(offset_base)) {
-                       pdst += 16;
-                       pp += 8;
-                       offset_base += 8;
-                       continue;
-               }
-               dirty_flag[(offset_base >> 3)] = false;
-               for(int ii = 0; ii < 8; ii++) {
-                       srcdat[ii << 1]       =  pp[ii];
-                       srcdat[(ii << 1) + 1] =  srcdat[ii << 1] & 0x0f;
-                       srcdat[ii << 1]       = (srcdat[ii << 1] & 0x0f) >> 4;
-               }
-               scrntype_t* aptr = alpha_buffer_16[offset_base << 1];
-               for(int ii = 0; ii < 16; ii++) {
-                       data_cache_16[ii] = apalette_16[layer][srcdat1[ii]];
-               }
-               // ToDo: For hadrdware that does not support alpha blending(not RGBA32).
-               for(int ii = 0; ii < 16; ii++) {
-                       pdst[ii] = data_cache_16[ii];
-               }
-               pdst += 16;
-               pp += 8;
-               offset_base += 8;
-       }
-}
-
-void TOWNS_CRTC::render_line_16_not_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
-{
-       // Simplify render: Must set 32pixels
-       uint32_t wordptr = 0;
-       int ip;
-       uint32_t src;
-       uint32_t src1, src2;
-       scrntype_t *pdst = framebuffer;
-       uint8_t *pp = (uint8_t *)vramptr;
-       if(framebuffer == NULL) return;
-       if(vramptr == NULL) return;
-
-       uintptr_t offset_base = (uintptr_t)startaddr;
-       uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
-       uintptr_t offset;
-       // offet_base = (offset_base + [value_of_offset_register]) & mask.
-       offset_base = (offet_base & 0x3ffff) + base;
-       pp = &(pp[offset_base]);
-       
-       if(check_dirty_and_calc_alpha(offset_base)) {
-               //dirty_flag[(offset_base >> 3)] = false; // OK?
-               for(ip = 0; ip < words; ip++) {
-                       uint8_t sdat = pp[ip];
-                       scrntype_t pdat = apalette_16[layer][sdat];
-                       pdst[ii] = pdat;
-               }
-       }
-}
-
-void TOWNS_CRTC::render_line_256_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
-{
-       uint32_t wordptr = 0;
-       int nwords = (int)words / 8;
-       int ip;
-       __DECL_ALIGNED(16) uint8_t src[8];
-       scrntype_t *pdst  = framebuffer;
-       uint8_t *pp = (uint8_t *)vramptr;
-       
-       if(framebuffer == NULL) return;
-       if(vramptr == NULL) return;
-
-       uintptr_t offset_base = (uintptr_t)startaddr;
-       uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
-       // offet_base = (offset_base + [value_of_offset_register]) & mask.
-       offset_base = (offet_base & 0x3ffff) + base;
-       pp = &(pp[offset_base >> 2]);
-       
-       for(ip = 0; ip < nwords; ip++) {
-               if(check_dirty_and_calc_alpha(offset_base)) {
-                       dirty_flag[offset_base >> 3] = false;
-                       for(int i = 0; i < 8; i++) {
-                               src[i] = pp[i];
-                       }
-                       // ToDo: Super Impose.
-                       for(int i = 0; i < 8; i++) {
-                               pdst[i] = apalette_256_pixel[src[i]];
-                       }
-               }
-               offset_base += 8;
-               pp += 8;
-               pdst += 8;
-       }
-}
-
-void TOWNS_CRTC::render_line_256_not_boundary(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t startaddr, uint32_t words)
-{
-       uint32_t wordptr = 0;
-       int nwords = (int)words / 8;
-       int ip;
-       uint8_t *pp = (uint8_t *)vramptr;
-       uint8_t src;
-       if(framebuffer == NULL) return;
-       if(vramptr == NULL) return;
-
-       uintptr_t offset_base = (uintptr_t)startaddr;
-       uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
-       // offet_base = (offset_base + [value_of_offset_register]) & mask.
-       offset_base = (offet_base & 0x3ffff) + base;
-       pp = &(pp[offset_base >> 2]);
-       
-       for(ip = 0; ip < nwords; ip++) {
-               if(check_dirty_and_calc_alpha(offset_base + ip)) {
-                       // Keep dirty?
-                       src = pp[ip];
-                       // ToDo: Super Impose.
-                       pdst[ip] = apalette_256_pixel[src];
-               }
-       }
-}
-
-
-// To be used table??
-void TOWNS_CRTC::render_line_32768_boundary(int layer, scrntype_t *pixcache, uint16_t *vramptr, uint32_t words)
-{
-       uint32_t wordptr = 0;
-       int nwords = (int)words / 4;
-       int ip;
-       uint16_t src16;
-       scrntype_t *pdst = pixcache;
-       uint16_t *pp = (uint16_t *)vramptr;
-       uint16_t *cachep = (uint16_t *)srcdat;
-       __DECL_ALIGNED(16) uint16_t rgb[4];
-       __DECL_ALIGNED(sizeof(scrntype_t) * 4) scrntype_t dcache[4];
-       int i = 0;
-       
-       if(framebuffer == NULL) return;
-       if(vramptr == NULL) return;
-
-       uintptr_t offset_base = (uintptr_t)startaddr;
-       uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
-       // offet_base = (offset_base + [value_of_offset_register]) & mask.
-       offset_base = (offet_base & 0x3ffff) + base;
-       pp = &(pp[offset_base >> 1]);
-
-       for(ip = 0; ip < nwords; ip++) {
-               if(check_dirty_and_calc_alpha(offset_base)) {
-                       dirty_flag[(offset_base >> 3)] = false;
-                       for(int i = 0; i < 4; i++) {
-                               rgb[i] = pp[i];
-                       }
-                       for(int ii = 0; ii < 4; ii++) {
-                               dcache[ii] = table_32768c[rgb[ii]];
-                       }
-                       for(int ii = 0; ii < 4; ii++) {
-                               pdst[ii] = dcache[ii];
-                       }
-               }
-               offset_base += 8;
-               pdst += 4;
-               pp += 4;
-       }
-}
-
-void TOWNS_CRTC::render_line_32768_not_boundary(int layer, scrntype_t *pixcache, uint16_t *vramptr, uint32_t words)
-{
-       uint32_t wordptr = 0;
-       int nwords = (int)words / 4;
-       int ip;
-       uint16_t src16;
-       scrntype_t *pdst = pixcache;
-       uint16_t *pp = (uint16_t *)vramptr;
-       uint16_t *cachep = (uint16_t *)srcdat;
-       int i = 0;
-       
-       if(framebuffer == NULL) return;
-       if(vramptr == NULL) return;
-
-       uintptr_t offset_base = (uintptr_t)startaddr;
-       uintptr_t base = ((layer == 0) ? 0x00000 : 0x40000);
-       // offet_base = (offset_base + [value_of_offset_register]) & mask.
-       offset_base = (offet_base & 0x3ffff) + base;
-       pp = &(pp[offset_base >> 1]);
-
-       for(ip = 0; ip < words; ip++) {
-               if(check_dirty_and_calc_alpha(offset_base)) {
-                       // Keep dirty?
-                       pdst[ip] = table_32768c[pp[ip]];
-               }
-               offset_base++;
-       }
-}
-// ToDo: Super impose.
-void TOWNS_CRTC::mix_layers(scrntype* dst, scrntype_t* upper, scrntype_t *upper_alpha, scrntype_t* lower, int width)
-{
-       scrntype_t* src1 = upper;
-       scrntype_t* src2 = lower;
-       
-       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t dcache1[8];
-       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t dcache2[8];
-       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t dcache3[8];
-       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t acache1[8];
-       __DECL_ALIGNED(sizeof(scrntype_t) * 8) scrntype_t acache2[8];
-       if(src1 == NULL) {
-               if(src2 == NULL) {
-                       for(int i = 0; i < width; i++) {
-                               dst[i] = RGBA_COLOR(0, 0, 0, 255);
-                       }
-               } else {
-                       // Upper don't display, lower displayed.
-                       int iwidth = width / 8;
-                       for(int i = 0; i < iwidth; i++) {
-                               for(int ii = 0; ii < 8; ii++) {
-                                       dcache2[ii] = src2[ii];
-                               }
-                               for(int ii = 0; ii < 8; ii++) {
-                                       dst[ii] = dcache2[ii];
-                               }
-                               src2 += 8;
-                               dst += 8;
-                       }
-                       width = width - (iwidth * 8);
-                       if(width > 0) {
-                               for(int i = 0; i < width; i++) {
-                                       sdt[i] = src2[i];
-                               }
-                       }
-               }
-       } else { 
-               if(src2 == NULL) { // upper only
-                       int iwidth = width / 8;
-                       for(int i = 0; i < iwidth; i++) {
-                               for(int ii = 0; ii < 8; ii++) {
-                                       dcache1[ii] = src1[ii];
-                               }
-                               for(int ii = 0; ii < 8; ii++) {
-                                       dst[ii] = dcache1[ii];
-                               }
-                               src1 += 8;
-                               dst += 8;
-                       }
-                       width = width - (iwidth * 8);
-                       if(width > 0) {
-                               for(int i = 0; i < width; i++) {
-                                       sdt[i] = src2[i];
-                               }
-                       }
-               } else { // Both lives
-                       if(upper_alpha == NULL) {
-                               for(int i = 0; i < 8; i++) {
-                                       acache1[i] = RGBA_COLOR(255, 255, 255, 255);
-                               }
-                       }
-                       int iwidth = width / 8;
-                       for(int i = 0; i < iwidth; i++) {
-                               if(upper_alpha != NULL) {
-                                       for(int ii = 0; ii < 8; i++) {
-                                               acache1[ii] = upper_alpha[ii];
-                                       }
-                                       upper_alpha += 8;
-                               }
-                               for(int ii = 0; ii < 8; i++) {
-                                       acache2[ii] = ~acache1[ii];
-                               }
-                               for(int ii = 0; ii < 8; ii++) {
-                                       dcache1[ii] = src1[ii];
-                                       dcache2[ii] = src2[ii];
-                               }
-                               for(int ii = 0; ii < 8; ii++) {
-                                       dcache2[ii] = dcache2[ii] * acache1[ii]; // Mask Upper
-                                       //dcache3[ii] = (dcache2[ii] == RGBA_COLOR(0, 0, 0, 0)) ? dcache1[ii] : dcache2[ii];
-                                       dcache1[ii] = dcache1[ii] * acache2[ii]; // Mask Lower.
-                                       dcache3[ii] = dcache1[ii] | dcache2[ii];
-                               }
-                               for(int ii = 0; ii < 8; ii++) {
-                                       dst[ii] = dcache3[ii];
-                               }
-                               src1 += 8;
-                               src2 += 8;
-                               dst += 8;
-                       }
-                       width = width - (iwidth * 8) ;
-                       scrntype_t d1, d2, a1, a2;
-                       for(int i = 0; i < width; i++) {
-                               if(upper_alpha != NULL) {
-                                       a1 = upper_alpha[i];
-                               } else {
-                                       a1 = RGBA_COLOR(255, 255, 255, 255);
-                               }
-                               a2 = ~a1;
-                               d1 = src1[i];
-                               d2 = src2[i];
-                               d2 = d2 * a1;
-                               d1 = d1 * a2;
-                               dst[i] = d1 | d2;
-                       }
-               }
-       }
-}
-
-void TOWNS_CRTC::vzoom_pixel(scrntype_t*src, int width, int srclines, scrntype_t* dst, int stride, int dstlines, float vzoom)
-{
-       if(src == dst) return;
-       if(vzoom <= 0.0f) return;
-       if((src == NULL) || (dst == NULL)) return;
-       if(width <= 0) return;
-       if(srclines <= 0) return;
-       if(dstlines <= 0) return;
-
-       scrntype_t *psrc = src;
-       scrntype_t *pdst = dst;
-
-       float vzoom_int = floor(vzoom);
-       float vzoom_mod = vzoom - vzoom_int;
-       float nmod = 0.0f;
-       int nint = (int)vzoom_int;
-       int srcline = 0;
-       int linecount = 0;
-       for(srcline = 0; srcline < srclines; srcline++) {
-               int ifactor = nint;
-               if(nmod >= 1.0f) {
-                       nmod = nmod - 1.0f;
-                       ifactor++;
-               }
-               for(int ii = 0; ii < ifactor; ii++) {
-                       // ToDo: Mask, blend.
-                       memcpy(pdst, psrc, width * sizeof(scrntype_t));
-                       linecount++;
-                       if(linecount >= dstlines) goto _exit0;;
-                       pdst += stride;
-               }
-               psrc += stride;
-               nmod = nmod + vzoom_mod;
-       }
-_exit0:        
-       return;
-}
-               
-void TOWNS_CRTC::hzoom_pixel(scrntype_t* src, int width, scrntype_t* dst, int dst_width, float hzoom)
-{
-       if(src == dst) return;
-       if(hzoom <= 0.0f) return;
-       if((src == NULL) || (dst == NULL)) return;
-       if(width <= 0) return;
-       if(dst_width <= 0) return;
-
-       scrntype_t* pdst = dst;
-       float hzoom_int = floor(hzoom);
-       float hzoom_mod = hzoom - hzoom_int;
-       float nmod = 0.0f;
-       int nint = (int)hzoom_int;
-       if((nint == 1) && (hzoom_mod <= 0.0f)) {
-               // x1.0
-               scrntype_t *sp = src;
-               scrntype_t pcache[4];
-               int nw = width / 4;
-               int dx = 0;
-               int ycount = 0;
-               for(int ii = 0; ii < nw; ii++) {
-                       if((dx + 3) >= dst_width) break;
-                       for(int j = 0; j < 4; j++) {
-                               pcache[j] = sp[j];
-                       }
-                       // ToDo: Mask/Alpha
-                       for(int j = 0; j < 4; j++) {
-                               pdst[j] = pcache[j];
-                       }
-                       dx += 4;
-                       pdst += 4;
-                       sp += 4;
-               }
-               nw = width - dx;
-               if(dx >= dst_width) return;
-               for(int ii = 0; ii < nw; ii++) {
-                       if(dx >= dst_width) goto __exit_0;
-                       // ToDo: Mask/Alpha
-                       pcache[ii] = sp[ii];
-                       pdst[ii] = pcache[ii];
-                       dx++;
-               }
-       } else {
-               scrntype_t *sp = src;
-               int dx = 0;
-               int xcount = 0;
-               for(int i = 0; i < width; i++) {
-                       // ToDo : Storage via SIMD.
-                       if(dx >= dst_width) goto __exit_0;
-                       
-                       int ifactor = nint;
-                       if(nmod >= 1.0f) {
-                               ifactor++;
-                               nmod = nmod - 1.0f;
-                       }
-                       scrntype_t pix = *sp++;
-                       scrntype_t pcache[4];
-                       // ToDo: MASK/ALPHA
-               
-                       int jfactor = ifactor / 4;
-                       xcount = 0;
-                       for(int k = 0; k < 4; k++) {
-                               pcache[k] = pix;
-                       }
-                       for(int j = 0; j < jfactor; j++) {
-                               if((dx + 3) >= dst_width) break; 
-                               for(int k = 0; k < 4; k++) {
-                                       pdst[k] = pcache[k];
-                               }
-                               xcount += 4;
-                               pdst += 4;
-                               dx += 4;
-                       }
-                       ifactor = ifactor - xcount;
-                       if(ifactor < 0) ifactor = 0;
-                       for(int k = 0; k < ifactor; k++) {
-                               if(dx >= dst_width) goto __exit_0;
-                               pdst[k] = pcache[k];
-                               dx++;
-                       }
-                       nmod = nmod + hzoom_mod;
-                       
-                       pdst += ifactor;
-               }               
-       }
-__exit_0:
-       return;
-}