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