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:
Fri Dec 29 05:17:10 2017 +0000
Revision:
23:f88837b8f914
Child:
45:bbfc6002118c
PokittoLib mbed and Github are back in sync with all contributions from Hanski and Spinal included

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 23:f88837b8f914 53 #if POK_ENABLE_SD > 0
Pokitto 23:f88837b8f914 54
Pokitto 23:f88837b8f914 55
Pokitto 23:f88837b8f914 56 #include "PokittoDisplay.h"
Pokitto 23:f88837b8f914 57 #include "ImageFormat.h"
Pokitto 23:f88837b8f914 58
Pokitto 23:f88837b8f914 59 Pokitto::Core _game;
Pokitto 23:f88837b8f914 60 Pokitto::Display pokdisp;
Pokitto 23:f88837b8f914 61
Pokitto 23:f88837b8f914 62 int openImageFileFromSD(char* filepath, uint16_t **palette_out, uint8_t **bitmap_out) {
Pokitto 23:f88837b8f914 63
Pokitto 23:f88837b8f914 64 // Reset the out pointers.
Pokitto 23:f88837b8f914 65 *palette_out = 0;
Pokitto 23:f88837b8f914 66 *bitmap_out = 0;
Pokitto 23:f88837b8f914 67
Pokitto 23:f88837b8f914 68 BITMAPFILEHEADER bf;
Pokitto 23:f88837b8f914 69 BITMAPINFO bmi;
Pokitto 23:f88837b8f914 70
Pokitto 23:f88837b8f914 71 uint32_t bytes_read=0, bmpsize=0;
Pokitto 23:f88837b8f914 72
Pokitto 23:f88837b8f914 73 /** numcol is the number of colors for output */
Pokitto 23:f88837b8f914 74 unsigned int numcol = 0;
Pokitto 23:f88837b8f914 75
Pokitto 23:f88837b8f914 76 if (POK_COLORDEPTH == 8) numcol=256;
Pokitto 23:f88837b8f914 77 else if (POK_COLORDEPTH == 4) numcol=16;
Pokitto 23:f88837b8f914 78 else if (POK_COLORDEPTH == 2) numcol=4;
Pokitto 23:f88837b8f914 79 else if (POK_COLORDEPTH == 1) numcol=1;
Pokitto 23:f88837b8f914 80
Pokitto 23:f88837b8f914 81 if (!isThisFileOpen(filepath)) {
Pokitto 23:f88837b8f914 82 fileClose(); // close any open files
Pokitto 23:f88837b8f914 83 fileOpen(filepath, FILE_MODE_READONLY | FILE_MODE_BINARY);
Pokitto 23:f88837b8f914 84 }
Pokitto 23:f88837b8f914 85 else
Pokitto 23:f88837b8f914 86 return -1; // Already open, not good.
Pokitto 23:f88837b8f914 87
Pokitto 23:f88837b8f914 88 if (fileOK() && fileReadBytes((uint8_t*)&bf, sizeof(bf)) == sizeof(bf) ) {
Pokitto 23:f88837b8f914 89 bytes_read += sizeof(bf);
Pokitto 23:f88837b8f914 90 }
Pokitto 23:f88837b8f914 91 else
Pokitto 23:f88837b8f914 92 {
Pokitto 23:f88837b8f914 93 POK_TRACE("Error reading BMP header\n");
Pokitto 23:f88837b8f914 94 fileClose();
Pokitto 23:f88837b8f914 95 return(-1);
Pokitto 23:f88837b8f914 96 }
Pokitto 23:f88837b8f914 97
Pokitto 23:f88837b8f914 98 if (fileReadBytes((uint8_t*)&bmi,sizeof(bmi.bmiHeader)) != sizeof(bmi.bmiHeader)) {
Pokitto 23:f88837b8f914 99 POK_TRACE("Error reading BMP info\n");
Pokitto 23:f88837b8f914 100 fileClose();
Pokitto 23:f88837b8f914 101 return(-1);
Pokitto 23:f88837b8f914 102 }
Pokitto 23:f88837b8f914 103 bytes_read += sizeof(bmi.bmiHeader);
Pokitto 23:f88837b8f914 104
Pokitto 23:f88837b8f914 105 /** Check image validity */
Pokitto 23:f88837b8f914 106
Pokitto 23:f88837b8f914 107 if (bf.bfType != 0x4D42) {
Pokitto 23:f88837b8f914 108 POK_TRACE("Bitmap file has an unrecognized format (4D42 id missing from beginning).\n");
Pokitto 23:f88837b8f914 109 POK_TRACE("BMP2POK accepts .BMP files that have an indexed (1,-bit, 4-bit or 8-bit) color palette.\n");
Pokitto 23:f88837b8f914 110 fileClose();
Pokitto 23:f88837b8f914 111 return(-1);
Pokitto 23:f88837b8f914 112 }
Pokitto 23:f88837b8f914 113 if (bmi.bmiHeader.biBitCount != POK_COLORDEPTH ) {
Pokitto 23:f88837b8f914 114 POK_TRACE("ERROR!\nThe image color depth should be the same as screen color depth!\n");
Pokitto 23:f88837b8f914 115 }
Pokitto 23:f88837b8f914 116 if (bmi.bmiHeader.biWidth%32 && bmi.bmiHeader.biBitCount == 1) {
Pokitto 23:f88837b8f914 117 POK_TRACE("ERROR!\nPadding of 1-bit (monochrome) images is not yet supported\n");
Pokitto 23:f88837b8f914 118 POK_TRACE("1-bit images need to have width that is divisible by 32!\n");
Pokitto 23:f88837b8f914 119 POK_TRACE("Adjust size of source image.\n");
Pokitto 23:f88837b8f914 120 fileClose();
Pokitto 23:f88837b8f914 121 return(-1);
Pokitto 23:f88837b8f914 122 }
Pokitto 23:f88837b8f914 123 if (bmi.bmiHeader.biWidth%4) {
Pokitto 23:f88837b8f914 124 POK_TRACE("Width is not divisible by 4\n");
Pokitto 23:f88837b8f914 125 fileClose();
Pokitto 23:f88837b8f914 126 return(-1);
Pokitto 23:f88837b8f914 127 }
Pokitto 23:f88837b8f914 128 if (bmi.bmiHeader.biWidth%8 && bmi.bmiHeader.biBitCount==4) {
Pokitto 23:f88837b8f914 129 if (bmi.bmiHeader.biWidth%4) {
Pokitto 23:f88837b8f914 130 POK_TRACE("ERROR!\n4-bit source images have to have a width that is divisible by 4\n");
Pokitto 23:f88837b8f914 131 fileClose();
Pokitto 23:f88837b8f914 132 return(-1);
Pokitto 23:f88837b8f914 133 }
Pokitto 23:f88837b8f914 134 }
Pokitto 23:f88837b8f914 135 if (bmi.bmiHeader.biBitCount != 8 && bmi.bmiHeader.biBitCount != 4 && bmi.bmiHeader.biBitCount != 1)
Pokitto 23:f88837b8f914 136 {
Pokitto 23:f88837b8f914 137 POK_TRACE("Only 8bpp, 4bpp & 1bpp BMP files are supported\n");
Pokitto 23:f88837b8f914 138 fileClose();
Pokitto 23:f88837b8f914 139 return(-1);
Pokitto 23:f88837b8f914 140 }
Pokitto 23:f88837b8f914 141 if (bmi.bmiHeader.biCompression != 0 &&
Pokitto 23:f88837b8f914 142 !(bmi.bmiHeader.biCompression == BI_RLE4 && bmi.bmiHeader.biBitCount == 4))
Pokitto 23:f88837b8f914 143 {
Pokitto 23:f88837b8f914 144 POK_TRACE("Only RLE compression for bitmaps with 4 bpp is supported\n");
Pokitto 23:f88837b8f914 145 fileClose();
Pokitto 23:f88837b8f914 146 return(-1);
Pokitto 23:f88837b8f914 147 }
Pokitto 23:f88837b8f914 148
Pokitto 23:f88837b8f914 149 /* If the height is negative the bmp image is in the correct way.
Pokitto 23:f88837b8f914 150 If the heigh is positive the bmp image is vertically mirrored
Pokitto 23:f88837b8f914 151 */
Pokitto 23:f88837b8f914 152 int biAbsHeight = bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 153 if (bmi.bmiHeader.biHeight < 0 )
Pokitto 23:f88837b8f914 154 biAbsHeight = - bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 155
Pokitto 23:f88837b8f914 156 /** Read and copy palette **/
Pokitto 23:f88837b8f914 157
Pokitto 23:f88837b8f914 158 int c = bmi.bmiHeader.biClrUsed;
Pokitto 23:f88837b8f914 159 if (c==0) c = 1 << bmi.bmiHeader.biBitCount; // from MS BMP specs. 0 means 2^n colors
Pokitto 23:f88837b8f914 160 bmi.bmiHeader.biClrUsed = c;
Pokitto 23:f88837b8f914 161
Pokitto 23:f88837b8f914 162 /* Allocate memory for the output parameter */
Pokitto 23:f88837b8f914 163 if (numcol>bmi.bmiHeader.biClrUsed) numcol = bmi.bmiHeader.biClrUsed;
Pokitto 23:f88837b8f914 164 *palette_out = (uint16_t*) malloc(numcol*2);
Pokitto 23:f88837b8f914 165 if (*palette_out == NULL)
Pokitto 23:f88837b8f914 166 {
Pokitto 23:f88837b8f914 167 POK_TRACE("Error allocating temporary palette buffer.\n");
Pokitto 23:f88837b8f914 168 free(*palette_out);
Pokitto 23:f88837b8f914 169 return(-1);
Pokitto 23:f88837b8f914 170 }
Pokitto 23:f88837b8f914 171
Pokitto 23:f88837b8f914 172 /* seek to the beginning of the color table - because of gimp */
Pokitto 23:f88837b8f914 173 fileSeekAbsolute(bf.bfOffBits-c*4); //gfx data star minus color table
Pokitto 23:f88837b8f914 174
Pokitto 23:f88837b8f914 175 for (unsigned int c=0;c<numcol;c++) {
Pokitto 23:f88837b8f914 176
Pokitto 23:f88837b8f914 177 RGBQUAD rgbValue;
Pokitto 23:f88837b8f914 178 fileReadBytes((uint8_t*)&rgbValue, sizeof(RGBQUAD));
Pokitto 23:f88837b8f914 179 bytes_read += sizeof(RGBQUAD);
Pokitto 23:f88837b8f914 180
Pokitto 23:f88837b8f914 181 unsigned int r,g,b,o;
Pokitto 23:f88837b8f914 182 r = rgbValue.rgbRed >> 3; // 5 bit
Pokitto 23:f88837b8f914 183 g = rgbValue.rgbGreen >> 2; // 6 bits
Pokitto 23:f88837b8f914 184 b = rgbValue.rgbBlue >> 3; // 5 bits
Pokitto 23:f88837b8f914 185 o = (r<<11)|(g<<5)|b;
Pokitto 23:f88837b8f914 186
Pokitto 23:f88837b8f914 187 (*palette_out)[c] = o;
Pokitto 23:f88837b8f914 188 }
Pokitto 23:f88837b8f914 189
Pokitto 23:f88837b8f914 190 /** Read and copy image data **/
Pokitto 23:f88837b8f914 191
Pokitto 23:f88837b8f914 192 /* Get image data size. If the biSizeImage is given (>0) for RLE image, use that to reduce memory usage. */
Pokitto 23:f88837b8f914 193 bmpsize = bmi.bmiHeader.biWidth * biAbsHeight*bmi.bmiHeader.biBitCount/8;
Pokitto 23:f88837b8f914 194 if (bmi.bmiHeader.biCompression == BI_RLE4)
Pokitto 23:f88837b8f914 195 bmpsize = (bmi.bmiHeader.biSizeImage > 0) ? bmi.bmiHeader.biSizeImage : bmpsize;
Pokitto 23:f88837b8f914 196
Pokitto 23:f88837b8f914 197 // SEEK to the beginning of the data
Pokitto 23:f88837b8f914 198 fileSeekAbsolute(bf.bfOffBits);
Pokitto 23:f88837b8f914 199
Pokitto 23:f88837b8f914 200 /* Allocate output data buffer */
Pokitto 23:f88837b8f914 201 *bitmap_out = (uint8_t *) malloc(bmpsize + 2); // header takes 2 bytes
Pokitto 23:f88837b8f914 202 if (*bitmap_out == NULL)
Pokitto 23:f88837b8f914 203 {
Pokitto 23:f88837b8f914 204 POK_TRACE("Error allocating temporary data buffer, is image too big?\n");
Pokitto 23:f88837b8f914 205 free(*palette_out);
Pokitto 23:f88837b8f914 206 return(-1);
Pokitto 23:f88837b8f914 207 }
Pokitto 23:f88837b8f914 208
Pokitto 23:f88837b8f914 209 /* Store image size to the pokitto bitmap header */
Pokitto 23:f88837b8f914 210 uint32_t outindex = 0;
Pokitto 23:f88837b8f914 211 (*bitmap_out)[outindex++] = bmi.bmiHeader.biWidth;
Pokitto 23:f88837b8f914 212 (*bitmap_out)[outindex++] = biAbsHeight;
Pokitto 23:f88837b8f914 213
Pokitto 23:f88837b8f914 214 if (bmi.bmiHeader.biCompression == BI_RLE4) {
Pokitto 23:f88837b8f914 215 bool eofReached = false;
Pokitto 23:f88837b8f914 216 while (outindex < bmpsize && !eofReached ) {
Pokitto 23:f88837b8f914 217 /* Read byte from the file. */
Pokitto 23:f88837b8f914 218 unsigned char rleByte;
Pokitto 23:f88837b8f914 219 if (fileReadBytes(&rleByte, sizeof(rleByte)) != sizeof(rleByte))
Pokitto 23:f88837b8f914 220 {
Pokitto 23:f88837b8f914 221 /* End of file reached. Allocate a new bitmap which is of the exact size of the data */
Pokitto 23:f88837b8f914 222 eofReached = true;
Pokitto 23:f88837b8f914 223
Pokitto 23:f88837b8f914 224 /* Allocate output data buffer */
Pokitto 23:f88837b8f914 225 uint8_t* old_bitmap = *bitmap_out;
Pokitto 23:f88837b8f914 226 *bitmap_out = NULL;
Pokitto 23:f88837b8f914 227 *bitmap_out = (uint8_t *) malloc(outindex); // header takes 2 bytes
Pokitto 23:f88837b8f914 228 if (*bitmap_out == NULL)
Pokitto 23:f88837b8f914 229 {
Pokitto 23:f88837b8f914 230 POK_TRACE("Error allocating temporary data buffer, is image too big?\n");
Pokitto 23:f88837b8f914 231 free(old_bitmap);
Pokitto 23:f88837b8f914 232 free(*palette_out);
Pokitto 23:f88837b8f914 233 return(-1);
Pokitto 23:f88837b8f914 234 }
Pokitto 23:f88837b8f914 235
Pokitto 23:f88837b8f914 236 /* Copy data */
Pokitto 23:f88837b8f914 237 for (int i=0; i<outindex;i++)
Pokitto 23:f88837b8f914 238 (*bitmap_out)[i] = old_bitmap[i];
Pokitto 23:f88837b8f914 239
Pokitto 23:f88837b8f914 240 /* Free original bitmap */
Pokitto 23:f88837b8f914 241 free(old_bitmap);
Pokitto 23:f88837b8f914 242 }
Pokitto 23:f88837b8f914 243 else {
Pokitto 23:f88837b8f914 244 /* Store byte */
Pokitto 23:f88837b8f914 245 (*bitmap_out)[outindex++] = rleByte;
Pokitto 23:f88837b8f914 246 }
Pokitto 23:f88837b8f914 247 } // end while
Pokitto 23:f88837b8f914 248 }
Pokitto 23:f88837b8f914 249 else {
Pokitto 23:f88837b8f914 250 /* Do vertical mirroring only for uncompressed data.
Pokitto 23:f88837b8f914 251 Note the compressed RLE data above could not be mirrored.
Pokitto 23:f88837b8f914 252 */
Pokitto 23:f88837b8f914 253 int widthInBytes = bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount/8;
Pokitto 23:f88837b8f914 254 int widthInBytesInc, incY, startY, endY;
Pokitto 23:f88837b8f914 255 if (bmi.bmiHeader.biHeight > 0 ) {
Pokitto 23:f88837b8f914 256 /* Mirror vertically */
Pokitto 23:f88837b8f914 257 widthInBytesInc = - widthInBytes;
Pokitto 23:f88837b8f914 258 incY = -1;
Pokitto 23:f88837b8f914 259 startY = biAbsHeight - 1;
Pokitto 23:f88837b8f914 260 endY = -1;
Pokitto 23:f88837b8f914 261 }
Pokitto 23:f88837b8f914 262 else {
Pokitto 23:f88837b8f914 263 /* Do not mirror */
Pokitto 23:f88837b8f914 264 widthInBytesInc = widthInBytes;
Pokitto 23:f88837b8f914 265 incY = 1;
Pokitto 23:f88837b8f914 266 startY = 0;
Pokitto 23:f88837b8f914 267 endY = biAbsHeight;
Pokitto 23:f88837b8f914 268 }
Pokitto 23:f88837b8f914 269
Pokitto 23:f88837b8f914 270 /* Copy all bytes to the output bitmap */
Pokitto 23:f88837b8f914 271 for ( int y = startY, beginLine=startY*widthInBytes; y != endY; y += incY, beginLine += widthInBytesInc) {
Pokitto 23:f88837b8f914 272
Pokitto 23:f88837b8f914 273 /* Go to the beginning of the previous or next line */
Pokitto 23:f88837b8f914 274 outindex = beginLine;
Pokitto 23:f88837b8f914 275
Pokitto 23:f88837b8f914 276 for ( int xbyte = 0; xbyte < widthInBytes; xbyte++) {
Pokitto 23:f88837b8f914 277
Pokitto 23:f88837b8f914 278 /* Read byte from the file. */
Pokitto 23:f88837b8f914 279 unsigned char byteOfPixels;
Pokitto 23:f88837b8f914 280 if (fileReadBytes(&byteOfPixels, sizeof(byteOfPixels)) != sizeof(byteOfPixels))
Pokitto 23:f88837b8f914 281 {
Pokitto 23:f88837b8f914 282 POK_TRACE("Error reading BMP data\n");
Pokitto 23:f88837b8f914 283 fileClose();
Pokitto 23:f88837b8f914 284 free(*bitmap_out);
Pokitto 23:f88837b8f914 285 free(*palette_out);
Pokitto 23:f88837b8f914 286 return(-1);
Pokitto 23:f88837b8f914 287 }
Pokitto 23:f88837b8f914 288
Pokitto 23:f88837b8f914 289 /* Copy a byte from the file to the bitmap */
Pokitto 23:f88837b8f914 290 (*bitmap_out)[2 + outindex] = byteOfPixels;
Pokitto 23:f88837b8f914 291 outindex++;
Pokitto 23:f88837b8f914 292 } // end for
Pokitto 23:f88837b8f914 293 } // end for
Pokitto 23:f88837b8f914 294 } // end if
Pokitto 23:f88837b8f914 295
Pokitto 23:f88837b8f914 296 // Done with the file reading.
Pokitto 23:f88837b8f914 297 fileClose();
Pokitto 23:f88837b8f914 298
Pokitto 23:f88837b8f914 299 return 0;
Pokitto 23:f88837b8f914 300 }
Pokitto 23:f88837b8f914 301
Pokitto 23:f88837b8f914 302 int directDrawImageFileFromSD(int16_t sx, int16_t sy, char* filepath) {
Pokitto 23:f88837b8f914 303
Pokitto 23:f88837b8f914 304 return(directDrawImageFileFromSD(0, 0, 0/* full width */, 0/* full height */, sx, sy, filepath));
Pokitto 23:f88837b8f914 305 }
Pokitto 23:f88837b8f914 306
Pokitto 23:f88837b8f914 307 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 308
Pokitto 23:f88837b8f914 309 BITMAPFILEHEADER bf;
Pokitto 23:f88837b8f914 310 BITMAPINFO bmi;
Pokitto 23:f88837b8f914 311
Pokitto 23:f88837b8f914 312 uint32_t bytes_read=0;
Pokitto 23:f88837b8f914 313
Pokitto 23:f88837b8f914 314 if (!isThisFileOpen(filepath)) {
Pokitto 23:f88837b8f914 315 fileClose(); // close any open files
Pokitto 23:f88837b8f914 316 fileOpen(filepath, FILE_MODE_READONLY | FILE_MODE_BINARY);
Pokitto 23:f88837b8f914 317 }
Pokitto 23:f88837b8f914 318 else {
Pokitto 23:f88837b8f914 319 POK_TRACE("Error! Already open\n");
Pokitto 23:f88837b8f914 320 return -1; // Already open, not good.
Pokitto 23:f88837b8f914 321 }
Pokitto 23:f88837b8f914 322
Pokitto 23:f88837b8f914 323 if (fileOK() && fileReadBytes((uint8_t*)&bf, sizeof(bf)) == sizeof(bf) ) { //!HV why we have to check fileOK()?
Pokitto 23:f88837b8f914 324 bytes_read += sizeof(bf);
Pokitto 23:f88837b8f914 325 }
Pokitto 23:f88837b8f914 326 else
Pokitto 23:f88837b8f914 327 {
Pokitto 23:f88837b8f914 328 POK_TRACE("Error reading BMP header\n");
Pokitto 23:f88837b8f914 329 fileClose();
Pokitto 23:f88837b8f914 330 return(-1);
Pokitto 23:f88837b8f914 331 }
Pokitto 23:f88837b8f914 332
Pokitto 23:f88837b8f914 333 if (fileReadBytes((uint8_t*)&bmi,sizeof(bmi.bmiHeader)) != sizeof(bmi.bmiHeader)) {
Pokitto 23:f88837b8f914 334 POK_TRACE("Error reading BMP info\n");
Pokitto 23:f88837b8f914 335 fileClose();
Pokitto 23:f88837b8f914 336 return(-1);
Pokitto 23:f88837b8f914 337 }
Pokitto 23:f88837b8f914 338 bytes_read += sizeof(bmi.bmiHeader);
Pokitto 23:f88837b8f914 339
Pokitto 23:f88837b8f914 340 /** Check image validity */
Pokitto 23:f88837b8f914 341
Pokitto 23:f88837b8f914 342 if (bf.bfType != 0x4D42) {
Pokitto 23:f88837b8f914 343 POK_TRACE("Bitmap file has an unrecognized format (4D42 id missing from beginning).\n");
Pokitto 23:f88837b8f914 344 POK_TRACE("BMP2POK accepts .BMP files that have an indexed (1,-bit, 4-bit or 8-bit) color palette.\n");
Pokitto 23:f88837b8f914 345 fileClose();
Pokitto 23:f88837b8f914 346 return(-1);
Pokitto 23:f88837b8f914 347 }
Pokitto 23:f88837b8f914 348 if (bmi.bmiHeader.biBitCount != 24 ) {
Pokitto 23:f88837b8f914 349 POK_TRACE("ERROR!\nThe image color depth should be the same as screen color depth (%d)!\n");
Pokitto 23:f88837b8f914 350 fileClose();
Pokitto 23:f88837b8f914 351 return(-1);
Pokitto 23:f88837b8f914 352 }
Pokitto 23:f88837b8f914 353 if (bmi.bmiHeader.biCompression != 0 )
Pokitto 23:f88837b8f914 354 {
Pokitto 23:f88837b8f914 355 POK_TRACE("Compression is not supported.\n");
Pokitto 23:f88837b8f914 356 fileClose();
Pokitto 23:f88837b8f914 357 return(-1);
Pokitto 23:f88837b8f914 358 }
Pokitto 23:f88837b8f914 359
Pokitto 23:f88837b8f914 360 /* If the height is negative the bmp image is in the correct way.
Pokitto 23:f88837b8f914 361 If the heigh is positive the bmp image is vertically mirrored
Pokitto 23:f88837b8f914 362 */
Pokitto 23:f88837b8f914 363 int biAbsHeight = bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 364 if (bmi.bmiHeader.biHeight < 0 )
Pokitto 23:f88837b8f914 365 biAbsHeight = - bmi.bmiHeader.biHeight;
Pokitto 23:f88837b8f914 366
Pokitto 23:f88837b8f914 367 /** Zero size parameter means full image size */
Pokitto 23:f88837b8f914 368 if(iw==0) iw = bmi.bmiHeader.biWidth; // 0 means full image width
Pokitto 23:f88837b8f914 369 if(ih==0) ih = biAbsHeight; // 0 means full image width
Pokitto 23:f88837b8f914 370
Pokitto 23:f88837b8f914 371 /** Check parameters */
Pokitto 23:f88837b8f914 372 if( ix + iw > bmi.bmiHeader.biWidth ) {
Pokitto 23:f88837b8f914 373 POK_TRACE("Error! Invalid parameter\n");
Pokitto 23:f88837b8f914 374 fileClose();
Pokitto 23:f88837b8f914 375 return(-1);
Pokitto 23:f88837b8f914 376 }
Pokitto 23:f88837b8f914 377 if( iy + ih > biAbsHeight ) {
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( sx > pokdisp.getWidth()-1 || sx<-iw) {
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( sy > pokdisp.getHeight()-1 || sy<-ih) {
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
Pokitto 23:f88837b8f914 393 /** Zero size parameter means full image size */
Pokitto 23:f88837b8f914 394 if(iw==0) iw = bmi.bmiHeader.biWidth; // 0 means full image width
Pokitto 23:f88837b8f914 395 if(ih==0) ih = biAbsHeight; // 0 means full image width
Pokitto 23:f88837b8f914 396
Pokitto 23:f88837b8f914 397 /** Clip image to screen dimensions */
Pokitto 23:f88837b8f914 398
Pokitto 23:f88837b8f914 399 int16_t clipX1OnScreen = max( 0, sx);
Pokitto 23:f88837b8f914 400 int16_t clipX2OnScreen = min( pokdisp.getWidth()-1, sx+iw-1);
Pokitto 23:f88837b8f914 401 int16_t clipWidthOnScreen = clipX2OnScreen-clipX1OnScreen+1;
Pokitto 23:f88837b8f914 402 int16_t clipY1OnScreen = max( 0, sy);
Pokitto 23:f88837b8f914 403 int16_t clipY2OnScreen = min( pokdisp.getHeight()-1, sy+ih-1);
Pokitto 23:f88837b8f914 404 int16_t clipHeightOnScreen = clipY2OnScreen-clipY1OnScreen+1;
Pokitto 23:f88837b8f914 405
Pokitto 23:f88837b8f914 406 uint16_t skipImagePixelsAtLineStart = ix+(clipX1OnScreen-sx);
Pokitto 23:f88837b8f914 407 uint16_t skipImagePixelsAtLineStartAsBytes = skipImagePixelsAtLineStart*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 408 uint16_t skipImagePixelsAtLineEndAsBytes = (bmi.bmiHeader.biWidth-(skipImagePixelsAtLineStart+clipWidthOnScreen))*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 409
Pokitto 23:f88837b8f914 410 uint16_t skipImageRowsAtImageStart = iy+(clipY1OnScreen-sy);
Pokitto 23:f88837b8f914 411 uint16_t skipImageRowsAtImageEnd = biAbsHeight-(skipImageRowsAtImageStart+clipHeightOnScreen);
Pokitto 23:f88837b8f914 412
Pokitto 23:f88837b8f914 413 /* Vertical loop parameters */
Pokitto 23:f88837b8f914 414 int incY, startY, pastEndY;
Pokitto 23:f88837b8f914 415 uint32_t skipImageRowsAsBytes = 0;
Pokitto 23:f88837b8f914 416 if (bmi.bmiHeader.biHeight > 0 ) {
Pokitto 23:f88837b8f914 417 /* Mirror vertically */
Pokitto 23:f88837b8f914 418 incY = -1;
Pokitto 23:f88837b8f914 419 startY = clipY2OnScreen;
Pokitto 23:f88837b8f914 420 pastEndY = clipY1OnScreen-1;
Pokitto 23:f88837b8f914 421 skipImageRowsAsBytes = skipImageRowsAtImageEnd*bmi.bmiHeader.biWidth*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 422 }
Pokitto 23:f88837b8f914 423 else {
Pokitto 23:f88837b8f914 424 /* Do not mirror */
Pokitto 23:f88837b8f914 425 incY = 1;
Pokitto 23:f88837b8f914 426 startY = clipY1OnScreen ;
Pokitto 23:f88837b8f914 427 pastEndY = clipY2OnScreen+1;
Pokitto 23:f88837b8f914 428 skipImageRowsAsBytes = skipImageRowsAtImageStart*bmi.bmiHeader.biWidth*3; // 3 bytes per pixel
Pokitto 23:f88837b8f914 429 }
Pokitto 23:f88837b8f914 430
Pokitto 23:f88837b8f914 431 /** Read and copy image data directly to the screen **/
Pokitto 23:f88837b8f914 432
Pokitto 23:f88837b8f914 433 /* Seek to the beginning of the data */
Pokitto 23:f88837b8f914 434 fileSeekAbsolute(bf.bfOffBits);
Pokitto 23:f88837b8f914 435
Pokitto 23:f88837b8f914 436 /* Seek until the image rect starts */
Pokitto 23:f88837b8f914 437 if (skipImageRowsAsBytes>0) fileSeekRelative( skipImageRowsAsBytes );
Pokitto 23:f88837b8f914 438
Pokitto 23:f88837b8f914 439 /* Copy all bytes to the output bitmap */
Pokitto 23:f88837b8f914 440 for ( int y = startY; y != pastEndY; y += incY) {
Pokitto 23:f88837b8f914 441
Pokitto 23:f88837b8f914 442 /* Seek until the image rect starts */
Pokitto 23:f88837b8f914 443 if (skipImagePixelsAtLineStartAsBytes>0) fileSeekRelative( skipImagePixelsAtLineStartAsBytes );
Pokitto 23:f88837b8f914 444
Pokitto 23:f88837b8f914 445 for ( int x = clipX1OnScreen; x <= clipX2OnScreen; x++) {
Pokitto 23:f88837b8f914 446
Pokitto 23:f88837b8f914 447 /* Read RGB pixel from the file. For 24 bpp the pixel is stored to 3 bytes*/
Pokitto 23:f88837b8f914 448 uint32_t rgb24;
Pokitto 23:f88837b8f914 449 if (fileReadBytes((uint8_t*)&rgb24, 3) != 3)
Pokitto 23:f88837b8f914 450 {
Pokitto 23:f88837b8f914 451 POK_TRACE("Error reading BMP data\n");
Pokitto 23:f88837b8f914 452 fileClose();
Pokitto 23:f88837b8f914 453 return(-1);
Pokitto 23:f88837b8f914 454 }
Pokitto 23:f88837b8f914 455
Pokitto 23:f88837b8f914 456 /* Copy a pixel from the file directly to the screen */
Pokitto 23:f88837b8f914 457 // uint8_t r,g,b;
Pokitto 23:f88837b8f914 458 // r = (xrgb >> (3 + 16)) & 0x1f; // 5 bit
Pokitto 23:f88837b8f914 459 // g = (xrgb >> (2 + 8)) & 0x3f; // 6 bits
Pokitto 23:f88837b8f914 460 // b = (xrgb >> 3) & 0x1f; // 5 bits
Pokitto 23:f88837b8f914 461 // uint16_t targetpixel = (r<<11) | (g<<5) | b;
Pokitto 23:f88837b8f914 462
Pokitto 23:f88837b8f914 463 uint16_t targetpixel =
Pokitto 23:f88837b8f914 464 ((rgb24 >> 8) & 0x0000F800) | // red (bits 15-11)
Pokitto 23:f88837b8f914 465 ((rgb24 >> 5) & 0x000007E0) | // green (bits 10-5)
Pokitto 23:f88837b8f914 466 ((rgb24 >> 3) & 0x0000001F); // blue (bits 4-0)
Pokitto 23:f88837b8f914 467 _game.display.directPixel(x, y, targetpixel);
Pokitto 23:f88837b8f914 468 } // end for
Pokitto 23:f88837b8f914 469
Pokitto 23:f88837b8f914 470 /* Skip pixels at line end */
Pokitto 23:f88837b8f914 471 if (skipImagePixelsAtLineEndAsBytes>0) fileSeekRelative( skipImagePixelsAtLineEndAsBytes );
Pokitto 23:f88837b8f914 472
Pokitto 23:f88837b8f914 473 } // end for
Pokitto 23:f88837b8f914 474
Pokitto 23:f88837b8f914 475 // Done with the file reading.
Pokitto 23:f88837b8f914 476 fileClose();
Pokitto 23:f88837b8f914 477
Pokitto 23:f88837b8f914 478 return 0;
Pokitto 23:f88837b8f914 479 }
Pokitto 23:f88837b8f914 480
Pokitto 23:f88837b8f914 481 #endif
Pokitto 23:f88837b8f914 482