mirror of
https://github.com/DarkStore-3DS/Universal-Core.git
synced 2026-07-06 08:49:06 +00:00
Add spritesheet and change image format
This commit is contained in:
+2
-2
@@ -60,8 +60,8 @@ private:
|
|||||||
static u8 textBuf[2][256 * 192];
|
static u8 textBuf[2][256 * 192];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u8 tileWidth, tileHeight;
|
u8 tileWidth = 0, tileHeight = 0;
|
||||||
u16 tileSize;
|
u16 tileSize = 0;
|
||||||
u16 questionMark = 0;
|
u16 questionMark = 0;
|
||||||
std::vector<u8> fontTiles;
|
std::vector<u8> fontTiles;
|
||||||
std::vector<u8> fontWidths;
|
std::vector<u8> fontWidths;
|
||||||
|
|||||||
+8
-8
@@ -28,9 +28,9 @@
|
|||||||
#define _UNIVERSAL_CORE_GUI_HPP
|
#define _UNIVERSAL_CORE_GUI_HPP
|
||||||
|
|
||||||
#include "font.hpp"
|
#include "font.hpp"
|
||||||
#include "image.hpp"
|
|
||||||
#include "screen.hpp"
|
#include "screen.hpp"
|
||||||
#include "sprite.hpp"
|
#include "sprite.hpp"
|
||||||
|
#include "spritesheet.hpp"
|
||||||
|
|
||||||
#include <nds/ndstypes.h>
|
#include <nds/ndstypes.h>
|
||||||
|
|
||||||
@@ -66,23 +66,23 @@ namespace Gui {
|
|||||||
void clearScreen(bool top);
|
void clearScreen(bool top);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Load an image (TODO: spritesheets?).
|
Load an a spritesheet
|
||||||
|
|
||||||
Path: Path to the image file. (GFX)
|
Path: Path to the spritesheet file. (TDX)
|
||||||
sheet: Reference to the Image declaration.
|
sheet: Reference to the Spritesheet declaration.
|
||||||
*/
|
*/
|
||||||
bool loadSheet(const char *Path, Image &image);
|
bool loadSheet(const char *Path, Spritesheet &image);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Draw an image.
|
Draw an image.
|
||||||
image: The image which should be used.
|
image: The spritesheet which should be used.
|
||||||
imgIndex: For compatibility with 3DS, unused.
|
imgIndex: Index within the spritesheet.
|
||||||
x: The X Position where the sprite should be drawn.
|
x: The X Position where the sprite should be drawn.
|
||||||
y: The Y Position where the sprite should be drawn.
|
y: The Y Position where the sprite should be drawn.
|
||||||
ScaleX: The X-Scale for the sprite. (Optional!)
|
ScaleX: The X-Scale for the sprite. (Optional!)
|
||||||
ScaleY: The Y-Scale for the sprite. (Optional!)
|
ScaleY: The Y-Scale for the sprite. (Optional!)
|
||||||
*/
|
*/
|
||||||
void DrawSprite(Image image, size_t imgindex, int x, int y, float ScaleX = 1.0f, float ScaleY = 1.0f);
|
void DrawSprite(Spritesheet &sheet, size_t imgindex, int x, int y, float ScaleX = 1.0f, float ScaleY = 1.0f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialize the GUI.
|
Initialize the GUI.
|
||||||
|
|||||||
+28
-36
@@ -33,46 +33,52 @@
|
|||||||
|
|
||||||
class Image {
|
class Image {
|
||||||
private:
|
private:
|
||||||
u16 _width;
|
u32 _width = 0;
|
||||||
u16 _height;
|
u32 _height = 0;
|
||||||
std::vector<u8> _bitmap;
|
u8 _paletteStart = 0;
|
||||||
std::vector<u16> _palette;
|
std::vector<u8> _bitmap = {};
|
||||||
u16 _palOfs;
|
std::vector<u16> _palette = {};
|
||||||
|
|
||||||
|
static void decompressGrf(void *dst, const void *src);
|
||||||
|
|
||||||
|
void load(const u8 *grf, u8 paletteStart);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Image drawing class
|
* @brief Image drawing class
|
||||||
* @param paths The paths to try load the image from, from highest to lowest priority
|
* @param paths The paths to try load the image from, from highest to lowest priority
|
||||||
|
* @param paletteStart Where to start the palette in VRAM
|
||||||
*/
|
*/
|
||||||
Image(const std::vector<std::string> &paths);
|
Image(const std::vector<std::string> &paths, u8 paletteStart);
|
||||||
/**
|
/**
|
||||||
* @brief Text printing class
|
* @brief Image drawing class
|
||||||
* @param path The path to load the image from
|
* @param path The path to load the image from
|
||||||
|
* @param paletteStart Where to start the palette in VRAM
|
||||||
*/
|
*/
|
||||||
Image(const std::string &path) : Image(std::vector<std::string>({path})) {};
|
Image(const std::string &path, u8 paletteStart) : Image(std::vector<std::string>({path}), paletteStart) {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Image drawing class
|
* @brief Image drawing class
|
||||||
* @param file The file to load the image from, seeked to the '.GFX' magic
|
* @param grf Pointer to a GRF in memory
|
||||||
|
* @param paletteStart Where to start the palette in VRAM
|
||||||
*/
|
*/
|
||||||
Image(FILE *file);
|
Image(const u8 *grf, u8 paletteStart);
|
||||||
|
|
||||||
Image() {};
|
|
||||||
~Image(void) {};
|
~Image(void) {};
|
||||||
|
|
||||||
u16 width(void) const { return _width; }
|
u16 width(void) const { return _width; }
|
||||||
u16 height(void) const { return _height; }
|
u16 height(void) const { return _height; }
|
||||||
|
u8 paletteStart(void) const { return _paletteStart; }
|
||||||
std::vector<u8> bitmap(void) const { return _bitmap; }
|
std::vector<u8> bitmap(void) const { return _bitmap; }
|
||||||
std::vector<u16> palette(void) const { return _palette; }
|
std::vector<u16> palette(void) const { return _palette; }
|
||||||
u16 palOfs(void) const { return _palOfs; }
|
|
||||||
|
void changePaletteStart(u8 paletteStart);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draws the image to a background layer, faster but without alpha, scaling, or palette offsetting
|
* @brief Copies the palette into VRAM
|
||||||
* @param x The X position to draw at
|
* @param paletteStart Where to start the palette in VRAM
|
||||||
* @param y The Y position to draw at
|
|
||||||
* @param copyPal (Optional) Whether to copy the image's palette into palette VRAM
|
|
||||||
*/
|
*/
|
||||||
void draw(int x, int y, bool copyPal = true);
|
void copyPalette(int paletteStart);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draws the image to a background layer, slower but can skip alpha, scale, and offset the palette
|
* @brief Draws the image to a background layer, slower but can skip alpha, scale, and offset the palette
|
||||||
@@ -80,22 +86,9 @@ public:
|
|||||||
* @param y The Y position to draw at
|
* @param y The Y position to draw at
|
||||||
* @param scaleX (Optional) The scale for the X axis
|
* @param scaleX (Optional) The scale for the X axis
|
||||||
* @param scaleY (Optional) The scale for the Y axis
|
* @param scaleY (Optional) The scale for the Y axis
|
||||||
* @param paletteOffset (Optional) How much to offset the palette by
|
* @param skipAlpha (Optional) Whether to skip transparent pixels, draws faster when disabled at 1.0 scale
|
||||||
* @param copyPal (Optional) Whether to copy the image's palette into palette VRAM
|
|
||||||
*/
|
*/
|
||||||
void drawSpecial(int x, int y, float scaleX = 1.0f, float scaleY = 1.0f, int paletteOffset = 0, bool copyPal = true);
|
void draw(int x, int y, float scaleX = 1.0f, float scaleY = 1.0f, bool skipAlpha = true);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Draws a segment of an image to a background layer, faster but overwrites alpha and no scaling or palette offsetting
|
|
||||||
* @param x The X position to draw at
|
|
||||||
* @param y The Y position to draw at
|
|
||||||
* @param imageX The X position in the image to draw from
|
|
||||||
* @param imageY The Y position in the image to draw from
|
|
||||||
* @param w The width to draw
|
|
||||||
* @param h The height to draw
|
|
||||||
* @param copyPal (Optional) Whether to copy the image's palette into palette VRAM
|
|
||||||
*/
|
|
||||||
void drawSegment(int x, int y, int imageX, int imageY, int w, int h, bool copyPal = true);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draws a segment of an image to a background layer, slower but can skip alpha, scale, and offset the palette
|
* @brief Draws a segment of an image to a background layer, slower but can skip alpha, scale, and offset the palette
|
||||||
@@ -107,10 +100,9 @@ public:
|
|||||||
* @param h The height to draw
|
* @param h The height to draw
|
||||||
* @param scaleX (Optional) The scale for the X axis
|
* @param scaleX (Optional) The scale for the X axis
|
||||||
* @param scaleY (Optional) The scale for the Y axis
|
* @param scaleY (Optional) The scale for the Y axis
|
||||||
* @param paletteOffset (Optional) How much to offset the palette by
|
* @param skipAlpha (Optional) Whether to skip transparent pixels, draws faster when disabled at 1.0 scale
|
||||||
* @param copyPal (Optional) Whether to copy the image's palette into palette VRAM
|
|
||||||
*/
|
*/
|
||||||
void drawSegmentSpecial(int x, int y, int imageX, int imageY, int w, int h, float scaleX = 1.0f, float scaleY = 1.0f, int paletteOffset = 0, bool copyPal = true);
|
void drawSegment(int x, int y, int imageX, int imageY, int w, int h, float scaleX = 1.0f, float scaleY = 1.0f, bool skipAlpha = true);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Universal-Core
|
||||||
|
* Copyright (C) 2021 Universal-Team
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||||
|
* * Requiring preservation of specified reasonable legal notices or
|
||||||
|
* author attributions in that material or in the Appropriate Legal
|
||||||
|
* Notices displayed by works containing it.
|
||||||
|
* * Prohibiting misrepresentation of the origin of that material,
|
||||||
|
* or requiring that modified versions of such material be marked in
|
||||||
|
* reasonable ways as different from the original version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UNIVERSAL_CORE_SPRITESHEET_HPP
|
||||||
|
#define _UNIVERSAL_CORE_SPRITESHEET_HPP
|
||||||
|
|
||||||
|
#include "image.hpp"
|
||||||
|
|
||||||
|
class Spritesheet {
|
||||||
|
private:
|
||||||
|
static Image _blank;
|
||||||
|
|
||||||
|
std::vector<Image *> _images;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Image group class
|
||||||
|
* @param paths The paths to try load the spritesheet from, from highest to lowest priority
|
||||||
|
* @param indexes The image indexes to load, if blank all images will be loaded
|
||||||
|
*/
|
||||||
|
Spritesheet(const std::vector<std::string> &paths, const std::vector<u32> indexes = {});
|
||||||
|
/**
|
||||||
|
* @brief Image group class
|
||||||
|
* @param path The path to load the spritesheet from
|
||||||
|
* @param indexes The image indexes to load, if blank all images will be loaded
|
||||||
|
*/
|
||||||
|
Spritesheet(const std::string &path, const std::vector<u32> indexes = {}) : Spritesheet(std::vector<std::string>({path}), indexes) {};
|
||||||
|
|
||||||
|
~Spritesheet(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the number of images in the spritesheet
|
||||||
|
*/
|
||||||
|
size_t size(void) { return _images.size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the Image at index
|
||||||
|
* @param index The Image to get
|
||||||
|
*/
|
||||||
|
Image &operator[](size_t index);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
+4
-9
@@ -87,8 +87,8 @@ void Gui::clearTextBufs(void) {
|
|||||||
DefaultFont->clear();
|
DefaultFont->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gui::DrawSprite(Image image, size_t imgindex, int x, int y, float ScaleX, float ScaleY) {
|
void Gui::DrawSprite(Spritesheet &sheet, size_t imgindex, int x, int y, float ScaleX, float ScaleY) {
|
||||||
image.drawSpecial(x, y, ScaleX, ScaleY);
|
sheet[imgindex].draw(x, y, 0x20, ScaleX, ScaleY);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Gui::loadFont(Font &fnt, const char *Path) {
|
bool Gui::loadFont(Font &fnt, const char *Path) {
|
||||||
@@ -98,18 +98,13 @@ bool Gui::loadFont(Font &fnt, const char *Path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Gui::loadSheet(const char *Path, Image &image) {
|
bool Gui::loadSheet(const char *Path, Spritesheet &sheet) {
|
||||||
if(Path && access(Path, F_OK) == 0) // Only load if found.
|
if(Path && access(Path, F_OK) == 0) // Only load if found.
|
||||||
image = Image(Path);
|
sheet = Spritesheet(Path);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Reinitialize the GUI.
|
|
||||||
|
|
||||||
fontRegion: The region to use for the system font.
|
|
||||||
*/
|
|
||||||
bool Gui::reinit(const char *FontPath) {
|
bool Gui::reinit(const char *FontPath) {
|
||||||
return Gui::init(FontPath);
|
return Gui::init(FontPath);
|
||||||
}
|
}
|
||||||
|
|||||||
+132
-103
@@ -27,10 +27,37 @@
|
|||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
#include "screenCommon.hpp"
|
#include "screenCommon.hpp"
|
||||||
|
|
||||||
#include "tonccpy.h"
|
#include "tonccpy.h"
|
||||||
|
|
||||||
Image::Image(const std::vector<std::string> &paths) {
|
#include <nds/bios.h>
|
||||||
|
|
||||||
|
void Image::decompressGrf(void *dst, const void *src) {
|
||||||
|
if(!src || !dst)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 header = *(u32*)src;
|
||||||
|
u32 size = header >> 8;
|
||||||
|
|
||||||
|
switch(header & 0xF0) {
|
||||||
|
case 0x00: // No compression
|
||||||
|
tonccpy(dst, (u8*)src + 4, size);
|
||||||
|
break;
|
||||||
|
case 0x10: // LZ77
|
||||||
|
decompress(src, dst, LZ77);
|
||||||
|
break;
|
||||||
|
case 0x20: // Huffman
|
||||||
|
decompress(src, dst, HUFF);
|
||||||
|
break;
|
||||||
|
case 0x30: // RLE
|
||||||
|
decompress(src, dst, RLE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Image::Image(const std::vector<std::string> &paths, u8 paletteStart) {
|
||||||
// Attempt to load from the given paths
|
// Attempt to load from the given paths
|
||||||
FILE *file = nullptr;
|
FILE *file = nullptr;
|
||||||
for(const auto &path : paths) {
|
for(const auto &path : paths) {
|
||||||
@@ -43,136 +70,138 @@ Image::Image(const std::vector<std::string> &paths) {
|
|||||||
if(!file)
|
if(!file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Return if not in the correct format
|
fseek(file, 0, SEEK_END);
|
||||||
char magic[5] = {0};
|
long size = ftell(file);
|
||||||
fread(magic, 1, 4, file);
|
fseek(file, 0, SEEK_SET);
|
||||||
if(strcmp(magic, ".GFX"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Read image
|
u8 *grf = new u8[size];
|
||||||
fread(&_width, 1, 2, file);
|
if(grf) {
|
||||||
fread(&_height, 1, 2, file);
|
fread(grf, 1, size, file);
|
||||||
_bitmap = std::vector<u8>(_width * _height);
|
|
||||||
fread(_bitmap.data(), 1, _bitmap.size(), file);
|
|
||||||
u16 palCount;
|
|
||||||
fread(&palCount, 1, 2, file);
|
|
||||||
fread(&_palOfs, 1, 2, file);
|
|
||||||
_palette = std::vector<u16>(palCount);
|
|
||||||
fread(_palette.data(), 2, palCount, file);
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
Image::Image(FILE *file) {
|
load(grf, paletteStart);
|
||||||
// Return if no file
|
|
||||||
if(!file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Return if not in the correct format
|
delete[] grf;
|
||||||
char magic[5];
|
|
||||||
fread(magic, 1, 4, file);
|
|
||||||
if(strcmp(magic, ".GFX"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Read image
|
|
||||||
fread(&_width, 1, 2, file);
|
|
||||||
fread(&_height, 1, 2, file);
|
|
||||||
_bitmap = std::vector<u8>(_width * _height);
|
|
||||||
fread(_bitmap.data(), 1, _bitmap.size(), file);
|
|
||||||
u16 palCount;
|
|
||||||
fread(&palCount, 1, 2, file);
|
|
||||||
fread(&_palOfs, 1, 2, file);
|
|
||||||
_palette = std::vector<u16>(palCount);
|
|
||||||
fread(_palette.data(), 2, palCount, file);
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::draw(int x, int y, bool copyPal) {
|
|
||||||
SCALE_3DS(x);
|
|
||||||
SCALE_3DS(y);
|
|
||||||
|
|
||||||
if(copyPal)
|
|
||||||
tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs, _palette.data(), _palette.size() * 2);
|
|
||||||
|
|
||||||
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + y * 256 + x;
|
|
||||||
|
|
||||||
// If full width and X is 0, copy it all in one go
|
|
||||||
if(_width == 256 && x == 0) {
|
|
||||||
tonccpy(dst, _bitmap.data(), _width * _height);
|
|
||||||
} else {
|
|
||||||
for(int i = 0; i < _height; i++) {
|
|
||||||
tonccpy(dst + i * 256, _bitmap.data() + i * _width, _width);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::drawSpecial(int x, int y, float scaleX, float scaleY, int paletteOffset,
|
Image::Image(const u8 *grf, u8 paletteStart) {
|
||||||
bool copyPal) {
|
load(grf, paletteStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::load(const u8 *grf, u8 paletteStart) {
|
||||||
|
const u32 *ptr = (u32 *)grf;
|
||||||
|
if(!ptr || ptr[0] != 0x46464952 || ptr[2] != 0x20465247) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 size = ptr[1]; // RIFF size
|
||||||
|
ptr += 3; // Skip to first section
|
||||||
|
|
||||||
|
while((u8 *)ptr < grf + size) {
|
||||||
|
switch(*ptr) {
|
||||||
|
case 0x20524448: { // 'HDR '
|
||||||
|
memcpy(&_width, ptr + 4, 4);
|
||||||
|
memcpy(&_height, ptr + 5, 4);
|
||||||
|
break;
|
||||||
|
} case 0x20584647: { // 'GFX '
|
||||||
|
_bitmap = std::vector<u8>(ptr[2] >> 8);
|
||||||
|
decompressGrf(_bitmap.data(), ptr + 2);
|
||||||
|
changePaletteStart(paletteStart);
|
||||||
|
break;
|
||||||
|
} case 0x204C4150: { // 'PAL '
|
||||||
|
_palette = std::vector<u16>((ptr[2] >> 8) / 2);
|
||||||
|
decompressGrf(_palette.data(), ptr + 2);
|
||||||
|
break;
|
||||||
|
} default: {
|
||||||
|
// Not supported yet
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += 2 + ptr[1] / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::changePaletteStart(u8 paletteStart) {
|
||||||
|
int moveBy = paletteStart - _paletteStart;
|
||||||
|
|
||||||
|
if(moveBy != 0) {
|
||||||
|
for(u8 &px : _bitmap) {
|
||||||
|
px += moveBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paletteStart = paletteStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::copyPalette(int paletteStart) {
|
||||||
|
tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + paletteStart, _palette.data(), _palette.size() * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::draw(int x, int y, float scaleX, float scaleY, bool skipAlpha) {
|
||||||
SCALE_3DS(x);
|
SCALE_3DS(x);
|
||||||
SCALE_3DS(y);
|
SCALE_3DS(y);
|
||||||
|
char s[64];
|
||||||
if(copyPal)
|
// _bitmap[0] = 39;
|
||||||
tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs + paletteOffset, _palette.data(), _palette.size() * 2);
|
snprintf(s, sizeof(s), "%lu, %lu, %u, %u, 0x%X", _width, _height, _bitmap.size(), _bitmap[0], 0);
|
||||||
|
|
||||||
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + y * 256 + x;
|
|
||||||
|
|
||||||
// If the scale is 1 use faster integer math
|
// If the scale is 1 use faster integer math
|
||||||
if(scaleX == 1.0f && scaleY == 1.0f) {
|
if(scaleX == 1.0f && scaleY == 1.0f) {
|
||||||
for(int i = 0; i < _height; i++) {
|
if(skipAlpha) {
|
||||||
for(int j = 0; j < _width; j++) {
|
for(u32 i = 0; i < _height; i++) {
|
||||||
u8 px = _bitmap[i * _width + j];
|
u8 *src = _bitmap.data() + i * _width;
|
||||||
if(_palette[px - _palOfs] & 0x8000)
|
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + (y + i) * 256 + x;
|
||||||
toncset(dst + i * 256 + j, px + paletteOffset, 1);
|
for(u32 j = 0; j < _width; j++) {
|
||||||
|
if(_palette[src[j] - _paletteStart] != 0x7C1F)
|
||||||
|
toncset(dst + j, src[j], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + y * 256 + x;
|
||||||
|
for(u32 i = 0; i < _height; i++) {
|
||||||
|
tonccpy(dst + i * 256, _bitmap.data() + i * _width, _width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < _height * scaleY; i++) {
|
for(u32 i = 0; i < _height * scaleY; i++) {
|
||||||
for(int j = 0; j < _width * scaleX; j++) {
|
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + (y + i) * 256 + x;
|
||||||
|
for(u32 j = 0; j < _width * scaleX; j++) {
|
||||||
u8 px = _bitmap[int(i / scaleY) * _width + int(j / scaleX)];
|
u8 px = _bitmap[int(i / scaleY) * _width + int(j / scaleX)];
|
||||||
if(_palette[px - _palOfs] & 0x8000)
|
if(_palette[px - _paletteStart] != 0x7C1F || !skipAlpha)
|
||||||
toncset(dst + i * 256 + j, px + paletteOffset, 1);
|
toncset(dst + j, px, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::drawSegment(int x, int y, int imageX, int imageY, int w, int h, bool copyPal) {
|
void Image::drawSegment(int x, int y, int imageX, int imageY, int w, int h, float scaleX, float scaleY, bool skipAlpha) {
|
||||||
SCALE_3DS(x);
|
SCALE_3DS(x);
|
||||||
SCALE_3DS(y);
|
SCALE_3DS(y);
|
||||||
|
|
||||||
if(copyPal)
|
|
||||||
tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs, _palette.data(), _palette.size() * 2);
|
|
||||||
|
|
||||||
for(int i = 0; i < h; i++) {
|
|
||||||
tonccpy((u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + (y + i) * 256 + x,
|
|
||||||
_bitmap.data() + (imageY + i) * _width + imageX, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::drawSegmentSpecial(int x, int y, int imageX, int imageY, int w, int h, float scaleX,
|
|
||||||
float scaleY, int paletteOffset, bool copyPal) {
|
|
||||||
SCALE_3DS(x);
|
|
||||||
SCALE_3DS(y);
|
|
||||||
|
|
||||||
if(copyPal)
|
|
||||||
tonccpy((currentScreen ? BG_PALETTE : BG_PALETTE_SUB) + _palOfs + paletteOffset, _palette.data(), _palette.size() * 2);
|
|
||||||
|
|
||||||
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + y * 256 + x;
|
|
||||||
|
|
||||||
// If the scale is 1 use faster integer math
|
// If the scale is 1 use faster integer math
|
||||||
if(scaleX == 1.0f && scaleY == 1.0f) {
|
if(scaleX == 1.0f && scaleY == 1.0f) {
|
||||||
for(int i = 0; i < h; i++) {
|
if(skipAlpha) {
|
||||||
for(int j = 0; j < w; j++) {
|
for(int i = 0; i < h; i++) {
|
||||||
u8 px = _bitmap[i * _width + j];
|
u8 *src = _bitmap.data() + i * _width;
|
||||||
if(_palette[px - _palOfs] & 0x8000)
|
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + (y + i) * 256 + x;
|
||||||
toncset(dst + i * 256 + j, px + paletteOffset, 1);
|
for(int j = 0; j < w; j++) {
|
||||||
|
if(_palette[src[j] - _paletteStart] != 0x7C1F)
|
||||||
|
toncset(dst + j, src[j], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < h; i++) {
|
||||||
|
tonccpy((u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + (y + i) * 256 + x,
|
||||||
|
_bitmap.data() + (imageY + i) * _width + imageX, w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < h * scaleY; i++) {
|
for(u32 i = 0; i < h * scaleY; i++) {
|
||||||
for(int j = 0; j < w * scaleX; j++) {
|
u8 *dst = (u8 *)bgGetGfxPtr(currentScreen ? 3 : 7) + (y + i) * 256 + x;
|
||||||
|
for(u32 j = 0; j < w * scaleX; j++) {
|
||||||
u8 px = _bitmap[(imageY + int(i / scaleY)) * _width + imageX + int(j / scaleX)];
|
u8 px = _bitmap[(imageY + int(i / scaleY)) * _width + imageX + int(j / scaleX)];
|
||||||
if(_palette[px - _palOfs] & 0x8000)
|
if(_palette[px - _paletteStart] != 0x7C1F || !skipAlpha)
|
||||||
toncset(dst + i * 256 + j, px + paletteOffset, 1);
|
toncset(dst + j, px, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -194,7 +194,7 @@ void Sprite::drawImage(int x, int y, const Image &image, float scaleX, float sca
|
|||||||
if(scaleX == 1.0f && scaleY == 1.0f) {
|
if(scaleX == 1.0f && scaleY == 1.0f) {
|
||||||
for(int i = 0; i < image.height(); i++) {
|
for(int i = 0; i < image.height(); i++) {
|
||||||
for(int j = 0; j < image.width(); j++) {
|
for(int j = 0; j < image.width(); j++) {
|
||||||
u16 px = image.palette()[image.bitmap()[i * image.width() + j] - image.palOfs()];
|
u16 px = image.palette()[image.bitmap()[i * image.width() + j] - image.paletteStart()];
|
||||||
if(px & 0x8000)
|
if(px & 0x8000)
|
||||||
_gfx[(y + i) * _height + x + j] = px;
|
_gfx[(y + i) * _height + x + j] = px;
|
||||||
}
|
}
|
||||||
@@ -203,7 +203,7 @@ void Sprite::drawImage(int x, int y, const Image &image, float scaleX, float sca
|
|||||||
for(int i = 0; i < image.height() * scaleY; i++) {
|
for(int i = 0; i < image.height() * scaleY; i++) {
|
||||||
for(int j = 0; j < image.width() * scaleX; j++) {
|
for(int j = 0; j < image.width() * scaleX; j++) {
|
||||||
u16 px =
|
u16 px =
|
||||||
image.palette()[image.bitmap()[int(i / scaleY) * image.width() + int(j / scaleX)] - image.palOfs()];
|
image.palette()[image.bitmap()[int(i / scaleY) * image.width() + int(j / scaleX)] - image.paletteStart()];
|
||||||
if(px & 0x8000)
|
if(px & 0x8000)
|
||||||
_gfx[(y + i) * _height + j + x] = px;
|
_gfx[(y + i) * _height + j + x] = px;
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ void Sprite::drawImageSegment(int x, int y, int imageX, int imageY, int w, int h
|
|||||||
if(scaleX == 1.0f && scaleY == 1.0f) {
|
if(scaleX == 1.0f && scaleY == 1.0f) {
|
||||||
for(int i = 0; i < h; i++) {
|
for(int i = 0; i < h; i++) {
|
||||||
for(int j = 0; j < w; j++) {
|
for(int j = 0; j < w; j++) {
|
||||||
u16 px = image.palette()[image.bitmap()[(imageY + i) * image.width() + imageX + j] - image.palOfs()];
|
u16 px = image.palette()[image.bitmap()[(imageY + i) * image.width() + imageX + j] - image.paletteStart()];
|
||||||
if(px & 0x8000)
|
if(px & 0x8000)
|
||||||
_gfx[(y + i) * _height + x + j] = px;
|
_gfx[(y + i) * _height + x + j] = px;
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ void Sprite::drawImageSegment(int x, int y, int imageX, int imageY, int w, int h
|
|||||||
for(int j = 0; j < w * scaleX; j++) {
|
for(int j = 0; j < w * scaleX; j++) {
|
||||||
u16 px = image.palette()[image.bitmap()[(imageY + int(i / scaleY)) * image.width() + imageX +
|
u16 px = image.palette()[image.bitmap()[(imageY + int(i / scaleY)) * image.width() + imageX +
|
||||||
int(j / scaleX)] -
|
int(j / scaleX)] -
|
||||||
image.palOfs()];
|
image.paletteStart()];
|
||||||
if(px & 0x8000)
|
if(px & 0x8000)
|
||||||
_gfx[(y + i) * _height + x + j] = px;
|
_gfx[(y + i) * _height + x + j] = px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Universal-Core
|
||||||
|
* Copyright (C) 2021 Universal-Team
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||||
|
* * Requiring preservation of specified reasonable legal notices or
|
||||||
|
* author attributions in that material or in the Appropriate Legal
|
||||||
|
* Notices displayed by works containing it.
|
||||||
|
* * Prohibiting misrepresentation of the origin of that material,
|
||||||
|
* or requiring that modified versions of such material be marked in
|
||||||
|
* reasonable ways as different from the original version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "spritesheet.hpp"
|
||||||
|
|
||||||
|
#include <nds.h>
|
||||||
|
|
||||||
|
Image Spritesheet::_blank = Image(nullptr, 0);
|
||||||
|
|
||||||
|
Spritesheet::Spritesheet(const std::vector<std::string> &paths, const std::vector<u32> indexes) {
|
||||||
|
// Attempt to load from the given paths
|
||||||
|
FILE *file = nullptr;
|
||||||
|
for(const auto &path : paths) {
|
||||||
|
file = fopen(path.c_str(), "rb");
|
||||||
|
if(file)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return if no file found
|
||||||
|
if(!file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 magic;
|
||||||
|
fread(&magic, 4, 1, file);
|
||||||
|
if(magic != 0x5844542E) // '.TDX'
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 imageCount;
|
||||||
|
fread(&imageCount, 4, 1, file);
|
||||||
|
|
||||||
|
_images.resize(imageCount);
|
||||||
|
|
||||||
|
for(u32 i = 0; i < imageCount; i++) {
|
||||||
|
nocashMessage(std::to_string(std::find(indexes.begin(), indexes.end(), i) - indexes.begin()).c_str());
|
||||||
|
if(indexes.size() == 0 || std::find(indexes.begin(), indexes.end(), i) != indexes.end()) {
|
||||||
|
fseek(file, 0x10 + i * 8, SEEK_SET);
|
||||||
|
|
||||||
|
u32 offset, size;
|
||||||
|
fread(&offset, 4, 1, file);
|
||||||
|
fread(&size, 4, 1, file);
|
||||||
|
|
||||||
|
u8 *grf = new u8[size];
|
||||||
|
fseek(file, offset, SEEK_SET);
|
||||||
|
fread(grf, 1, size, file);
|
||||||
|
|
||||||
|
_images[i] = new Image(grf, 0);
|
||||||
|
|
||||||
|
delete[] grf;
|
||||||
|
} else {
|
||||||
|
_images[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
Spritesheet::~Spritesheet(void) {
|
||||||
|
for(Image *image : _images) {
|
||||||
|
if(image)
|
||||||
|
delete image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image &Spritesheet::operator[](size_t index) {
|
||||||
|
if(_images[index] && index < _images.size())
|
||||||
|
return *_images[index];
|
||||||
|
else
|
||||||
|
return _blank;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user