lsnes rr2-β24
[lsnes.git] / src / lua / loadbitmap.cpp
blob70a41f6f23c23830d117b40c350200668eb9636d
1 #include "lua/bitmap.hpp"
2 #include "library/zip.hpp"
3 #include <limits>
5 namespace
7 inline uint64_t tocolor(unsigned r, unsigned g, unsigned b, unsigned a)
9 if(!a)
10 return -1;
11 else
12 return (static_cast<int64_t>(256 - a) << 24) | (static_cast<int64_t>(r) << 16) |
13 (static_cast<int64_t>(g) << 8) | static_cast<int64_t>(b);
17 struct lua_loaded_bitmap lua_loaded_bitmap::load(std::istream& file)
19 struct lua_loaded_bitmap b;
20 std::string magic;
21 unsigned pcolors;
22 unsigned R;
23 unsigned G;
24 unsigned B;
25 unsigned A;
26 file >> magic;
27 if(magic != "LSNES-BITMAP")
28 throw std::runtime_error("Bitmap load: Wrong magic");
29 file >> b.w;
30 file >> b.h;
31 if(b.h >= std::numeric_limits<size_t>::max() / b.w)
32 throw std::runtime_error("Bitmap load: Bitmap too large");
33 b.bitmap.resize(b.w * b.h);
34 file >> pcolors;
35 if(pcolors > 65536)
36 throw std::runtime_error("Bitmap load: Palette too big");
37 if(pcolors > 0) {
38 //Paletted.
39 b.d = false;
40 b.palette.resize(pcolors);
41 for(size_t i = 0; i < pcolors; i++) {
42 file >> R;
43 file >> G;
44 file >> B;
45 file >> A;
46 if(R > 255 || G > 255 || B > 255 || A > 256) //Yes, a can be 256.
47 throw std::runtime_error("Bitmap load: Palette entry out of range");
48 b.palette[i] = tocolor(R, G, B, A);
50 for(size_t i = 0; i < b.w * b.h; i++) {
51 file >> R;
52 if(R >= pcolors)
53 throw std::runtime_error("Bitmap load: color index out of range");
54 b.bitmap[i] = R;
56 } else {
57 //Direct.
58 b.d = true;
59 for(size_t i = 0; i < b.w * b.h; i++) {
60 file >> R;
61 file >> G;
62 file >> B;
63 file >> A;
64 if(R > 255 || G > 255 || B > 255 || A > 256) //Yes, a can be 256.
65 throw std::runtime_error("Bitmap load: Color out of range");
66 b.bitmap[i] = tocolor(R, G, B, A);
69 if(!file)
70 throw std::runtime_error("Bitmap load: Error reading bitmap");
71 return b;
74 struct lua_loaded_bitmap lua_loaded_bitmap::load(const std::string& name)
76 struct lua_loaded_bitmap b;
77 std::istream& file = zip::openrel(name, "");
78 try {
79 b = lua_loaded_bitmap::load(file);
80 delete &file;
81 return b;
82 } catch(...) {
83 delete &file;
84 throw;