WordleDS/source/image.cpp
Pk11 37f3516804
Online word synchronization (#21)
* WIP get words from internet

Using a (to be created) mirror since I don't want to bloat this up with HTTPS and the official API is HTTPS only
Untested so far

* wifi.hpp

* Remove unused includes

* Derp fix

* Derp fix part 2

* Fix errors

* Try fix build error

* Allow loading JSON directly

* Update share URL

* Restore word list order, add known guess order

* Use the word order

* Wi-Fi fixes

* Use IDs from internet and save to mod.json

* Simplify image drawing

* WIP Improve graphics – move popup to layer, main menu icons to sprites

Allows the popup to be used in other places like settings, will allow easily only showing the update sprite if using an online mod

* Further simplify image drawing, bug fix

* Load main menu button graphics/sprites

positions TODO

* Fix palettes

* Add update button, fix some bugs

* Fix updating words

* Only allow infinite when word order outdated

* Minor cleanup

* Remove unused include

* Add Python script to update mod.json

* Fix backwards compatibility with old mods

Note that the old bgBottomBox is simply unused, the new popupBox will simply be used instead
2023-03-02 19:32:58 -06:00

88 lines
2.3 KiB
C++

#include "image.hpp"
#include "tonccpy.h"
#include <nds/arm9/sassert.h>
#include <nds/arm9/background.h>
#include <nds/arm9/decompress.h>
// sassert but it fixes the brightness
#undef sassert
#define sassert(e,...) ((e) ? (void)0 : (setBrightness(2, 0), __sassert(__FILE__, __LINE__, #e, __VA_ARGS__)))
#define CHUNK_ID(a, b, c, d) ((u32)((a) | (b) << 8 | (c) << 16 | (d) << 24))
bool Image::grfDecompress(const void *src, void *dst, bool vram) {
if(src == nullptr || dst == nullptr)
return false;
u32 header = *(u32*)src;
uint size = header >> 8;
switch(header & 0xF0) {
case 0x00: // No compression
tonccpy(dst, (u8*)src + 4, size);
return true;
case 0x10: // LZ77
decompress(src, dst, vram ? LZ77Vram : LZ77);
return true;
case 0x20: // Huffman
decompress(src, dst, HUFF);
return true;
case 0x30: // RLE
decompress(src, dst, vram ? RLEVram : RLE);
return true;
default:
return false;
}
}
Image::Image(const char *path, u32 width, u32 height, const u8 *fallback, bool enforceSize) {
FILE *file = fopen(path, "rb");
if(file) {
fread(&_header, 1, sizeof(GrfHeader), file);
_buffer = std::shared_ptr<u8[]>(new u8[_header.fileSize - sizeof(GrfHeader) + 8]);
fread(_buffer.get(), 1, _header.fileSize - sizeof(GrfHeader) + 8, file);
fclose(file);
} else {
tonccpy(&_header, fallback, sizeof(GrfHeader));
}
if(enforceSize) {
sassert(_header.texWidth == width, "Invalid image width\n(%ld, should be %ld)\n\n%s", _header.texWidth, width, path);
sassert(_header.texHeight == height, "Invalid image height\n(%ld, should be %ld)\n\n%s", _header.texHeight, height, path);
}
const u8 *src = _buffer != nullptr ? _buffer.get() : (fallback + sizeof(GrfHeader));
for(u32 i = 0, size = 0; i < _header.fileSize - 4; i += size + 8) {
switch(*(u32 *)src) {
case CHUNK_ID('G','F','X',' '):
_tiles = src + 8;
break;
case CHUNK_ID('M', 'A','P',' '):
_map = (u16 *)(src + 8);
break;
case CHUNK_ID('P','A','L',' '):
_pal = (u16 *)(src + 8);
break;
default:
break;
}
size = ((u32 *)src)[1];
src += size + 8;
}
}
const Image &Image::decompressAll(int bg, void *palDst) const {
decompressTiles(bgGetGfxPtr(bg));
decompressMap(bgGetMapPtr(bg));
decompressPal(palDst != nullptr ? palDst : (bg < 4 ? BG_PALETTE : BG_PALETTE_SUB));
return *this;
};