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

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

PokittoLib

Library for programming Pokitto hardware

How to Use

  1. Import this library to online compiler (see button "import" on the right hand side
  2. DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
  3. Change My_settings.h according to your project
  4. Start coding!
Committer:
Pokitto
Date:
Wed Dec 25 23:59:52 2019 +0000
Revision:
71:531419862202
Parent:
45:bbfc6002118c
Changed Mode2 C++ refresh code (graphical errors)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pokitto 23:f88837b8f914 1 /**************************************************************************/
Pokitto 23:f88837b8f914 2 /*!
Pokitto 23:f88837b8f914 3 @file BmpImage.cpp
Pokitto 23:f88837b8f914 4 @author Hannu Viitala. Original BMP decoder code by Jonne Valola.
Pokitto 23:f88837b8f914 5
Pokitto 23:f88837b8f914 6 @section LICENSE
Pokitto 23:f88837b8f914 7
Pokitto 23:f88837b8f914 8 Software License Agreement (BSD License)
Pokitto 23:f88837b8f914 9
Pokitto 23:f88837b8f914 10 Copyright (c) 2016, Jonne Valola
Pokitto 23:f88837b8f914 11 All rights reserved.
Pokitto 23:f88837b8f914 12
Pokitto 23:f88837b8f914 13 Redistribution and use in source and binary forms, with or without
Pokitto 23:f88837b8f914 14 modification, are permitted provided that the following conditions are met:
Pokitto 23:f88837b8f914 15 1. Redistributions of source code must retain the above copyright
Pokitto 23:f88837b8f914 16 notice, this list of conditions and the following disclaimer.
Pokitto 23:f88837b8f914 17 2. Redistributions in binary form must reproduce the above copyright
Pokitto 23:f88837b8f914 18 notice, this list of conditions and the following disclaimer in the
Pokitto 23:f88837b8f914 19 documentation and/or other materials provided with the distribution.
Pokitto 23:f88837b8f914 20 3. Neither the name of the copyright holders nor the
Pokitto 23:f88837b8f914 21 names of its contributors may be used to endorse or promote products
Pokitto 23:f88837b8f914 22 derived from this software without specific prior written permission.
Pokitto 23:f88837b8f914 23
Pokitto 23:f88837b8f914 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
Pokitto 23:f88837b8f914 25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Pokitto 23:f88837b8f914 26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Pokitto 23:f88837b8f914 27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
Pokitto 23:f88837b8f914 28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Pokitto 23:f88837b8f914 29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Pokitto 23:f88837b8f914 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Pokitto 23:f88837b8f914 31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Pokitto 23:f88837b8f914 32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Pokitto 23:f88837b8f914 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Pokitto 23:f88837b8f914 34 */
Pokitto 23:f88837b8f914 35 /**************************************************************************/
Pokitto 23:f88837b8f914 36
Pokitto 23:f88837b8f914 37 #if POKITTO_USE_WIN_SIMULATOR
Pokitto 23:f88837b8f914 38 #include "defines_win_SIM.h"
Pokitto 23:f88837b8f914 39 #endif
Pokitto 23:f88837b8f914 40
Pokitto 23:f88837b8f914 41 #define PROJ_MBED 1
Pokitto 23:f88837b8f914 42
Pokitto 23:f88837b8f914 43 #if PROJ_LINUX || PROJ_MBED
Pokitto 23:f88837b8f914 44 #include "defines_linux_SIM.h"
Pokitto 23:f88837b8f914 45 #endif
Pokitto 23:f88837b8f914 46
Pokitto 23:f88837b8f914 47 #include "Pokitto.h"
Pokitto 23:f88837b8f914 48 #include "PokittoDisk.h"
Pokitto 23:f88837b8f914 49 #ifdef POK_SIM
Pokitto 23:f88837b8f914 50 #include "FileIO.h"
Pokitto 23:f88837b8f914 51 #endif
Pokitto 23:f88837b8f914 52
Pokitto 45:bbfc6002118c 53
Pokitto 45:bbfc6002118c 54 #define max(a,b) ((a)>(b)?(a):(b))
Pokitto 45:bbfc6002118c 55 #define min(a,b) ((a)<(b)?(a):(b))
Pokitto 45:bbfc6002118c 56
Pokitto 45:bbfc6002118c 57
Pokitto 23:f88837b8f914 58 #if POK_ENABLE_SD > 0
Pokitto 23:f88837b8f914 59
Pokitto 23:f88837b8f914 60
Pokitto 23:f88837b8f914 61 #include "PokittoDisplay.h"
Pokitto 23:f88837b8f914 62 #include "ImageFormat.h"
Pokitto 23:f88837b8f914 63
Pokitto 23:f88837b8f914 64 Pokitto::Core _game;
Pokitto 23:f88837b8f914 65 Pokitto::Display pokdisp;
Pokitto 23:f88837b8f914 66
Pokitto 23:f88837b8f914 67 int openImageFileFromSD(char* filepath, uint16_t **palette_out, uint8_t **bitmap_out) {
Pokitto 23:f88837b8f914 68
Pokitto 23:f88837b8f914 69 // Reset the out pointers.
Pokitto 23:f88837b8f914 70 *palette_out = 0;
Pokitto 23:f88837b8f914 71 *bitmap_out = 0;
Pokitto 23:f88837b8f914 72
Pokitto 23:f88837b8f914 73 BITMAPFILEHEADER bf;
Pokitto 23:f88837b8f914 74 BITMAPINFO bmi;
Pokitto 23:f88837b8f914 75
Pokitto 23:f88837b8f914 76 uint32_t bytes_read=0, bmpsize=0;
Pokitto 23:f88837b8f914 77
Pokitto 23:f88837b8f914 78 /** numcol is the number of colors for output */
Pokitto 23:f88837b8f914 79 unsigned int numcol = 0;
Pokitto 23:f88837b8f914 80
Pokitto 23:f88837b8f914 81 if (POK_COLORDEPTH == 8) numcol=256;
Pokitto 23:f88837b8f914 82 else if (POK_COLORDEPTH == 4) numcol=16;
Pokitto 23:f88837b8f914 83 else if (POK_COLORDEPTH == 2) numcol=4;
Pokitto 23:f88837b8f914 84 else if (POK_COLORDEPTH == 1) numcol=1;
Pokitto 23:f88837b8f914 85
Pokitto 23:f88837b8f914 86 if (!isThisFileOpen(filepath)) {
Pokitto 23:f88837b8f914 87 fileClose(); // close any open files
Pokitto 23:f88837b8f914 88 fileOpen(filepath, FILE_MODE_READONLY | FILE_MODE_BINARY);
Pokitto 23:f88837b8f914 89 }
Pokitto 23:f88837b8f914 90 else
Pokitto 23:f88837b8f914 91 return -1; // Already open, not good.
Pokitto 23:f88837b8f914 92
Pokitto 23:f88837b8f914 93 if (fileOK() && fileReadBytes((uint8_t*)&bf, sizeof(bf)) == sizeof(bf) ) {
Pokitto 23:f88837b8f914 94 bytes_read += sizeof(bf);
Pokitto 23:f88837b8f914 95 }
Pokitto 23:f88837b8f914 96 else
Pokitto 23:f88837b8f914 97 {
Pokitto 23:f88837b8f914 98 POK_TRACE("Error reading BMP header\n");
Pokitto 23:f88837b8f914 99 fileClose();
Pokitto 23:f88837b8f914 100 return(-1);
Pokitto 23:f88837b8f914 101 }
Pokitto 23:f88837b8f914 102
Pokitto 23:f88837b8f914 103 if (fileReadBytes((uint8_t*)&bmi,sizeof(bmi.bmiHeader)) != sizeof(bmi.bmiHeader)) {
Pokitto 23:f88837b8f914 104 POK_TRACE("Error reading BMP info\n");
Pokitto 23:f88837b8f914 105 fileClose();
Pokitto 23:f88837b8f914 106 return(-1);
Pokitto 23:f88837b8f914 107 }
Pokitto 23:f88837b8f914 108 bytes_read += sizeof(bmi.bmiHeader);
Pokitto 23:f88837b8f914 109
Pokitto 23:f88837b8f914 110 /** Check image validity */
Pokitto 23:f88837b8f914 111
Pokitto 23:f88837b8f914 112 if (bf.bfType != 0x4D42) {
Pokitto 23:f88837b8f914 113 POK_TRACE("Bitmap file has an unrecognized format (4D42 id missing from beginning).\n");
Pokitto 23:f88837b8f914 114 POK_TRACE("BMP2POK accepts .BMP files that have an indexed (1,-bit, 4-bit or 8-bit) color palette.\n");
Pokitto 23:f88837b8f914 115 fileClose();
Pokitto 23:f88837b8f914 116 return(-1);
Pokitto 23:f88837b8f914 117 }
Pokitto 23:f88837b8f914 118 if (bmi.bmiHeader.biBitCount != POK_COLORDEPTH ) {
Pokitto 23:f88837b8f914 119 POK_TRACE("ERROR!\nThe image color depth should be the same as screen color depth!\n");
Pokitto 23:f88837b8f914 120 }
Pokitto 23:f88837b8f914 121 if (bmi.bmiHeader.biWidth%32 && bmi.bmiHeader.biBitCount == 1) {
Pokitto 23:f88837b8f914 122 POK_TRACE("ERROR!\nPadding of 1-bit (monochrome) images is not yet supported\n");
Pokitto 23:f88837b8f914 123 POK_TRACE("1-bit images need to have width that is divisible by 32!\n");
Pokitto 23:f88837b8f914 124 POK_TRACE("Adjust size of source image.\n");
Pokitto 23:f88837b8f914 125 fileClose();
Pokitto 23:f88837b8f914 126 return(-1);
Pokitto 23:f88837b8f914 127 }
Pokitto 23:f88837b8f914 128 if (bmi.bmiHeader.biWidth%4) {
Pokitto 23:f88837b8f914 129 POK_TRACE("Width is not divisible by 4\n");
Pokitto 23:f88837b8f914 130 fileClose();
Pokitto 23:f88837b8f914 131 return(-1);
Pokitto 23:f88837b8f914 132 }
Pokitto 23:f88837b8f914 133 if (bmi.bmiHeader.biWidth%8 && bmi.bmiHeader.biBitCount==4) {
Pokitto 23:f88837b8f914 134 if (bmi.bmiHeader.biWidth%4) {
Pokitto 23:f88837b8f914 135 POK_TRACE("ERROR!\n4-bit source images have to have a width that is divisible by 4\n");
Pokitto 23:f88837b8f914 136 fileClose();
Pokitto 23:f88837b8f914 137 return(-1);
Pokitto 23:f88837b8f914 138 }
Pokitto 23:f88837b8f914 139 }
Pokitto 23:f88837b8f914 140 if (bmi.bmiHeader.biBitCount != 8 && bmi.bmiHeader.biBitCount != 4 && bmi.bmiHeader.biBitCount != 1)
Pokitto 23:f88837b8f914 141 {
Pokitto 23:f88837b8f914 142 POK_TRACE("Only 8bpp, 4bpp & 1bpp BMP files are supported\n");
Pokitto 23:f88837b8f914 143 fileClose();
Pokitto 23:f88837b8f914 144 return(-1);
Pokitto 23:f88837b8f914 145 }
Pokitto 23:f88837b8f914 146 if (bmi.bmiHeader.biCompression != 0 &&
Pokitto 23:f88837b8f914 147 !(bmi.bmiHeader.biCompression == BI_RLE4 && bmi.bmiHeader.biBitCount == 4))
Pokitto 23:f88837b8f914 148 {
Pokitto 23:f88837b8f914 149 POK_TRACE("Only RLE compression for bitmaps with 4 bpp is supported\n");
Pokitto 23:f88837b8f914 150 fileClose();
Pokitto 23:f88837b8f914 151 return(-1);
Pokitto 23:f88837b8f914 152 }
Pokitto 23:f88837b8f914 153
Pokitto 23:f88837b8f914 154 /* If the height is negative the bmp image is in the correct way.
Pokitto 23:f88837b8f914 155 If the heigh is positive the bmp image is vertically mirrored
Pokitto 23:f88837b8f914 156 */
Pokitto 23:f88837b8f914 157 int biAbsHeight = bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 158 if (bmi.bmiHeader.biHeight < 0 )
Pokitto 23:f88837b8f914 159 biAbsHeight = - bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 160
Pokitto 23:f88837b8f914 161 /** Read and copy palette **/
Pokitto 23:f88837b8f914 162
Pokitto 23:f88837b8f914 163 int c = bmi.bmiHeader.biClrUsed;
Pokitto 23:f88837b8f914 164 if (c==0) c = 1 << bmi.bmiHeader.biBitCount; // from MS BMP specs. 0 means 2^n colors
Pokitto 23:f88837b8f914 165 bmi.bmiHeader.biClrUsed = c;
Pokitto 23:f88837b8f914 166
Pokitto 23:f88837b8f914 167 /* Allocate memory for the output parameter */
Pokitto 23:f88837b8f914 168 if (numcol>bmi.bmiHeader.biClrUsed) numcol = bmi.bmiHeader.biClrUsed;
Pokitto 23:f88837b8f914 169 *palette_out = (uint16_t*) malloc(numcol*2);
Pokitto 23:f88837b8f914 170 if (*palette_out == NULL)
Pokitto 23:f88837b8f914 171 {
Pokitto 23:f88837b8f914 172 POK_TRACE("Error allocating temporary palette buffer.\n");
Pokitto 23:f88837b8f914 173 free(*palette_out);
Pokitto 23:f88837b8f914 174 return(-1);
Pokitto 23:f88837b8f914 175 }
Pokitto 23:f88837b8f914 176
Pokitto 23:f88837b8f914 177 /* seek to the beginning of the color table - because of gimp */
Pokitto 23:f88837b8f914 178 fileSeekAbsolute(bf.bfOffBits-c*4); //gfx data star minus color table
Pokitto 23:f88837b8f914 179
Pokitto 23:f88837b8f914 180 for (unsigned int c=0;c<numcol;c++) {
Pokitto 23:f88837b8f914 181
Pokitto 23:f88837b8f914 182 RGBQUAD rgbValue;
Pokitto 23:f88837b8f914 183 fileReadBytes((uint8_t*)&rgbValue, sizeof(RGBQUAD));
Pokitto 23:f88837b8f914 184 bytes_read += sizeof(RGBQUAD);
Pokitto 23:f88837b8f914 185
Pokitto 23:f88837b8f914 186 unsigned int r,g,b,o;
Pokitto 23:f88837b8f914 187 r = rgbValue.rgbRed >> 3; // 5 bit
Pokitto 23:f88837b8f914 188 g = rgbValue.rgbGreen >> 2; // 6 bits
Pokitto 23:f88837b8f914 189 b = rgbValue.rgbBlue >> 3; // 5 bits
Pokitto 23:f88837b8f914 190 o = (r<<11)|(g<<5)|b;
Pokitto 23:f88837b8f914 191
Pokitto 23:f88837b8f914 192 (*palette_out)[c] = o;
Pokitto 23:f88837b8f914 193 }
Pokitto 23:f88837b8f914 194
Pokitto 23:f88837b8f914 195 /** Read and copy image data **/
Pokitto 23:f88837b8f914 196
Pokitto 23:f88837b8f914 197 /* Get image data size. If the biSizeImage is given (>0) for RLE image, use that to reduce memory usage. */
Pokitto 23:f88837b8f914 198 bmpsize = bmi.bmiHeader.biWidth * biAbsHeight*bmi.bmiHeader.biBitCount/8;
Pokitto 23:f88837b8f914 199 if (bmi.bmiHeader.biCompression == BI_RLE4)
Pokitto 23:f88837b8f914 200 bmpsize = (bmi.bmiHeader.biSizeImage > 0) ? bmi.bmiHeader.biSizeImage : bmpsize;
Pokitto 23:f88837b8f914 201
Pokitto 23:f88837b8f914 202 // SEEK to the beginning of the data
Pokitto 23:f88837b8f914 203 fileSeekAbsolute(bf.bfOffBits);
Pokitto 23:f88837b8f914 204
Pokitto 23:f88837b8f914 205 /* Allocate output data buffer */
Pokitto 23:f88837b8f914 206 *bitmap_out = (uint8_t *) malloc(bmpsize + 2); // header takes 2 bytes
Pokitto 23:f88837b8f914 207 if (*bitmap_out == NULL)
Pokitto 23:f88837b8f914 208 {
Pokitto 23:f88837b8f914 209 POK_TRACE("Error allocating temporary data buffer, is image too big?\n");
Pokitto 23:f88837b8f914 210 free(*palette_out);
Pokitto 23:f88837b8f914 211 return(-1);
Pokitto 23:f88837b8f914 212 }
Pokitto 23:f88837b8f914 213
Pokitto 23:f88837b8f914 214 /* Store image size to the pokitto bitmap header */
Pokitto 23:f88837b8f914 215 uint32_t outindex = 0;
Pokitto 23:f88837b8f914 216 (*bitmap_out)[outindex++] = bmi.bmiHeader.biWidth;
Pokitto 23:f88837b8f914 217 (*bitmap_out)[outindex++] = biAbsHeight;
Pokitto 23:f88837b8f914 218
Pokitto 23:f88837b8f914 219 if (bmi.bmiHeader.biCompression == BI_RLE4) {
Pokitto 23:f88837b8f914 220 bool eofReached = false;
Pokitto 23:f88837b8f914 221 while (outindex < bmpsize && !eofReached ) {
Pokitto 23:f88837b8f914 222 /* Read byte from the file. */
Pokitto 23:f88837b8f914 223 unsigned char rleByte;
Pokitto 23:f88837b8f914 224 if (fileReadBytes(&rleByte, sizeof(rleByte)) != sizeof(rleByte))
Pokitto 23:f88837b8f914 225 {
Pokitto 23:f88837b8f914 226 /* End of file reached. Allocate a new bitmap which is of the exact size of the data */
Pokitto 23:f88837b8f914 227 eofReached = true;
Pokitto 23:f88837b8f914 228
Pokitto 23:f88837b8f914 229 /* Allocate output data buffer */
Pokitto 23:f88837b8f914 230 uint8_t* old_bitmap = *bitmap_out;
Pokitto 23:f88837b8f914 231 *bitmap_out = NULL;
Pokitto 23:f88837b8f914 232 *bitmap_out = (uint8_t *) malloc(outindex); // header takes 2 bytes
Pokitto 23:f88837b8f914 233 if (*bitmap_out == NULL)
Pokitto 23:f88837b8f914 234 {
Pokitto 23:f88837b8f914 235 POK_TRACE("Error allocating temporary data buffer, is image too big?\n");
Pokitto 23:f88837b8f914 236 free(old_bitmap);
Pokitto 23:f88837b8f914 237 free(*palette_out);
Pokitto 23:f88837b8f914 238 return(-1);
Pokitto 23:f88837b8f914 239 }
Pokitto 23:f88837b8f914 240
Pokitto 23:f88837b8f914 241 /* Copy data */
Pokitto 23:f88837b8f914 242 for (int i=0; i<outindex;i++)
Pokitto 23:f88837b8f914 243 (*bitmap_out)[i] = old_bitmap[i];
Pokitto 23:f88837b8f914 244
Pokitto 23:f88837b8f914 245 /* Free original bitmap */
Pokitto 23:f88837b8f914 246 free(old_bitmap);
Pokitto 23:f88837b8f914 247 }
Pokitto 23:f88837b8f914 248 else {
Pokitto 23:f88837b8f914 249 /* Store byte */
Pokitto 23:f88837b8f914 250 (*bitmap_out)[outindex++] = rleByte;
Pokitto 23:f88837b8f914 251 }
Pokitto 23:f88837b8f914 252 } // end while
Pokitto 23:f88837b8f914 253 }
Pokitto 23:f88837b8f914 254 else {
Pokitto 23:f88837b8f914 255 /* Do vertical mirroring only for uncompressed data.
Pokitto 23:f88837b8f914 256 Note the compressed RLE data above could not be mirrored.
Pokitto 23:f88837b8f914 257 */
Pokitto 23:f88837b8f914 258 int widthInBytes = bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount/8;
Pokitto 23:f88837b8f914 259 int widthInBytesInc, incY, startY, endY;
Pokitto 23:f88837b8f914 260 if (bmi.bmiHeader.biHeight > 0 ) {
Pokitto 23:f88837b8f914 261 /* Mirror vertically */
Pokitto 23:f88837b8f914 262 widthInBytesInc = - widthInBytes;
Pokitto 23:f88837b8f914 263 incY = -1;
Pokitto 23:f88837b8f914 264 startY = biAbsHeight - 1;
Pokitto 23:f88837b8f914 265 endY = -1;
Pokitto 23:f88837b8f914 266 }
Pokitto 23:f88837b8f914 267 else {
Pokitto 23:f88837b8f914 268 /* Do not mirror */
Pokitto 23:f88837b8f914 269 widthInBytesInc = widthInBytes;
Pokitto 23:f88837b8f914 270 incY = 1;
Pokitto 23:f88837b8f914 271 startY = 0;
Pokitto 23:f88837b8f914 272 endY = biAbsHeight;
Pokitto 23:f88837b8f914 273 }
Pokitto 23:f88837b8f914 274
Pokitto 23:f88837b8f914 275 /* Copy all bytes to the output bitmap */
Pokitto 23:f88837b8f914 276 for ( int y = startY, beginLine=startY*widthInBytes; y != endY; y += incY, beginLine += widthInBytesInc) {
Pokitto 23:f88837b8f914 277
Pokitto 23:f88837b8f914 278 /* Go to the beginning of the previous or next line */
Pokitto 23:f88837b8f914 279 outindex = beginLine;
Pokitto 23:f88837b8f914 280
Pokitto 23:f88837b8f914 281 for ( int xbyte = 0; xbyte < widthInBytes; xbyte++) {
Pokitto 23:f88837b8f914 282
Pokitto 23:f88837b8f914 283 /* Read byte from the file. */
Pokitto 23:f88837b8f914 284 unsigned char byteOfPixels;
Pokitto 23:f88837b8f914 285 if (fileReadBytes(&byteOfPixels, sizeof(byteOfPixels)) != sizeof(byteOfPixels))
Pokitto 23:f88837b8f914 286 {
Pokitto 23:f88837b8f914 287 POK_TRACE("Error reading BMP data\n");
Pokitto 23:f88837b8f914 288 fileClose();
Pokitto 23:f88837b8f914 289 free(*bitmap_out);
Pokitto 23:f88837b8f914 290 free(*palette_out);
Pokitto 23:f88837b8f914 291 return(-1);
Pokitto 23:f88837b8f914 292 }
Pokitto 23:f88837b8f914 293
Pokitto 23:f88837b8f914 294 /* Copy a byte from the file to the bitmap */
Pokitto 23:f88837b8f914 295 (*bitmap_out)[2 + outindex] = byteOfPixels;
Pokitto 23:f88837b8f914 296 outindex++;
Pokitto 23:f88837b8f914 297 } // end for
Pokitto 23:f88837b8f914 298 } // end for
Pokitto 23:f88837b8f914 299 } // end if
Pokitto 23:f88837b8f914 300
Pokitto 23:f88837b8f914 301 // Done with the file reading.
Pokitto 23:f88837b8f914 302 fileClose();
Pokitto 23:f88837b8f914 303
Pokitto 23:f88837b8f914 304 return 0;
Pokitto 23:f88837b8f914 305 }
Pokitto 23:f88837b8f914 306
Pokitto 23:f88837b8f914 307 int directDrawImageFileFromSD(int16_t sx, int16_t sy, char* filepath) {
Pokitto 23:f88837b8f914 308
Pokitto 23:f88837b8f914 309 return(directDrawImageFileFromSD(0, 0, 0/* full width */, 0/* full height */, sx, sy, filepath));
Pokitto 23:f88837b8f914 310 }
Pokitto 23:f88837b8f914 311
Pokitto 23:f88837b8f914 312 int directDrawImageFileFromSD(uint16_t ix, uint16_t iy, uint16_t iw, uint16_t ih, int16_t sx, int16_t sy, char* filepath) {
Pokitto 23:f88837b8f914 313
Pokitto 23:f88837b8f914 314 BITMAPFILEHEADER bf;
Pokitto 23:f88837b8f914 315 BITMAPINFO bmi;
Pokitto 23:f88837b8f914 316
Pokitto 23:f88837b8f914 317 uint32_t bytes_read=0;
Pokitto 23:f88837b8f914 318
Pokitto 23:f88837b8f914 319 if (!isThisFileOpen(filepath)) {
Pokitto 23:f88837b8f914 320 fileClose(); // close any open files
Pokitto 23:f88837b8f914 321 fileOpen(filepath, FILE_MODE_READONLY | FILE_MODE_BINARY);
Pokitto 23:f88837b8f914 322 }
Pokitto 23:f88837b8f914 323 else {
Pokitto 23:f88837b8f914 324 POK_TRACE("Error! Already open\n");
Pokitto 23:f88837b8f914 325 return -1; // Already open, not good.
Pokitto 23:f88837b8f914 326 }
Pokitto 23:f88837b8f914 327
Pokitto 23:f88837b8f914 328 if (fileOK() && fileReadBytes((uint8_t*)&bf, sizeof(bf)) == sizeof(bf) ) { //!HV why we have to check fileOK()?
Pokitto 23:f88837b8f914 329 bytes_read += sizeof(bf);
Pokitto 23:f88837b8f914 330 }
Pokitto 23:f88837b8f914 331 else
Pokitto 23:f88837b8f914 332 {
Pokitto 23:f88837b8f914 333 POK_TRACE("Error reading BMP header\n");
Pokitto 23:f88837b8f914 334 fileClose();
Pokitto 23:f88837b8f914 335 return(-1);
Pokitto 23:f88837b8f914 336 }
Pokitto 23:f88837b8f914 337
Pokitto 23:f88837b8f914 338 if (fileReadBytes((uint8_t*)&bmi,sizeof(bmi.bmiHeader)) != sizeof(bmi.bmiHeader)) {
Pokitto 23:f88837b8f914 339 POK_TRACE("Error reading BMP info\n");
Pokitto 23:f88837b8f914 340 fileClose();
Pokitto 23:f88837b8f914 341 return(-1);
Pokitto 23:f88837b8f914 342 }
Pokitto 23:f88837b8f914 343 bytes_read += sizeof(bmi.bmiHeader);
Pokitto 23:f88837b8f914 344
Pokitto 23:f88837b8f914 345 /** Check image validity */
Pokitto 23:f88837b8f914 346
Pokitto 23:f88837b8f914 347 if (bf.bfType != 0x4D42) {
Pokitto 23:f88837b8f914 348 POK_TRACE("Bitmap file has an unrecognized format (4D42 id missing from beginning).\n");
Pokitto 23:f88837b8f914 349 POK_TRACE("BMP2POK accepts .BMP files that have an indexed (1,-bit, 4-bit or 8-bit) color palette.\n");
Pokitto 23:f88837b8f914 350 fileClose();
Pokitto 23:f88837b8f914 351 return(-1);
Pokitto 23:f88837b8f914 352 }
Pokitto 23:f88837b8f914 353 if (bmi.bmiHeader.biBitCount != 24 ) {
Pokitto 23:f88837b8f914 354 POK_TRACE("ERROR!\nThe image color depth should be the same as screen color depth (%d)!\n");
Pokitto 23:f88837b8f914 355 fileClose();
Pokitto 23:f88837b8f914 356 return(-1);
Pokitto 23:f88837b8f914 357 }
Pokitto 23:f88837b8f914 358 if (bmi.bmiHeader.biCompression != 0 )
Pokitto 23:f88837b8f914 359 {
Pokitto 23:f88837b8f914 360 POK_TRACE("Compression is not supported.\n");
Pokitto 23:f88837b8f914 361 fileClose();
Pokitto 23:f88837b8f914 362 return(-1);
Pokitto 23:f88837b8f914 363 }
Pokitto 23:f88837b8f914 364
Pokitto 23:f88837b8f914 365 /* If the height is negative the bmp image is in the correct way.
Pokitto 23:f88837b8f914 366 If the heigh is positive the bmp image is vertically mirrored
Pokitto 23:f88837b8f914 367 */
Pokitto 23:f88837b8f914 368 int biAbsHeight = bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 369 if (bmi.bmiHeader.biHeight < 0 )
Pokitto 23:f88837b8f914 370 biAbsHeight = - bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 371
Pokitto 23:f88837b8f914 372 /** Zero size parameter means full image size */
Pokitto 23:f88837b8f914 373 if(iw==0) iw = bmi.bmiHeader.biWidth; // 0 means full image width
Pokitto 23:f88837b8f914 374 if(ih==0) ih = biAbsHeight; // 0 means full image width
Pokitto 23:f88837b8f914 375
Pokitto 23:f88837b8f914 376 /** Check parameters */
Pokitto 23:f88837b8f914 377 if( ix + iw > bmi.bmiHeader.biWidth ) {
Pokitto 23:f88837b8f914 378 POK_TRACE("Error! Invalid parameter\n");
Pokitto 23:f88837b8f914 379 fileClose();
Pokitto 23:f88837b8f914 380 return(-1);
Pokitto 23:f88837b8f914 381 }
Pokitto 23:f88837b8f914 382 if( iy + ih > biAbsHeight ) {
Pokitto 23:f88837b8f914 383 POK_TRACE("Error! Invalid parameter\n");
Pokitto 23:f88837b8f914 384 fileClose();
Pokitto 23:f88837b8f914 385 return(-1);
Pokitto 23:f88837b8f914 386 }
Pokitto 23:f88837b8f914 387 if( sx > pokdisp.getWidth()-1 || sx<-iw) {
Pokitto 23:f88837b8f914 388 POK_TRACE("Error! Invalid parameter\n");
Pokitto 23:f88837b8f914 389 fileClose();
Pokitto 23:f88837b8f914 390 return(-1);
Pokitto 23:f88837b8f914 391 }
Pokitto 23:f88837b8f914 392 if( sy > pokdisp.getHeight()-1 || sy<-ih) {
Pokitto 23:f88837b8f914 393 POK_TRACE("Error! Invalid parameter\n");
Pokitto 23:f88837b8f914 394 fileClose();
Pokitto 23:f88837b8f914 395 return(-1);
Pokitto 23:f88837b8f914 396 }
Pokitto 23:f88837b8f914 397
Pokitto 23:f88837b8f914 398 /** Zero size parameter means full image size */
Pokitto 23:f88837b8f914 399 if(iw==0) iw = bmi.bmiHeader.biWidth; // 0 means full image width
Pokitto 23:f88837b8f914 400 if(ih==0) ih = biAbsHeight; // 0 means full image width
Pokitto 23:f88837b8f914 401
Pokitto 23:f88837b8f914 402 /** Clip image to screen dimensions */
Pokitto 23:f88837b8f914 403
Pokitto 23:f88837b8f914 404 int16_t clipX1OnScreen = max( 0, sx);
Pokitto 23:f88837b8f914 405 int16_t clipX2OnScreen = min( pokdisp.getWidth()-1, sx+iw-1);
Pokitto 23:f88837b8f914 406 int16_t clipWidthOnScreen = clipX2OnScreen-clipX1OnScreen+1;
Pokitto 23:f88837b8f914 407 int16_t clipY1OnScreen = max( 0, sy);
Pokitto 23:f88837b8f914 408 int16_t clipY2OnScreen = min( pokdisp.getHeight()-1, sy+ih-1);
Pokitto 23:f88837b8f914 409 int16_t clipHeightOnScreen = clipY2OnScreen-clipY1OnScreen+1;
Pokitto 23:f88837b8f914 410
Pokitto 23:f88837b8f914 411 uint16_t skipImagePixelsAtLineStart = ix+(clipX1OnScreen-sx);
Pokitto 23:f88837b8f914 412 uint16_t skipImagePixelsAtLineStartAsBytes = skipImagePixelsAtLineStart*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 413 uint16_t skipImagePixelsAtLineEndAsBytes = (bmi.bmiHeader.biWidth-(skipImagePixelsAtLineStart+clipWidthOnScreen))*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 414
Pokitto 23:f88837b8f914 415 uint16_t skipImageRowsAtImageStart = iy+(clipY1OnScreen-sy);
Pokitto 23:f88837b8f914 416 uint16_t skipImageRowsAtImageEnd = biAbsHeight-(skipImageRowsAtImageStart+clipHeightOnScreen);
Pokitto 23:f88837b8f914 417
Pokitto 23:f88837b8f914 418 /* Vertical loop parameters */
Pokitto 23:f88837b8f914 419 int incY, startY, pastEndY;
Pokitto 23:f88837b8f914 420 uint32_t skipImageRowsAsBytes = 0;
Pokitto 23:f88837b8f914 421 if (bmi.bmiHeader.biHeight > 0 ) {
Pokitto 23:f88837b8f914 422 /* Mirror vertically */
Pokitto 23:f88837b8f914 423 incY = -1;
Pokitto 23:f88837b8f914 424 startY = clipY2OnScreen;
Pokitto 23:f88837b8f914 425 pastEndY = clipY1OnScreen-1;
Pokitto 23:f88837b8f914 426 skipImageRowsAsBytes = skipImageRowsAtImageEnd*bmi.bmiHeader.biWidth*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 427 }
Pokitto 23:f88837b8f914 428 else {
Pokitto 23:f88837b8f914 429 /* Do not mirror */
Pokitto 23:f88837b8f914 430 incY = 1;
Pokitto 23:f88837b8f914 431 startY = clipY1OnScreen ;
Pokitto 23:f88837b8f914 432 pastEndY = clipY2OnScreen+1;
Pokitto 23:f88837b8f914 433 skipImageRowsAsBytes = skipImageRowsAtImageStart*bmi.bmiHeader.biWidth*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 434 }
Pokitto 23:f88837b8f914 435
Pokitto 23:f88837b8f914 436 /** Read and copy image data directly to the screen **/
Pokitto 23:f88837b8f914 437
Pokitto 23:f88837b8f914 438 /* Seek to the beginning of the data */
Pokitto 23:f88837b8f914 439 fileSeekAbsolute(bf.bfOffBits);
Pokitto 23:f88837b8f914 440
Pokitto 23:f88837b8f914 441 /* Seek until the image rect starts */
Pokitto 23:f88837b8f914 442 if (skipImageRowsAsBytes>0) fileSeekRelative( skipImageRowsAsBytes );
Pokitto 23:f88837b8f914 443
Pokitto 23:f88837b8f914 444 /* Copy all bytes to the output bitmap */
Pokitto 23:f88837b8f914 445 for ( int y = startY; y != pastEndY; y += incY) {
Pokitto 23:f88837b8f914 446
Pokitto 23:f88837b8f914 447 /* Seek until the image rect starts */
Pokitto 23:f88837b8f914 448 if (skipImagePixelsAtLineStartAsBytes>0) fileSeekRelative( skipImagePixelsAtLineStartAsBytes );
Pokitto 23:f88837b8f914 449
Pokitto 23:f88837b8f914 450 for ( int x = clipX1OnScreen; x <= clipX2OnScreen; x++) {
Pokitto 23:f88837b8f914 451
Pokitto 23:f88837b8f914 452 /* Read RGB pixel from the file. For 24 bpp the pixel is stored to 3 bytes*/
Pokitto 23:f88837b8f914 453 uint32_t rgb24;
Pokitto 23:f88837b8f914 454 if (fileReadBytes((uint8_t*)&rgb24, 3) != 3)
Pokitto 23:f88837b8f914 455 {
Pokitto 23:f88837b8f914 456 POK_TRACE("Error reading BMP data\n");
Pokitto 23:f88837b8f914 457 fileClose();
Pokitto 23:f88837b8f914 458 return(-1);
Pokitto 23:f88837b8f914 459 }
Pokitto 23:f88837b8f914 460
Pokitto 23:f88837b8f914 461 /* Copy a pixel from the file directly to the screen */
Pokitto 23:f88837b8f914 462 // uint8_t r,g,b;
Pokitto 23:f88837b8f914 463 // r = (xrgb >> (3 + 16)) & 0x1f; // 5 bit
Pokitto 23:f88837b8f914 464 // g = (xrgb >> (2 + 8)) & 0x3f; // 6 bits
Pokitto 23:f88837b8f914 465 // b = (xrgb >> 3) & 0x1f; // 5 bits
Pokitto 23:f88837b8f914 466 // uint16_t targetpixel = (r<<11) | (g<<5) | b;
Pokitto 23:f88837b8f914 467
Pokitto 23:f88837b8f914 468 uint16_t targetpixel =
Pokitto 23:f88837b8f914 469 ((rgb24 >> 8) & 0x0000F800) | // red (bits 15-11)
Pokitto 23:f88837b8f914 470 ((rgb24 >> 5) & 0x000007E0) | // green (bits 10-5)
Pokitto 23:f88837b8f914 471 ((rgb24 >> 3) & 0x0000001F); // blue (bits 4-0)
Pokitto 23:f88837b8f914 472 _game.display.directPixel(x, y, targetpixel);
Pokitto 23:f88837b8f914 473 } // end for
Pokitto 23:f88837b8f914 474
Pokitto 23:f88837b8f914 475 /* Skip pixels at line end */
Pokitto 23:f88837b8f914 476 if (skipImagePixelsAtLineEndAsBytes>0) fileSeekRelative( skipImagePixelsAtLineEndAsBytes );
Pokitto 23:f88837b8f914 477
Pokitto 23:f88837b8f914 478 } // end for
Pokitto 23:f88837b8f914 479
Pokitto 23:f88837b8f914 480 // Done with the file reading.
Pokitto 23:f88837b8f914 481 fileClose();
Pokitto 23:f88837b8f914 482
Pokitto 23:f88837b8f914 483 return 0;
Pokitto 23:f88837b8f914 484 }
Pokitto 23:f88837b8f914 485
Pokitto 23:f88837b8f914 486 #endif
Pokitto 23:f88837b8f914 487