Jonne Valola / PokittoLib Featured

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

PokittoLib

Library for programming Pokitto hardware

How to Use

  1. Import this library to online compiler (see button "import" on the right hand side
  2. DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
  3. Change My_settings.h according to your project
  4. Start coding!

Files at this revision

API Documentation at this revision

Comitter:
Pokitto
Date:
Sat Mar 23 19:19:23 2019 +0000
Parent:
60:8b6a110feeea
Commit message:
Mode 15 support added

Changed in this revision

POKITTO_CORE/PokittoDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoDisplay.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWLCD.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWLCD.h Show annotated file Show diff for this revision Revisions of this file
--- a/POKITTO_CORE/PokittoDisplay.cpp	Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_CORE/PokittoDisplay.cpp	Sat Mar 23 19:19:23 2019 +0000
@@ -71,6 +71,7 @@
 #include "PokittoSound.h"
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 #ifdef DISABLEAVRMIN
 #include <algorithm>
 using std::min;
@@ -92,8 +93,6 @@
 
 using namespace Pokitto;
 
-
-
 uint8_t* Display::m_scrbuf;
 uint8_t* Display::m_tileset;
 uint8_t* Display::m_tilebuf;
@@ -124,7 +123,7 @@
 const unsigned char* Display::font;
 int8_t Display::adjustCharStep = 1;
 int8_t Display::adjustLineStep = 1;
-bool Display::fixedWidthFont = false;
+bool Display::fixedWidthFont = false, Display::flipFontVertical = false;
 
 /** drawing canvas **/
 //uint8_t* Display::canvas; // points to the active buffer. if null, draw direct to screen
@@ -139,7 +138,7 @@
 #elif (POK_SCREENMODE == MODE_HI_4COLOR)
     uint8_t Display::width = POK_LCD_W;
     uint8_t Display::height = POK_LCD_H;
-    uint8_t __attribute__((section (".bss"))) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution
+    uint8_t __attribute__((section (".bss"))) __attribute__ ((aligned)) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution
 #elif (POK_SCREENMODE == MODE_FAST_16COLOR)
     uint8_t Display::width = POK_LCD_W/2;
     uint8_t Display::height = POK_LCD_H/2;
@@ -164,10 +163,19 @@
     uint8_t Display::width = 110;
     uint8_t Display::height = 88;
     uint8_t Display::screenbuffer[110*88]; // 8bit 110x88
+#elif (POK_SCREENMODE == MIXMODE)
+    uint8_t Display::width = 110;
+    uint8_t Display::height = 88;
+    uint8_t Display::screenbuffer[110*88]; // 8bit 110x88 or 4bit 110x176
+    uint8_t Display::scanType[88]; // scanline bit depth indicator
+#elif (POK_SCREENMODE == MODE64)
+    uint8_t Display::width = 110;
+    uint8_t Display::height = 176;
+    uint8_t __attribute__ ((aligned)) Display::screenbuffer[110*176]; // 8bit 110x176
 #elif (POK_SCREENMODE == MODE15)
     uint8_t Display::width = 220;
     uint8_t Display::height = 176;
-    uint8_t Display::screenbuffer[0x4BA0];
+    uint8_t __attribute__ ((aligned)) Display::screenbuffer[0x4BA0];
 #else
     uint8_t Display::width = 84;
     uint8_t Display::height = 48;
@@ -206,7 +214,7 @@
     #endif // POK_GAMEBUINO_SUPPORT
 
     // Reset sprites
-    m_tilecolorbuf = NULL; //!!HV
+    m_tilecolorbuf = NULL;
     for (uint8_t s = 0; s < SPRITE_COUNT; s++) m_sprites[s].bitmapData = NULL;
 }
 
@@ -289,6 +297,14 @@
 		lcdRefreshMode13(m_scrbuf, paletteptr, palOffset);
 		#endif
 
+		#if POK_SCREENMODE == MIXMODE
+		lcdRefreshMixMode(m_scrbuf, paletteptr, scanType);
+		#endif
+
+		#if POK_SCREENMODE == MODE64
+		lcdRefreshMode64(m_scrbuf, paletteptr);
+		#endif
+
         #if POK_SCREENMODE == MODE_GAMEBOY
         lcdRefreshModeGBC(m_scrbuf, paletteptr);
         #endif
@@ -352,7 +368,9 @@
         directcolor = COLOR_WHITE;
         invisiblecolor = COLOR_BLACK;
         directbgcolor = 0x0001; // Cannot be black as that is transparent color
-        if (POK_SCREENMODE == MODE_FAST_16COLOR )
+        if (POK_SCREENMODE == MODE_FAST_16COLOR ||
+            POK_SCREENMODE == MODE13
+        )
             directtextrotated = false;
         else
             directtextrotated = true;
@@ -484,39 +502,92 @@
     // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
     uint16_t bitcolumn; //16 bits for 2x8 bit high characters
 
+    if( fontSize != 2 ) fontSize = 1;
+
+    void (*drawPixelFG)(int16_t,int16_t, uint8_t) = &Display::drawPixelNOP;
+    void (*drawPixelBG)(int16_t,int16_t, uint8_t) = &Display::drawPixelNOP;
+    if( x>=0 && y >= 0 && x+w*fontSize<width && y+(h+1)*fontSize<height ){
+	if( color != invisiblecolor )
+	    drawPixelFG = &Display::drawPixelRaw;
+	if( bgcolor != invisiblecolor )
+	    drawPixelBG = &Display::drawPixelRaw;
+    }else{
+	if( color != invisiblecolor )
+	    drawPixelFG = &Display::drawPixel;
+	if( bgcolor != invisiblecolor )
+	    drawPixelBG = &Display::drawPixel;
+    }
+
+    void (*drawPixel[])(int16_t,int16_t, uint8_t) = {drawPixelBG, drawPixelFG};
+    uint8_t colors[] = {bgcolor, color};
+
+#if PROJ_ARDUBOY > 0
+#else
+    if( fontSize != 2 ){
+#endif
+
+    for (i = 0; i < numBytes; i++) {
+	bitcolumn = *bitmap++;
+	if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
+	for (j = 0; j <= h; j++) { // was j<=h
+	    uint8_t c = colors[ bitcolumn & 1 ];
+
+#if PROJ_ARDUBOY > 0
+	    drawPixel[ bitcolumn&1 ](x, y + 7 - j,c);
+#elif PROJ_SUPPORT_FONTROTATION > 0
+       // if font flipping & rotation is allowed - do not slow down old programs!
+       if (flipFontVertical) {
+           drawPixel[ bitcolumn&1 ](x, y + h - j,c);
+       } else {
+           drawPixel[ bitcolumn&1 ](x, y + j,c);
+       }
+#else
+	   // "Normal" case
+	    drawPixel[ bitcolumn&1 ](x, y + j,c);
+#endif // PROJ_ARDUBOY
+	    bitcolumn>>=1;
+
+	}
+#if PROJ_SUPPORT_FONTROTATION > 0
+	if (flipFontVertical) x--;
+	else x++;
+#else
+    x++;
+#endif
+    }
+
+#if PROJ_SUPPORT_FONTROTATION > 0
+    if (flipFontVertical) return -numBytes-adjustCharStep;
+    else return numBytes+adjustCharStep; // for character stepping
+#else
+    return numBytes+adjustCharStep;
+#endif
+
+
+#if PROJ_ARDUBOY > 0
+#else
+    }else{
+
 	for (i = 0; i < numBytes; i++) {
-            bitcolumn = *bitmap++;
-            if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
-            for (j = 0; j <= h; j++) { // was j<=h
-                #if PROJ_ARDUBOY > 0
-                if (bitcolumn&0x1) {
-                    drawPixel(x + i, y + 7 - j,color);
-                } else drawPixel(x + i, y + 7 - j,bgcolor);
-                bitcolumn>>=1;
-                #else
-                if (fontSize==2) {
-                  if (bitcolumn&0x1) {
-                            drawPixel(x + (i<<1)  , y + (j<<1),color);
-                            drawPixel(x + (i<<1)+1, y + (j<<1),color);
-                            drawPixel(x + (i<<1)  , y + (j<<1)+1,color);
-                            drawPixel(x + (i<<1)+1, y + (j<<1)+1,color);
-                        } else {
-                            drawPixel(x + (i<<1)  , y + (j<<1),bgcolor);
-                            drawPixel(x + (i<<1)+1, y + (j<<1),bgcolor);
-                            drawPixel(x + (i<<1)  , y + (j<<1)+1,bgcolor);
-                            drawPixel(x + (i<<1)+1, y + (j<<1)+1,bgcolor);
-                        }
-                } else {
-                    if (bitcolumn&0x1) drawPixel(x + i, y + j,color);
-                    else drawPixel(x + i, y + j,bgcolor);
-                }
-                bitcolumn>>=1;
-                #endif // PROJ_ARDUBOY
+	    bitcolumn = *bitmap++;
+	    if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
+	    for (j = 0; j <= h; j++) { // was j<=h
+		uint8_t c = colors[ bitcolumn & 1 ];
 
-            }
+		drawPixel[ bitcolumn&1 ](x + (i<<1)  , y + (j<<1), c);
+		drawPixel[ bitcolumn&1 ](x + (i<<1)+1, y + (j<<1), c);
+		drawPixel[ bitcolumn&1 ](x + (i<<1)  , y + (j<<1)+1, c);
+		drawPixel[ bitcolumn&1 ](x + (i<<1)+1, y + (j<<1)+1, c);
+		bitcolumn>>=1;
+
+	    }
+	}
+
+	return (numBytes+adjustCharStep)<<1;
+
     }
-    if (fontSize==2) return (numBytes+adjustCharStep)<<1;
-    return numBytes+adjustCharStep; // for character stepping
+#endif // PROJ_ARDUBOY
+
 }
 
 void Display::clear() {
@@ -532,13 +603,13 @@
         uint16_t j = POK_BITFRAME;
         if (bgcolor & 0x1) memset((void*)m_scrbuf,0xFF,j);// R
         else memset((void*)m_scrbuf,0x00,j);// R
-        if ((bgcolor>>1) & 0x1) memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME),0xFF,j);// G
-        else memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME),0x00,j);// G
-        if ((bgcolor>>2) & 0x1) memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME*2),0xFF,j);// B
-        else memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME*2),0x00,j);// B
+        if ((bgcolor>>1) & 0x1) memset((char*)m_scrbuf+POK_BITFRAME,0xFF,j);// G
+        else memset((char*)m_scrbuf+POK_BITFRAME,0x00,j);// G
+        if ((bgcolor>>2) & 0x1) memset((char*)m_scrbuf+POK_BITFRAME*2,0xFF,j);// B
+        else memset((char*)m_scrbuf+POK_BITFRAME*2,0x00,j);// B
         setCursor(0,0);
         return;
-    } else {
+    } else if (bpp==4) {
         c = (c & 0x0F) | (c << 4);
     }
     uint16_t j = sizeof(screenbuffer);
@@ -621,12 +692,10 @@
     clipX = x; clipY = y; clipW = w; clipH = h;
 }
 
+void Display::drawPixelNOP(int16_t x,int16_t y, uint8_t col) {
+}
 
-void Display::drawPixel(int16_t x,int16_t y, uint8_t col) {
-    if (col==invisiblecolor) return; // do not draw transparent pixels
-    if ((uint16_t)x >= width || (uint16_t)y >= height) return;
-    col &= (PALETTE_SIZE-1);
-
+void Display::drawPixelRaw(int16_t x,int16_t y, uint8_t col) {
     #if POK_COLORDEPTH == 8
         m_scrbuf[x+width*y] = col;
     #endif
@@ -689,75 +758,16 @@
     #endif // POK_GAMEBUINO_SUPPORT
 }
 
+void Display::drawPixel(int16_t x,int16_t y, uint8_t col) {
+    if (col==invisiblecolor) return; // do not draw transparent pixels
+    if ((uint16_t)x >= width || (uint16_t)y >= height) return;
+    col &= (PALETTE_SIZE-1);
+    drawPixelRaw( x, y, col );
+}
+
 void Display::drawPixel(int16_t x,int16_t y) {
     if ((uint16_t)x >= width || (uint16_t)y >= height) return;
-
-    #if POK_COLORDEPTH == 8
-        m_scrbuf[x+width*y] = color;
-    #endif
-
-    #if POK_GAMEBUINO_SUPPORT > 0
-
-	uint8_t c = color;
-	uint8_t ct = color;
-	if(ct == INVERT){
-	 ct = !getPixel(x, y); //jonne - was c = !getP...
-	}
-
-    uint16_t bitptr=0;
-    for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
-	c = ct & 1; // take the lowest bit of the color index number
-	if(c == 0){ //white - or actually "Clear bit"
-    #if DISPLAY_ROT == NOROT
-		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
-    #elif DISPLAY_ROT == ROTCCW
-		m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV(x % 8);
-    #elif DISPLAY_ROT == ROT180
-		m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV((LCDHEIGHT - y - 1) % 8);
-    #elif DISPLAY_ROT == ROTCW
-		m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitbtr] &= ~_BV((LCDWIDTH - x - 1) % 8);
-    #endif
-		//return; //jonne
-	} else { //black - or actually "Set bit"
-    #if DISPLAY_ROT == NOROT
-		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
-    #elif DISPLAY_ROT == ROTCCW
-		m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] |= _BV(x % 8);
-    #elif DISPLAY_ROT == ROT180
-		m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDHEIGHT - y - 1) % 8);
-    #elif DISPLAY_ROT == ROTCW
-		m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDWIDTH - x -1) % 8);
-    #endif
-		//return; //jonne
-	}
-	ct >>=1; // shift to get next bit
-	bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
-    } // POK_COLOURDEPTH
-
-    #else
-
-    /** NOT Gamebuino */
-    #if POK_COLORDEPTH == 1
-        if (color) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
-        m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
-    #elif POK_COLORDEPTH == 2
-        uint16_t i = y*(width>>2) + (x>>2);
-        uint8_t pixel = m_scrbuf[i];
-        uint8_t column = x&0x03;
-        if (column==3) pixel = (pixel&0xFC)|(color); // bits 0-1
-        else if (column==2) pixel = (pixel&0xF3)|(color<<2); // bits 2-3
-        else if (column==1) pixel = (pixel&0xCF)|(color<<4); // bits 4-5
-        else pixel = (pixel&0x3F)|(color<<6); // bits 6-7
-        m_scrbuf[i] = pixel;
-    #elif POK_COLORDEPTH == 3
-    #elif POK_COLORDEPTH == 4
-            uint16_t i = y*(width>>1) + (x>>1);
-            uint8_t pixel = m_scrbuf[i];
-            if (x&1) pixel = (pixel&0xF0)|(color);
-            else pixel = (pixel&0x0F) | (color<<4);
-            m_scrbuf[i] = pixel;
-    #endif // POK_COLORDEPTH
-    #endif // POK_GAMEBUINO_SUPPORT
+    drawPixelRaw( x, y, color );
 }
 
 uint8_t Display::getPixel(int16_t x,int16_t y) {
@@ -1496,6 +1506,7 @@
         int16_t bitFrame = w * h / 8;
         for (i = 0; i < w; i++) {
         byteNum = i / 8;
+        //bitNum = i % 8;
 
         uint8_t bitcount=0;
         for (j = 0; j <= h/8; j++) {
@@ -1518,7 +1529,8 @@
     else if (m_colordepth==4) {
 
     /** 4bpp fast version */
-	int16_t scrx,scry,xclip,xjump,scrxjump;
+	int16_t scrx,scry,xjump,scrxjump;
+	int16_t xclip;
     xclip=xjump=scrxjump=0;
     /** y clipping */
     if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
@@ -1555,8 +1567,9 @@
                         uint8_t sourcepixel = *bitmap;
                         if ((sourcepixel&0x0F) != invisiblecolor) {
                             sourcepixel <<=4;
-                            uint8_t targetpixel = *scrptr;// & 0x0F;
-                            targetpixel |= sourcepixel;
+                            volatile uint8_t targetpixel = *scrptr;// & 0x0F;
+                            targetpixel &= 0xF; //clear upper nibble
+                            targetpixel |= sourcepixel; //now OR it
                             *scrptr = targetpixel;
                         }
                         //scrptr++;
@@ -1566,9 +1579,11 @@
                 }
                 bitmap += xjump; // needed if x<0 clipping occurs
             } else { /** ODD pixel starting line **/
+                uint8_t sourcepixel;
+                uint8_t targetpixel;
                 for (scrx = x; scrx < w+x-xclip; scrx+=2) {
-                    uint8_t sourcepixel = *bitmap;
-                    uint8_t targetpixel = *scrptr;
+                    sourcepixel = *bitmap;
+                    targetpixel = *scrptr;
                     // store higher nibble of source pixel in lower nibble of target
                     if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
                     *scrptr = targetpixel;
@@ -1579,6 +1594,12 @@
                     *scrptr = targetpixel;
                     bitmap++;
                 }
+                if (xclip) {
+                    // last line, store higher nibble of last source pixel in lower nibble of last address
+                    sourcepixel = *bitmap >> 4;
+                    if(sourcepixel!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | sourcepixel;
+                    *scrptr = targetpixel;
+                }
                 bitmap+=xjump;
             }
             // increment the y jump in the scrptr
@@ -1591,16 +1612,15 @@
     /** 4bpp fast version */
 
     if (m_colordepth==8) {
-	int16_t scrx,scry,xjump,scrxjump;
-    xjump=scrxjump=0;
+    int16_t scrx,scry;//,scrxjump;
+    int16_t xjump=0;
     /** y clipping */
     if (y<0) { h+=y; bitmap -= y*w; y=0;}
     else if (y+h>height) { h -=(y-height);}
     /** x clipping */
     if (x<0) { w+=x; xjump = (-x); bitmap += xjump; x=0;}
     else if (x+w>width) {
-            scrxjump = x;
-            xjump=(x+w-width)+scrxjump;
+            xjump=(x+w-width);
             w = width-x;}
 
     uint8_t* scrptr = m_scrbuf + (y*width + x);
@@ -1614,8 +1634,8 @@
                     bitmap++;
                     scrptr++;
                 }
-            bitmap += xjump; // needed if x<0 clipping occurs
-        scrptr = scrptr + (width - w)+scrxjump;
+            bitmap += xjump; // needed if horizontal clipping occurs
+            scrptr = scrptr + (width - w);
     }
     return;
     }
@@ -1779,83 +1799,105 @@
     } // end for scry
 }
 
-void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap)
+void Display::drawBitmapDataXFlipped(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap)
 {
-    int16_t w = *bitmap;
-	int16_t h = *(bitmap + 1);
-    bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
     /** visibility check */
     if (y<-h || y>height) return; //invisible
     if (x<-w || x>width) return;  //invisible
     /** 1 bpp mode */
-    if (m_colordepth<2) {
-    int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
-    for (i = 0; i < w; i++) {
-        byteNum = i / 8;
-        bitNum = i % 8;
-        for (j = 0; j < h; j++) {
-            uint8_t source = *(bitmap + j * byteWidth + byteNum);
-            if (source & (0x80 >> bitNum)) {
-                drawPixel(x + w - i, y + j);
+    if (m_colordepth<2)
+    {
+        int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+        for (i = 0; i < w; i++)
+        {
+            byteNum = i / 8;
+            bitNum = i % 8;
+            for (j = 0; j < h; j++)
+            {
+                uint8_t source = *(bitmap + j * byteWidth + byteNum);
+                if (source & (0x80 >> bitNum))
+                {
+                    drawPixel(x + w - i, y + j);
+                }
             }
         }
-    }
 
-    return;
+        return;
     }
     /** 2 bpp mode */
-    if (m_colordepth<4) {
-    int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
-    for (i = 0; i < w; i++) {
-        byteNum = i / 4;
-        bitNum = (i % 4)<<1;
-        for (j = 0; j < h; j++) {
-            uint8_t source = *(bitmap + j * byteWidth + byteNum);
-            uint8_t output = (source & (0xC0 >> bitNum));
-            output >>= (6-bitNum);
-            if (output != invisiblecolor) {
-                setColor(output);
-                drawPixel(x + i, y + j);
+    else if (m_colordepth==2)
+    {
+        int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
+        for (i = 0; i < w; i++)
+        {
+            byteNum = i / 4;
+            bitNum = (i % 4)<<1;
+            for (j = 0; j < h; j++)
+            {
+                uint8_t source = *(bitmap + j * byteWidth + byteNum);
+                uint8_t output = (source & (0xC0 >> bitNum));
+                output >>= (6-bitNum);
+                if (output != invisiblecolor)
+                {
+                    setColor(output);
+                    drawPixel(x + i, y + j);
+                }
             }
         }
-    }
 
-    return;
+        return;
     }
-    /** 4bpp fast version */
-	int16_t scrx,scry,xclip,xjump,scrxjump;
-    xclip=xjump=scrxjump=0;
-    /** y clipping */
-    if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
-    else if (y+h>height) { h -=(y-height);}
-    /** x clipping */
-    bitmap += ((w>>1)-1); //inverted!
-    if (x<0) {
+    else if (m_colordepth==4)
+    {
+        /** 4bpp fast version */
+        int16_t scrx,scry,xclip,xjump,scrxjump;
+        xclip=xjump=scrxjump=0;
+        /** y clipping */
+        if (y<0)
+        {
+            h+=y;
+            bitmap -= y*(w>>1);
+            y=0;
+        }
+        else if (y+h>height)
+        {
+            h -=(y-height);
+        }
+        /** x clipping */
+        bitmap += ((w>>1)-1); //inverted!
+        if (x<0)
+        {
             xclip=(x&1)<<1;
             w+=x;
             xjump = ((-x)>>1);
             //bitmap += xjump; // do not clip left edge of source, as bitmap is inverted !
             x=0;
-            }
-    else if (x+w>width) {
+        }
+        else if (x+w>width)
+        {
             xclip = (x&1)<<1;
             scrxjump = x&1;
             xjump=((x+w-width)>>1)+scrxjump;
-            w = width-x;}
+            w = width-x;
+        }
 
-    //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1));
-    uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
-    /** ONLY 4-bit mode for time being **/
-    for (scry = y; scry < y+h; scry+=1) {
-    //    for (scry = y; scry < y+2; scry+=1) {
+        //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1));
+        uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+        /** ONLY 4-bit mode for time being **/
+        for (scry = y; scry < y+h; scry+=1)
+        {
+            //    for (scry = y; scry < y+2; scry+=1) {
             if (scry>=height) return;
-            if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
+            if ((x&1)==0)   /** EVEN pixel starting line, very simple, just copypaste **/
+            {
                 //for (scrx = w+x-xclip-1; scrx >= x; scrx-=2) {
-                for (scrx = x; scrx < w+x-xclip; scrx+=2) {
+                for (scrx = x; scrx < w+x-xclip; scrx+=2)
+                {
                     uint8_t sourcepixel = *(bitmap);
-                    if (xclip) {
-                            sourcepixel <<=4;
-                            sourcepixel |= ((*(bitmap-1))>>4);//inverted!
+                    if (xclip)
+                    {
+                        sourcepixel <<=4;
+                        sourcepixel |= ((*(bitmap-1))>>4);//inverted!
                     }
                     uint8_t targetpixel = *scrptr;
                     // NIBBLES ARE INVERTED BECAUSE PICTURE IS FLIPPED !!!
@@ -1866,11 +1908,14 @@
                     scrptr++;
                 }
                 bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
-                if (xclip){
-                    if (w&1) {
+                if (xclip)
+                {
+                    if (w&1)
+                    {
                         /**last pixel is odd pixel due to clipping & odd width*/
                         uint8_t sourcepixel = *bitmap;
-                        if ((sourcepixel&0x0F) != invisiblecolor) {
+                        if ((sourcepixel&0x0F) != invisiblecolor)
+                        {
                             sourcepixel <<=4;
                             uint8_t targetpixel = *scrptr;// & 0x0F;
                             targetpixel |= sourcepixel;
@@ -1882,8 +1927,11 @@
                     scrptr++;
                 }
                 bitmap += xjump; // needed if x<0 clipping occurs
-            } else { /** ODD pixel starting line **/
-                for (scrx = x; scrx < w+x-xclip; scrx+=2 ) {
+            }
+            else     /** ODD pixel starting line **/
+            {
+                for (scrx = x; scrx < w+x-xclip; scrx+=2 )
+                {
                     uint8_t sourcepixel = *bitmap;
                     uint8_t targetpixel = *scrptr;
                     // inverted !!! store lower nibble of source pixel in lower nibble of target
@@ -1901,7 +1949,62 @@
             }
             // increment the y jump in the scrptr
             scrptr = scrptr + ((width - w)>>1)+scrxjump;
+        }
     }
+    /** 8 bpp mode */
+    else if (m_colordepth==8)
+    {
+        int16_t scrx,scry;//,scrxjump;
+        int16_t xjump=0;
+        /** y clipping */
+        if (y<0)
+        {
+            h+=y;
+            bitmap -= y*w;
+            y=0;
+        }
+        else if (y+h>height)
+        {
+            h -=(y-height);
+        }
+        /** x clipping */
+        if (x<0)
+        {
+            w+=x;
+            xjump = (-x);
+            bitmap += xjump;
+            x=0;
+        }
+        else if (x+w>width)
+        {
+            xjump=(x+w-width);
+            w = width-x;
+        }
+
+        uint8_t* scrptr = m_scrbuf + (y*width + x) + w;
+        for (scry = y; scry < y+h; scry+=1)
+        {
+            if (scry>=height) return;
+            for (scrx = x; scrx < w+x; scrx++)
+            {
+                uint8_t sourcepixel = *bitmap;
+                uint8_t targetpixel = *scrptr;
+                if (sourcepixel != invisiblecolor )
+                    targetpixel = sourcepixel;
+                *scrptr = targetpixel;
+                bitmap++;
+                scrptr--;
+            }
+            bitmap += xjump; // needed if horizontal clipping occurs
+            scrptr = scrptr + (width + w);
+        }
+        return;
+    }
+}
+
+void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap)
+{
+    drawBitmapDataXFlipped(x, y, bitmap[0], bitmap[1], bitmap + 2);
 }
 
 void Display::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip) {
@@ -2338,6 +2441,7 @@
   }
 }
 
+
 void Display::draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap)
 {
     int8_t scry;
@@ -2441,6 +2545,14 @@
     lcdRefreshMode13(m_scrbuf, paletteptr, palOffset);
 #endif
 
+#if POK_SCREENMODE == MIXMODE
+    lcdRefreshMixMode(m_scrbuf, paletteptr, scanType);
+#endif
+
+#if POK_SCREENMODE == MODE64
+    lcdRefreshMode64(m_scrbuf, paletteptr);
+#endif
+
 #if POK_SCREENMODE == MODE_GAMEBOY
     lcdRefreshModeGBC(scr, paletteptr);
 #endif
@@ -2476,6 +2588,8 @@
     m_tilebuf[i]=t;
 };
 
+
+
 // Convert an integer to a hexadecimal string
 char* itoa_hex(int num, char* dest, int destLen) {
     int i = destLen-1;
@@ -2489,6 +2603,7 @@
 }
 
 // Draw the crash screen and wait forever
+#define STR_TO_UPPER(str_from, str_to) for( int32_t i=0; i <= strlen(str_from); i++ ) str_to[i] = toupper(str_from[i]);
 void ShowCrashScreenAndWait( const char* texLine1, const char* texLine2, const char* texLine3, const char* texLine4, const char* texLine5 ) {
 
     // draw screen red
@@ -2505,15 +2620,17 @@
     Display::fixedWidthFont = true; // Needed for the non-proportional C64 font (default value=false)
     Display::enableDirectPrinting(true);
 
+    char convertedStr[128] = {0};
+
     // Draw texts
     int  yOffsetInPixels = 5;
     Display::set_cursor(0, 9 + yOffsetInPixels);
-    Display::print("  ");    Display::println(texLine1);
-    Display::print("  ");    Display::println(texLine2);
-    Display::print("  ");    Display::println(texLine3);
+    Display::print("  ");    STR_TO_UPPER(texLine1, convertedStr); Display::println(convertedStr);
+    Display::print("  ");    STR_TO_UPPER(texLine2, convertedStr); Display::println(convertedStr);
+    Display::print("  ");    STR_TO_UPPER(texLine3, convertedStr); Display::println(convertedStr);
     Display::println();
-    Display::print("  *");   Display::println(texLine4);
-    Display::print("  *");   Display::println(texLine5);
+    Display::print("  *");   STR_TO_UPPER(texLine4, convertedStr); Display::println(convertedStr);
+    Display::print("  *");   STR_TO_UPPER(texLine5, convertedStr); Display::println(convertedStr);
 
     Display::set_cursor(0, 0 + yOffsetInPixels);
 
--- a/POKITTO_CORE/PokittoDisplay.h	Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_CORE/PokittoDisplay.h	Sat Mar 23 19:19:23 2019 +0000
@@ -141,12 +141,14 @@
 private:
     static uint8_t* canvas;
     static uint8_t bpp;
-    static uint8_t m_colordepth;
 public:
+    static uint8_t m_colordepth; // public to be used elsewhere
+    static uint8_t subMode; // for mixed mode switching
     static uint8_t palOffset;
     static uint8_t width;
     static uint8_t height;
     static uint8_t screenbuffer[];
+    static uint8_t scanType[]; // for mixed screen mode
 
     // PROPERTIES
     static void setColorDepth(uint8_t);
@@ -312,6 +314,8 @@
     static void drawRleBitmap(int16_t x, int16_t y, const uint8_t* bitmap);
     /** Draw animated bitmap frame */
     static void drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame);
+    /** Draw bitmap data flipped on x-axis*/
+    static void drawBitmapDataXFlipped(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap);
     /** Draw bitmap flipped on x-axis*/
     static void drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap);
     /** Draw bitmap with options */
@@ -391,7 +395,7 @@
     static int16_t cursorX,cursorY;
     static uint8_t fontSize;
     static int8_t adjustCharStep, adjustLineStep;
-	static bool fixedWidthFont;
+	static bool fixedWidthFont, flipFontVertical;
 
     static void inc_txtline();
     static void printNumber(unsigned long, uint8_t);
--- a/POKITTO_HW/HWLCD.cpp	Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_HW/HWLCD.cpp	Sat Mar 23 19:19:23 2019 +0000
@@ -453,11 +453,132 @@
  * @param updRectH The update rect.
  * @param paletteptr The screen palette.
 */
+
+
+#define MODE1_LOOP					\
+  "	adds %[t], %[palette]"			"\n"	\
+  "	ldm %[t], {%[t], %[x]}"			"\n"	\
+  "	str %[t], [%[LCD], 0]"			"\n"	\
+  "	movs %[t], 252"	"\n"				\
+  "	str %[WRBit], [%[LCD], %[t]]"   	"\n"	\
+  "	str %[WRBit], [%[LCD], 124]"		"\n"	\
+  "	str %[x], [%[LCD], 0]"			"\n"	\
+  "	str %[WRBit], [%[LCD], %[t]]"   	"\n"	\
+  "	movs %[t], 0x0F"			"\n"	\
+  "	ands %[t], %[t], %[c]"			"\n"	\
+  "	str %[WRBit], [%[LCD], 124]"		"\n"	\
+							\
+  "	lsls %[t], 3"				"\n"    \
+  "	adds %[t], %[palette]"			"\n"	\
+  "	ldm %[t], {%[t], %[x]}"			"\n"	\
+  "	str %[t], [%[LCD], 0]"			"\n"	\
+  "	movs %[t], 252"	"\n"				\
+  "	str %[WRBit], [%[LCD], %[t]]"   	"\n"	\
+  "	str %[WRBit], [%[LCD], 124]"		"\n"	\
+  "	str %[x], [%[LCD], 0]"			"\n"	\
+  "	str %[WRBit], [%[LCD], %[t]]"   	"\n"	\
+  "	lsrs %[c], 8"				"\n"	\
+  "	movs %[t], 0xF0"			"\n"	\
+  "	ands %[t], %[t], %[c]"			"\n"	\
+  "	lsrs %[t], %[t], 1"			"\n"	\
+  "	str %[WRBit], [%[LCD], 124]"		"\n"
+
+
 void Pokitto::lcdRefreshMode1(uint8_t * scrbuf, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH, uint16_t* paletteptr) {
 
-    uint16_t x,y;
+
+#ifdef XPERIMENTAL
+//#define __ARMCC_VERSION 1
+#endif
+
+#ifndef __ARMCC_VERSION
+
+  write_command(0x03); write_data(0x1038);
+  write_command(0x20);  // Horizontal DRAM Address
+  write_data(0);
+  write_command(0x21);  // Vertical DRAM Address
+  write_data(0);
+  write_command(0x22); // write data to DRAM
+  CLR_CS_SET_CD_RD_WR;
+
+  uint8_t *end=&scrbuf[POK_SCREENBUFFERSIZE>>1]+4;
+
+  volatile uint32_t palette[32];
+  for( uint32_t i=0; i<16; ++i ){
+    palette[(i<<1)+1] = static_cast<uint32_t>(paletteptr[i&3 ]) << 3;
+    palette[(i<<1)  ] = static_cast<uint32_t>(paletteptr[i>>2]) << 3;
+  }
+
+  SET_MASK_P2;
+
+  uint32_t c, WRBit = 1<<12;
+
+  register uint32_t x asm("r2");
+  register uint32_t t asm("r1");
+
+  asm volatile(
+
+	 ".syntax unified"         		"\n"
+	 "ldm %[scrbuf]!, {%[c]}"		"\n" // load 4 bytes (16 pixels)
+	 "movs %[t], 0xF0"			"\n"
+	 "ands %[t], %[t], %[c]"		"\n"
+	 "lsrs %[t], %[t], 1"			"\n"
+	 "mode1Loop%=:" 			"\n"
+	 MODE1_LOOP
+	 MODE1_LOOP
+	 MODE1_LOOP
+	 "	adds %[t], %[palette]"			"\n"
+	 "	ldm %[t], {%[t], %[x]}"			"\n"
+	 "	str %[t], [%[LCD], 0]"			"\n"
+	 "	movs %[t], 252"	"\n"
+	 "	str %[WRBit], [%[LCD], %[t]]"   	"\n"
+	 "	str %[WRBit], [%[LCD], 124]"		"\n"
+	 "	str %[x], [%[LCD], 0]"			"\n"
+	 "	str %[WRBit], [%[LCD], %[t]]"   	"\n"
+	 "	movs %[t], 0x0F"			"\n"
+	 "	ands %[t], %[t], %[c]"			"\n"
+	 "	str %[WRBit], [%[LCD], 124]"		"\n"
+
+	 "	lsls %[t], 3"				"\n"
+	 "	adds %[t], %[palette]"			"\n"
+	 "	ldm %[t], {%[t], %[x]}"			"\n"
+	 "	str %[t], [%[LCD], 0]"			"\n"
+	 "	movs %[t], 252"	"\n"
+	 "	str %[WRBit], [%[LCD], %[t]]"   	"\n"
+	 "	str %[WRBit], [%[LCD], 124]"		"\n"
+	 "	str %[x], [%[LCD], 0]"			"\n"
+	 "	str %[WRBit], [%[LCD], %[t]]"   	"\n"
+
+	 "	ldm %[scrbuf]!, {%[c]}"		"\n" // load next 4 bytes
+	 "	movs %[t], 0xF0"		"\n"
+	 "	ands %[t], %[t], %[c]"		"\n"
+	 "	lsrs %[t], %[t], 1"		"\n"
+	 "	str %[WRBit], [%[LCD], 124]"		"\n"
+
+	 "cmp %[end], %[scrbuf]"            	"\n"
+	 "bne mode1Loop%="       		"\n" // if scrbuf < end, loop
+
+	 : // outputs
+	   [c]"+l" (c),
+	   [t]"+l" (t),
+	   [end]"+h" (end),
+	   [scrbuf]"+l" (scrbuf),
+	   [WRBit]"+l" (WRBit),
+	   [x]"+l" (x)
+
+	 : // inputs
+	   [LCD]"l" (0xA0002188),
+	   [palette]"l" (palette)
+
+	 : // clobbers
+	   "cc"
+	       );
+
+
+#else
+    uint16_t x,y,xptr;
     uint16_t scanline[4][176]; // read 4 half-nibbles = 4 pixels at a time
-    uint8_t *d;
+    uint8_t *d, yoffset=0;
 
     // If not the full screen is updated, check the validity of the update rect.
     if ( updRectX != 0 || updRectY != 0 ||updRectW != LCDWIDTH ||updRectH != LCDHEIGHT ) {
@@ -477,6 +598,7 @@
     xptr = 8;
     setDRAMptr(8, 0);
     #else
+    xptr = 0;
     setDRAMptr(0, 0);
     #endif
 
@@ -484,6 +606,7 @@
         d = scrbuf+(x>>2);// point to beginning of line in data
 
         /** find colours in one scanline **/
+        uint8_t s=0;
         d += (updRectY * 220/4);
         for (y=updRectY; y<updRectY+updRectH; y++) {
             uint8_t tdata = *d;
@@ -555,6 +678,7 @@
             }
         }
     }
+#endif
 
     #ifdef POK_SIM
     simulator.refreshDisplay();
@@ -945,7 +1069,7 @@
     #endif
 }
 
-  
+
 #define MODE2_INNER_LOOP_B				\
   "	ldm %[scanline]!, {%[c]}"   "\n"		\
 	       "	str %[c], [%[LCD], 0]"    "\n"	\
@@ -955,98 +1079,104 @@
 	       "	str %[t], [%[LCD], 124]"  "\n"	\
 	       "	subs %[x], 1"             "\n"	\
 	       "	str %[t], [%[LCD], %[c]]" "\n"	\
-    
+
 
 void Pokitto::lcdRefreshMode2(uint8_t * scrbuf, uint16_t* paletteptr ) {
-  uint32_t x,y;
+  uint32_t x,y,byte,c,t=1<<12;
   uint32_t scanline[110];
 
   write_command(0x03); write_data(0x1038);
   write_command(0x20);  // Horizontal DRAM Address
   write_data(0);  // 0
   write_command(0x21);  // Vertical DRAM Address
-  write_data(1);
+
+#ifndef __ARMCC_VERSION
+  write_data(1); // still has pixel 0 bug
   write_command(0x22); // write data to DRAM
   CLR_CS_SET_CD_RD_WR;
   SET_MASK_P2;
 
-#ifndef __ARMCC_VERSION
-   asm volatile(
+  #ifdef PROJ_SHOW_FPS_COUNTER
+  setDRAMptr(0, 8);
+  y=4;
+  #endif
+
+  asm volatile(
 	 ".syntax unified"         "\n"
-	 
+
 	 "mov r10, %[scanline]"    "\n"
 	 "mov r11, %[t]"           "\n"
-	 
+
 	 "mode2OuterLoop:"        "\n"
-	 
+
 	 "movs %[x], 110"          "\n"
 	 "mode2InnerLoopA:"
 
 
-	 "	ldrb %[byte], [%[scrbuf],0]"   "\n"				
+	 "	ldrb %[byte], [%[scrbuf],0]"   "\n"
 	 "	lsrs %[c], %[byte], 4"    "\n"
 
 	 "	movs %[t], 15" "\n"
-	 "	ands %[byte], %[t]"    "\n"		
-	 
-	 "	lsls %[c], 1"             "\n"			
-	 "	ldrh %[t], [%[paletteptr], %[c]]"      "\n"	
-	 "	lsls %[t], %[t], 3"       "\n"			
-	 "	str %[t], [%[LCD], 0]"    "\n"			
-	 "	mov %[c], r11" "\n"				
-	 "	str %[c], [%[LCD], 124]"  "\n"			
-	 "	stm %[scanline]!, {%[t]}" "\n"			
-	 "	movs %[t], 252"   "\n"				
-	 "	str %[c], [%[LCD], %[t]]" "\n"			
-	 "	str %[c], [%[LCD], 124]"  "\n"			
-	 "	lsls %[byte], %[byte], 1"             "\n"			
+	 "	ands %[byte], %[t]"    "\n"
+
+	 "	lsls %[c], 1"             "\n"
+	 "	ldrh %[t], [%[paletteptr], %[c]]"      "\n"
+	 "	lsls %[t], %[t], 3"       "\n"
+	 "	str %[t], [%[LCD], 0]"    "\n"
+	 "	mov %[c], r11" "\n"
+	 "	str %[c], [%[LCD], 124]"  "\n"
+	 "	stm %[scanline]!, {%[t]}" "\n"
+	 "	movs %[t], 252"   "\n"
+	 "	str %[c], [%[LCD], %[t]]" "\n"
+	 "	str %[c], [%[LCD], 124]"  "\n"
+	 "	lsls %[byte], %[byte], 1"             "\n"
 	 "	str %[c], [%[LCD], %[t]]" "\n"
 
-	 "	ldrh %[t], [%[paletteptr], %[byte]]"      "\n"	
-	 "	lsls %[t], %[t], 3"       "\n"			
-	 "	str %[t], [%[LCD], 0]"    "\n"			
-	 "	mov %[c], r11" "\n"				
-	 "	str %[c], [%[LCD], 124]"  "\n"			
-	 "	stm %[scanline]!, {%[t]}" "\n"			
-	 "	movs %[t], 252"   "\n"				
-	 "	str %[c], [%[LCD], %[t]]" "\n"			
-	 "	str %[c], [%[LCD], 124]"  "\n"			
-	 "	adds %[scrbuf], %[scrbuf], 1" "\n"		
+	 "	ldrh %[t], [%[paletteptr], %[byte]]"      "\n"
+	 "	lsls %[t], %[t], 3"       "\n"
+	 "	str %[t], [%[LCD], 0]"    "\n"
+	 "	mov %[c], r11" "\n"
+	 "	str %[c], [%[LCD], 124]"  "\n"
+	 "	stm %[scanline]!, {%[t]}" "\n"
+	 "	movs %[t], 252"   "\n"
 	 "	str %[c], [%[LCD], %[t]]" "\n"
-	 
-	 "	subs %[x], 2"          "\n"	
+	 "	str %[c], [%[LCD], 124]"  "\n"
+	 "	adds %[scrbuf], %[scrbuf], 1" "\n"
+	 "	str %[c], [%[LCD], %[t]]" "\n"
+
+	 "	subs %[x], 2"          "\n"
 	 "	bne mode2InnerLoopA"  "\n"
 
 	 "mov %[scanline], r10"    "\n"
 	 "movs %[x], 110"          "\n"
 	 "mov %[t], r11"           "\n"
 	 "mode2InnerLoopB:"
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
-	 MODE2_INNER_LOOP_B	 
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
+	 MODE2_INNER_LOOP_B
 	 "	bne mode2InnerLoopB"     "\n"
-	 
+
 	 "mov %[scanline], r10"    "\n"
 	 "movs %[t], 1"              "\n"
 	 "movs %[c], 88"             "\n"
 	 "add %[y], %[t]"            "\n" // y++... derpy, but it's the outer loop
 	 "cmp %[y], %[c]"            "\n"
 	 "bne mode2OuterLoop"       "\n" // if y != 88, loop
-	 
+
 	 : // outputs
 	   [c]"+l" (c),
 	   [t]"+l" (t),
 	   [x]"+l" (x),
 	   [y]"+h" (y),  // +:Read-Write l:lower (0-7) register
 	   [scrbuf]"+l" (scrbuf)
-	   
+
 	 : // inputs
 	   [LCD]"l" (0xA0002188),
 	   [scanline]"l" (scanline),
@@ -1056,8 +1186,13 @@
 	   "cc", "r10", "r11"
        );
 
- 
+
 #else
+  write_data(0); // does not have pixel 0 bug
+  write_command(0x22); // write data to DRAM
+  CLR_CS_SET_CD_RD_WR;
+  SET_MASK_P2;
+
 uint8_t* d = scrbuf;// point to beginning of line in data
 
   #ifdef PROJ_SHOW_FPS_COUNTER
@@ -1713,122 +1848,132 @@
 }
 
 #define MODE13_INNER_LOOP_A						\
-  "	ldrb %[t], [%[scrbuf],0]"   "\n"				\
-	       "	add %[t], %[t], %[offset]"  "\n"		\
+	       "	add %[t], %[t], r10"	   "\n" 		\
 	       "	uxtb %[c], %[t] " "\n"				\
 	       "	lsls %[c], 1"             "\n"			\
 	       "	ldrh %[t], [%[paletteptr], %[c]]"      "\n"	\
 	       "	lsls %[t], %[t], 3"       "\n"			\
 	       "	str %[t], [%[LCD], 0]"    "\n"			\
-	       "	mov %[c], r11" "\n"				\
-	       "	str %[c], [%[LCD], 124]"  "\n"			\
-	       "	stm %[scanline]!, {%[t]}" "\n"			\
-	       "	movs %[t], 252"   "\n"				\
-	       "	str %[c], [%[LCD], %[t]]" "\n"			\
-	       "	str %[c], [%[LCD], 124]"  "\n"			\
+	       "	movs %[c], 252"   "\n"				\
+	       "	str %[offset], [%[LCD], %[c]]" "\n"		\
+	       "	stm %[scanline]!, {%[t]}"      "\n"		\
+	       "	str %[offset], [%[LCD], 124]"  "\n"		\
+	       "	str %[offset], [%[LCD], %[c]]" "\n"		\
 	       "	adds %[scrbuf], %[scrbuf], 1" "\n"		\
-	       "	str %[c], [%[LCD], %[t]]" "\n"
-  
-#define MODE13_INNER_LOOP_B				\
-  "	ldm %[scanline]!, {%[c]}"   "\n"		\
-	       "	str %[c], [%[LCD], 0]"    "\n"	\
-	       "	str %[t], [%[LCD], 124]"  "\n"	\
-	       "	movs %[c], 252"   "\n"		\
-	       "	str %[t], [%[LCD], %[c]]" "\n"	\
-	       "	str %[t], [%[LCD], 124]"  "\n"	\
-	       "	subs %[x], 1"             "\n"	\
-	       "	str %[t], [%[LCD], %[c]]" "\n"	\
+	       "	ldrb %[t], [%[scrbuf],0]"   "\n"		\
+	       "	str %[offset], [%[LCD], 124]"  "\n"
 
- 
+// This can be made 1 cycle faster (x -= 10 instead of x--),
+// but there will be noise
+#define MODE13_INNER_LOOP_B					\
+	       "	str %[c], [%[LCD], 0]"    "\n"		\
+	       "	str %[offset], [%[LCD], %[t]]" "\n"	\
+	       "	ldr %[c], [%[scanline]]"   "\n"		\
+	       "	str %[offset], [%[LCD], 124]"  "\n"	\
+	       "	str %[offset], [%[LCD], %[t]]" "\n"	\
+	       "	adds %[scanline], 4"             "\n"	\
+	       "	subs %[x], 1"			"\n"	\
+	       "	str %[offset], [%[LCD], 124]"  "\n"
+
+
  void Pokitto::lcdRefreshMode13(uint8_t * scrbuf, uint16_t* paletteptr, uint8_t offset){
    uint32_t scanline[110]; // read two nibbles = pixels at a time
-   
+
    write_command_16(0x03); write_data_16(0x1038);
    write_command(0x20); write_data(0);
-   write_command(0x21); write_data(1);
+   write_command(0x21); write_data(0);
    write_command(0x22);
    CLR_CS_SET_CD_RD_WR;
    SET_MASK_P2;
-   
-   uint32_t x, y=0;
-   
+
+   uint32_t x, y=0, c, t;
+
 #ifndef __ARMCC_VERSION
+   #ifdef PROJ_SHOW_FPS_COUNTER
+   setDRAMptr(0, 8);
+   y=4;
+   #endif
+
    asm volatile(
 	 ".syntax unified"         "\n"
-	 
-	 "mov r10, %[scanline]"    "\n"
-	 
-	 "movs %[t], 1"            "\n"
-	 "lsls %[t], %[t], 12"     "\n"
-	 "mov r11, %[t]"           "\n"
-	 
+
+	 "mov r10, %[offset]"	   "\n"
+	 "movs %[offset], 1"            "\n"
+	 "lsls %[offset], %[offset], 12"     "\n"
+
 	 "mode13OuterLoop:"        "\n"
-	 
+
 	 "movs %[x], 110"          "\n"
+	 "ldrb %[t], [%[scrbuf],0]"   "\n"
 	 "mode13InnerLoopA:"
 	 MODE13_INNER_LOOP_A
 	 MODE13_INNER_LOOP_A
-	 "	subs %[x], 2"          "\n"	
+	 "	subs %[x], 2"          "\n"
 	 "	bne mode13InnerLoopA"  "\n"
 
-	 "mov %[scanline], r10"    "\n"
+	 "subs %[scanline], 220"    "\n"
+	 "subs %[scanline], 220"    "\n"
+
 	 "movs %[x], 110"          "\n"
-	 "mov %[t], r11"           "\n"
+	 "movs %[t], 252"           "\n"
+	 "ldm %[scanline]!, {%[c]}"   "\n"
 	 "mode13InnerLoopB:"
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
-	 MODE13_INNER_LOOP_B	 
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
+	 MODE13_INNER_LOOP_B
 	 "	bne mode13InnerLoopB"     "\n"
-	 
-	 "mov %[scanline], r10"    "\n"
+
+	 "subs %[scanline], 220"    "\n"
+	 "subs %[scanline], 224"    "\n"
 	 "movs %[t], 1"              "\n"
 	 "movs %[c], 88"             "\n"
-	 "add %[y], %[t]"            "\n" // y++... derpy, but it's the outer loop
+	 "add %[y], %[t]"            "\n"
 	 "cmp %[y], %[c]"            "\n"
 	 "bne mode13OuterLoop"       "\n" // if y != 88, loop
-	 
+
 	 : // outputs
 	   [c]"+l" (c),
 	   [t]"+l" (t),
 	   [x]"+l" (x),
 	   [y]"+h" (y),  // +:Read-Write l:lower (0-7) register
-	   [scrbuf]"+l" (scrbuf)
-	   
+	   [scrbuf]"+l" (scrbuf),
+	   [offset]"+l" (offset)
+
 	 : // inputs
 	   [LCD]"l" (0xA0002188),
 	   [scanline]"l" (scanline),
-	   [paletteptr]"l" (paletteptr),
-	   [offset]"l" (offset)
+	   [paletteptr]"l" (paletteptr)
+
 	 : // clobbers
-	   "cc", "r10", "r11"
+	   "cc", "r10"
        );
 
 #else
    uint8_t* d = scrbuf;// point to beginning of line in data
    for(y=0;y<88;y++){
-     
+
      uint32_t* s = scanline;
-     
+
      for(x=0;x<110;x+=10){
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
-       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);	
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+       *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
      }
-     
+
      s = scanline;
      uint32_t c = *s;
      for(x=0;x<110;x+=10){
@@ -1843,13 +1988,113 @@
        *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s);
        *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s);
      }
-   
+
    }
 #endif
  }
 
+
+
+ void Pokitto::lcdRefreshMode64( uint8_t * scrbuf, uint16_t* paletteptr ){
+   uint8_t *end = &scrbuf[ POK_SCREENBUFFERSIZE+4 ];
+   write_command_16(0x03); write_data_16(0x1038);
+   write_command(0x20); write_data(0);
+#ifdef PROJ_SHOW_FPS_COUNTER
+  write_data(8);
+  scrbuf += 110*8;
+#else
+  write_data(0);
+#endif
+   write_command(0x21); write_data(0);
+   write_command(0x22);
+   CLR_CS_SET_CD_RD_WR;
+   SET_MASK_P2;
+
+   uint32_t TGL = 1<<12, CLR = 252, c, t;
+#ifndef __ARMCC_VERSION
+   asm volatile(
+	 ".syntax unified"         "\n"
+	 "ldm %[scrbuf]!, {%[c]}" "\n"
+	 "lsls %[t], %[c], 24" 			"\n"
+	 "mode64loop%=:"    "\n"
+	 "lsrs %[c], %[c], 8" 			"\n"
+	 "lsrs %[t], %[t], 23" 			"\n"
+	 "ldrh %[t], [%[paletteptr], %[t]]" 	"\n"
+	 "lsls %[t], 3" 			"\n"
+	 "str %[t], [%[LCD], 0]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "lsls %[t], %[c], 24" 			"\n"
+	 "lsrs %[c], %[c], 8" 			"\n"
+	 "lsrs %[t], %[t], 23" 			"\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "ldrh %[t], [%[paletteptr], %[t]]" 	"\n"
+	 "lsls %[t], 3" 			"\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+
+	 "str %[t], [%[LCD], 0]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "lsls %[t], %[c], 24" 			"\n"
+	 "lsrs %[t], %[t], 23" 			"\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "ldrh %[t], [%[paletteptr], %[t]]" 	"\n"
+	 "lsls %[t], 3" 			"\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+	 "str %[t], [%[LCD], 0]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "lsrs %[c], %[c], 8" 			"\n"
+	 "lsls %[t], %[c], 1" 			"\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "ldrh %[t], [%[paletteptr], %[t]]" 	"\n"
+	 "lsls %[t], 3" 			"\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+
+	 "str %[t], [%[LCD], 0]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "ldm %[scrbuf]!, {%[c]}" "\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+	 "str %[TGL], [%[LCD], %[CLR]]" 	"\n"
+	 "lsls %[t], %[c], 24" 			"\n"
+	 "cmp %[scrbuf], %[end]" "\n"
+	 "str %[TGL], [%[LCD], 124]" 		"\n"
+
+	 "bne mode64loop%=" "\n"
+
+	 : // outputs
+	   [c]"+l" (c),
+	   [t]"+l" (t),
+	   [scrbuf]"+l" (scrbuf)
+
+	 : // inputs
+	   [CLR]"l" (CLR),
+	   [TGL]"l" (TGL),
+	   [LCD]"l" (0xA0002188),
+	   [paletteptr]"l" (paletteptr),
+	   [end]"h" (end)
+
+	 : // clobbers
+	   "cc"
+       );
+
+#else
+
+   c = uint32_t(paletteptr[(*scrbuf)&255])<<3;
+   while( scrbuf < end-4 ){
+       *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+       *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+       *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+       *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+   }
+   
+#endif
+ }
+
+ 
+ 
 void Pokitto::lcdRefreshMode14(uint8_t * scrbuf, uint16_t* paletteptr) {
-uint16_t x,y;
+uint16_t x,y,data,xptr;
 uint16_t scanline[176]; uint16_t* scptr;
 uint8_t *d;
 
@@ -1986,10 +2231,99 @@
 #else
 
 void Pokitto::lcdRefreshMode15(uint16_t* paletteptr, uint8_t* scrbuf){
-uint16_t x,y;
+//    #define __ARMCC_VERSION
+#ifndef __ARMCC_VERSION
+    
+#define MODE15_LOOP				\
+    "ands %[tmp], %[color]" "\n"		\
+	"lsrs %[tmp], 2" "\n"			\
+	"ldr %[tmp], [%[palette], %[tmp]]" "\n" \
+	"str %[tmp], [%[LCD]]" "\n"		\
+	"str %[WRBit], [%[LCD], %[CLR]]" "\n"	\
+	"movs %[tmp], 0x0F" "\n"		\
+	"ands %[tmp], %[color]" "\n"		\
+	"str %[WRBit], [%[LCD], 124]" "\n"	\
+	"lsls %[tmp], 2" "\n"			\
+	"ldr %[tmp], [%[palette], %[tmp]]" "\n" \
+	"str %[tmp], [%[LCD]]" "\n"		\
+	"str %[WRBit], [%[LCD], %[CLR]]" "\n"	\
+	"movs %[tmp], 0xF0" "\n"		\
+	"lsrs %[color], 8" "\n"			\
+	"str %[WRBit], [%[LCD], 124]" "\n"
+
+#define MODE15_ENDLOOP					\
+    "ands %[tmp], %[color]" "\n"			\
+	"lsrs %[tmp], 2" "\n"				\
+	"ldr %[tmp], [%[palette], %[tmp]]" "\n"		\
+	"str %[tmp], [%[LCD]]" "\n"			\
+	"str %[WRBit], [%[LCD], %[CLR]]" "\n"		\
+	"movs %[tmp], 0x0F" "\n"			\
+	"ands %[tmp], %[color]" "\n"			\
+	"str %[WRBit], [%[LCD], 124]" "\n"		\
+	"lsls %[tmp], 2" "\n"				\
+	"ldr %[tmp], [%[palette], %[tmp]]" "\n"		\
+	"str %[tmp], [%[LCD]]" "\n"			\
+	"str %[WRBit], [%[LCD], %[CLR]]" "\n"		\
+	"ldm %[scrbuf]!, {%[color]}" "\n"		\
+	"movs %[tmp], 0xF0" "\n"			\
+	"str %[WRBit], [%[LCD], 124]" "\n"
+    
+  uint8_t *end=&scrbuf[POK_SCREENBUFFERSIZE]+4;
+  volatile uint32_t palette[16];
+  for( uint32_t i=0; i<16; ++i )
+      palette[i] = uint32_t(paletteptr[i]) << 3;
+
+  write_command(0x03); write_data(0x1038);
+  write_command(0x21);  // Vertical DRAM Address
+  write_data(0);
+  write_command(0x20);  // Horizontal DRAM Address
+#ifdef PROJ_SHOW_FPS_COUNTER
+  write_data(8);
+  scrbuf += 110*8;
+#else
+  write_data(0);
+#endif
+  write_command(0x22); // write data to DRAM
+  CLR_CS_SET_CD_RD_WR;
+
+
+  SET_MASK_P2;
+
+  uint32_t WRBit = 1<<12, color, tmp;
+  asm volatile(
+      ".syntax unified" "\n"
+      "ldm %[scrbuf]!, {%[color]}" "\n"      
+      "movs %[tmp], 0xF0" "\n"
+      "mode15Loop%=:" "\n"
+      MODE15_LOOP
+      MODE15_LOOP
+      MODE15_LOOP
+      MODE15_ENDLOOP      
+      "cmp %[end], %[scrbuf]" "\n"
+      "bne mode15Loop%=" "\n"
+      :
+      [tmp]"+l" (tmp),
+      [color]"+l" (color),
+      [end]"+h" (end),
+      [scrbuf]"+l" (scrbuf),
+      [WRBit]"+l" (WRBit)
+      
+      :
+      [CLR]"l" (252),
+      [LCD]"l" (0xA0002188),
+      [palette]"l" (palette)
+      
+      :
+      "cc"
+      );
+    
+#else
+    
+uint16_t x,y,xptr;
 uint16_t scanline[2][176]; // read two nibbles = pixels at a time
-uint8_t *d;
+uint8_t *d, yoffset=0;
 
+xptr = 0;
 //setDRAMptr(xptr,yoffset);
 
 write_command(0x20); write_data(0);
@@ -2042,11 +2376,130 @@
         setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
     }
   }
+
+#endif
+
 }
 #endif //ADEKTOSMODE15
 
+void Pokitto::lcdRefreshMixMode(const uint8_t * screenBuffer, const uint16_t * palettePointer, const uint8_t * scanType)
+{
+	write_command(0x03);
+	write_data(0x1038);
+
+	// Horizontal DRAM Address
+	write_command(0x20);
+	write_data(0);
+
+	// Vertical DRAM Address
+	write_command(0x21);
+	write_data(0);
+
+	// write data to DRAM
+	write_command(0x22);
+	CLR_CS_SET_CD_RD_WR;
+	SET_MASK_P2;
+
+	uint32_t scanline[220];
+
+	// point to beginning of line in data
+	const uint8_t * d = screenBuffer;
+	for(uint32_t y = 0; y < 176; ++y)
+	{
+		// find colours in one scanline
+		uint8_t scanTypeIndex = y >> 1;
+		uint8_t lineIndex = 0;
+		switch(scanType[scanTypeIndex])
+		{
+			case 0:
+			{
+				// point to beginning of line in data
+				d = &screenBuffer[110 * scanTypeIndex];
+				for(uint8_t x = 0; x < (220 / 2); ++x)
+				{
+					uint32_t color = static_cast<uint32_t>(palettePointer[*d]) << 3;
+					++d;
+					scanline[lineIndex] = color;
+					++lineIndex;
+					scanline[lineIndex] = color;
+					++lineIndex;
+				}
+				break;
+			}
+			case 1:
+			{
+				for(uint8_t x = 0; x < (220 / 4); ++x)
+				{
+					uint8_t t = *d;
+					++d;
+
+					uint32_t color1 = static_cast<uint32_t>(palettePointer[256 + (t >> 4)]) << 3;
+					scanline[lineIndex] = color1;
+					++lineIndex;
+					scanline[lineIndex] = color1;
+					++lineIndex;
+
+					uint32_t color2 = static_cast<uint32_t>(palettePointer[256 + (t & 0xF)]) << 3;
+					scanline[lineIndex] = color2;
+					++lineIndex;
+					scanline[lineIndex] = color2;
+					++lineIndex;
+				}
+				break;
+			}
+			case 2:
+			{
+				for(uint8_t x = 0; x < (220 / 4); ++x)
+				{
+					uint8_t t = *d;
+					++d;
+
+					scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 6) & 0x03)]) << 3;
+					++lineIndex;
+
+					scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 4) & 0x03)]) << 3;
+					++lineIndex;
+
+					scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 2) & 0x03)]) << 3;
+					++lineIndex;
+
+					scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 0) & 0x03)]) << 3;
+					++lineIndex;
+				}
+				break;
+			}
+		}
+
+        uint32_t color = scanline[0];
+        #define WRITE_SCANLINE *LCD = color; TGL_WR_OP(color = scanline[++i]);
+
+		volatile uint32_t * LCD = reinterpret_cast< volatile uint32_t * >(0xA0002188);
+		for (uint8_t i = 0; i < 220;)
+		{
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE  WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE  WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE  WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE	WRITE_SCANLINE
+			WRITE_SCANLINE  WRITE_SCANLINE	WRITE_SCANLINE
+		}
+
+		#undef WRITE_SCANLINE
+	}
+
+	CLR_MASK_P2;
+}
+
+
 void Pokitto::blitWord(uint16_t c) {
     setup_data_16(c);CLR_WR;SET_WR;
 }
 
 
+
--- a/POKITTO_HW/HWLCD.h	Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_HW/HWLCD.h	Sat Mar 23 19:19:23 2019 +0000
@@ -81,6 +81,8 @@
 extern void lcdRefreshMode3(uint8_t *, uint16_t*);
 extern void lcdRefreshModeGBC(uint8_t *, uint16_t*);
 extern void lcdRefreshMode13(uint8_t *, uint16_t*, uint8_t);
+extern void lcdRefreshMixMode(const uint8_t *, const uint16_t*, const uint8_t*);
+extern void lcdRefreshMode64(uint8_t *, uint16_t*);
 
 extern void lcdRefreshMode15(uint16_t*, uint8_t*);
 
@@ -147,14 +149,14 @@
 #define CLR_MASK_P2 LPC_GPIO_PORT->MASK[2] = 0; // all on
 
 #define TGL_WR_OP(OP)							\
-  LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN;			\
+  LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN;			\
   OP;									\
-  LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN;
+  LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN;			
 
 #define TGL_WR								\
-  LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN;			\
-  __asm("nop"); \
-  LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN;
+  LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN;			\
+  __asm("nop");								\
+  LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN;			
 
 /**************************************************************************/
 /**                          SETUP GPIO & DATA                           **/