PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Diff: POKITTO_CORE/PokittoDisplay.cpp
- Revision:
- 35:4f7edccf8ed6
- Parent:
- 31:f4b9b85c7b62
- Child:
- 42:798b5d67b372
diff -r 427237571c6a -r 4f7edccf8ed6 POKITTO_CORE/PokittoDisplay.cpp --- 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 */