PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Dependents: YATTT sd_map_test cPong SnowDemo ... more
PokittoDisplay.cpp
00001 /**************************************************************************/ 00002 /*! 00003 @file PokittoDisplay.cpp 00004 @author Jonne Valola 00005 00006 @section LICENSE 00007 00008 Software License Agreement (BSD License) 00009 00010 Copyright (c) 2016, Jonne Valola 00011 All rights reserved. 00012 00013 Redistribution and use in source and binary forms, with or without 00014 modification, are permitted provided that the following conditions are met: 00015 1. Redistributions of source code must retain the above copyright 00016 notice, this list of conditions and the following disclaimer. 00017 2. Redistributions in binary form must reproduce the above copyright 00018 notice, this list of conditions and the following disclaimer in the 00019 documentation and/or other materials provided with the distribution. 00020 3. Neither the name of the copyright holders nor the 00021 names of its contributors may be used to endorse or promote products 00022 derived from this software without specific prior written permission. 00023 00024 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 00025 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00026 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00028 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00029 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00031 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00033 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 */ 00035 /**************************************************************************/ 00036 00037 00038 /* THE SEGMENT BELOW PERTAINS TO CIRCLE DRAWING FUNCTIONS ONLY 00039 * 00040 This is the core graphics library for all our displays, providing a common 00041 set of graphics primitives (points, lines, circles, etc.). It needs to be 00042 paired with a hardware-specific library for each display device we carry 00043 (to handle the lower-level functions). 00044 Adafruit invests time and resources providing this open source code, please 00045 support Adafruit & open-source hardware by purchasing products from Adafruit! 00046 Copyright (c) 2013 Adafruit Industries. All rights reserved. 00047 Redistribution and use in source and binary forms, with or without 00048 modification, are permitted provided that the following conditions are met: 00049 - Redistributions of source code must retain the above copyright notice, 00050 this list of conditions and the following disclaimer. 00051 - Redistributions in binary form must reproduce the above copyright notice, 00052 this list of conditions and the following disclaimer in the documentation 00053 and/or other materials provided with the distribution. 00054 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00055 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00056 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00057 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00058 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00059 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00060 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00061 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00062 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00063 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00064 POSSIBILITY OF SUCH DAMAGE. 00065 */ 00066 00067 #include "PokittoDisplay.h " 00068 #include "Pokitto_settings.h " 00069 #include "GBcompatibility.h" 00070 #include "PokittoCore.h " 00071 #include "PokittoSound.h " 00072 #include <stdio.h> 00073 #include <string.h> 00074 #include <ctype.h> 00075 #ifdef DISABLEAVRMIN 00076 #include <algorithm> 00077 using std::min; 00078 using std::max; 00079 #endif // DISABLEAVRMIN 00080 00081 #ifndef POK_SIM 00082 #include "HWLCD.h " 00083 #else 00084 #include "SimLCD.h" 00085 #endif 00086 00087 extern "C" void CheckStack(); 00088 extern char _ebss[]; // In map file 00089 extern char _vStackTop[]; // In map file 00090 00091 Pokitto::Core core; 00092 Pokitto::Sound _pdsound; 00093 00094 using namespace Pokitto; 00095 00096 uint8_t* Display::m_scrbuf; 00097 uint8_t* Display::m_tileset; 00098 uint8_t* Display::m_tilebuf; 00099 uint8_t* Display::m_tilecolorbuf; 00100 uint8_t Display::m_mode, Display::m_colordepth; 00101 uint8_t Display::palOffset; 00102 SpriteInfo Display::m_sprites[SPRITE_COUNT]; 00103 uint8_t Display::fontSize=1; 00104 int16_t Display::cursorX,Display::cursorY; 00105 uint16_t Display::m_w,Display::m_h; 00106 uint8_t Display::fontWidth, Display::fontHeight; 00107 bool Display::textWrap=true; 00108 00109 uint8_t Display::persistence = 0; 00110 uint16_t Display::color = 1; 00111 uint16_t Display::bgcolor = 0; 00112 uint16_t Display::invisiblecolor = 17; 00113 uint16_t Display::directcolor=0xFFFF; 00114 uint16_t Display::directbgcolor=0x0; 00115 bool Display::directtextrotated=false; 00116 int16_t Display::clipX = 0; 00117 int16_t Display::clipY = 0; 00118 int16_t Display::clipW = LCDWIDTH; 00119 int16_t Display::clipH = LCDHEIGHT; 00120 00121 uint16_t* Display::paletteptr; 00122 uint16_t Display::palette[PALETTE_SIZE]; 00123 const unsigned char* Display::font; 00124 int8_t Display::adjustCharStep = 1; 00125 int8_t Display::adjustLineStep = 1; 00126 bool Display::fixedWidthFont = false, Display::flipFontVertical = false; 00127 00128 /** drawing canvas **/ 00129 //uint8_t* Display::canvas; // points to the active buffer. if null, draw direct to screen 00130 00131 /** screenbuffer **/ 00132 uint8_t Display::bpp = POK_COLORDEPTH; 00133 #ifndef POK_TILEDMODE 00134 #if (POK_SCREENMODE == MODE_HI_MONOCHROME) 00135 uint8_t Display::width = POK_LCD_W; 00136 uint8_t Display::height = POK_LCD_H; 00137 uint8_t Display::screenbuffer[((POK_LCD_H+1)*POK_LCD_W)*POK_COLORDEPTH/8]; // maximum resolution 00138 #elif (POK_SCREENMODE == MODE_HI_4COLOR) 00139 uint8_t Display::width = POK_LCD_W; 00140 uint8_t Display::height = POK_LCD_H; 00141 uint8_t __attribute__((section (".bss"))) __attribute__ ((aligned)) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution 00142 #elif (POK_SCREENMODE == MODE_FAST_16COLOR) 00143 uint8_t Display::width = POK_LCD_W/2; 00144 uint8_t Display::height = POK_LCD_H/2; 00145 uint8_t Display::screenbuffer[(((POK_LCD_H/2)+1)*POK_LCD_W/2)*POK_COLORDEPTH/8]; // half resolution 00146 #elif (POK_SCREENMODE == MODE_HI_16COLOR) 00147 uint8_t Display::width = POK_LCD_W; 00148 uint8_t Display::height = POK_LCD_H; 00149 uint8_t Display::screenbuffer[POK_LCD_H*POK_LCD_W/2]; // 4 bits per pixel 00150 #elif (POK_SCREENMODE == MODE_LAMENES) 00151 uint8_t Display::width = 128; 00152 uint8_t Display::height = 120; 00153 uint8_t Display::screenbuffer[((121)*128)*POK_COLORDEPTH/8]; // half resolution 00154 #elif (POK_SCREENMODE == MODE_GAMEBOY) 00155 uint8_t Display::width = 160; 00156 uint8_t Display::height = 144; 00157 uint8_t Display::screenbuffer[160*144/4]; 00158 #elif (POK_SCREENMODE == MODE14) 00159 uint8_t Display::width = 220; 00160 uint8_t Display::height = 176; 00161 uint8_t Display::screenbuffer[14520]; 00162 #elif (POK_SCREENMODE == MODE13) 00163 uint8_t Display::width = 110; 00164 uint8_t Display::height = 88; 00165 uint8_t Display::screenbuffer[110*88]; // 8bit 110x88 00166 #elif (POK_SCREENMODE == MIXMODE) 00167 uint8_t Display::width = 110; 00168 uint8_t Display::height = 88; 00169 uint8_t Display::screenbuffer[110*88]; // 8bit 110x88 or 4bit 110x176 00170 uint8_t Display::scanType[88]; // scanline bit depth indicator 00171 #elif (POK_SCREENMODE == MODE64) 00172 uint8_t Display::width = 110; 00173 uint8_t Display::height = 176; 00174 uint8_t __attribute__ ((aligned)) Display::screenbuffer[110*176]; // 8bit 110x176 00175 #elif (POK_SCREENMODE == MODE15) 00176 uint8_t Display::width = 220; 00177 uint8_t Display::height = 176; 00178 uint8_t __attribute__ ((aligned)) Display::screenbuffer[0x4BA0]; 00179 #else 00180 uint8_t Display::width = 84; 00181 uint8_t Display::height = 48; 00182 uint8_t Display::screenbuffer[128*64]; // not needed because Gamebuino and Arduboy have their own buffer 00183 #endif 00184 #else //Tiledmode 00185 #if (POK_SCREENMODE == MODE_TILED_1BIT) 00186 uint8_t Display::width = POK_LCD_W; 00187 uint8_t Display::height = POK_LCD_H; 00188 uint8_t Display::screenbuffer[0]; 00189 #else 00190 uint8_t Display::width = POK_LCD_W; 00191 uint8_t Display::height = POK_LCD_H; 00192 uint8_t Display::screenbuffer[0]; 00193 #endif 00194 #endif //tiledmode 00195 00196 // RLE decoding 00197 #define RLE_ESC_EOL 0 00198 #define RLE_ESC_EOB 1 00199 #define RLE_ESC_OFFSET 2 00200 00201 Display::Display() { 00202 m_scrbuf = screenbuffer; 00203 setDefaultPalette(); 00204 m_mode = 1; // direct printing on by default 00205 m_w = POK_LCD_W; 00206 m_h = POK_LCD_H; 00207 setFont(DEFAULT_FONT); 00208 invisiblecolor=17; 00209 bgcolor=0; 00210 if (POK_COLORDEPTH) m_colordepth = POK_COLORDEPTH; 00211 else m_colordepth = 4; 00212 #if POK_GAMEBUINO_SUPPORT 00213 setColorDepth(1); 00214 #endif // POK_GAMEBUINO_SUPPORT 00215 00216 // Reset sprites 00217 m_tilecolorbuf = NULL; 00218 for (uint8_t s = 0; s < SPRITE_COUNT; s++) m_sprites[s].bitmapData = NULL; 00219 } 00220 00221 uint16_t Display::getWidth() { 00222 return width; 00223 } 00224 00225 uint8_t Display::getNumberOfColors() { 00226 return 1<<POK_COLORDEPTH; 00227 } 00228 00229 uint16_t Display::getHeight() { 00230 return height; 00231 } 00232 00233 uint8_t Display::getColorDepth() { 00234 return m_colordepth; 00235 } 00236 00237 void Display::setColorDepth(uint8_t v) { 00238 if (v > POK_COLORDEPTH) v=POK_COLORDEPTH; 00239 m_colordepth = v; 00240 } 00241 00242 void Display::clearLCD() { 00243 lcdFillSurface(0); 00244 setCursor(0,0); // old basic computer style 00245 } 00246 00247 void Display::fillLCD(uint16_t c) { 00248 lcdFillSurface(c); 00249 } 00250 00251 void Display::directPixel(int16_t x, int16_t y, uint16_t color) { 00252 if ((invisiblecolor < PALETTE_SIZE) && (invisiblecolor < 16) && (color == palette[invisiblecolor])) return; 00253 lcdPixel(x,y,color); 00254 } 00255 00256 void Display::directTile(int16_t x, int16_t y, int16_t x2, int16_t y2, uint16_t* gfx) { 00257 lcdTile(x,y,x2,y2,gfx); 00258 } 00259 00260 void Display::directRectangle(int16_t x, int16_t y,int16_t x2, int16_t y2, uint16_t color) { 00261 lcdRectangle(x,y,x2,y2,color); 00262 } 00263 00264 void Display::begin() { 00265 lcdInit(); 00266 } 00267 00268 void Display::setCursor(int16_t x,int16_t y) { 00269 cursorX = x; 00270 cursorY = y; 00271 } 00272 00273 /** 00274 * Update the display. 00275 * The update rect is used for drawing only part of the screen buffer to LCD. Because of speed optimizations, the 00276 * x, y, and width of the update rect must be dividable by 4 pixels, and the height must be dividable by 8 pixels. 00277 * Note: The update rect is currently used for 220x176, 4 colors, screen mode only. 00278 * @param useDirectMode True, if only direct screen drawing is used. False, if the screen buffer is drawn. Note: If sprites are enabled, they are drawn in both modes. 00279 * @param updRectX The update rect. 00280 * @param updRectY The update rect. 00281 * @param updRectW The update rect. 00282 * @param updRectH The update rect. 00283 */ 00284 void Display::update(bool useDirectDrawMode, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH) { 00285 00286 #if POK_SCREENMODE == MODE_HI_4COLOR 00287 // If there is one or more sprites, use sprite enabled drawing. 00288 if (m_sprites[0].bitmapData != NULL) 00289 lcdRefreshMode1Spr(m_scrbuf, updRectX, updRectY, updRectW, updRectH, paletteptr, m_sprites, useDirectDrawMode); 00290 else if (!useDirectDrawMode) 00291 lcdRefreshMode1(m_scrbuf, updRectX, updRectY, updRectW, updRectH, paletteptr); 00292 #endif 00293 00294 // For the screen modes that do not support sprites, return if the direct draw mode is used. 00295 if (! useDirectDrawMode) { 00296 #if POK_SCREENMODE == MODE13 00297 lcdRefreshMode13(m_scrbuf, paletteptr, palOffset); 00298 #endif 00299 00300 #if POK_SCREENMODE == MIXMODE 00301 lcdRefreshMixMode(m_scrbuf, paletteptr, scanType); 00302 #endif 00303 00304 #if POK_SCREENMODE == MODE64 00305 lcdRefreshMode64(m_scrbuf, paletteptr); 00306 #endif 00307 00308 #if POK_SCREENMODE == MODE_GAMEBOY 00309 lcdRefreshModeGBC(m_scrbuf, paletteptr); 00310 #endif 00311 00312 #if POK_SCREENMODE == MODE_HI_16COLOR 00313 lcdRefreshMode3(m_scrbuf, paletteptr); 00314 #endif 00315 00316 #if POK_SCREENMODE == MODE_FAST_16COLOR 00317 lcdRefreshMode2(m_scrbuf, paletteptr); 00318 #endif 00319 00320 #if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR 00321 lcdRefreshGB(m_scrbuf, paletteptr); 00322 #endif 00323 00324 #if POK_SCREENMODE == MODE_ARDUBOY_16COLOR 00325 lcdRefreshAB(m_scrbuf, paletteptr); 00326 #endif 00327 00328 #if POK_SCREENMODE == MODE14 00329 lcdRefreshMode14(m_scrbuf, paletteptr); 00330 #endif 00331 00332 #if POK_SCREENMODE == MODE15 00333 lcdRefreshMode15(paletteptr, m_scrbuf); 00334 #endif 00335 00336 #if POK_SCREENMODE == MODE_TILED_1BIT 00337 lcdRefreshT1(m_tilebuf, m_tilecolorbuf, m_tileset, paletteptr); 00338 #endif 00339 } 00340 00341 if (!persistence) clear(); 00342 00343 /** draw volume bar if visible **/ 00344 #if POK_SHOW_VOLUME > 0 00345 if (core.volbar_visible) { 00346 core.drawvolbar(4,20,_pdsound.getVolume(),true); 00347 core.volbar_visible--; 00348 } 00349 #endif // POK_SHOW_VOLUME 00350 00351 /** draw FPS if visible **/ 00352 #ifdef PROJ_SHOW_FPS_COUNTER 00353 00354 if(core.fps_counter_updated) { 00355 00356 // Store current state 00357 bool temp = isDirectPrintingEnabled(); 00358 uint16_t oldcol = directcolor; 00359 uint16_t oldinvisiblecolor = invisiblecolor; 00360 uint16_t oldbgcol = directbgcolor; 00361 bool olddirecttextrotated = directtextrotated; 00362 int8_t oldadjustCharStep = adjustCharStep; 00363 const unsigned char * oldFont = font; 00364 00365 // Print FPS 00366 char str[16]; 00367 sprintf(str,"FPS:%d ", (int)core.fps_counter); 00368 directcolor = COLOR_WHITE; 00369 invisiblecolor = COLOR_BLACK; 00370 directbgcolor = 0x0001; // Cannot be black as that is transparent color 00371 if (POK_SCREENMODE == MODE_FAST_16COLOR || 00372 POK_SCREENMODE == MODE13 00373 ) 00374 directtextrotated = false; 00375 else 00376 directtextrotated = true; 00377 adjustCharStep = 0; 00378 setFont(fontC64); 00379 enableDirectPrinting(true); 00380 print(0,0, str); 00381 00382 // Restore state 00383 enableDirectPrinting(temp); 00384 directcolor = oldcol; 00385 invisiblecolor = oldinvisiblecolor; 00386 directbgcolor = oldbgcol; 00387 directtextrotated = olddirecttextrotated; 00388 adjustCharStep = oldadjustCharStep; 00389 setFont(oldFont); 00390 00391 core.fps_counter_updated = false; 00392 } 00393 #endif 00394 } 00395 00396 void Display::directBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t depth, uint8_t scale) { 00397 uint8_t w = *bitmap; 00398 uint8_t h = *(bitmap + 1); 00399 bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height 00400 int16_t i, j; 00401 int8_t byteNum, bitNum, byteWidth = (w + 7) >> 3; 00402 00403 if (depth == 1) { 00404 for (i = 0; i < w; i++) { 00405 byteNum = i / 8; 00406 bitNum = i % 8; 00407 for (j = 0; j < h; j++) { 00408 if (*(bitmap + j * byteWidth + byteNum) & (0x80 >> bitNum)) { //0x80 = B10000000 00409 if (scale==1) directPixel(x + i, y + j,directcolor); 00410 else { 00411 directPixel(x + i + i, y + j + j,directcolor); 00412 directPixel(x + 1 + i + i, y + j + j,directcolor); 00413 directPixel(x + i + i, y + j + j + 1,directcolor); 00414 directPixel(x + i + i + 1 , y + j + j + 1,directcolor); 00415 } 00416 } 00417 } 00418 } 00419 } else if (depth == 4) { 00420 for (j = 0; j < h; j+=1) { 00421 for (i = 0; i < w; i+=2) { 00422 uint16_t col = paletteptr[*bitmap>>4]; //higher nibble 00423 if (scale==2) { 00424 directPixel(x + (i<<1), y + (j<<1),col); 00425 directPixel(x + (i<<1) + 1, y + (j<<1),col); 00426 directPixel(x + (i<<1) + 1, y + (j<<1) + 1,col); 00427 directPixel(x + (i<<1), y + (j<<1) + 1,col); 00428 } else directPixel(x + i, y + j,col); 00429 col = paletteptr[*bitmap&0xF]; // lower nibble 00430 if (scale==2) { 00431 directPixel(x + (i<<1) + 2, y + (j<<1),col); 00432 directPixel(x + (i<<1) + 1 + 2, y + (j<<1),col); 00433 directPixel(x + (i<<1) + 1 + 2, y + (j<<1) + 1,col); 00434 directPixel(x + (i<<1) + 2 , y + (j<<1) + 1,col); 00435 } else directPixel(x + i + 1, y + j,col); 00436 bitmap++; 00437 } 00438 } 00439 } 00440 00441 } 00442 00443 int Display::directChar(int16_t x, int16_t y, uint16_t index){ 00444 const uint8_t* bitmap = font; 00445 uint8_t w = *bitmap; 00446 uint8_t h = *(bitmap + 1); 00447 uint8_t hbytes=0, xtra=1; 00448 if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit 00449 hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes 00450 //bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !) 00451 bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !) 00452 //int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3; 00453 int8_t i, j, numBytes; 00454 numBytes = *bitmap++; //first byte of char is the width in bytes 00455 // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column 00456 uint16_t bitcolumn; //16 bits for 2x8 bit high characters 00457 00458 for (i = 0; i < numBytes; i++) { 00459 bitcolumn = *bitmap++; 00460 if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts 00461 for (j = 0; j < h; j++) { 00462 if (bitcolumn&0x1) { 00463 if (fontSize==2) { 00464 directPixel(x + (i<<1) , y + (j<<1),directcolor); 00465 directPixel(x + (i<<1)+1, y + (j<<1),directcolor); 00466 directPixel(x + (i<<1) , y + (j<<1)+1,directcolor); 00467 directPixel(x + (i<<1)+1, y + (j<<1)+1,directcolor); 00468 } else { 00469 if(directtextrotated) directPixel(y + h - j - 1, x + i,directcolor); 00470 else directPixel(x + i, y + j,directcolor); 00471 } 00472 00473 } else if (directbgcolor != invisiblecolor) { 00474 if (fontSize==2) { 00475 directPixel(x + (i<<1) , y + (j<<1),directbgcolor); 00476 directPixel(x + (i<<1)+1, y + (j<<1),directbgcolor); 00477 directPixel(x + (i<<1) , y + (j<<1)+1,directbgcolor); 00478 directPixel(x + (i<<1)+1, y + (j<<1)+1,directbgcolor); 00479 } else { 00480 if(directtextrotated) directPixel(y + h - j - 1, x + i,directbgcolor); 00481 else directPixel(x + i, y + j,directbgcolor); 00482 } 00483 } 00484 bitcolumn>>=1; 00485 } 00486 } 00487 return (numBytes+adjustCharStep)*fontSize; // for character stepping 00488 } 00489 00490 int Display::bufferChar(int16_t x, int16_t y, uint16_t index){ 00491 const uint8_t* bitmap = font; 00492 uint8_t w = *bitmap; 00493 uint8_t h = *(bitmap + 1); 00494 uint8_t hbytes=0, xtra=1; 00495 if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit 00496 hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes 00497 //bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !) 00498 bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !) 00499 //int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3; 00500 int8_t i, j, numBytes; 00501 numBytes = *bitmap++; //first byte of char is the width in bytes 00502 // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column 00503 uint16_t bitcolumn; //16 bits for 2x8 bit high characters 00504 00505 if( fontSize != 2 ) fontSize = 1; 00506 00507 void (*drawPixelFG)(int16_t,int16_t, uint8_t) = &Display::drawPixelNOP; 00508 void (*drawPixelBG)(int16_t,int16_t, uint8_t) = &Display::drawPixelNOP; 00509 if( x>=0 && y >= 0 && x+w*fontSize<width && y+(h+1)*fontSize<height ){ 00510 if( color != invisiblecolor ) 00511 drawPixelFG = &Display::drawPixelRaw; 00512 if( bgcolor != invisiblecolor ) 00513 drawPixelBG = &Display::drawPixelRaw; 00514 }else{ 00515 if( color != invisiblecolor ) 00516 drawPixelFG = &Display::drawPixel; 00517 if( bgcolor != invisiblecolor ) 00518 drawPixelBG = &Display::drawPixel; 00519 } 00520 00521 void (*drawPixel[])(int16_t,int16_t, uint8_t) = {drawPixelBG, drawPixelFG}; 00522 uint8_t colors[] = {(uint8_t)bgcolor, (uint8_t)color}; 00523 00524 #if PROJ_ARDUBOY > 0 00525 #else 00526 if( fontSize != 2 ){ 00527 #endif 00528 00529 for (i = 0; i < numBytes; i++) { 00530 bitcolumn = *bitmap++; 00531 if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts 00532 for (j = 0; j <= h; j++) { // was j<=h 00533 uint8_t c = colors[ bitcolumn & 1 ]; 00534 00535 #if PROJ_ARDUBOY > 0 00536 drawPixel[ bitcolumn&1 ](x, y + 7 - j,c); 00537 #elif PROJ_SUPPORT_FONTROTATION > 0 00538 // if font flipping & rotation is allowed - do not slow down old programs! 00539 if (flipFontVertical) { 00540 drawPixel[ bitcolumn&1 ](x, y + h - j,c); 00541 } else { 00542 drawPixel[ bitcolumn&1 ](x, y + j,c); 00543 } 00544 #else 00545 // "Normal" case 00546 drawPixel[ bitcolumn&1 ](x, y + j,c); 00547 #endif // PROJ_ARDUBOY 00548 bitcolumn>>=1; 00549 00550 } 00551 #if PROJ_SUPPORT_FONTROTATION > 0 00552 if (flipFontVertical) x--; 00553 else x++; 00554 #else 00555 x++; 00556 #endif 00557 } 00558 00559 #if PROJ_SUPPORT_FONTROTATION > 0 00560 if (flipFontVertical) return -numBytes-adjustCharStep; 00561 else return numBytes+adjustCharStep; // for character stepping 00562 #else 00563 return numBytes+adjustCharStep; 00564 #endif 00565 00566 00567 #if PROJ_ARDUBOY > 0 00568 #else 00569 }else{ 00570 00571 for (i = 0; i < numBytes; i++) { 00572 bitcolumn = *bitmap++; 00573 if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts 00574 for (j = 0; j <= h; j++) { // was j<=h 00575 uint8_t c = colors[ bitcolumn & 1 ]; 00576 00577 drawPixel[ bitcolumn&1 ](x + (i<<1) , y + (j<<1), c); 00578 drawPixel[ bitcolumn&1 ](x + (i<<1)+1, y + (j<<1), c); 00579 drawPixel[ bitcolumn&1 ](x + (i<<1) , y + (j<<1)+1, c); 00580 drawPixel[ bitcolumn&1 ](x + (i<<1)+1, y + (j<<1)+1, c); 00581 bitcolumn>>=1; 00582 00583 } 00584 } 00585 00586 return (numBytes+adjustCharStep)<<1; 00587 00588 } 00589 #endif // PROJ_ARDUBOY 00590 00591 } 00592 00593 void Display::clear() { 00594 00595 uint8_t c=0; 00596 c = bgcolor & (PALETTE_SIZE-1) ; //don't let palette go out of bounds 00597 if (bpp==1 && bgcolor) c=0xFF; // bgcolor !=0, set all pixels 00598 else if (bpp==2) { 00599 c = bgcolor & 0x3; 00600 c = c | (c << 2); 00601 c = c | (c << 4); 00602 } else if (bpp==3){ 00603 uint16_t j = POK_BITFRAME; 00604 if (bgcolor & 0x1) memset((void*)m_scrbuf,0xFF,j);// R 00605 else memset((void*)m_scrbuf,0x00,j);// R 00606 if ((bgcolor>>1) & 0x1) memset((char*)m_scrbuf+POK_BITFRAME,0xFF,j);// G 00607 else memset((char*)m_scrbuf+POK_BITFRAME,0x00,j);// G 00608 if ((bgcolor>>2) & 0x1) memset((char*)m_scrbuf+POK_BITFRAME*2,0xFF,j);// B 00609 else memset((char*)m_scrbuf+POK_BITFRAME*2,0x00,j);// B 00610 setCursor(0,0); 00611 return; 00612 } else if (bpp==4) { 00613 c = (c & 0x0F) | (c << 4); 00614 } 00615 uint16_t j = sizeof(screenbuffer); 00616 memset((void*)m_scrbuf,c,j); 00617 00618 setCursor(0,0); 00619 00620 } 00621 00622 void Display::scroll(int16_t pixelrows) { 00623 uint16_t index = 0, index2=0,oc; 00624 if (pixelrows==0) return; 00625 if (pixelrows >= height) pixelrows=height-1; 00626 if (bpp == 4) index2 = pixelrows*width/2; 00627 else if (bpp == 2) index2 = pixelrows*width/4; 00628 else return; 00629 oc = color; 00630 color = bgcolor; 00631 if (pixelrows>0) { 00632 for (uint16_t y=0;y<height-pixelrows;y++) { 00633 for (uint16_t x=0;x<(width/8)*bpp;x++) screenbuffer[index++]=screenbuffer[index2++]; 00634 } 00635 fillRect(0,cursorY,width,height); 00636 } else { 00637 for (uint16_t y=pixelrows;y<height;y++) { 00638 for (uint16_t x=0;x<(width*bpp)/8;x++) screenbuffer[index2++]=screenbuffer[index++]; 00639 } 00640 fillRect(0,0,width,pixelrows); 00641 } 00642 color=oc; 00643 } 00644 00645 void Display::fillScreen(uint16_t c) { 00646 c = c & (PALETTE_SIZE-1) ; //don't let palette go out of bounds 00647 if (bpp==1 && c) c=0xFF; // set all pixels 00648 else if (bpp==2) { 00649 c = c & 0x3; 00650 c = c | (c << 2); 00651 c = c | (c << 4); 00652 } else { 00653 c = (c & 0x0F) | (c << 4); 00654 } 00655 memset((void*)m_scrbuf,c,sizeof(screenbuffer)); 00656 } 00657 00658 void Display::setDefaultPalette() { 00659 #if PICOPALETTE 00660 loadRGBPalette(palettePico); 00661 #else 00662 loadRGBPalette(POK_DEFAULT_PALETTE); 00663 #endif //PICOPALETTE 00664 } 00665 00666 void Display::setColor(uint8_t c) { 00667 color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit 00668 } 00669 00670 void Display::setColor(uint8_t c,uint8_t bgc){ 00671 color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit 00672 bgcolor = bgc & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit 00673 } 00674 00675 void Display::setInvisibleColor(uint16_t c){ 00676 invisiblecolor = c; // invisible color can have values beyond 255 for identification purposes 00677 } 00678 00679 uint8_t Display::getColor() { 00680 return color; 00681 } 00682 00683 uint8_t Display::getBgColor() { 00684 return bgcolor; 00685 } 00686 00687 uint16_t Display::getInvisibleColor() { 00688 return invisiblecolor; 00689 } 00690 00691 void Display::setClipRect(int16_t x, int16_t y, int16_t w, int16_t h) { 00692 clipX = x; clipY = y; clipW = w; clipH = h; 00693 } 00694 00695 void Display::drawPixelNOP(int16_t x,int16_t y, uint8_t col) { 00696 } 00697 00698 void Display::drawPixelRaw(int16_t x,int16_t y, uint8_t col) { 00699 #if POK_COLORDEPTH == 8 00700 m_scrbuf[x+width*y] = col; 00701 #endif 00702 00703 #if POK_GAMEBUINO_SUPPORT >0 00704 00705 uint8_t c = col; 00706 uint8_t ct = col; 00707 00708 uint16_t bitptr=0; 00709 for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) { 00710 c = ct & 1; // take the lowest bit of the color index number 00711 if(c == 0){ //white - or actually "Clear bit" 00712 m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8); 00713 } else { //black - or actually "Set bit" 00714 m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8); 00715 } 00716 ct >>=1; // shift to get next bit 00717 bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit 00718 } // POK_COLOURDEPTH 00719 00720 #else 00721 #if POK_COLORDEPTH == 1 00722 if (col) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;} 00723 m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7)); 00724 #elif POK_COLORDEPTH == 2 00725 if (col) { 00726 col &= 3; 00727 } 00728 uint16_t i = y*(width>>2) + (x>>2); 00729 uint8_t pixel = m_scrbuf[i]; 00730 uint8_t column = x&0x03; 00731 if (column==3) pixel = (pixel&0xFC)|(col); // bits 0-1 00732 else if (column==2) pixel = (pixel&0xF3)|(col<<2); // bits 2-3 00733 else if (column==1) pixel = (pixel&0xCF)|(col<<4); // bits 4-5 00734 else pixel = (pixel&0x3F)|(col<<6); // bits 6-7 00735 m_scrbuf[i] = pixel; 00736 #elif POK_COLORDEPTH == 3 00737 uint8_t c = col; 00738 uint8_t ct = col; 00739 00740 uint16_t bitptr=0; 00741 for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) { 00742 c = ct & 1; // take the lowest bit of the color index number 00743 if(c == 0){ //white - or actually "Clear bit" 00744 m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8); 00745 } else { //black - or actually "Set bit" 00746 m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8); 00747 } 00748 ct >>=1; // shift to get next bit 00749 bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit 00750 } // POK_COLOURDEPTH 00751 #elif POK_COLORDEPTH == 4 00752 uint16_t i = y*(width>>1) + (x>>1); 00753 uint8_t pixel = m_scrbuf[i]; 00754 if (x&1) pixel = (pixel&0xF0)|(col); 00755 else pixel = (pixel&0x0F) | (col<<4); 00756 m_scrbuf[i] = pixel; 00757 #endif // POK_COLORDEPTH 00758 #endif // POK_GAMEBUINO_SUPPORT 00759 } 00760 00761 void Display::drawPixel(int16_t x,int16_t y, uint8_t col) { 00762 if (col==invisiblecolor) return; // do not draw transparent pixels 00763 if ((uint16_t)x >= width || (uint16_t)y >= height) return; 00764 col &= (PALETTE_SIZE-1); 00765 drawPixelRaw( x, y, col ); 00766 } 00767 00768 void Display::drawPixel(int16_t x,int16_t y) { 00769 if ((uint16_t)x >= width || (uint16_t)y >= height) return; 00770 drawPixelRaw( x, y, color ); 00771 } 00772 00773 uint8_t Display::getPixel(int16_t x,int16_t y) { 00774 if ((uint16_t)x >= width || (uint16_t)y >= height) return 0; 00775 #if POK_COLORDEPTH == 8 00776 uint16_t i = y*width+x; 00777 return m_scrbuf[i]; 00778 #endif // POK_COLORDEPTH 00779 00780 #if POK_GAMEBUINO_SUPPORT 00781 uint8_t color=0; //jonne 00782 for (uint8_t cbit=0; cbit<POK_COLORDEPTH;cbit++) { 00783 color |= (m_scrbuf[x + (y / 8) * LCDWIDTH+POK_BITFRAME*cbit] >> (y % 8)) & 0x1 ; //jonne - added +504*cbit 00784 } 00785 return color; 00786 #else 00787 /** not gamebuino */ 00788 #if POK_COLORDEPTH == 1 00789 return (m_scrbuf[(y >> 3) * width + x] & (0x80 >> (y & 7))) ? 1:0; 00790 #elif POK_COLORDEPTH == 2 00791 uint16_t i = y*(width>>2) + (x>>2); 00792 uint8_t pixel = m_scrbuf[i]; 00793 uint8_t column = x&0x03; 00794 if (column==0) return pixel & 0x03; // bits 0-1 00795 else if (column==1) return (pixel & 0x0C)>>2; // bits 2-3 00796 else if (column==2) return (pixel & 0x30)>>4; // bits 4-5 00797 else return pixel>>6;; // bits 6-7 00798 #elif POK_COLORDEPTH == 3 00799 #elif POK_COLORDEPTH == 4 00800 uint16_t i = y*(width>>1) + (x>>1); 00801 uint8_t pixel = m_scrbuf[i]; 00802 if (x&1) return pixel & 0x0F; 00803 else return pixel>>4; 00804 #endif // POK_COLORDEPTH 00805 #endif // POK_GAMEBUINO_SUPPORT 00806 } 00807 00808 void Display::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { 00809 if ((uint16_t)x0 >= width || (uint16_t)y0 >= height || (uint16_t)x1 >= width || (uint16_t)y1 >= height ) { 00810 if (clipLine (&x0,&y0,&x1,&y1)==0) return; // line out of bounds 00811 } 00812 if (x0 == x1) 00813 drawColumn(x0,y0,y1); 00814 else if (y0 == y1) 00815 drawRow(x0,x1,y0); 00816 else { 00817 int e; 00818 signed int dx,dy,j, temp; 00819 signed char s1,s2, xchange; 00820 signed int x,y; 00821 00822 x = x0; 00823 y = y0; 00824 00825 //take absolute value 00826 if (x1 < x0) { 00827 dx = x0 - x1; 00828 s1 = -1; 00829 } 00830 else if (x1 == x0) { 00831 dx = 0; 00832 s1 = 0; 00833 } 00834 else { 00835 dx = x1 - x0; 00836 s1 = 1; 00837 } 00838 00839 if (y1 < y0) { 00840 dy = y0 - y1; 00841 s2 = -1; 00842 } 00843 else if (y1 == y0) { 00844 dy = 0; 00845 s2 = 0; 00846 } 00847 else { 00848 dy = y1 - y0; 00849 s2 = 1; 00850 } 00851 00852 xchange = 0; 00853 00854 if (dy>dx) { 00855 temp = dx; 00856 dx = dy; 00857 dy = temp; 00858 xchange = 1; 00859 } 00860 00861 e = ((int)dy<<1) - dx; 00862 00863 for (j=0; j<=dx; j++) { 00864 drawPixel(x,y); 00865 00866 if (e>=0) { 00867 if (xchange==1) x = x + s1; 00868 else y = y + s2; 00869 e = e - ((int)dx<<1); 00870 } 00871 if (xchange==1) 00872 y = y + s2; 00873 else 00874 x = x + s1; 00875 e = e + ((int)dy<<1); 00876 } 00877 } 00878 } 00879 00880 uint8_t Display::clipLine(int16_t *x0, int16_t *y0, int16_t *x1, int16_t *y1){ 00881 // Check X bounds 00882 if (*x1 < *x0) { 00883 //std::swap (*x1,*x0); // swap so that we dont have to check x1 also 00884 swapWT(int16_t*, x1, x0); 00885 //std::swap (*y1,*y0); // y needs to be swaaped also 00886 swapWT(int16_t*, y1, y0); 00887 } 00888 00889 if (*x0 >= width) return 0; // whole line is out of bounds 00890 00891 // Clip against X0 = 0 00892 if (*x0 < 0) { 00893 if (*x1 < 0) return 0; // nothing visible 00894 int32_t dx = (*x1 - *x0); 00895 int32_t dy = ((*y1 - *y0) << 16); // 16.16 fixed point calculation trick 00896 int32_t m = dy/dx; 00897 *y0 = *y0 + ((m*-*x0) >> 16); // get y0 at boundary 00898 *x0 = 0; 00899 } 00900 00901 // Clip against x1 >= width 00902 if (*x1 >= width) { 00903 int32_t dx = (*x1 - *x0); 00904 int32_t dy = ((*y1 - *y0) << 16); // 16.16 fixed point calculation trick 00905 int32_t m = dy / dx; 00906 *y1 = *y1 + ((m * ((width - 1) - *x1)) >> 16); // get y0 at boundary 00907 *x1 = width-1; 00908 } 00909 00910 // Check Y bounds 00911 if (*y1 < *y0) { 00912 //std::swap (*x1,*x0); // swap so that we dont have to check x1 also 00913 swapWT(int16_t*, x1, x0); 00914 //std::swap (*y1,*y0); // y needs to be swaaped also 00915 swapWT(int16_t*, y1, y0); 00916 } 00917 00918 if (*y0 >= height) return 0; // whole line is out of bounds 00919 00920 if (*y0 < 0) { 00921 if (*y1 < 0) return 0; // nothing visible 00922 int32_t dx = (*x1 - *x0) << 16; 00923 int32_t dy = (*y1 - *y0); // 16.16 fixed point calculation trick 00924 int32_t m = dx / dy; 00925 *x0 = *x0 + ((m * -(*y0)) >> 16); // get x0 at boundary 00926 *y0 = 0; 00927 } 00928 00929 // Clip against y1 >= height 00930 if (*y1 >= height) { 00931 int32_t dx = (*x1 - *x0) << 16; 00932 int32_t dy = (*y1 - *y0); // 16.16 fixed point calculation trick 00933 int32_t m = dx / dy; 00934 *x1 = *x1 + ((m * ((height - 1) - *y1)) >> 16); // get y0 at boundary 00935 *y1 = height-1; 00936 } 00937 return 1; // clipped succesfully 00938 } 00939 00940 void Display::map1BitColumn(int16_t x, int16_t sy, int16_t ey, const uint8_t* bitmap, uint16_t column){ 00941 if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds 00942 if ((uint16_t)x>=width) return; //completely out of bounds 00943 if (sy>ey) { 00944 int y=sy; 00945 sy=ey; 00946 ey=y; // swap around so that x0 is less than x1 00947 } 00948 uint16_t bmw,bmh; 00949 float texelstep, texelindex; 00950 bmw = *(bitmap); 00951 bmh = *(bitmap+1); 00952 if (column>bmw-1) column=bmw-1; 00953 bitmap += 2; 00954 bitmap += column; 00955 texelstep = (float)bmh/((float)ey-(float)sy); 00956 texelindex = 0; 00957 for (int y=sy; y <= ey; y++, texelindex += texelstep) { 00958 uint8_t texel; 00959 uint8_t currbyte, bit; 00960 currbyte = texelindex / 8; 00961 bit = 7-((uint16_t) texelindex & 0x7); 00962 texel=*(bitmap+currbyte*bmw); 00963 if (texel & (1<<bit)) drawPixel(x,y); 00964 else if (bgcolor != invisiblecolor) drawPixel(x,y,bgcolor); 00965 } 00966 }; 00967 00968 void Display::drawColumn(int16_t x, int16_t sy, int16_t ey){ 00969 if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds 00970 if ((uint16_t)x>=width) return; //completely out of bounds 00971 if (sy>ey) { 00972 int y=sy; 00973 sy=ey; 00974 ey=y; // swap around so that x0 is less than x1 00975 } 00976 for (int y=sy; y <= ey; y++) { 00977 drawPixel(x,y); 00978 } 00979 } 00980 00981 void Display::drawRow(int16_t x0, int16_t x1, int16_t y){ 00982 if ((uint16_t)x0>=width && (uint16_t)x1>=width) return; //completely out of bounds 00983 if ((uint16_t)y>=height) return; //completely out of bounds 00984 00985 if (x0>x1) { 00986 int x=x0; 00987 x0=x1; 00988 x1=x; // swap around so that x0 is less than x1 00989 } 00990 for (int x=x0; x <= x1; x++) { 00991 drawPixel(x,y); 00992 } 00993 } 00994 00995 void Display::drawFastVLine(int16_t x, int16_t y, int16_t h){ 00996 if (h<0) {y += h; h = -h;} 00997 drawColumn(x,y,y+h); 00998 } 00999 01000 void Display::drawFastHLine(int16_t x, int16_t y, int16_t w){ 01001 if (w<0) {x += w; w = -w;} 01002 drawRow(x,x+w-1,y); 01003 } 01004 01005 void Display::drawRectangle(int16_t x0, int16_t y0, int16_t w, int16_t h) { 01006 drawColumn(x0,y0,y0+h); 01007 drawColumn(x0+w,y0,y0+h); 01008 drawRow(x0,x0+w,y0); 01009 drawRow(x0,x0+w,y0+h); 01010 } 01011 01012 void Display::fillRectangle(int16_t x0,int16_t y0, int16_t w, int16_t h){ 01013 int16_t x,y,x1,y1; 01014 x1=x0+w;y1=y0+h; 01015 if ((x0<0 && x1<0) || (x0>=width && x1 >=width)) return; //completely out of bounds 01016 if ((y0<0 && y1<0) || (y0>=height && y1 >=height)) return; //completely out of bounds 01017 if (x0>x1) {x=x1;x1=x0;} 01018 else x=x0; 01019 if (y0>y1) {y=y1;y1=y0;} 01020 else y=y0; 01021 if (x<0) x=0; 01022 if (y<0) y=0; 01023 for (;x<x1;x++) drawColumn(x,y,y1); 01024 } 01025 01026 void Display::fillRect(int16_t x, int16_t y, int16_t w, int16_t h) { 01027 fillRectangle(x,y,w,h); 01028 } 01029 01030 void Display::drawRect(int16_t x, int16_t y, int16_t w, int16_t h) { 01031 drawRectangle(x,y,w,h); 01032 } 01033 01034 void Display::drawCircle(int16_t x0, int16_t y0, int16_t r) { 01035 int16_t f = 1 - r; 01036 int16_t ddF_x = 1; 01037 int16_t ddF_y = -2 * r; 01038 int16_t x = 0; 01039 int16_t y = r; 01040 01041 drawPixel(x0, y0 + r); 01042 drawPixel(x0, y0 - r); 01043 drawPixel(x0 + r, y0); 01044 drawPixel(x0 - r, y0); 01045 01046 while (x < y) { 01047 if (f >= 0) { 01048 01049 y--; 01050 ddF_y += 2; 01051 f += ddF_y; 01052 } 01053 x++; 01054 ddF_x += 2; 01055 f += ddF_x; 01056 01057 drawPixel(x0 + x, y0 + y); 01058 drawPixel(x0 - x, y0 + y); 01059 drawPixel(x0 + x, y0 - y); 01060 drawPixel(x0 - x, y0 - y); 01061 drawPixel(x0 + y, y0 + x); 01062 drawPixel(x0 - y, y0 + x); 01063 drawPixel(x0 + y, y0 - x); 01064 drawPixel(x0 - y, y0 - x); 01065 01066 } 01067 } 01068 01069 void Display::drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername) { 01070 int16_t f = 1 - r; 01071 int16_t ddF_x = 1; 01072 int16_t ddF_y = -2 * r; 01073 int16_t x = 0; 01074 int16_t y = r; 01075 01076 while (x < y) { 01077 if (f >= 0) { 01078 y--; 01079 ddF_y += 2; 01080 f += ddF_y; 01081 } 01082 x++; 01083 ddF_x += 2; 01084 f += ddF_x; 01085 if (cornername & 0x4) { 01086 drawPixel(x0 + x, y0 + y); 01087 drawPixel(x0 + y, y0 + x); 01088 } 01089 if (cornername & 0x2) { 01090 drawPixel(x0 + x, y0 - y); 01091 drawPixel(x0 + y, y0 - x); 01092 } 01093 if (cornername & 0x8) { 01094 drawPixel(x0 - y, y0 + x); 01095 drawPixel(x0 - x, y0 + y); 01096 } 01097 if (cornername & 0x1) { 01098 01099 drawPixel(x0 - y, y0 - x); 01100 drawPixel(x0 - x, y0 - y); 01101 } 01102 } 01103 } 01104 01105 void Display::fillCircle(int16_t x0, int16_t y0, int16_t r) { 01106 drawFastVLine(x0, y0 - r, 2 * r ); 01107 fillCircleHelper(x0, y0, r, 3, 0); 01108 } 01109 01110 void Display::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername, int16_t delta) { 01111 int16_t f = 1 - r; 01112 int16_t ddF_x = 1; 01113 int16_t ddF_y = -2 * r; 01114 int16_t x = 0; 01115 int16_t y = r; 01116 01117 while (x < y) { 01118 if (f >= 0) { 01119 y--; 01120 ddF_y += 2; 01121 f += ddF_y; 01122 } 01123 x++; 01124 ddF_x += 2; 01125 f += ddF_x; 01126 01127 if (cornername & 0x1) { 01128 drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne 01129 drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne 01130 } 01131 if (cornername & 0x2) { 01132 01133 drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne 01134 drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne 01135 } 01136 } 01137 } 01138 01139 void Display::drawRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) { 01140 if (r<2) {drawRectangle(x,y,w,h);return;} 01141 // smarter version 01142 drawFastHLine(x + r, y, w - 2 * r); // Top 01143 drawFastHLine(x + r, y + h - 1, w - 2 * r); // Bottom 01144 drawFastVLine(x, y + r, h - 2 * r); // Left 01145 drawFastVLine(x + w - 1, y + r, h - 2 * r); // Right 01146 // draw four corners 01147 drawCircleHelper(x + r, y + r, r, 1); 01148 drawCircleHelper(x + w - r - 1, y + r, r, 2); 01149 drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4); 01150 drawCircleHelper(x + r, y + h - r - 1, r, 8); 01151 } 01152 01153 void Display::fillRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) { 01154 if (r<2) {fillRectangle(x,y,w,h);return;} 01155 fillRectangle(x + r, y, w - 2 * r, h-1); 01156 // draw four corners 01157 fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1); 01158 fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1); 01159 } 01160 01161 void Display::drawTriangle(int16_t x0, int16_t y0, 01162 int16_t x1, int16_t y1, 01163 int16_t x2, int16_t y2) { 01164 drawLine(x0, y0, x1, y1); 01165 drawLine(x1, y1, x2, y2); 01166 drawLine(x2, y2, x0, y0); 01167 } 01168 01169 void Display::fillTriangle(int16_t x0, int16_t y0, 01170 int16_t x1, int16_t y1, 01171 int16_t x2, int16_t y2) { 01172 int16_t a, b, y, last; 01173 01174 // Sort coordinates by Y order (y2 >= y1 >= y0) 01175 if (y0 > y1) { 01176 swapWT(int16_t,y0, y1); 01177 swapWT(int16_t,x0, x1); 01178 } 01179 if (y1 > y2) { 01180 swapWT(int16_t,y2, y1); 01181 swapWT(int16_t,x2, x1); 01182 } 01183 if (y0 > y1) { 01184 swapWT(int16_t,y0, y1); 01185 swapWT(int16_t,x0, x1); 01186 } 01187 01188 if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing 01189 a = b = x0; 01190 if (x1 < a) a = x1; 01191 else if (x1 > b) b = x1; 01192 if (x2 < a) a = x2; 01193 else if (x2 > b) b = x2; 01194 drawFastHLine(a, y0, b - a + 1); 01195 return; 01196 } 01197 01198 int16_t 01199 dx01 = x1 - x0, 01200 dy01 = y1 - y0, 01201 dx02 = x2 - x0, 01202 dy02 = y2 - y0, 01203 dx12 = x2 - x1, 01204 dy12 = y2 - y1, 01205 sa = 0, 01206 sb = 0; 01207 01208 // For upper part of triangle, find scanline crossings for segments 01209 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 01210 // is included here (and second loop will be skipped, avoiding a /0 01211 // error there), otherwise scanline y1 is skipped here and handled 01212 // in the second loop...which also avoids a /0 error here if y0=y1 01213 // (flat-topped triangle). 01214 if (y1 == y2) last = y1; // Include y1 scanline 01215 else last = y1 - 1; // Skip it 01216 01217 for (y = y0; y <= last; y++) { 01218 a = x0 + sa / dy01; 01219 b = x0 + sb / dy02; 01220 sa += dx01; 01221 sb += dx02; 01222 /* longhand: 01223 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); 01224 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); 01225 */ 01226 if (a > b) swapWT(int16_t,a, b); 01227 drawFastHLine(a, y, b - a + 1); 01228 } 01229 01230 // For lower part of triangle, find scanline crossings for segments 01231 // 0-2 and 1-2. This loop is skipped if y1=y2. 01232 sa = dx12 * (y - y1); 01233 sb = dx02 * (y - y0); 01234 for (; y <= y2; y++) { 01235 a = x1 + sa / dy12; 01236 b = x0 + sb / dy02; 01237 sa += dx12; 01238 sb += dx02; 01239 01240 if (a > b) swapWT(int16_t,a, b); 01241 drawFastHLine(a, y, b - a + 1); 01242 } 01243 } 01244 01245 void Display::setFont(const unsigned char * f) { 01246 font = f; 01247 fontWidth = *(font)+1; 01248 fontHeight = *(font + 1)+1; 01249 } 01250 01251 void Display::drawMonoBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t index) { 01252 uint8_t w = *bitmap; 01253 uint8_t h = *(bitmap + 1); 01254 uint8_t xtra=0; 01255 if (w&0x7) xtra=1; 01256 bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !) 01257 #if POK_GAMEBUINO_SUPPORT > 0 01258 int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3; 01259 for (i = 0; i < w; i++) { 01260 byteNum = i / 8; 01261 bitNum = i % 8; 01262 for (j = 0; j < h; j++) { 01263 uint8_t source = *(bitmap + j * byteWidth + byteNum); 01264 if (source & (0x80 >> bitNum)) { 01265 drawPixel(x + i, y + j); 01266 } 01267 } 01268 } 01269 #else 01270 /** not gamebuino */ 01271 int8_t scrx,scry; 01272 uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1)); 01273 int8_t bitptr; 01274 for (scry = y; scry < y+h; scry+=1) { 01275 if ((x&1)==0) { /** EVEN pixel starting line**/ 01276 for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) { 01277 uint8_t targetpixel = *scrptr; 01278 if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // upper nibble 01279 else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // upper nibble 01280 bitptr--; 01281 if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble 01282 else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble 01283 bitptr--; 01284 if (bitptr<0) { bitptr = 7; bitmap++; } 01285 *scrptr = targetpixel; 01286 scrptr++; 01287 } 01288 } else { /** ODD pixel starting line **/ 01289 for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) { 01290 uint8_t targetpixel = *scrptr; 01291 // store higher nibble of source pixel in lower nibble of target 01292 if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble 01293 else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble 01294 *scrptr = targetpixel; // store 01295 bitptr--;scrptr++;targetpixel = *scrptr; 01296 // store lower nibble of source pixel in higher nibble of target 01297 if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // higher nibble 01298 else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // higher nibble 01299 *scrptr = targetpixel; // store 01300 bitptr--; // do not increment scrptr here ! 01301 } 01302 } 01303 if (bitptr!=7) bitmap++; // force skip to next line 01304 // increment the y jump in the scrptr 01305 scrptr = scrptr + ((width - w)>>1); 01306 } 01307 #endif // POK_GAMEBUINO_SUPPORT 01308 } 01309 01310 01311 void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame) 01312 { 01313 int16_t w = *bitmap; 01314 int16_t h = *(bitmap + 1); 01315 uint8_t framew = *(bitmap+2); 01316 bitmap = bitmap + 3; //add an offset to the pointer to start after the width and height 01317 /** visibility check */ 01318 if (y<-h || y>height) return; //invisible 01319 if (x<-framew || x>width) return; //invisible 01320 /** 1 bpp mode */ 01321 if (m_colordepth<2) { 01322 int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3; 01323 for (i = 0; i < w; i++) { 01324 byteNum = i / 8; 01325 bitNum = i % 8; 01326 for (j = 0; j < h; j++) { 01327 uint8_t source = *(bitmap + j * byteWidth + byteNum); 01328 if (source & (0x80 >> bitNum)) { 01329 drawPixel(x + i, y + j); 01330 } 01331 } 01332 } 01333 01334 return; 01335 } 01336 /** 2 bpp mode */ 01337 if (m_colordepth<4) { 01338 int16_t i, j, byteNum, bitNum, byteWidth = w >> 2; 01339 for (i = 0; i < w; i++) { 01340 byteNum = i / 4; 01341 bitNum = (i % 4)<<1; 01342 for (j = 0; j < h; j++) { 01343 uint8_t source = *(bitmap + j * byteWidth + byteNum); 01344 uint8_t output = (source & (0xC0 >> bitNum)); 01345 output >>= (6-bitNum); 01346 if (output != invisiblecolor) { 01347 setColor(output); 01348 drawPixel(x + i, y + j); 01349 } 01350 } 01351 } 01352 01353 return; 01354 } 01355 /** 4bpp fast version */ 01356 int16_t scrx,scry,xclip,xjump,scrxjump; 01357 xclip=xjump=scrxjump=0; 01358 bitmap += (framew*frame)>>1; 01359 /** y clipping */ 01360 if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;} 01361 else if (y+h>height) { h -=(y-height);} 01362 /** x clipping */ 01363 xjump = (w-framew)>>1; 01364 if (x<0) { xclip=(x&1)<<1; framew+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;} 01365 else if (x+framew>width) { 01366 xclip = (x&1)<<1; 01367 scrxjump = x&1; 01368 xjump=((x+framew-width)>>1)+scrxjump; 01369 framew = width-x;} 01370 01371 uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1)); 01372 /** ONLY 4-bit mode for time being **/ 01373 for (scry = y; scry < y+h; scry+=1) { 01374 if (scry>=height) return; 01375 if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/ 01376 for (scrx = x; scrx < framew+x-xclip; scrx+=2) { 01377 uint8_t sourcepixel = *bitmap; 01378 if (xclip) { 01379 sourcepixel <<=4; 01380 sourcepixel |= ((*(bitmap+1))>>4); 01381 } 01382 uint8_t targetpixel = *scrptr; 01383 if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0); 01384 if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F); 01385 *scrptr = targetpixel; 01386 bitmap++; 01387 scrptr++; 01388 } 01389 if (xclip){ 01390 if (framew&1) { 01391 /**last pixel is odd pixel due to clipping & odd width*/ 01392 uint8_t sourcepixel = *bitmap; 01393 if ((sourcepixel&0x0F) != invisiblecolor) { 01394 sourcepixel <<=4; 01395 uint8_t targetpixel = *scrptr;// & 0x0F; 01396 targetpixel |= sourcepixel; 01397 *scrptr = targetpixel; 01398 } 01399 //scrptr++; 01400 } 01401 bitmap++; 01402 scrptr++; 01403 } 01404 bitmap += xjump; // needed if x<0 clipping occurs 01405 } else { /** ODD pixel starting line **/ 01406 for (scrx = x; scrx < framew+x-xclip; scrx+=2) { 01407 uint8_t sourcepixel = *bitmap; 01408 uint8_t targetpixel = *scrptr; 01409 // store higher nibble of source pixel in lower nibble of target 01410 if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 ); 01411 *scrptr = targetpixel; 01412 scrptr++; 01413 targetpixel = *scrptr; 01414 // store lower nibble of source pixel in higher nibble of target 01415 if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4); 01416 *scrptr = targetpixel; 01417 bitmap++; 01418 } 01419 bitmap+=xjump; 01420 } 01421 // increment the y jump in the scrptr 01422 scrptr = scrptr + ((width - framew)>>1)+scrxjump; 01423 } 01424 } 01425 01426 01427 void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap) 01428 { 01429 int16_t w = *bitmap; 01430 int16_t h = *(bitmap + 1); 01431 bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height 01432 drawBitmapData(x, y, w, h, bitmap); 01433 } 01434 01435 void Display::drawBitmapData(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap) { 01436 /** visibility check */ 01437 if (y<-h || y>height) return; //invisible 01438 if (x<-w || x>width) return; //invisible 01439 /** 1 bpp mode */ 01440 if (m_colordepth<2) { 01441 int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3; 01442 for (i = 0; i < w; i++) { 01443 byteNum = i / 8; 01444 bitNum = i % 8; 01445 for (j = 0; j < h; j++) { 01446 uint8_t source = *(bitmap + j * byteWidth + byteNum); 01447 if (source & (0x80 >> bitNum)) { 01448 drawPixel(x + i, y + j); 01449 } 01450 } 01451 } 01452 01453 return; 01454 } 01455 /** 2 bpp mode */ 01456 else if (m_colordepth==2) { 01457 if(clipH > 0) { 01458 01459 // Clip 01460 int16_t x1 = max(x, clipX); 01461 int16_t x2 = min(x + w, clipX + clipW); 01462 int16_t bmupdateX = x1 - x; 01463 int16_t bmupdateX2 = x2 - x; 01464 int16_t y1 = max(y, clipY); 01465 int16_t y2 = min(y + h, clipY + clipH); 01466 int16_t bmupdateY = y1 - y; 01467 int16_t bmupdateY2 = y2 - y; 01468 01469 int16_t i, j, byteNum, bitNum, byteWidth = w >> 2; 01470 for (i = bmupdateX; i < bmupdateX2; i++) { 01471 byteNum = i / 4; 01472 bitNum = (i % 4)<<1; 01473 for (j = bmupdateY; j < bmupdateY2; j++) { 01474 uint8_t source = *(bitmap + (j * byteWidth) + byteNum); 01475 uint8_t output = (source & (0xC0 >> bitNum)); 01476 output >>= (6-bitNum); 01477 if (output != invisiblecolor) { 01478 setColor(output); 01479 drawPixel(x + i, y + j); 01480 } 01481 } 01482 } 01483 } 01484 else { 01485 int16_t i, j, byteNum, bitNum, byteWidth = w >> 2; 01486 for (i = 0; i < w; i++) { 01487 byteNum = i / 4; 01488 bitNum = (i % 4)<<1; 01489 for (j = 0; j < h; j++) { 01490 uint8_t source = *(bitmap + (j * byteWidth) + byteNum); 01491 uint8_t output = (source & (0xC0 >> bitNum)); 01492 output >>= (6-bitNum); 01493 if (output != invisiblecolor) { 01494 setColor(output); 01495 drawPixel(x + i, y + j); 01496 } 01497 } 01498 } 01499 } 01500 return; 01501 } 01502 01503 /** 3 bpp mode */ 01504 else if (m_colordepth==3) { 01505 int16_t i, j, byteNum, byteWidth = (w + 7) >> 3; 01506 int16_t bitFrame = w * h / 8; 01507 for (i = 0; i < w; i++) { 01508 byteNum = i / 8; 01509 //bitNum = i % 8; 01510 01511 uint8_t bitcount=0; 01512 for (j = 0; j <= h/8; j++) { 01513 uint8_t r_val = *(bitmap + j * byteWidth + byteNum); 01514 uint8_t g_val = *(bitmap + bitFrame + j * byteWidth + byteNum); 01515 uint8_t b_val = *(bitmap + (bitFrame<<1) + j * byteWidth + byteNum); 01516 for (bitcount=0; bitcount<8; bitcount++) { 01517 uint8_t col = (r_val&0x1) | ((g_val&0x1)<<1) | ((b_val&0x1)<<2); 01518 r_val >>= 1; g_val >>= 1; b_val >>= 1; 01519 drawPixel(x + i, y + j+bitcount,col); 01520 } 01521 } 01522 } 01523 01524 return; 01525 } 01526 01527 01528 /** 4bpp fast version */ 01529 else if (m_colordepth==4) { 01530 01531 /** 4bpp fast version */ 01532 int16_t scrx,scry,xjump,scrxjump; 01533 int16_t xclip; 01534 xclip=xjump=scrxjump=0; 01535 /** y clipping */ 01536 if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;} 01537 else if (y+h>height) { h -=(y-height);} 01538 /** x clipping */ 01539 if (x<0) { xclip=(x&1)<<1; w+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;} 01540 else if (x+w>width) { 01541 xclip = (x&1)<<1; 01542 scrxjump = x&1; 01543 xjump=((x+w-width)>>1)+scrxjump; 01544 w = width-x;} 01545 01546 uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1)); 01547 /** ONLY 4-bit mode for time being **/ 01548 for (scry = y; scry < y+h; scry+=1) { 01549 if (scry>=height) return; 01550 if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/ 01551 for (scrx = x; scrx < w+x-xclip; scrx+=2) { 01552 uint8_t sourcepixel = *bitmap; 01553 if (xclip) { 01554 sourcepixel <<=4; 01555 sourcepixel |= ((*(bitmap+1))>>4); 01556 } 01557 uint8_t targetpixel = *scrptr; 01558 if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0); 01559 if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F); 01560 *scrptr = targetpixel; 01561 bitmap++; 01562 scrptr++; 01563 } 01564 if (xclip){ 01565 if (w&1) { 01566 /**last pixel is odd pixel due to clipping & odd width*/ 01567 uint8_t sourcepixel = *bitmap; 01568 if ((sourcepixel&0x0F) != invisiblecolor) { 01569 sourcepixel <<=4; 01570 volatile uint8_t targetpixel = *scrptr;// & 0x0F; 01571 targetpixel &= 0xF; //clear upper nibble 01572 targetpixel |= sourcepixel; //now OR it 01573 *scrptr = targetpixel; 01574 } 01575 //scrptr++; 01576 } 01577 bitmap++; 01578 scrptr++; 01579 } 01580 bitmap += xjump; // needed if x<0 clipping occurs 01581 } else { /** ODD pixel starting line **/ 01582 uint8_t sourcepixel; 01583 uint8_t targetpixel; 01584 for (scrx = x; scrx < w+x-xclip; scrx+=2) { 01585 sourcepixel = *bitmap; 01586 targetpixel = *scrptr; 01587 // store higher nibble of source pixel in lower nibble of target 01588 if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 ); 01589 *scrptr = targetpixel; 01590 scrptr++; 01591 targetpixel = *scrptr; 01592 // store lower nibble of source pixel in higher nibble of target 01593 if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4); 01594 *scrptr = targetpixel; 01595 bitmap++; 01596 } 01597 if (xclip) { 01598 // last line, store higher nibble of last source pixel in lower nibble of last address 01599 sourcepixel = *bitmap >> 4; 01600 if(sourcepixel!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | sourcepixel; 01601 *scrptr = targetpixel; 01602 } 01603 bitmap+=xjump; 01604 } 01605 // increment the y jump in the scrptr 01606 scrptr = scrptr + ((width - w)>>1)+scrxjump; 01607 } 01608 01609 return; 01610 } 01611 01612 /** 4bpp fast version */ 01613 01614 if (m_colordepth==8) { 01615 int16_t scrx,scry;//,scrxjump; 01616 int16_t xjump=0; 01617 /** y clipping */ 01618 if (y<0) { h+=y; bitmap -= y*w; y=0;} 01619 else if (y+h>height) { h -=(y-height);} 01620 /** x clipping */ 01621 if (x<0) { w+=x; xjump = (-x); bitmap += xjump; x=0;} 01622 else if (x+w>width) { 01623 xjump=(x+w-width); 01624 w = width-x;} 01625 01626 uint8_t* scrptr = m_scrbuf + (y*width + x); 01627 for (scry = y; scry < y+h; scry+=1) { 01628 if (scry>=height) return; 01629 for (scrx = x; scrx < w+x; scrx++) { 01630 uint8_t sourcepixel = *bitmap; 01631 uint8_t targetpixel = *scrptr; 01632 if (sourcepixel != invisiblecolor ) targetpixel = sourcepixel; 01633 *scrptr = targetpixel; 01634 bitmap++; 01635 scrptr++; 01636 } 01637 bitmap += xjump; // needed if horizontal clipping occurs 01638 scrptr = scrptr + (width - w); 01639 } 01640 return; 01641 } 01642 01643 01644 } 01645 01646 void Display::drawRleBitmap(int16_t x, int16_t y, const uint8_t* rlebitmap) 01647 { 01648 // ONLY can copy 4-bit bitmap to 4-bit screen mode for time being 01649 #if (POK_SCREENMODE != MODE_FAST_16COLOR) 01650 return; 01651 #endif 01652 01653 int16_t w = *rlebitmap; 01654 int16_t h = *(rlebitmap + 1); 01655 rlebitmap = rlebitmap + 2; //add an offset to the pointer to start after the width and height 01656 01657 // visibility check 01658 if (y<-h || y>height) return; //invisible 01659 if (x<-w || x>width) return; //invisible 01660 01661 // Clipping is not supported 01662 if ((x < 0) || (x+w > width) || (y < 0) || (y+h > height)) return; 01663 01664 // Currently only support RLE bitmaps in 16 color mode. 01665 if (m_colordepth != 4) // 01666 return; 01667 01668 // Go through each line. 01669 uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1)); 01670 bool is_endofbitmap = false; 01671 for (int16_t scry = y; scry < y+h && !is_endofbitmap;) { 01672 01673 // Process one line. Go through each pixel run and escape command in RLE data. 01674 for (int16_t scrx = x;;) { 01675 uint8_t rle_count = *rlebitmap++; 01676 01677 if (rle_count == 0) { 01678 01679 /* Escape or absolute mode */ 01680 01681 uint8_t rle_escape_or_runsize = *rlebitmap++; 01682 if ( rle_escape_or_runsize == RLE_ESC_EOL) { 01683 // End of line. 01684 break; 01685 } 01686 else if ( rle_escape_or_runsize == RLE_ESC_EOB) { 01687 // End of bitmap. 01688 is_endofbitmap = true; 01689 break; 01690 } 01691 else if ( rle_escape_or_runsize == RLE_ESC_OFFSET) { 01692 // Move position in target. 01693 // TODO: not tested yet. 01694 uint8_t xoffset = *rlebitmap++; 01695 uint8_t yoffset = *rlebitmap++; 01696 scrptr += (xoffset>1); 01697 scrx += xoffset; 01698 scrptr += yoffset*width; 01699 scry += yoffset; 01700 } 01701 else { 01702 01703 /* Absolute mode. Copy pixels from the source bitmap to the target screen. */ 01704 01705 int16_t runsize = rle_escape_or_runsize; 01706 uint8_t targetpixel = *scrptr; // initial value 01707 uint8_t sourcepixel = *rlebitmap; // initial value 01708 for( int16_t runx = 0; runx < runsize; ) { 01709 if (scrx&0x1) { // screen pixel is in the low nibble 01710 if (runx&0x1) { // bitmap pixel is in the low nibble 01711 if ((sourcepixel&0x0F) != invisiblecolor) 01712 targetpixel = (targetpixel&0xF0) | (sourcepixel&0x0F); // Copy low to low nibble. 01713 rlebitmap++; 01714 } 01715 else // bitmap pixel is in the high nibble 01716 if ((sourcepixel>>4) != invisiblecolor) 01717 targetpixel = (targetpixel&0xF0) | (sourcepixel>>4); // Copy high to low nibble. 01718 01719 // Copy the byte to the target. 01720 *scrptr = targetpixel; 01721 scrptr++; 01722 } 01723 else { // screen pixel is in the high nibble 01724 targetpixel = *scrptr; 01725 sourcepixel = *rlebitmap; 01726 if (runx&0x1) { // bitmap pixel is sourcepixel = *rlebitmapin the low nibble 01727 if ((sourcepixel&0x0F) != invisiblecolor ) 01728 targetpixel = (targetpixel&0x0F) | ((sourcepixel<<4)&0xF0); // Copy low to high nibble. 01729 rlebitmap++; // read the new source byte 01730 } 01731 else // bitmap pixel is in the high nibble 01732 if ((sourcepixel>>4) != invisiblecolor ) 01733 targetpixel = (targetpixel&0x0F) | (sourcepixel&0xF0); // Copy high to high nibble. 01734 } 01735 runx++; 01736 scrx++; 01737 } // end for 01738 01739 // If this is odd target index, copy the byte to the target. 01740 if (scrx&0x1) { 01741 *scrptr = targetpixel; 01742 scrptr++; 01743 } 01744 01745 // In absolute mode the source size is always padded to the word boundary. 01746 if (runsize%4) { 01747 int16_t padpixcount = 4 - (runsize%4); 01748 rlebitmap += padpixcount>>1; // skip n padding bytes 01749 } 01750 } 01751 } 01752 else { 01753 01754 /* Encoded mode. Duplicate one pixel pair to the all required pixels on the target screen */ 01755 01756 int16_t runsize = rle_count; 01757 uint8_t clonepixelpair = *rlebitmap++; 01758 uint8_t targetpixel = *scrptr; // initial value 01759 for( int16_t runx = 0; runx < runsize; ) { 01760 if (scrx&0x1) { // screen pixel is in the low nibble 01761 if (runx&0x1) { // bitmap pixel is in the low nibble 01762 if ((clonepixelpair&0x0F) != invisiblecolor) 01763 targetpixel = (targetpixel&0xF0) | (clonepixelpair&0x0F); // Copy low to low nibble. 01764 } 01765 else // bitmap pixel is in the high nibble 01766 if ((clonepixelpair>>4) != invisiblecolor) 01767 targetpixel = (targetpixel&0xF0) | (clonepixelpair>>4); // Copy high to low nibble. 01768 01769 // Copy the byte to the target. 01770 *scrptr = targetpixel; 01771 scrptr++; 01772 } 01773 else { // screen pixel is in the high nibble 01774 targetpixel = *scrptr; 01775 if (runx&0x1) {// bitmap pixel is in the low nibble 01776 if ((clonepixelpair&0x0F) != invisiblecolor ) 01777 targetpixel = (targetpixel&0x0F) | ((clonepixelpair<<4)&0xF0); // Copy low to high nibble. 01778 } 01779 else // bitmap pixel is in the high nibble 01780 if ((clonepixelpair>>4) != invisiblecolor ) 01781 targetpixel = (targetpixel&0x0F) | (clonepixelpair&0xF0); // Copy high to high nibble. 01782 } 01783 runx++; 01784 scrx++; 01785 01786 } // end for 01787 01788 // If this is odd target index, copy the byte to the target. 01789 if (scrx&0x1) { 01790 *scrptr = targetpixel; 01791 scrptr++; 01792 } 01793 } // end if 01794 } // end while 01795 01796 // Increment the target screen pointer and index. 01797 scrptr = scrptr + ((width - w)>>1); 01798 scry++; 01799 } // end for scry 01800 } 01801 01802 void Display::drawBitmapDataXFlipped(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap) 01803 { 01804 /** visibility check */ 01805 if (y<-h || y>height) return; //invisible 01806 if (x<-w || x>width) return; //invisible 01807 /** 1 bpp mode */ 01808 if (m_colordepth<2) 01809 { 01810 int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3; 01811 for (i = 0; i < w; i++) 01812 { 01813 byteNum = i / 8; 01814 bitNum = i % 8; 01815 for (j = 0; j < h; j++) 01816 { 01817 uint8_t source = *(bitmap + j * byteWidth + byteNum); 01818 if (source & (0x80 >> bitNum)) 01819 { 01820 drawPixel(x + w - i, y + j); 01821 } 01822 } 01823 } 01824 01825 return; 01826 } 01827 /** 2 bpp mode */ 01828 else if (m_colordepth==2) 01829 { 01830 int16_t i, j, byteNum, bitNum, byteWidth = w >> 2; 01831 for (i = 0; i < w; i++) 01832 { 01833 byteNum = i / 4; 01834 bitNum = (i % 4)<<1; 01835 for (j = 0; j < h; j++) 01836 { 01837 uint8_t source = *(bitmap + j * byteWidth + byteNum); 01838 uint8_t output = (source & (0xC0 >> bitNum)); 01839 output >>= (6-bitNum); 01840 if (output != invisiblecolor) 01841 { 01842 setColor(output); 01843 drawPixel(x + i, y + j); 01844 } 01845 } 01846 } 01847 01848 return; 01849 } 01850 else if (m_colordepth==4) 01851 { 01852 /** 4bpp fast version */ 01853 int16_t scrx,scry,xclip,xjump,scrxjump; 01854 xclip=xjump=scrxjump=0; 01855 /** y clipping */ 01856 if (y<0) 01857 { 01858 h+=y; 01859 bitmap -= y*(w>>1); 01860 y=0; 01861 } 01862 else if (y+h>height) 01863 { 01864 h -=(y-height); 01865 } 01866 /** x clipping */ 01867 bitmap += ((w>>1)-1); //inverted! 01868 if (x<0) 01869 { 01870 xclip=(x&1)<<1; 01871 w+=x; 01872 xjump = ((-x)>>1); 01873 //bitmap += xjump; // do not clip left edge of source, as bitmap is inverted ! 01874 x=0; 01875 } 01876 else if (x+w>width) 01877 { 01878 xclip = (x&1)<<1; 01879 scrxjump = x&1; 01880 xjump=((x+w-width)>>1)+scrxjump; 01881 w = width-x; 01882 } 01883 01884 //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1)); 01885 uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1)); 01886 /** ONLY 4-bit mode for time being **/ 01887 for (scry = y; scry < y+h; scry+=1) 01888 { 01889 // for (scry = y; scry < y+2; scry+=1) { 01890 if (scry>=height) return; 01891 if ((x&1)==0) /** EVEN pixel starting line, very simple, just copypaste **/ 01892 { 01893 //for (scrx = w+x-xclip-1; scrx >= x; scrx-=2) { 01894 for (scrx = x; scrx < w+x-xclip; scrx+=2) 01895 { 01896 uint8_t sourcepixel = *(bitmap); 01897 if (xclip) 01898 { 01899 sourcepixel <<=4; 01900 sourcepixel |= ((*(bitmap-1))>>4);//inverted! 01901 } 01902 uint8_t targetpixel = *scrptr; 01903 // NIBBLES ARE INVERTED BECAUSE PICTURE IS FLIPPED !!! 01904 if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0xF0) | (sourcepixel>>4); 01905 if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel<<4); 01906 *scrptr = targetpixel; 01907 bitmap--; 01908 scrptr++; 01909 } 01910 bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!! 01911 if (xclip) 01912 { 01913 if (w&1) 01914 { 01915 /**last pixel is odd pixel due to clipping & odd width*/ 01916 uint8_t sourcepixel = *bitmap; 01917 if ((sourcepixel&0x0F) != invisiblecolor) 01918 { 01919 sourcepixel <<=4; 01920 uint8_t targetpixel = *scrptr;// & 0x0F; 01921 targetpixel |= sourcepixel; 01922 *scrptr = targetpixel; 01923 } 01924 //scrptr++; 01925 } 01926 bitmap++; 01927 scrptr++; 01928 } 01929 bitmap += xjump; // needed if x<0 clipping occurs 01930 } 01931 else /** ODD pixel starting line **/ 01932 { 01933 for (scrx = x; scrx < w+x-xclip; scrx+=2 ) 01934 { 01935 uint8_t sourcepixel = *bitmap; 01936 uint8_t targetpixel = *scrptr; 01937 // inverted !!! store lower nibble of source pixel in lower nibble of target 01938 if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F ); 01939 *scrptr = targetpixel; 01940 scrptr++; 01941 targetpixel = *scrptr; 01942 // inverted ! store higher nibble of source pixel in higher nibble of target 01943 if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel & 0xF0); 01944 *scrptr = targetpixel; 01945 bitmap--; 01946 } 01947 bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!! 01948 bitmap+=xjump; 01949 } 01950 // increment the y jump in the scrptr 01951 scrptr = scrptr + ((width - w)>>1)+scrxjump; 01952 } 01953 } 01954 /** 8 bpp mode */ 01955 else if (m_colordepth==8) 01956 { 01957 int16_t scrx,scry;//,scrxjump; 01958 int16_t xjump=0; 01959 /** y clipping */ 01960 if (y<0) 01961 { 01962 h+=y; 01963 bitmap -= y*w; 01964 y=0; 01965 } 01966 else if (y+h>height) 01967 { 01968 h -=(y-height); 01969 } 01970 /** x clipping */ 01971 if (x<0) 01972 { 01973 w+=x; 01974 xjump = (-x); 01975 bitmap += xjump; 01976 x=0; 01977 } 01978 else if (x+w>width) 01979 { 01980 xjump=(x+w-width); 01981 w = width-x; 01982 } 01983 01984 uint8_t* scrptr = m_scrbuf + (y*width + x) + w; 01985 for (scry = y; scry < y+h; scry+=1) 01986 { 01987 if (scry>=height) return; 01988 for (scrx = x; scrx < w+x; scrx++) 01989 { 01990 uint8_t sourcepixel = *bitmap; 01991 uint8_t targetpixel = *scrptr; 01992 if (sourcepixel != invisiblecolor ) 01993 targetpixel = sourcepixel; 01994 *scrptr = targetpixel; 01995 bitmap++; 01996 scrptr--; 01997 } 01998 bitmap += xjump; // needed if horizontal clipping occurs 01999 scrptr = scrptr + (width + w); 02000 } 02001 return; 02002 } 02003 } 02004 02005 void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap) 02006 { 02007 drawBitmapDataXFlipped(x, y, bitmap[0], bitmap[1], bitmap + 2); 02008 } 02009 02010 void Display::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip) { 02011 #if PROJ_GAMEBUINO == 0 02012 if (!flip) drawBitmap(x,y,bitmap); 02013 else drawBitmapXFlipped(x,y,bitmap); 02014 #else 02015 if((rotation == NOROT) && (flip == NOFLIP)){ 02016 drawBitmap(x,y,bitmap); //use the faster algorithm 02017 return; 02018 } 02019 uint8_t w = bitmap[0]; 02020 uint8_t h = bitmap[1]; 02021 bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height 02022 int8_t i, j, //coordinates in the raw bitmap 02023 k, l, //coordinates in the rotated/flipped bitmap 02024 byteNum, bitNum, byteWidth = (w + 7) >> 3; 02025 02026 rotation %= 4; 02027 02028 for (i = 0; i < w; i++) { 02029 byteNum = i / 8; 02030 bitNum = i % 8; 02031 for (j = 0; j < h; j++) { 02032 if (bitmap[j * byteWidth + byteNum] & (B10000000 >> bitNum)) { 02033 switch (rotation) { 02034 case NOROT: //no rotation 02035 k = i; 02036 l = j; 02037 break; 02038 case ROTCCW: //90° counter-clockwise 02039 k = j; 02040 l = w - i - 1; 02041 break; 02042 case ROT180: //180° 02043 k = w - i - 1; 02044 l = h - j - 1; 02045 break; 02046 case ROTCW: //90° clockwise 02047 k = h - j - 1; 02048 l = i; 02049 break; 02050 } 02051 if (flip) { 02052 flip %= 4; 02053 if (flip & B00000001) { //horizontal flip 02054 k = w - k; 02055 } 02056 if (flip & B00000010) { //vertical flip 02057 l = h - l; 02058 } 02059 } 02060 k += x; //place the bitmap on the screen 02061 l += y; 02062 drawPixel(k, l); 02063 } 02064 } 02065 } 02066 #endif //PROJ_GAMEBUINO 02067 02068 } 02069 02070 uint8_t* Display::getBuffer() { 02071 return m_scrbuf; 02072 } 02073 02074 uint8_t Display::getBitmapPixel(const uint8_t* bitmap, uint16_t x, uint16_t y) { 02075 uint16_t w = *bitmap; 02076 uint8_t sourcebyte = bitmap[2+(y * ((w+7)>>3))+ (x>>3)]; 02077 return sourcebyte & (0x80>>(x&7)); 02078 } 02079 02080 int Display::print_char(uint8_t x, uint8_t y, unsigned char c) { 02081 c -= font[2]; 02082 if (m_mode) return directChar(x,y,c); 02083 return bufferChar(x,y,c); 02084 } 02085 02086 void Display::drawChar(int8_t x, int8_t y, unsigned char c, uint8_t size) { 02087 print_char(x,y,c); 02088 return; 02089 } 02090 02091 02092 bool Display::isDirectPrintingEnabled() { 02093 return m_mode; 02094 } 02095 02096 void Display::enableDirectPrinting(uint8_t m) { 02097 if (m) { 02098 m_mode=true; 02099 m_w = POK_LCD_W; 02100 m_h = POK_LCD_H; 02101 } else { 02102 m_mode=false; 02103 m_w = getWidth(); 02104 m_h = getHeight(); 02105 } 02106 } 02107 02108 void Display::write(uint8_t c) { 02109 int charstep=0; 02110 if(font[3]) { 02111 // only caps in this font 02112 if (c>=97) c-=32; 02113 } 02114 switch(c) { 02115 case '\0': //null 02116 break; 02117 case '\n': //line feed 02118 cursorX = 0; 02119 inc_txtline(); 02120 break; 02121 case 8: //backspace 02122 cursorX -= font[0]; 02123 charstep=print_char(cursorX,cursorY,' '); 02124 break; 02125 case 13: //carriage return 02126 cursorX = 0; 02127 break; 02128 case 14: //form feed new page(clear screen) 02129 //clear_screen(); 02130 break; 02131 default: 02132 if (cursorX >= (m_w - font[0])) { 02133 cursorX = 0; 02134 if (textWrap) inc_txtline(); 02135 else return; // stop outputting text 02136 charstep=print_char(cursorX,cursorY,c); 02137 } 02138 else 02139 charstep=print_char(cursorX,cursorY,c); 02140 #ifndef FULLWIDTHSPACES 02141 if (c==' ' && adjustCharStep) charstep=(charstep>>1)+1; 02142 #endif 02143 cursorX += charstep; 02144 } 02145 } 02146 02147 void Display::inc_txtline() { 02148 if (cursorY > m_h - 2*font[1]) //= (height - (font[1]+1))) 02149 #if SCROLL_TEXT > 0 02150 scroll(font[1] + adjustLineStep); 02151 #else 02152 cursorY = 0; 02153 #endif 02154 else 02155 cursorY += font[1] + adjustLineStep; 02156 } 02157 02158 /* default implementation: may be overridden */ 02159 void Display::write(const char *str) 02160 { 02161 while (*str) 02162 write(*str++); 02163 } 02164 02165 /* default implementation: may be overridden */ 02166 void Display::write(const uint8_t *buffer, uint8_t size) 02167 { 02168 while (size--) 02169 write(*buffer++); 02170 } 02171 02172 void Display::print(const char str[]) 02173 { 02174 write(str); 02175 } 02176 02177 void Display::print(char c, int base) 02178 { 02179 print((long) c, base); 02180 } 02181 02182 void Display::print(unsigned char b, int base) 02183 { 02184 print((unsigned long) b, base); 02185 } 02186 02187 void Display::print(int n, int base) 02188 { 02189 print((long) n, base); 02190 } 02191 02192 void Display::print(unsigned int n, int base) 02193 { 02194 print((unsigned long) n, base); 02195 } 02196 02197 void Display::print(long n, int base) 02198 { 02199 if (base == 0) { 02200 write(n); 02201 } else if (base == 10) { 02202 if (n < 0) { 02203 print('-'); 02204 n = -n; 02205 } 02206 printNumber(n, 10); 02207 } else { 02208 printNumber(n, base); 02209 } 02210 } 02211 02212 void Display::print(unsigned long n, int base) 02213 { 02214 if (base == 0) write(n); 02215 else printNumber(n, base); 02216 } 02217 02218 void Display::print(double n, int digits) 02219 { 02220 printFloat(n, digits); 02221 } 02222 02223 void Display::println(void) 02224 { 02225 print('\r'); 02226 print('\n'); 02227 } 02228 02229 void Display::println(const char c[]) 02230 { 02231 print(c); 02232 println(); 02233 } 02234 02235 void Display::println(char c, int base) 02236 { 02237 print(c, base); 02238 println(); 02239 } 02240 02241 void Display::println(unsigned char b, int base) 02242 { 02243 print(b, base); 02244 println(); 02245 } 02246 02247 void Display::println(int n, int base) 02248 { 02249 print(n, base); 02250 println(); 02251 } 02252 02253 void Display::println(unsigned int n, int base) 02254 { 02255 print(n, base); 02256 println(); 02257 } 02258 02259 void Display::println(long n, int base) 02260 { 02261 print(n, base); 02262 println(); 02263 } 02264 02265 void Display::println(unsigned long n, int base) 02266 { 02267 print(n, base); 02268 println(); 02269 } 02270 02271 void Display::println(double n, int digits) 02272 { 02273 print(n, digits); 02274 println(); 02275 } 02276 02277 void Display::set_cursor(uint8_t x, uint8_t y) { 02278 cursorX = x; 02279 cursorY = y; 02280 } 02281 02282 void Display::print(uint8_t x, uint8_t y, const char str[]) { 02283 cursorX = x; 02284 cursorY = y; 02285 write(str); 02286 02287 } 02288 void Display::print(uint8_t x, uint8_t y, char c, int base) { 02289 cursorX = x; 02290 cursorY = y; 02291 print((long) c, base); 02292 } 02293 void Display::print(uint8_t x, uint8_t y, unsigned char b, int base) { 02294 cursorX = x; 02295 cursorY = y; 02296 print((unsigned long) b, base); 02297 } 02298 void Display::print(uint8_t x, uint8_t y, int n, int base) { 02299 cursorX = x; 02300 cursorY = y; 02301 print((long) n, base); 02302 } 02303 void Display::print(uint8_t x, uint8_t y, unsigned int n, int base) { 02304 cursorX = x; 02305 cursorY = y; 02306 print((unsigned long) n, base); 02307 } 02308 void Display::print(uint8_t x, uint8_t y, long n, int base) { 02309 cursorX = x; 02310 cursorY = y; 02311 print(n,base); 02312 } 02313 void Display::print(uint8_t x, uint8_t y, unsigned long n, int base) { 02314 cursorX = x; 02315 cursorY = y; 02316 print(n,base); 02317 } 02318 void Display::print(uint8_t x, uint8_t y, double n, int digits) { 02319 cursorX = x; 02320 cursorY = y; 02321 print(n,digits); 02322 } 02323 02324 void Display::println(uint8_t x, uint8_t y, const char c[]) 02325 { 02326 cursorX = x; 02327 cursorY = y; 02328 print(c); 02329 println(); 02330 } 02331 02332 void Display::println(uint8_t x, uint8_t y, char c, int base) 02333 { 02334 cursorX = x; 02335 cursorY = y; 02336 print(c, base); 02337 println(); 02338 } 02339 02340 void Display::println(uint8_t x, uint8_t y, unsigned char b, int base) 02341 { 02342 cursorX = x; 02343 cursorY = y; 02344 print(b, base); 02345 println(); 02346 } 02347 02348 void Display::println(uint8_t x, uint8_t y, int n, int base) 02349 { 02350 cursorX = x; 02351 cursorY = y; 02352 print(n, base); 02353 println(); 02354 } 02355 02356 void Display::println(uint8_t x, uint8_t y, unsigned int n, int base) 02357 { 02358 cursorX = x; 02359 cursorY = y; 02360 print(n, base); 02361 println(); 02362 } 02363 02364 void Display::println(uint8_t x, uint8_t y, long n, int base) 02365 { 02366 cursorX = x; 02367 cursorY = y; 02368 print(n, base); 02369 println(); 02370 } 02371 02372 void Display::println(uint8_t x, uint8_t y, unsigned long n, int base) 02373 { 02374 cursorX = x; 02375 cursorY = y; 02376 print(n, base); 02377 println(); 02378 } 02379 02380 void Display::println(uint8_t x, uint8_t y, double n, int digits) 02381 { 02382 cursorX = x; 02383 cursorY = y; 02384 print(n, digits); 02385 println(); 02386 } 02387 02388 void Display::printNumber(unsigned long n, uint8_t base) 02389 { 02390 unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. 02391 unsigned long i = 0; 02392 02393 if (n == 0) { 02394 print('0'); 02395 return; 02396 } 02397 02398 while (n > 0) { 02399 buf[i++] = n % base; 02400 n /= base; 02401 } 02402 02403 for (; i > 0; i--) 02404 print((char) (buf[i - 1] < 10 ? 02405 '0' + buf[i - 1] : 02406 'A' + buf[i - 1] - 10)); 02407 } 02408 02409 void Display::printFloat(double number, uint8_t digits) 02410 { 02411 // Handle negative numbers 02412 if (number < 0.0) 02413 { 02414 print('-'); 02415 number = -number; 02416 } 02417 02418 // Round correctly so that print(1.999, 2) prints as "2.00" 02419 double rounding = 0.5; 02420 for (uint8_t i=0; i<digits; ++i) 02421 rounding /= 10.0; 02422 02423 number += rounding; 02424 02425 // Extract the integer part of the number and print it 02426 unsigned long int_part = (unsigned long)number; 02427 double remainder = number - (double)int_part; 02428 print(int_part); 02429 02430 // Print the decimal point, but only if there are digits beyond 02431 if (digits > 0) 02432 print("."); 02433 02434 // Extract digits from the remainder one at a time 02435 while (digits-- > 0) 02436 { 02437 remainder *= 10.0; 02438 int toPrint = int(remainder); 02439 print(toPrint); 02440 remainder -= toPrint; 02441 } 02442 } 02443 02444 02445 void Display::draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap) 02446 { 02447 int8_t scry; 02448 uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1)); 02449 02450 /** ONLY 4-bit mode for time being **/ 02451 02452 if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/ 02453 for (scry = y; scry < h+y; scry++) { 02454 uint8_t sourcepixel = *bitmap; 02455 uint8_t targetpixel = *scrptr; 02456 targetpixel = (targetpixel&0x0F) | (sourcepixel << 4); 02457 *scrptr = targetpixel; 02458 bitmap++; 02459 scrptr+=55; 02460 } 02461 } else { /** ODD pixel starting line **/ 02462 for (scry = y; scry < h+y; scry++) { 02463 uint8_t sourcepixel = *bitmap; 02464 uint8_t targetpixel = *scrptr; 02465 // store source pixel in lower nibble of target 02466 targetpixel = (targetpixel & 0xF0) | (sourcepixel); 02467 *scrptr = targetpixel; 02468 scrptr+=55; 02469 bitmap++; 02470 } 02471 } 02472 } 02473 02474 /** 02475 * Setup or disable the sprite. Note that enabled sprites must always have subsequent indices, starting from the index zero. 02476 * You cannot have gaps in indices of enabled sprites. 02477 * The max number of sprites can be changed by a SPRITE_COUNT define, the default is 4. 02478 * Note: the sprites currently work only in the 220 x 176 x 2bpp mode. 02479 * @param index The sprite index. The lower index is drawn first, i.e. is on bottom. 02480 * @param bitmap A pointer to a 2bpp bitmap. A NULL value means that the sprite is disabled. The ownership is not transferred, so the caller must keep the bitmap alive. 02481 * @param palette4x16bit Four color palette of 16bit elements. The first color value is considered as transparent. The palette is copied to the sprite struct, so the caller do not have to keep it alive. 02482 * @param x The initial x 02483 * @param y The initial y 02484 * @param doResetDirtyRect (default=true) True, if the previous coordinates are reseted. 02485 */ 02486 void Display::setSpriteBitmap(uint8_t index, const uint8_t* bitmap, const uint16_t* palette4x16bit, int16_t x, int16_t y, bool doResetDirtyRect ) { 02487 02488 setSprite(index, &(bitmap[2]), palette4x16bit, x, y, bitmap[0], bitmap[1], doResetDirtyRect); 02489 } 02490 02491 /** 02492 * Setup or disable the sprite. Note that enabled sprites must always have subsequent indices, starting from the index zero. 02493 * You cannot have gaps in indices of enabled sprites. 02494 * The max number of sprites can be changed by a SPRITE_COUNT define, the default is 4. 02495 * Note: the sprites currently work only in the 220 x 176 x 2bpp mode. 02496 * @param index The sprite index. The lower index is drawn first, i.e. is on bottom. Note that 02497 * @param data A pointer to a 2bpp pixel data of size w x h. A NULL value means that the sprite is disabled. The ownership is not transferred, so the caller must keep the data alive. 02498 * @param palette4x16bit Four color palette of 16bit elements. The first color value is considered as transparent. The palette is copied to the sprite struct, so the caller do not have to keep it alive. 02499 * @param x The initial x 02500 * @param y The initial y 02501 * @param w Width 02502 * @param h Height 02503 */ 02504 void Display::setSprite(uint8_t index, const uint8_t* data, const uint16_t* palette4x16bit, int16_t x, int16_t y, uint8_t w, uint8_t h, bool doResetDirtyRect ) { 02505 02506 if(index >= SPRITE_COUNT) return; 02507 m_sprites[index].bitmapData = data; 02508 m_sprites[index].x = x; 02509 m_sprites[index].y = y; 02510 if (doResetDirtyRect) { 02511 m_sprites[index].oldx = x; 02512 m_sprites[index].oldy = y; 02513 } 02514 m_sprites[index].w = w; 02515 m_sprites[index].h = h; 02516 if( palette4x16bit ) memcpy(m_sprites[index].palette, palette4x16bit, 4*2); 02517 } 02518 02519 /** 02520 * Set the sprite position. 02521 * @param index The sprite index 02522 * @param x 02523 * @param y 02524 */ 02525 void Display::setSpritePos(uint8_t index, int16_t x, int16_t y) { 02526 02527 if(index >= SPRITE_COUNT) return; 02528 m_sprites[index].x = x; 02529 m_sprites[index].y = y; 02530 } 02531 02532 void Display::lcdRefresh(unsigned char* scr, bool useDirectDrawMode) { 02533 02534 #if POK_SCREENMODE == MODE_HI_4COLOR 02535 // If there is one or more sprites, use sprite enabled drawing. 02536 if (m_sprites[0].bitmapData != NULL) 02537 lcdRefreshMode1Spr(scr, 0, 0, LCDWIDTH, LCDHEIGHT, paletteptr, m_sprites, useDirectDrawMode); 02538 else if (!useDirectDrawMode) 02539 lcdRefreshMode1(m_scrbuf, 0, 0, LCDWIDTH, LCDHEIGHT, paletteptr); 02540 #endif 02541 02542 // For the screen modes that do not support sprites, return if the direct draw mode is used. 02543 if (useDirectDrawMode) return; 02544 #if POK_SCREENMODE == MODE13 02545 lcdRefreshMode13(m_scrbuf, paletteptr, palOffset); 02546 #endif 02547 02548 #if POK_SCREENMODE == MIXMODE 02549 lcdRefreshMixMode(m_scrbuf, paletteptr, scanType); 02550 #endif 02551 02552 #if POK_SCREENMODE == MODE64 02553 lcdRefreshMode64(m_scrbuf, paletteptr); 02554 #endif 02555 02556 #if POK_SCREENMODE == MODE_GAMEBOY 02557 lcdRefreshModeGBC(scr, paletteptr); 02558 #endif 02559 02560 #if POK_SCREENMODE == MODE_FAST_16COLOR 02561 lcdRefreshMode2(scr, paletteptr); 02562 #endif 02563 02564 #if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR 02565 lcdRefreshGB(scr, paletteptr); 02566 #endif 02567 02568 #if POK_SCREENMODE == MODE_ARDUBOY_16COLOR 02569 lcdRefreshAB(scr, paletteptr); 02570 #endif 02571 02572 } 02573 02574 void Display::setFrameBufferTo(uint8_t* sb) { 02575 m_scrbuf = sb; 02576 }; 02577 02578 void Display::setTileBufferTo(uint8_t* tb) { 02579 m_tilebuf = tb; 02580 }; 02581 02582 void Display::loadTileset(const uint8_t* ts) { 02583 m_tileset = (uint8_t*) ts; 02584 }; 02585 02586 void Display::setTile(uint16_t i, uint8_t t) { 02587 if (!m_tilebuf) return; 02588 m_tilebuf[i]=t; 02589 }; 02590 02591 02592 02593 // Convert an integer to a hexadecimal string 02594 char* itoa_hex(int num, char* dest, int destLen) { 02595 int i = destLen-1; 02596 do { 02597 char c = (num % 16) + '0'; 02598 if (c > '9') c += 7; 02599 dest[i--] = c; 02600 num /= 16; 02601 } while (num && i >= 0); 02602 return &(dest[i+1]); 02603 } 02604 02605 // Draw the crash screen and wait forever 02606 #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]); 02607 void ShowCrashScreenAndWait( const char* texLine1, const char* texLine2, const char* texLine3, const char* texLine4, const char* texLine5 ) { 02608 02609 // draw screen red 02610 lcdFillSurface(COLOR_RED); 02611 02612 // Draw text 02613 Display::directcolor = COLOR_WHITE; 02614 Display::invisiblecolor = COLOR_RED; 02615 Display::directbgcolor = COLOR_RED; // Cannot be black as that is a transparent color 02616 Display::directtextrotated = false; 02617 Display::adjustCharStep = 0; 02618 Display::adjustLineStep = 0; 02619 Display::setFont(fntC64UIGfx); // A special font set that contains UI gfx in lower case letters. 02620 Display::fixedWidthFont = true; // Needed for the non-proportional C64 font (default value=false) 02621 Display::enableDirectPrinting(true); 02622 02623 char convertedStr[128] = {0}; 02624 02625 // Draw texts 02626 int yOffsetInPixels = 5; 02627 Display::set_cursor(0, 9 + yOffsetInPixels); 02628 Display::print(" "); STR_TO_UPPER(texLine1, convertedStr); Display::println(convertedStr); 02629 Display::print(" "); STR_TO_UPPER(texLine2, convertedStr); Display::println(convertedStr); 02630 Display::print(" "); STR_TO_UPPER(texLine3, convertedStr); Display::println(convertedStr); 02631 Display::println(); 02632 Display::print(" *"); STR_TO_UPPER(texLine4, convertedStr); Display::println(convertedStr); 02633 Display::print(" *"); STR_TO_UPPER(texLine5, convertedStr); Display::println(convertedStr); 02634 02635 Display::set_cursor(0, 0 + yOffsetInPixels); 02636 02637 // Frame 02638 Display::println(" abbbbbbbbbbbbbbbbbbbbbbbbc"); 02639 Display::print (" |"); Display::println(26*8, Display::cursorY,"|"); 02640 Display::print (" |"); Display::println(26*8, Display::cursorY,"|"); 02641 Display::print (" |"); Display::println(26*8, Display::cursorY,"|"); 02642 Display::print (" |"); Display::println(26*8, Display::cursorY,"|"); 02643 Display::print (" |"); Display::println(26*8, Display::cursorY,"|"); 02644 Display::print (" |"); Display::println(26*8, Display::cursorY,"|"); 02645 Display::println(" dbbbzybbbbbbbbbbbbbbbbbbbe"); 02646 Display::println(" {e"); 02647 02648 // Pokitto image 02649 Display::println (""); 02650 Display::println (" ijkl"); 02651 Display::println (" mnop"); 02652 Display::println (" qrst"); 02653 Display::println (" uvwx"); 02654 02655 // loop forever 02656 while(1){;} 02657 } 02658 02659 // Check the stack size and show a crash screen if the stack is too big. 02660 void CheckStack() { 02661 #ifndef POK_SIM 02662 #ifndef __ARMCC_VERSION 02663 int currStackTop; 02664 const int freeStackThreshold = 200; 02665 if ((int)&currStackTop - (int)_ebss < freeStackThreshold) { 02666 02667 // Create info string: "<stack size>:<current stack pointer>", e.g. "12345ABC:12345ABC" 02668 const int infoStringLen = 8+1+8; 02669 static char infoString[infoStringLen+1]; 02670 memset(infoString,0,infoStringLen+1); 02671 const int stackSize = (int)_vStackTop - (int)&currStackTop; 02672 const int tmpStrLen = 8; 02673 static char tmpStr[tmpStrLen+1]; 02674 memset(tmpStr,0,tmpStrLen+1); 02675 char* subStr = itoa_hex(stackSize, tmpStr, tmpStrLen); // keep ending null 02676 strcat(infoString, subStr); // Add stack size as hex string 02677 strcat(infoString, ":"); 02678 subStr = itoa_hex((int)&currStackTop, tmpStr, tmpStrLen); // keep ending null 02679 strcat(infoString, subStr); // Add stack pointer address as hex string 02680 02681 // Draw the crash screen and wait forever. Use static const strings to avoid more stack usage. 02682 static const char* texLine1 = "OOPS! PLEASE, RESTART"; 02683 static const char* texLine2 = "POKITTO OR RELOAD"; 02684 static const char* texLine3 = "SOFTWARE."; 02685 static const char* texLine4 = "STACK TOO BIG!"; 02686 ShowCrashScreenAndWait(texLine1, texLine2, texLine3, texLine4, infoString); 02687 } 02688 #endif 02689 #endif 02690 } 02691 02692 /** Eof */ 02693 02694 02695 02696
Generated on Tue Jul 12 2022 11:20:36 by 1.7.2