PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)

Revision:
35:4f7edccf8ed6
Parent:
31:f4b9b85c7b62
Child:
42:798b5d67b372
--- a/POKITTO_CORE/PokittoDisplay.cpp	Sat Mar 24 13:17:22 2018 +0000
+++ b/POKITTO_CORE/PokittoDisplay.cpp	Mon Apr 02 22:37:04 2018 +0000
@@ -78,6 +78,10 @@
 #include "SimLCD.h"
 #endif
 
+//extern "C" void CheckStack();
+//extern char _ebss[];  // In map file
+//extern char _vStackTop[];  // In map file
+
 Pokitto::Core core;
 Pokitto::Sound _pdsound;
 
@@ -147,6 +151,18 @@
     uint8_t Display::width = 160;
     uint8_t Display::height = 144;
     uint8_t Display::screenbuffer[160*144/4];
+#elif (POK_SCREENMODE == MODE14)
+    uint8_t Display::width = 220;
+    uint8_t Display::height = 176;
+    uint8_t Display::screenbuffer[14520];
+#elif (POK_SCREENMODE == MODE13)
+    uint8_t Display::width = 110;
+    uint8_t Display::height = 88;
+    uint8_t Display::screenbuffer[110*88]; // 8bit 110x88
+#elif (POK_SCREENMODE == MODE15)
+    uint8_t Display::width = 220;
+    uint8_t Display::height = 176;
+    uint8_t Display::screenbuffer[0x4BA0];
 #else
     uint8_t Display::width = 84;
     uint8_t Display::height = 48;
@@ -264,6 +280,9 @@
 
     // For the screen modes that do not support sprites, return if the direct draw mode is used.
     if (! useDirectDrawMode) {
+		#if POK_SCREENMODE == MODE13
+		lcdRefreshMode13(m_scrbuf, paletteptr, palOffset);
+		#endif
 
         #if POK_SCREENMODE == MODE_GAMEBOY
         lcdRefreshModeGBC(m_scrbuf, paletteptr);
@@ -285,6 +304,14 @@
         lcdRefreshAB(m_scrbuf, paletteptr);
         #endif
 
+        #if POK_SCREENMODE == MODE14
+        lcdRefreshMode14(m_scrbuf, paletteptr);
+        #endif
+
+        #if POK_SCREENMODE == MODE15
+        lcdRefreshMode15(paletteptr, m_scrbuf);
+        #endif
+
         #if POK_SCREENMODE == MODE_TILED_1BIT
         lcdRefreshT1(m_tilebuf, m_tilecolorbuf, m_tileset, paletteptr);
         #endif
@@ -301,37 +328,42 @@
     #endif // POK_SHOW_VOLUME
 
     /** draw FPS if visible **/
-    #ifdef PROJ_USE_FPS_COUNTER
+    #ifdef PROJ_SHOW_FPS_COUNTER
+
+    if(core.fps_counter_updated) {
 
-	// Store current state
-    bool temp = isDirectPrintingEnabled();
-    uint16_t oldcol = directcolor;
-    uint16_t oldinvisiblecolor = invisiblecolor;
-    uint16_t oldbgcol = directbgcolor;
-    bool olddirecttextrotated = directtextrotated;
-    int8_t oldadjustCharStep = adjustCharStep;
-    const unsigned char * oldFont = font;
+        // Store current state
+        bool temp = isDirectPrintingEnabled();
+        uint16_t oldcol = directcolor;
+        uint16_t oldinvisiblecolor = invisiblecolor;
+        uint16_t oldbgcol = directbgcolor;
+        bool olddirecttextrotated = directtextrotated;
+        int8_t oldadjustCharStep = adjustCharStep;
+        const unsigned char * oldFont = font;
 
-    // Print FPS
-    char str[16];
-    sprintf(str,"FPS:%d ", (int)core.fps_counter);
-    directcolor = COLOR_WHITE;
-    invisiblecolor = COLOR_BLACK;
-    directbgcolor = 0x0001; // Cannot be black as that is transparent color
-    directtextrotated = true;
-    adjustCharStep = 0;
-    setFont(fontC64);
-    enableDirectPrinting(true);
-    print(0,0, str);
+        // Print FPS
+        char str[16];
+        sprintf(str,"FPS:%d ", (int)core.fps_counter);
+        directcolor = COLOR_WHITE;
+        invisiblecolor = COLOR_BLACK;
+        directbgcolor = 0x0001; // Cannot be black as that is transparent color
+        directtextrotated = true;
+        adjustCharStep = 0;
+        setFont(fontC64);
+        enableDirectPrinting(true);
+        print(0,0, str);
 
-	// Restore state
-    enableDirectPrinting(temp);
-    directcolor = oldcol;
-    invisiblecolor =  oldinvisiblecolor;
-    directbgcolor = oldbgcol;
-    directtextrotated = olddirecttextrotated;
-    adjustCharStep = oldadjustCharStep;
-    setFont(font);
+        // Restore state
+        enableDirectPrinting(temp);
+        directcolor = oldcol;
+        invisiblecolor =  oldinvisiblecolor;
+        directbgcolor = oldbgcol;
+        directtextrotated = olddirecttextrotated;
+        adjustCharStep = oldadjustCharStep;
+        setFont(font);
+
+        core.fps_counter_updated = false;
+    }
     #endif
 }
 
@@ -475,6 +507,16 @@
         c = bgcolor & 0x3;
         c = c | (c << 2);
         c = c | (c << 4);
+    } else if (bpp==3){
+        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*)m_scrbuf+POK_BITFRAME,0xFF,j);// G
+        else memset((void*)m_scrbuf+POK_BITFRAME,0x00,j);// G
+        if ((bgcolor>>2) & 0x1) memset((void*)m_scrbuf+POK_BITFRAME*2,0xFF,j);// B
+        else memset((void*)m_scrbuf+POK_BITFRAME*2,0x00,j);// B
+        setCursor(0,0);
+        return;
     } else {
         c = (c & 0x0F) | (c << 4);
     }
@@ -602,6 +644,20 @@
         else pixel = (pixel&0x3F)|(col<<6); // bits 6-7
         m_scrbuf[i] = pixel;
     #elif POK_COLORDEPTH == 3
+    uint8_t c = col;
+	uint8_t ct = col;
+
+    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"
+		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
+	} else { //black - or actually "Set bit"
+		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
+	}
+	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
     #elif POK_COLORDEPTH == 4
     uint16_t i = y*(width>>1) + (x>>1);
     uint8_t pixel = m_scrbuf[i];
@@ -685,6 +741,11 @@
 
 uint8_t Display::getPixel(int16_t x,int16_t y) {
     if ((uint16_t)x >= width || (uint16_t)y >= height) return 0;
+    #if POK_COLORDEPTH == 8
+    uint16_t i = y*width+x;
+    return m_scrbuf[i];
+    #endif // POK_COLORDEPTH
+
     #if POK_GAMEBUINO_SUPPORT
     uint8_t color=0; //jonne
 	for (uint8_t cbit=0; cbit<POK_COLORDEPTH;cbit++) {
@@ -1363,7 +1424,7 @@
     return;
     }
     /** 2 bpp mode */
-    if (m_colordepth<4) {
+    else if (m_colordepth==2) {
         if(clipH > 0) {
 
             // Clip
@@ -1409,6 +1470,35 @@
         }
         return;
     }
+
+    /** 3 bpp mode */
+    else if (m_colordepth==3) {
+        int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+        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++) {
+            uint8_t r_val = *(bitmap + j * byteWidth + byteNum);
+            uint8_t g_val = *(bitmap + bitFrame + j * byteWidth + byteNum);
+            uint8_t b_val = *(bitmap + (bitFrame<<1) + j * byteWidth + byteNum);
+            for (bitcount=0; bitcount<8; bitcount++) {
+                uint8_t col = (r_val&0x1) | ((g_val&0x1)<<1) | ((b_val&0x1)<<2);
+                r_val >>= 1; g_val >>= 1; b_val >>= 1;
+                drawPixel(x + i, y + j+bitcount,col);
+            }
+            }
+        }
+
+    return;
+    }
+
+
+    /** 4bpp fast version */
+    else if (m_colordepth==4) {
+
     /** 4bpp fast version */
 	int16_t scrx,scry,xclip,xjump,scrxjump;
     xclip=xjump=scrxjump=0;
@@ -1447,7 +1537,7 @@
                         uint8_t sourcepixel = *bitmap;
                         if ((sourcepixel&0x0F) != invisiblecolor) {
                             sourcepixel <<=4;
-                            uint8_t targetpixel = *scrptr & 0x0F;
+                            uint8_t targetpixel = *scrptr;// & 0x0F;
                             targetpixel |= sourcepixel;
                             *scrptr = targetpixel;
                         }
@@ -1458,7 +1548,6 @@
                 }
                 bitmap += xjump; // needed if x<0 clipping occurs
             } else { /** ODD pixel starting line **/
-                //for (scrx = x; scrx < w+x-xclip; scrx+=2) {
                 for (scrx = x; scrx < w+x-xclip; scrx+=2) {
                     uint8_t sourcepixel = *bitmap;
                     uint8_t targetpixel = *scrptr;
@@ -1472,24 +1561,49 @@
                     *scrptr = targetpixel;
                     bitmap++;
                 }
-                if (xclip){
-                    if (w&1) {
-                        /**last pixel is odd pixel due to clipping & odd width*/
-                        uint8_t sourcepixel = *bitmap;
-                        sourcepixel >>=4; //top nibble of sourcebyte from bitmap...
-                        if (sourcepixel != invisiblecolor) {
-                            uint8_t targetpixel = *scrptr & 0xF0; //...put into the low nibble of the target
-                            targetpixel |= sourcepixel;
-                            *scrptr = targetpixel;
-                        }
-                        //scrptr++;
-                    }
-                }
                 bitmap+=xjump;
             }
             // increment the y jump in the scrptr
             scrptr = scrptr + ((width - w)>>1)+scrxjump;
     }
+
+    return;
+    }
+
+    /** 4bpp fast version */
+
+    if (m_colordepth==8) {
+	int16_t scrx,scry,xclip,xjump,scrxjump;
+    xclip=xjump=scrxjump=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) { xclip=x; w+=x; xjump = (-x); bitmap += xjump; x=0;}
+    else if (x+w>width) {
+            xclip = x;
+            scrxjump = x;
+            xjump=(x+w-width)+scrxjump;
+            w = width-x;}
+
+    uint8_t* scrptr = m_scrbuf + (y*width + x);
+    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 x<0 clipping occurs
+        scrptr = scrptr + (width - w)+scrxjump;
+    }
+    return;
+    }
+
+
 }
 
 void Display::drawRleBitmap(int16_t x, int16_t y, const uint8_t* rlebitmap)
@@ -2276,7 +2390,7 @@
     }
     m_sprites[index].w = w;
     m_sprites[index].h = h;
-    memcpy(m_sprites[index].palette, palette4x16bit, 4*2);
+    if( palette4x16bit ) memcpy(m_sprites[index].palette, palette4x16bit, 4*2);
 }
 
 /**
@@ -2304,6 +2418,9 @@
 
     // For the screen modes that do not support sprites, return if the direct draw mode is used.
     if (useDirectDrawMode) return;
+#if POK_SCREENMODE == MODE13
+    lcdRefreshMode13(m_scrbuf, paletteptr, palOffset);
+#endif
 
 #if POK_SCREENMODE == MODE_GAMEBOY
     lcdRefreshModeGBC(scr, paletteptr);
@@ -2340,6 +2457,99 @@
     m_tilebuf[i]=t;
 };
 
+// Convert an integer to a hexadecimal string
+char* itoa_hex(int num, char* dest, int destLen) {
+    int i = destLen-1;
+    do {
+        char c = (num % 16) + '0';
+        if (c > '9') c += 7;
+        dest[i--] = c;
+        num /= 16;
+    } while (num && i >= 0);
+    return &(dest[i+1]);
+}
+
+// Draw the crash screen and wait forever
+void ShowCrashScreenAndWait( const char* texLine1, const char* texLine2, const char* texLine3, const char* texLine4, const char* texLine5 ) {
+
+    // draw screen red
+    lcdFillSurface(COLOR_RED);
+
+    // Draw text
+    Display::directcolor = COLOR_WHITE;
+    Display::invisiblecolor = COLOR_RED;
+    Display::directbgcolor = COLOR_RED; // Cannot be black as that is a transparent color
+    Display::directtextrotated = false;
+    Display::adjustCharStep = 0;
+    Display::adjustLineStep = 0;
+    Display::setFont(fntC64UIGfx);  // A special font set that contains UI gfx in lower case letters.
+    Display::fixedWidthFont = true; // Needed for the non-proportional C64 font (default value=false)
+    Display::enableDirectPrinting(true);
+
+    // 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::println();
+    Display::print("  *");   Display::println(texLine4);
+    Display::print("  *");   Display::println(texLine5);
+
+    Display::set_cursor(0, 0 + yOffsetInPixels);
+
+    // Frame
+    Display::println(" abbbbbbbbbbbbbbbbbbbbbbbbc");
+    Display::print  (" |"); Display::println(26*8, Display::cursorY,"|");
+    Display::print  (" |"); Display::println(26*8, Display::cursorY,"|");
+    Display::print  (" |"); Display::println(26*8, Display::cursorY,"|");
+    Display::print  (" |"); Display::println(26*8, Display::cursorY,"|");
+    Display::print  (" |"); Display::println(26*8, Display::cursorY,"|");
+    Display::print  (" |"); Display::println(26*8, Display::cursorY,"|");
+    Display::println(" dbbbzybbbbbbbbbbbbbbbbbbbe");
+    Display::println("     {e");
+
+     // Pokitto image
+    Display::println  ("");
+    Display::println  ("  ijkl");
+    Display::println  ("  mnop");
+    Display::println  ("  qrst");
+    Display::println  ("  uvwx");
+
+   // loop forever
+    while(1){;}
+ }
+
+// Check the stack size and show a crash screen if the stack is too big.
+/*void CheckStack() {
+    #ifndef POK_SIM
+    int currStackTop;
+    const int freeStackThreshold = 400;
+    if ((int)&currStackTop - (int)_ebss < freeStackThreshold) {
+
+        // Create info string: "<stack size>:<current stack pointer>", e.g. "12345ABC:12345ABC"
+        const int infoStringLen = 8+1+8;
+        static char infoString[infoStringLen+1];
+        memset(infoString,0,infoStringLen+1);
+        const int stackSize = (int)_vStackTop - (int)&currStackTop;
+        const int tmpStrLen = 8;
+        static char tmpStr[tmpStrLen+1];
+        memset(tmpStr,0,tmpStrLen+1);
+        char* subStr = itoa_hex(stackSize, tmpStr, tmpStrLen); // keep ending null
+        strcat(infoString, subStr); // Add stack size as hex string
+        strcat(infoString, ":");
+        subStr = itoa_hex((int)&currStackTop, tmpStr, tmpStrLen); // keep ending null
+        strcat(infoString, subStr); // Add stack pointer address as hex string
+
+        // Draw the crash screen and wait forever. Use static const strings to avoid more stack usage.
+        static const char* texLine1 = "OOPS! PLEASE, RESTART";
+        static const char* texLine2 = "POKITTO OR RELOAD";
+        static const char* texLine3 = "SOFTWARE.";
+        static const char* texLine4 = "STACK TOO BIG!";
+        ShowCrashScreenAndWait(texLine1, texLine2, texLine3, texLine4, infoString);
+    }
+    #endif
+}*/
 
 /** Eof */