Added verbose task and extended Makefile for personnalised fxconv converters. Changed assets and started map loading converter and cc

This commit is contained in:
Ulysse Cura 2025-08-22 09:22:36 +02:00
parent dde228ca72
commit c56b462203
39 changed files with 473 additions and 1313 deletions

View File

@ -1,5 +1,7 @@
{ {
"files.associations": { "files.associations": {
"fxconv": "python",
"*.MIT": "markdown",
"complex": "cpp", "complex": "cpp",
"string": "cpp", "string": "cpp",
"iterator": "cpp", "iterator": "cpp",
@ -15,6 +17,7 @@
"system_error": "cpp", "system_error": "cpp",
"stdexcept": "cpp", "stdexcept": "cpp",
"iostream": "cpp", "iostream": "cpp",
"ios": "cpp" "ios": "cpp",
"vector2d.hpp": "c"
} }
} }

22
.vscode/tasks.json vendored
View File

@ -33,9 +33,27 @@
"reveal": "never", "reveal": "never",
"focus": false, "focus": false,
"panel": "shared", "panel": "shared",
"showReuseMessage": false,
"clear": true
}
},
{
"label": "Build Verbose",
"detail": "Build project with verbosity on",
"type": "shell",
"command": "make",
"args": [
"VERBOSE=1"
],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": true,
"panel": "shared",
"showReuseMessage": true, "showReuseMessage": true,
"clear": false "clear": true
} }
} }
] ]
} }

102
3rd_party/gint/image.h vendored Normal file
View File

@ -0,0 +1,102 @@
//---
// gint:image - Image manipulation
//
// Note: this module is currently only available on fx-CG.
//
// This module supports 3 bit depths: full-color 16-bit (RGB565), indexed 8-bit
// (P8) and indexed 4-bit (P4). All three have an "alpha" variation where one
// color is treated as transparent, leading to 6 total formats.
//---
#ifndef GINT_IMAGE
#define GINT_IMAGE
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
//---
// Image structures
//---
/* Image formats. Note that transparency really only indicates the default
rendering method, as a transparent background can always be added or removed
by a dynamic effect on any image. */
enum {
IMAGE_RGB565 = 0, /* RGB565 without alpha */
IMAGE_RGB565A = 1, /* RGB565 with one transparent color */
IMAGE_P8_RGB565 = 4, /* 8-bit palette, all opaque colors */
IMAGE_P8_RGB565A = 5, /* 8-bit with one transparent color */
IMAGE_P4_RGB565 = 6, /* 4-bit palette, all opaque colors */
IMAGE_P4_RGB565A = 3, /* 4-bit with one transparent color */
IMAGE_DEPRECATED_P8 = 2,
};
/* Quick macros to compare formats by storage size */
#define IMAGE_IS_RGB16(format) \
((format) == IMAGE_RGB565 || (format) == IMAGE_RGB565A)
#define IMAGE_IS_P8(format) \
((format) == IMAGE_P8_RGB565 || (format) == IMAGE_P8_RGB565A)
#define IMAGE_IS_P4(format) \
((format) == IMAGE_P4_RGB565 || (format) == IMAGE_P4_RGB565A)
/* Check whether image format has an alpha color */
#define IMAGE_IS_ALPHA(format) \
((format) == IMAGE_RGB565A || \
(format) == IMAGE_P8_RGB565A || \
(format) == IMAGE_P4_RGB565A)
/* Check whether image format uses a palette */
#define IMAGE_IS_INDEXED(format) \
(IMAGE_IS_P8(format) || IMAGE_IS_P4(format))
/* Image flags. These are used for memory management, mostly. */
enum {
IMAGE_FLAGS_DATA_RO = 0x01, /* Data is read-only */
IMAGE_FLAGS_PALETTE_RO = 0x02, /* Palette is read-only */
IMAGE_FLAGS_DATA_ALLOC = 0x04, /* Data is malloc()'d */
IMAGE_FLAGS_PALETTE_ALLOC = 0x08, /* Palette is malloc()'d */
};
/* image_t: gint's native bitmap image format
Images of this format can be created through this header's API but also by
using the fxSDK's built-in image converters with fxconv. */
typedef struct
{
/* Color format, one of the IMAGE_* values defined above */
uint8_t format;
/* Additional flags, a combination of IMAGE_FLAGS_* values */
uint8_t flags;
/* Number of colors in the palette; this includes alpha for transparent
images, as alpha is always the first entry.
RGB16: 0
P8: Ranges between 1 and 256
P4: 16 */
int16_t color_count;
/* Full width and height, in pixels */
uint16_t width;
uint16_t height;
/* Byte stride between lines */
uint32_t stride;
/* Pixel data in row-major order, left to right.
- RGB16: 2 bytes per entry, each row padded to 4 bytes for alignment.
Each 2-byte value is an RGB565 color.
- P8: 1 signed byte per entry. Each byte is a palette index shifted by
128 (to access the color, use palette[<value>+128]).
- P4: 4 bits per entry, each row padded to a full byte. Each entry is a
direct palette index between 0 and 15. */
void *data;
/* For P8 and P4, color palette. The number of entries allocated in the
array is equal to the color_count attribute. */
uint16_t *palette;
} __attribute__((packed, aligned(4))) bopti_image_t;
#ifdef __cplusplus
}
#endif
#endif // GINT_IMAGE

View File

@ -3,26 +3,29 @@ BUILD_DIR = build
# Source files # Source files
SOURCES := \ SOURCES := \
src/test.cpp src/main.cpp \
# src/main.cpp \ src/game_data/game_data.cpp
# src/game_data.cpp
# Assets files # Assets files
ASSETS := \ ASSETS := \
assets/player-sheets/player_idle_sheet.png \ assets/player-sheets/player_idle_sheet.png \
assets/player-sheets/player_walk_sheet.png \ assets/player-sheets/player_walk_sheet.png \
assets/tileset/tileset.png assets/player-sheets/player_run_sheet.png \
assets/tileset/tileset.png \
assets/maps/example.json
# Output target name # Output target name
OUTPUT := 2D_Engine_Casio_Tool OUTPUT := 2D_Engine_Casio_Tool
# Compiler and flags # Compiler and flags
CXX = ccache g++ CXX = ccache g++
CXXFLAGS = -Wall -Wextra -std=c++17 -O2 -I. -no-pie CXXFLAGS = -Wall -Wextra -std=c++17 -g -no-pie
INCLUDE_DIRS = 3rd_party
LDFLAGS = -no-pie LDFLAGS = -no-pie
# Converter flags # Converter flags
FXCONVFLAGS = --cg --toolchain= --arch=x86-64 --outputtarget=elf64-x86-64 FXCONV_FLAGS = --cg --toolchain= --arch=x86-64 --outputtarget=elf64-x86-64
FXCONV_CONVERTERS = assets/maps/map_converter.py
# Change output location # Change output location
OUTPUT := $(BUILD_DIR)/$(OUTPUT) OUTPUT := $(BUILD_DIR)/$(OUTPUT)
@ -63,14 +66,14 @@ $(BUILD_DIR)/%.o: %.cpp
$(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE)*100/$(TOTAL_FILES))))) $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE)*100/$(TOTAL_FILES)))))
@echo "[$(PERCENTAGE)%] $(GREEN)Building CXX object $@$(RESET)" @echo "[$(PERCENTAGE)%] $(GREEN)Building CXX object $@$(RESET)"
$(Q)mkdir -p $(dir $@) $(Q)mkdir -p $(dir $@)
$(Q)$(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@ $(Q)$(CXX) $(CXXFLAGS) $(INCLUDE_DIRS:%=-I%) -MMD -MP -c $< -o $@
# Convert .*.o from .* (png files for example) # Convert .*.o from .* (png files for example)
$(BUILD_DIR)/%.o: % $(BUILD_DIR)/%.o: %
$(eval CURRENT_FILE := $(shell echo $$(($(CURRENT_FILE)+1)))) $(eval CURRENT_FILE := $(shell echo $$(($(CURRENT_FILE)+1))))
$(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE)*100/$(TOTAL_FILES))))) $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE)*100/$(TOTAL_FILES)))))
@echo "[$(PERCENTAGE)%] $(GREEN)Building FXCONV object $@$(RESET)" @echo "[$(PERCENTAGE)%] $(GREEN)Building FXCONV object $@$(RESET)"
$(Q)fxconv $(FXCONVFLAGS) $< -o $@ $(Q)fxconv $(FXCONV_FLAGS) --converter=$(FXCONV_CONVERTERS) $< -o $@
$(Q)objcopy --add-section .note.GNU-stack=/dev/null $@ $(Q)objcopy --add-section .note.GNU-stack=/dev/null $@
# Source files dependencies # Source files dependencies

View File

@ -6,13 +6,15 @@ This tool is used to make game data for the 2D_Engine_Casio [Gitea](https://gite
## Licences and Credits ## Licences and Credits
- This program is open-source : you can redistribute and/or modify it under the term of the **GNU GPLv3**. - This program is open-source : you can redistribute and/or modify it under the term of the **GNU GPLv3**.
Copyright (C) 2025 Ulysse Cura. See [LICENSE](LICENSE) or [gnu.org/licenses/gpl-3.0.html](https://www.gnu.org/licenses/gpl-3.0.html). Copyright (c) 2025 Ulysse Cura.
See [LICENSE](LICENSE) or [gnu.org/licenses/gpl-3.0.html](https://www.gnu.org/licenses/gpl-3.0.html).
- Files from the gint project are used in directory [gint](gint). - Files from the gint project are used and modified in directory [gint](gint).
[Git](https://git.planet-casio.com/Lephenixnoir/gint) [Git](https://git.planet-casio.com/Lephenixnoir/gint)
- Folder [src/nlohmann/json](src/nlohmann/json) contains code under **MIT license** : - Folder [src/nlohmann/json](src/nlohmann/json) contains code under **MIT license** :
Copyright (c) 2013-2025 Niels Lohmann. See [LICENSE.MIT](src/nlohmann/json/LICENSE.MIT). Copyright (c) 2013-2025 Niels Lohmann.
See [LICENSE.MIT](src/nlohmann/json/LICENSE.MIT).
[GitHub](https://github.com/nlohmann/json) [GitHub](https://github.com/nlohmann/json)
- Assets are taken from the free pack offered by [Anokolisa](https://anokolisa.itch.io/). - Assets are taken from the free pack offered by [Anokolisa](https://anokolisa.itch.io/).

View File

@ -1,24 +0,0 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1532,0,0,0,794,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1581,0,904,905,1046,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,2176,2177,2178,2179,2180,2181,2182,0,1543,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,2225,2226,2227,2228,2229,2230,2231,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1729,2326,2327,2274,2275,2276,2277,2278,2279,2280,2176,2177,2178,2179,2180,2181,2182,0,0,0,0,0,0,
0,0,0,0,2176,2177,2178,2180,2181,1778,2375,2376,0,0,0,0,0,0,0,2225,2226,2227,2228,2229,2230,2231,0,0,0,0,0,0,
0,0,0,0,2225,2226,2227,2229,2230,2231,0,0,0,0,0,0,0,0,0,2274,2275,2276,2277,2278,2279,2280,0,0,0,0,0,0,
0,0,0,0,2274,2275,2276,2278,2279,2280,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;

92
assets/maps/example.json Normal file
View File

@ -0,0 +1,92 @@
{
"MapWidth": 2,
"MapHeight": 2,
"BackgroundLayer1": [
1,0,
0,0
],
"BackgroundLayer2": [
0,2,
0,0
],
"BackgroundLayer3": [
0,0,
3,0
],
"Foreground": [
0,0,
0,4
],
"Entities": [
{
"ID": 2034,
"Components": [
{
"Type": "TransformComponent",
"x": 128,
"y": 96,
"w": 32,
"h": 48,
"Speed": 0
},
{
"Type": "SpriteComponent",
"TextureName": "dungeon_door_sheet"
},
{
"Type": "AnimationSystem",
"NbFrames": 15,
"ActualFrame": 8,
"FrameDelayMs": 100,
"Play": false,
"Loop": false,
"Reverse": false
},
{
"Type": "DoorSystem",
"States": [
{
"Channel": 0,
"State": true
}
]
}
]
},
{
"ID": 542,
"StoreInteraction": true,
"Components": [
{
"Type": "TransformComponent",
"Bounds": {
"x": 256,
"y": 384,
"w": 48,
"h": 32
},
"Speed": 0
},
{
"Type": "SpriteComponent",
"TextureName": "lever_sheet"
},
{
"Type": "AnimationSystem",
"NbFrames": 3,
"ActualFrame": 0,
"FrameDelayMs": 300,
"Play": false,
"Loop": false,
"Reverse": false
},
{
"Type": "LeverSystem",
"Channel": 0
}
]
}
]
}

View File

@ -0,0 +1,3 @@
*.json:
custom-type: map
name_regex: (.*)\.json map_\1

View File

@ -0,0 +1,53 @@
import fxconv
from fxconv import u16, u32, ref
import json
def convert(input, output, params, target):
if params["custom-type"] == "map":
convert_map(input, output, params, target)
return 0
else:
return 1
def convert_map(input, output, params, target):
with open(input, "r") as fp:
map = json.load(fp)
w = map["MapWidth"]
h = map["MapHeight"]
background_layer1 = bytes(map["BackgroundLayer1"])
background_layer2 = bytes(map["BackgroundLayer2"])
background_layer3 = bytes(map["BackgroundLayer3"])
foreground = bytes(map["Foreground"])
entities = fxconv.Structure()
for entity in map["Entities"]:
e = fxconv.Structure()
e += u16(entity["ID"])
e += u32(entity["Components"].size())
for component in entity["Components"]:
c = fxconv.Structure()
match component["Type"]:
case "TransformComponent":
c += u32(component["x"])
c += u32(component["y"])
c += u32(component["w"])
c += u32(component["h"])
c += u32(component["Speed"])
case _:
raise fxconv.FxconvError(f"unknown component type {component["Type"]}")
e += ref(c)
o = fxconv.ObjectData()
o += u32(w) + u32(h)
o += ref(background_layer1)
o += ref(background_layer2)
o += ref(background_layer3)
o += ref(foreground)
o += u32(map["Entities"].size())
o += ref(entities)
fxconv.elf(o, output, params["name"], **target)

View File

@ -0,0 +1,10 @@
#!/usr/bin/bash
echo "Creating \"~/.tiled\" directory"
mkdir -p $HOME/.tiled/
echo "Copying extension to tiled directory"
cp "json_export_tool.py" "$HOME/.tiled/"
echo ""
echo "Don't forget to activate python in tiled !"

View File

@ -1,13 +1,14 @@
from tiled import * from tiled import *
import json
class Example(Plugin): class Json_Export_Tool(Plugin):
@classmethod @classmethod
def nameFilter(cls): def nameFilter(cls):
return "Example files (*.example)" return "Json files (*.json)"
@classmethod @classmethod
def shortName(cls): def shortName(cls):
return "example" return "json"
@classmethod @classmethod
def write(cls, tileMap, fileName): def write(cls, tileMap, fileName):
@ -28,6 +29,11 @@ class Example(Plugin):
else: else:
line += ',' line += ','
print(line, file=fileHandle) print(line, file=fileHandle)
return True return True
def write(cls, tileMap, fileName):
map = {}
with open(fileName, 'w') as fileHandle:
for i in tileMap.layerCount():
tileLayer = tileLayerAt(tileMap, i)
print("caca", file=fileHandle)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 947 B

View File

@ -1,83 +0,0 @@
//---
// config - Compile-time generate configuration
//---
#ifndef GINT_CONFIG
#define GINT_CONFIG
/* GINT_VERSION: Latest tag and number of additional commits
"2.1.0" = Release 2.1.0
"2.1.1-5" = 5 commits after release 2.1.1 */
#define GINT_VERSION "2.11.0"
/* GINT_HASH: Commit hash with 7 digits
0x03f7c0a0 = Commit 3f7c0a0 */
#define GINT_HASH 0xbadbd0f
/* GINT_HW_{FX,CG}: Identifies the type of hardware running the program. */
#if defined(FX9860G)
# define GINT_HW_FX 1
# define GINT_HW_CG 0
# define GINT_HW_CP 0
# define GINT_HW_SWITCH(FX,CG,CP) (FX)
#elif defined(FXCG50)
# define GINT_HW_FX 0
# define GINT_HW_CG 1
# define GINT_HW_CP 0
# define GINT_HW_SWITCH(FX,CG,CP) (CG)
#elif defined(FXCP)
# define GINT_HW_FX 0
# define GINT_HW_CG 0
# define GINT_HW_CP 1
# define GINT_HW_SWITCH(FX,CG,CP) (CP)
#endif
/* Shorthand to simplify definitions below. Won't be needed for long. */
#if defined(FX9860G_G3A)
# define GINT_FX9860G_G3A 1
#else
# define GINT_FX9860G_G3A 0
#endif
/* GINT_OS_{FX,CG}: Identifies the type of OS API we're assuming. Currently I
see no reason this would be different from hardware, but who knows. */
#define GINT_OS_FX GINT_HW_FX
#define GINT_OS_CG GINT_HW_CG
#define GINT_OS_CP GINT_HW_CP
#define GINT_OS_SWITCH GINT_HW_SWITCH
/* GINT_NO_OS_STACK: Disables using a chunk of the OS stack as a heap. The top
section covering 355/512 ko is otherwise used. (fx-CG 50) */
/* #undef GINT_NO_OS_STACK */
/* GINT_USER_VRAM: Selects whether to store VRAMs in the user stack or in the
OS stack. Deprecated, now controlled by GINT_NO_OS_STACK. (fx-CG 50) */
/* #undef GINT_USER_VRAM */
#ifdef GINT_USER_VRAM
# define GINT_NO_OS_STACK
#endif
/* GINT_STATIC_GRAY: Selects whether additional gray VRAMs are allocated
statically or in the system heap (fx-9860G) */
/* #undef GINT_STATIC_GRAY */
/* GINT_KMALLOC_DEBUG: Selects whether kmalloc debug functions are enabled
(these are mainly data structure integrity checks and information that make
sense for a developer). This is independent from statistics, which can be
enabled or disabled at runtime. */
/* #undef GINT_KMALLOC_DEBUG */
/* GINT_USB_DEBUG: Selects whether USB debug functions are enabled */
/* #undef GINT_USB_DEBUG */
/* GINT_RENDER_DMODE: Selects whether the dmode override is available on
rendering functions. */
#define GINT_RENDER_DMODE (GINT_HW_FX || GINT_FX9860G_G3A)
/* GINT_RENDER_{MONO,RGB}: Enable the mono/rgb rendering API.
Currently these are exclusive. */
#define GINT_RENDER_MONO (GINT_HW_FX || GINT_FX9860G_G3A)
#define GINT_RENDER_RGB ((GINT_HW_CG || GINT_HW_CP) && !GINT_FX9860G_G3A)
#endif /* GINT_CONFIG */

View File

@ -1,50 +0,0 @@
//---
// gint:defs:attributes - Macros for compiler-specific attributes
//---
#ifndef GINT_DEFS_ATTRIBUTES
#define GINT_DEFS_ATTRIBUTES
/* Objects from specific sections */
#define GSECTION(x) __attribute__((section(x)))
/* Objects from the gint's uninitialized BSS section */
#define GBSS __attribute__((section(".gint.bss")))
/* Additional sections that are only needed on SH3 */
#define GRODATA3 __attribute__((section(".gint.rodata.sh3")))
#define GDATA3 __attribute__((section(".gint.data.sh3")))
#define GBSS3 __attribute__((section(".gint.bss.sh3")))
/* Objects for the ILRAM, XRAM and YRAM regions */
#define GILRAM __attribute__((section(".ilram")))
#define GXRAM __attribute__((section(".xyram")))
#define GYRAM __attribute__((section(".xyram")))
/* Unused parameters or variables */
#define GUNUSED __attribute__((unused))
/* Functions that *must* be inlined */
#define GINLINE __attribute__((always_inline)) inline
/* Aligned variables */
#define GALIGNED(x) __attribute__((aligned(x)))
/* Packed structures. I require explicit alignment because if it's unspecified,
GCC cannot optimize access size, and reads to memory-mapped I/O with invalid
access sizes silently fail - honestly you don't want this to happen */
#define GPACKED(x) __attribute__((packed, aligned(x)))
/* Packed enumerations */
#define GPACKEDENUM __attribute__((packed))
/* Transparent unions */
#define GTRANSPARENT __attribute__((transparent_union))
/* Functions and globals that are visible through whole-program optimization */
#define GVISIBLE __attribute__((externally_visible))
/* Weak symbols */
#define GWEAK __attribute__((weak))
/* Constructors */
#define GCONSTRUCTOR __attribute__((constructor))
#define GDESTRUCTOR __attribute__((destructor))
/* Functions that do not return */
#define GNORETURN __attribute__((noreturn))
#endif /* GINT_DEFS_ATTRIBUTES */

View File

@ -1,68 +0,0 @@
//---
// gint:defs:types - Type definitions
//---
#ifndef GINT_DEFS_TYPES
#define GINT_DEFS_TYPES
#include "attributes.h"
/* For size_t, mainly */
#include <stddef.h>
/* For all fixed-width integer types */
#include <stdint.h>
/* For human-readable boolean types */
#include <stdbool.h>
/* Common system types: ssize_t, off_t, etc. */
#include <sys/types.h>
/* For va_list */
#include <stdarg.h>
/* Fixed-width types for bit fields are quite meaningless */
typedef unsigned int uint;
//---
// Short types
//---
typedef unsigned int uint;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
//---
// Structure elements
//----
/* Giving a type to padding bytes is misguiding, let's hide it in a macro */
#define pad_nam2(c) _ ## c
#define pad_name(c) pad_nam2(c)
#define pad(bytes) uint8_t pad_name(__COUNTER__)[bytes]
/* byte_union() - union between an uint8_t 'byte' element and a bit field */
#define byte_union(name, fields) \
union { \
uint8_t byte; \
struct { fields } GPACKED(1); \
} GPACKED(1) name
/* word_union() - union between an uint16_t 'word' element and a bit field */
#define word_union(name, fields) \
union { \
uint16_t word; \
struct { fields } GPACKED(2); \
} GPACKED(2) name
/* lword_union() - union between an uint32_t 'lword' element and a bit field */
#define lword_union(name, fields) \
union { \
uint32_t lword; \
struct { fields } GPACKED(4); \
} GPACKED(4) name
#endif /* GINT_DEFS_TYPES */

View File

@ -1,143 +0,0 @@
//---
// gint:display-cg - fx-CG 50 rendering functions
//
// This module covers rendering functions specific to the fx-CG 50. In addition
// to triple-buffering management, this mainly includes image manipulation
// tools as well as the very versatile dimage_effect() and dsubimage_effect()
// functions that support high-performance image rendering with a number of
// geometric and color effects.
//
// The fx-CG OS restricts the display to a 384x216 rectangle rougly around the
// center, leaving margins on three sides. However, gint configures the display
// to use the full 396x224 surface!
//---
#ifndef GINT_DISPLAY_CG
#define GINT_DISPLAY_CG
#ifdef __cplusplus
extern "C" {
#endif
#include "defs/types.h"
#include "image.h"
/* Dimensions of the VRAM */
#if GINT_HW_CG
#define DWIDTH 396
#define DHEIGHT 224
#elif GINT_HW_CP
#define DWIDTH 320
#define DHEIGHT 528
#endif
/* gint VRAM address. This value must always point to a 32-aligned buffer of
size 177408. Any function can use it freely to perform rendering or store
data when not drawing. Triple buffering is already implemented in gint, see
the dvram() function below.
In this module, colors are in the 16-bit big-endian R5G6B5 format, as it is
the format used by the display controller. */
extern uint16_t *gint_vram;
/* Provide a platform-agnostic definition of color_t.
Some functions also support transparency, in which case they take an [int]
as argument and recognize negative values as transparent. */
typedef uint16_t color_t;
enum {
/* Compatibility with fx9860g color names */
C_WHITE = 0xffff,
C_LIGHT = 0xad55,
C_DARK = 0x528a,
C_BLACK = 0x0000,
/* Other colors */
C_RED = 0xf800,
C_GREEN = 0x07e0,
C_BLUE = 0x001f,
C_NONE = -1,
C_INVERT = -2,
};
/* RGB color maker. Takes three channels of value 0..31 each (the extra bit of
green is not used). */
#define C_RGB(r,g,b) (((r) << 11) | ((g) << 6) | (b))
/* See <gint/image.h> for the details on image manipulation. */
typedef image_t bopti_image_t;
//---
// Video RAM management
//---
/* dsetvram(): Control video RAM address and triple buffering
Normal rendering under gint uses double-buffering: there is one image
displayed on the screen and one in memory, in a region called the video RAM
(VRAM). The application draws frames in the VRAM then sends them to the
screen only when they are finished, using dupdate().
On fx-CG, sending frames with dupdate() is a common bottleneck because it
takes about 11 ms. Fortunately, while the DMA is sending the frame to the
display, the CPU is available to do work in parallel. This function sets up
triple buffering (ie. a second VRAM) so that the CPU can start working on
the next frame while the DMA is sending the current one.
However, experience shows minimal performance improvements, because writing
to main RAM does not parallelize with DMA transfers. Since gint 2.8, this
is no longer the default, and the memory for the extra VRAM is instead
available via malloc().
VRAMs must be contiguous, 32-aligned, (2*396*224)-byte buffers with 32 bytes
of extra data on each side (ie. 32 bytes into a 32-aligned buffer of size
177472).
@main Main VRAM area, used alone if [secondary] is NULL
@secondary Additional VRAM area, enables triple buffering if non-NULL */
// TODO: In gint 3 the triple buffering mechanism will be removed. Applications
// that want to change VRAMs in-between every frame will be able to do so by
// talking directly to the video interface to set VRAM, and wrapping dupdate.
// Basically it will just no longer be handled by gint itself.
void dsetvram(uint16_t *main, uint16_t *secondary);
/* dgetvram() - Get VRAM addresses
Returns the VRAM buffer addresses used to render on fx-CG 50. */
void dgetvram(uint16_t **main, uint16_t **secondary);
//---
// VRAM backup
// On the fx-CP gint backs up the VRAM when loading and restores it when
// leaving. While this is a transparent mechanism, the following parts of the
// implementation are exposed at the internal API level.
//---
/* Encode the VRAM contents between [in_start] and [in_end] at [output]. While
[*in_end] is excluded from the encoding, it will be modified temporarily to
serve as bounds check, so it must not be accessed asynchronously during the
encoding. The size of the output is not known but is at most the distance
between in_end and in_start in bytes. Setting output = in_start to compress
in-place is supported. Returns the end pointer after encoding. */
uint8_t *gint_vrambackup_encode(
uint8_t *output, uint16_t *in_start, uint16_t *in_end);
/* Predefine palette based on the GUI at the Hollyhock loading screen. Contains
109 entries plus a 110th dummy entry used internally as bounds check. */
extern uint16_t gint_vrambackup_palette[110];
/* Get the pointer to the encoded VRAM backup created at load time. If [size]
is not NULL, sets the size in [*size]. The pointer is heap allocated and
remains owned by gint. */
void *gint_vrambackup_get(int *size);
/* Decode the load-time VRAM backup back to VRAM. */
void gint_vrambackup_show(void);
#ifdef __cplusplus
}
#endif
#endif /* GINT_DISPLAY_CG */

View File

@ -1,846 +0,0 @@
//---
// gint:image - Image manipulation and rendering
//
// Note: this module is currently only available on fx-CG.
//
// This header provides image manipulation functions. This mainly consists of a
// reference-based image format, various access and modification functions, and
// a number of high-performance transformations and rendering effects. If you
// find yourself limited by rendering time, note that RAM writing speed is
// often the bottleneck, and image rendering is much faster in Azur (which is
// what the renderer was initially designed for).
//
// This module supports 3 bit depths: full-color 16-bit (RGB565), indexed 8-bit
// (P8) and indexed 4-bit (P4). All three have an "alpha" variation where one
// color is treated as transparent, leading to 6 total formats.
//
// The image renderers support so-called *dynamic effects*, which are image
// transformations performed on-the-fly while rendering, without generating an
// intermediate image. They comprise straightforward transformations that
// achieve similar performance to straight rendering and can be combined to
// some extent, which makes them reliable whenever applicable.
//
// For images of the RGB16 and P8 bit depths, the module supports a rich API
// with image subsurfaces and a fairly large sets of geometric and color
// transforms, including some in-place. P4 is not supported in most of these
// functions because the dense bit packing is both impractical and slower for
// these applications.
//---
#ifndef GINT_IMAGE
#define GINT_IMAGE
#ifdef __cplusplus
extern "C" {
#endif
#include "config.h"
#include "defs/attributes.h"
#include <stdint.h>
struct dwindow;
//---
// Image structures
//---
/* Image formats. Note that transparency really only indicates the default
rendering method, as a transparent background can always be added or removed
by a dynamic effect on any image. */
enum {
IMAGE_RGB565 = 0, /* RGB565 without alpha */
IMAGE_RGB565A = 1, /* RGB565 with one transparent color */
IMAGE_P8_RGB565 = 4, /* 8-bit palette, all opaque colors */
IMAGE_P8_RGB565A = 5, /* 8-bit with one transparent color */
IMAGE_P4_RGB565 = 6, /* 4-bit palette, all opaque colors */
IMAGE_P4_RGB565A = 3, /* 4-bit with one transparent color */
IMAGE_DEPRECATED_P8 = 2,
};
/* Quick macros to compare formats by storage size */
#define IMAGE_IS_RGB16(format) \
((format) == IMAGE_RGB565 || (format) == IMAGE_RGB565A)
#define IMAGE_IS_P8(format) \
((format) == IMAGE_P8_RGB565 || (format) == IMAGE_P8_RGB565A)
#define IMAGE_IS_P4(format) \
((format) == IMAGE_P4_RGB565 || (format) == IMAGE_P4_RGB565A)
/* Check whether image format has an alpha color */
#define IMAGE_IS_ALPHA(format) \
((format) == IMAGE_RGB565A || \
(format) == IMAGE_P8_RGB565A || \
(format) == IMAGE_P4_RGB565A)
/* Check whether image format uses a palette */
#define IMAGE_IS_INDEXED(format) \
(IMAGE_IS_P8(format) || IMAGE_IS_P4(format))
/* Image flags. These are used for memory management, mostly. */
enum {
IMAGE_FLAGS_DATA_RO = 0x01, /* Data is read-only */
IMAGE_FLAGS_PALETTE_RO = 0x02, /* Palette is read-only */
IMAGE_FLAGS_DATA_ALLOC = 0x04, /* Data is malloc()'d */
IMAGE_FLAGS_PALETTE_ALLOC = 0x08, /* Palette is malloc()'d */
};
/* image_t: gint's native bitmap image format
Images of this format can be created through this header's API but also by
using the fxSDK's built-in image converters with fxconv. */
typedef struct
{
/* Color format, one of the IMAGE_* values defined above */
uint8_t format;
/* Additional flags, a combination of IMAGE_FLAGS_* values */
uint8_t flags;
/* Number of colors in the palette; this includes alpha for transparent
images, as alpha is always the first entry.
RGB16: 0
P8: Ranges between 1 and 256
P4: 16 */
int16_t color_count;
/* Full width and height, in pixels */
uint16_t width;
uint16_t height;
/* Byte stride between lines */
int stride;
/* Pixel data in row-major order, left to right.
- RGB16: 2 bytes per entry, each row padded to 4 bytes for alignment.
Each 2-byte value is an RGB565 color.
- P8: 1 signed byte per entry. Each byte is a palette index shifted by
128 (to access the color, use palette[<value>+128]).
- P4: 4 bits per entry, each row padded to a full byte. Each entry is a
direct palette index between 0 and 15. */
void *data;
/* For P8 and P4, color palette. The number of entries allocated in the
array is equal to the color_count attribute. */
uint16_t *palette;
} GPACKED(4) image_t;
/* Dynamic effects: these transformations can be applied on images while
rendering. Not all effects can be combined; unless specified otherwise:
- HFLIP and VFLIP can both be added regardless of any other effect
- At most one color effect can be applied */
enum {
/* Value 0x01 is reserved, because it is DIMAGE_NOCLIP, which although
part of the old API still needs to be supported. */
/* [Any]: Skip clipping the command against the source image */
IMAGE_NOCLIP_INPUT = 0x04,
/* [Any]: Skip clipping the command against the output VRAM */
IMAGE_NOCLIP_OUTPUT = 0x08,
/* [Any]: Skip clipping both */
IMAGE_NOCLIP = IMAGE_NOCLIP_INPUT | IMAGE_NOCLIP_OUTPUT,
// Geometric effects. These values should remain at exactly bit 8 and
// following, or change gint_image_mkcmd() along with it.
/* [Any]: Flip image vertically */
IMAGE_VFLIP = 0x0100,
/* [Any]: Flip image horizontally */
IMAGE_HFLIP = 0x0200,
// Color effects
/* [RGB565, P8_RGB565, P4_RGB565]: Make a color transparent
Adds one argument:
* Color to clear (RGB16: 16-bit value; P8/P4: palette index) */
IMAGE_CLEARBG = 0x10,
/* [RGB565, P8_RGB565, P4_RGB565]: Turn a color into another
Adds two arguments:
* Color to replace (RGB16: 16-bit value; P8/P4: palette index)
* Replacement color (16-bit value) */
IMAGE_SWAPCOLOR = 0x20,
/* [RGB565A, P8_RGB565A, P4_RGB565A]: Add a background
Adds one argument:
* Background color (16-bit value) */
IMAGE_ADDBG = 0x40,
/* [RGB565A, P8_RGB565A, P4_RGB565A]: Dye all non-transparent pixels
Adds one argument:
* Dye color (16-bit value) */
IMAGE_DYE = 0x80,
};
//---
// Image creation and destruction
//---
#if GINT_RENDER_RGB
/* image_alloc(): Create a new (uninitialized) image
This function allocates a new image of the specified dimensions and format.
It always allocates a new data array; if you need to reuse a data array, use
the lower-level image_create() or image_create_sub().
The first parameters [width] and [height] specify the dimensions of the new
image in pixels. The [format] should be one of the IMAGE_* formats, for
example IMAGE_RGB565A or IMAGE_P4_RGB565.
This function does not specify or initialize the palette of the new image;
use image_set_palette(), image_alloc_palette() or image_copy_palette()
after calling this function.
The returned image structure must be freed with image_free() after use.
@width Width of the new image
@height Height of the new image
@format Pixel format; one of the IMAGE_* formats defined above */
image_t *image_alloc(int width, int height, int format);
/* image_set_palette(): Specify an external palette for an image
This function sets the image's palette to the provided address. The number
of entries allocated must be specified in size. It is also the caller's
responsibility to ensure that the palette covers all the indices used in the
image data.
The old palette, if owned by the image, is freed. If [owns=true] the
palette's ownership is given to the image, otherwise it is kept external. */
void image_set_palette(image_t *img, uint16_t *palette, int size, bool owns);
/* image_alloc_palette(): Allocate a new palette for an image
This function allocates a new palette for an image. The number of entries is
specified in size; for P8 it can vary between 1 and 256, for P4 it is
ignored (P4 images always have 16 colors).
The old palette, if owned by the image, is freed. The entries of the new
palette are all initialized to 0. If size is -1, the format's default
palette size is used. Returns true on success. */
bool image_alloc_palette(image_t *img, int size);
/* image_copy_palette(): Copy another image's palette
This function allocates a new palette for an image, and initializes it with
a copy of another image's palette. For P8 the palette can be resized by
specifying a value other than -1 as the size; by default, the source image's
palette size is used (within the limits of the new format). Retuns true on
success. */
bool image_copy_palette(image_t const *src, image_t *dst, int size);
/* image_create(): Create a bare image with no data/palette
This function allocates a new image structure but without data or palette.
The [data] and [palette] members are NULL, [color_count] and [stride] are 0.
This function is useful to create images that reuse externally-provided
information. It is intended that the user of this function sets the [data]
and [stride] fields themselves, along with the IMAGE_FLAGS_DATA_ALLOC flag
if the image should own its data.
The [palette] and [color_count] members can be set with image_set_palette(),
image_alloc_palette(), image_copy_palette(), or manually.
The returned image structure must be freed with image_free() after use. */
image_t *image_create(int width, int height, int format);
/* image_create_vram(): Create a reference to gint_vram
This function creates a new RGB565 image that references gint_vram. Using
this image as target for transformation functions can effectively render
transformed images to VRAM.
The value of gint_vram is captured when this function is called, and does
not update after dupdate() when triple-buffering is used. The user should
account for this option. (Using this function twice then replacing one of
the [data] pointers is allowed.)
The VRAM image owns no data but it does own its own structure so it must
still be freed with image_free() after use. */
image_t *image_create_vram(void);
/* image_free(): Free and image and the data it owns
This function frees the provided image structure and the data that it owns.
Images converted by fxconv should not be freed; nonetheless, this functions
distinguishes them and should work. Images are not expected to be created on
the stack.
If the image has the IMAGE_FLAGS_DATA_ALLOC flag, the data pointer is also
freed. Similarly, the image has the IMAGE_FLAGS_PALETTE_ALLOC flag, the
palette is freed. Make sure to not free images when references to them still
exist, as this could cause the reference's pointers to become dangling. */
void image_free(image_t *img);
//---
// Basic image access and information
//---
/* image_valid(): Check if an image is valid
An image is considered valid if it has a valid profile, a non-NULL data
pointer, and for palette formats a valid palette pointer. */
bool image_valid(image_t const *img);
/* image_alpha(): Get the alpha value for an image format
This function returns the alpha value for any specific image format:
* RGB16: 0x0001
* P8: -128 (0x80)
* P4: 0
For non-transparent formats, it returns a value that is different from all
valid pixel values of the format, which means it is always safe to compare a
pixel value to the image_alpha() of the format. */
int image_alpha(int format);
/* image_get_pixel(): Read a pixel from the data array
This function reads a pixel from the image's data array at position (x,y).
It returns the pixel's value, which is either a full-color value (RGB16) or
a possibly-negative palette index (P8/P4). See the description of the [data]
field of image_t for more details. The value of the pixel can be decoded
into a 16-bit color either manually or by using the image_decode_pixel()
function.
Note that reading large amounts of image data with this function will be
slow; if you need reasonable performance, consider iterating on the data
array manually. */
int image_get_pixel(image_t const *img, int x, int y);
/* image_decode_pixel(): Decode a pixel value
This function decodes a pixel's value obtained from the data array (for
instance with image_get_pixel()). For RGB16 formats this does nothing, but
for palette formats this accesses the palette at a suitable position.
Note that reading large amounts of data with this function will be slow; if
you need reasonable performance, consider inlining the format-specific
method or iterating on the data array manually. */
int image_decode_pixel(image_t const *img, int pixel);
/* image_data_size(): Compute the size of the [data] array
This function returns the size of the data array, in bytes. This can be used
to duplicate it. Note that for sub-images this is a subsection of another
image's data array, and might be much larger than the sub-image. */
int image_data_size(image_t const *img);
//---
// Basic image modifications
//---
/* image_set_pixel(): Set a pixel in the data array
This function writes a pixel into the image's data array at position (x,y).
The pixel value must be of the proper format, as specified in the definition
of the [data] field of image_t.
Formats: RGB16, P8, P4 */
void image_set_pixel(image_t const *img, int x, int y, int value);
/* image_copy(): Convert and copy an image
This function copies an image into another image while converting certain
formats. Unlike transforms, this function does clip, so there are no
conditions on the size of the target.
If [copy_alpha] is true, transparent pixels are copied verbatim, which
effectively replaces the top-left corner of [dst] with [src]. If it's false,
transparent pixels of [src] are skipped, effectively rendering [src] over
the top-left corner of [src].
This function converts between all formats except from RGB16 to P8/P4, since
this requires generating a palette (which is a complex endeavour).
Conversions from P8/P4 to RGB16 simply decode the palette. Conversions
between P8/P4 preserve the contents but renumber the palette entries. From
P4 to P8, the image is always preserved. From P8 to P4, the image is only
preserved if it has less than 16 colors (this is intended to allow P4 images
to be converted to P8 for edition by this library, and then back to P4). The
following table summarizes the conversions:
Source format RGB16 P8 P4
Target format +-----------+----------------+------------------+
RGB16 | Copy Decode palette Decode palette |
P8 | - Copy Enlarge palette |
P4 | - Narrow palette Copy |
+-----------+----------------+------------------+
Note that conversions to RGB16 are not lossless because RGB565, P8 and P4
can represent any color; if a color equal to image_alpha(IMAGE_RGB565A) is
found during conversion, this function transforms it slightly to look
similar instead of erroneously generating a transparent pixel.
Formats: RGB16 RGB16, P8 Anything, P4 Anything
Size requirement: none (clipping is performed)
Supports in-place: No (useless) */
void image_copy(image_t const *src, image_t *dst, bool copy_alpha);
/* image_copy_alloc(): Convert and copy into a new image
This function is similar to image_copy(), but it allocates a target image of
the desired format before copying. */
image_t *image_copy_alloc(image_t const *src, int new_format);
/* image_fill(): Fill an image with a single pixel value */
void image_fill(image_t *img, int value);
/* image_clear(): Fill a transparent image with its transparent value */
void image_clear(image_t *img);
//---
// Sub-image extraction
//---
/* image_sub(): Build a reference to a sub-image
This function is used to create references to sub-images of RGB16 and P8
images. The [data] pointer of the sub-image points somewhere within the data
array of the source, and its [palette] pointer is identical to the source's.
The last parameter is a pointer to a preallocated image_t structure (usually
on the stack) that gets filled with the data. Doing this instead of
allocating a new object with malloc() means that there is no need to
image_free() the sub-image, and thus it can be used inline:
image_t tmp;
image_hflip(src, image_sub(dst, x, y, w, h, &tmp));
A preprocessor macro is used to make the last parameter optional. If it's
not specified, a pointer to a static image_t will be returned instead. This
is useful in inline calls as shown above, which then simplify to:
image_hflip(src, image_sub(dst, x, y, w, h));
However, another call to image_sub() or image_at() will override the
sub-image, so you should only use this in such temporary settings. If you
need multiple image_sub() or image_at() calls in the same statement, only
one can use the short form.
If the requested rectangle does not intersect the source, the sub-image will
be of dimension 0x0. If the image format does not support sub-images (P4),
the sub-image will test invalid with image_valid(). */
image_t *image_sub(image_t const *src, int x, int y, int w, int h,
image_t *dst);
/* Make the last parameter optional */
#define image_sub1(src, x, y, w, h, dst, ...) image_sub(src, x, y, w, h, dst)
#define image_sub(...) image_sub1(__VA_ARGS__, NULL)
/* image_at(): Build a reference to a position within a sub-image */
#define image_at(img, x, y) image_sub(img, x, y, -1, -1)
//---
// Geometric image transforms
//
// All geometric transforms render to position (0,0) of the target image and
// fail if the target image is not large enough to hold the transformed result
// (unlike the rendering functions which render only the visible portion).
//
// To render at position (x,y) of the target image, use img_at(). For instance:
// image_hflip(src, image_at(dst, x, y));
//
// Each transform function has an [_alloc] variant which does the same
// transform but allocates the target image on the fly and returns it. Remember
// that allocation can fail, so you need to check whether the returned image is
// valid.
//
// (You can still pass invalid images to transform functions. The invalid image
// will be ignored or returned unchanged, so you can chain calls and check for
// validity at the end of the chain.)
//
// Some functions support in-place transforms. This means they can be called
// with the source as destination, and will transform the image without needing
// new memory. For instance, image_hflip(src, src) flips in-place and replaces
// src with a flipped version of itself.
//
// (However, it is not possible to transform in-place if the source and
// destination intersect in non-trivial ways. The result will be incorrect.)
//
// When transforming to a new image, transparent pixels are ignored, so if the
// destination already has some data, it will not be erased automatically. Use
// image_clear() beforehand to achieve that effect. This allows alpha blending
// while transforming, which is especially useful on the VRAM.
//---
/* image_hflip(): Flip horizontally
Formats: RGB16, P8
Size requirement: destination at least as large as source (no clipping)
Supports in-place: Yes */
void image_hflip(image_t const *src, image_t *dst, bool copy_alpha);
image_t *image_hflip_alloc(image_t const *src);
/* image_vflip(): Flip vertically
Formats: RGB16, P8
Size requirement: destination at least as large as source (no clipping)
Supports in-place: Yes */
void image_vflip(image_t const *src, image_t *dst, bool copy_alpha);
image_t *image_vflip_alloc(image_t const *src);
/* image_linear(): Linear transformation
This function implements a generic linear transformation. This is a powerful
function that can perform any combination of rotation, mirroring and scaling
with nearest-neighbor sampling.
The [image_linear_map] structure defines the settings for the transform.
Users familiar with linear algebra might want to use it directly, but they
are most conveniently generated with the rotation and scaling functions
listed below.
Note: Currently the structure for the transform is modified by the
operation and cannot be reused.
The image_linear_alloc() variant allocates a new image in addition to
performing the transform. The image is created with size (map->dst_w,
map->dst_h) which is always a reasonable default. If a target image of
smaller size is supplied to image_linear(), clipping is performed; only the
top-left corner of the full output is actually rendered.
Formats: RGB16, P8
Size requirement: none (clipping is performed)
Supports in-place: No */
struct image_linear_map {
/* Dimensions of the source and destination */
int src_w, src_h, dst_w, dst_h;
/* Input and output stride in bytes */
int src_stride, dst_stride;
/* The following parameters define the linear transformation as a mapping
from coordinates in the destination image (x and y) into coordinates in
the source image (u and v).
- (u, v) indicate where the top-left corner of the destination lands in
the source image.
- (dx_u, dx_v) indicate the source-image movement for each movement of
x += 1 in the destination.
- (dy_u, dy_v) indicate the source-image movement for each movement of
y += 1 in the destination.
All of these values are specified as 16:16 fixed-point, ie. they encode
decimal values by multiplying them by 65536. */
int u, v, dx_u, dx_v, dy_u, dy_v;
};
void image_linear(image_t const *src, image_t *dst,
struct image_linear_map *map);
image_t *image_linear_alloc(image_t const *src,
struct image_linear_map *map);
/* image_scale(): Upscale or downscale an image
This function generates a linear map to be used in image_linear() to scale
the input image. The scaling factor gamma can be specified independently for
the x and y dimensions. It is expressed as 16:16 fixed-point; you can set
any decimal value multiplied by 65536, for instance 1.5*65536 to increase
the width and height by 50%. */
void image_scale(image_t const *src, int gamma_x, int gamma_y,
struct image_linear_map *map);
/* image_rotate(): Rotate an image around its center
This function generates a linear map to be used in image_linear() to perform
a rotation around the center of an image. If [resize=true], the target is
enlarged to make sure all the rotated pixels can be represented. This can
increase the final surface by a factor of up to 2. If the original image
doesn't extend to its corners, it is recommended to leave [resize=false] as
it noticeably affects performance. */
void image_rotate(image_t const *src, float angle, bool resize,
struct image_linear_map *map);
/* image_rotate_around(): Rotate an image around any point
This function generalizes image_rotate() by allowing rotations around any
center, even a point not within the image. The center is specified through
two coordinates (*center_x, *center_y). If the center is near the side of
the image, a normal rotation would move most of the pixels out of frame;
this function moves the frame to make sure the whole image remains visible.
*center_x and *center_y are updated to indicate the position of the center
of rotation within the new frame (the target image). */
void image_rotate_around(image_t const *src, float angle, bool resize,
int *center_x, int *center_y, struct image_linear_map *map);
/* image_rotate_around_scale(): Rotate an image around any point and scale it
This function generalizes image_rotate_around() by adding a scaling factor
to the transformation. The scaling factor gamma is expressed as 16:16
fixed-point. If [resize=true] the image is further extended to make sure no
parts are cut out, as in other rotation functions. */
void image_rotate_around_scale(
image_t const *src, float angle, int gamma,
bool resize, int *center_x, int *center_y,
struct image_linear_map *map);
//---
// Color transforms
//---
/* TODO: Color transforms */
//---
// Image rendering functions
//
// The following functions extend dimage() and dsubimage(). The [effects]
// parameter takes a combination of IMAGE_* flags and effects, limited to the
// combinations previously described, with additional arguments depending on
// the color effect being applied.
//
// dimage_effect(x, y, img, effects, ...)
// dsubimage_effect(x, y, img, left, top, w, h, effects, ...)
//
// However if you use these super-generic functions you will link the code for
// all effects and all formats into your add-in, which takes a fair amount of
// space. If that's a problem, you can use the more specific functions below:
//
// * dimage_<FORMAT>_<EFFECT>() for one particular format (rgb16, p8, p4) along
// with one particular color effect (clearbg, swapcolor, addbg, dye).
// * dimage_<FORMAT>() is like the above when no color effect is applied.
//
// All of them support the HFLIP and VFLIP flags. For effect-specific functions
// the corresponding effect flag can be omitted (fi. IMAGE_CLEARBG is implicit
// when using dimage_p8_clearbg()).
//---
/* dimage_effect(): Generalized dimage() supporting dynamic effects */
#define dimage_effect(x, y, img, eff, ...) \
dsubimage_effect(x, y, img, 0, 0, (img)->width, (img)->height, eff, \
##__VA_ARGS__)
/* dsubimage_effect(): Generalized dsubimage() supporting dynamic effects */
void dsubimage_effect(int x, int y, image_t const *img,
int left, int top, int w, int h, int effects, ...);
/* Specific versions for each format */
#define DIMAGE_SIG1(NAME, ...) \
void dimage_ ## NAME(int x, int y, image_t const *img,##__VA_ARGS__); \
void dsubimage_ ## NAME(int x, int y, image_t const *img, \
int left, int top, int w, int h, ##__VA_ARGS__);
#define DIMAGE_SIG(NAME, ...) \
DIMAGE_SIG1(rgb16 ## NAME, ##__VA_ARGS__) \
DIMAGE_SIG1(p8 ## NAME, ##__VA_ARGS__) \
DIMAGE_SIG1(p4 ## NAME, ##__VA_ARGS__)
/* d[sub]image_{rgb16,p8,p4}_effect(..., effects, <extra arguments>) */
DIMAGE_SIG(_effect, int effects, ...)
/* d[sub]image_{rgb16,p8,p4}(..., effects) (no color effect, like dimage()) */
DIMAGE_SIG(, int effects)
/* d[sub]image_{rgb16,p8,p4}_clearbg(..., effects, bg_color_or_index) */
DIMAGE_SIG(_clearbg, int effects, int bg_color_or_index)
/* d[sub]image_{rgb16,p8,p4}_swapcolor(..., effects, source, replacement) */
DIMAGE_SIG(_swapcolor, int effects, int source, int replacement)
/* d[sub]image_{rgb16,p8,p4}_addbg(..., effects, bg_color) */
DIMAGE_SIG(_addbg, int effects, int bg_color)
/* d[sub]image_{rgb16,p8,p4}_dye(..., effects, dye_color) */
DIMAGE_SIG(_dye, int effects, int dye_color)
/* d[sub]image_p4_clearbg_alt(..., effects, bg_index)
This is functionally identical to CLEARBG, but it uses an alternative
rendering method that is faster for larger images with wide transparent
areas. You can swap it with the normal CLEARBG freely. */
DIMAGE_SIG1(p4_clearbg_alt, int effects, int bg_index)
#define dimage_rgb16_effect(x, y, img, eff, ...) \
dsubimage_rgb16_effect(x, y, img, 0, 0, (img)->width, (img)->height, \
eff, ##__VA_ARGS__)
#define dimage_p8_effect(x, y, img, eff, ...) \
dsubimage_p8_effect(x, y, img, 0, 0, (img)->width, (img)->height, \
eff, ##__VA_ARGS__)
#define dimage_p4_effect(x, y, img, eff, ...) \
dsubimage_p4_effect(x, y, img, 0, 0, (img)->width, (img)->height, \
eff, ##__VA_ARGS__)
#undef DIMAGE_SIG
#undef DIMAGE_SIG1
//---
// Clipping utilities
//---
/* Double box specifying both a source and target area */
struct gint_image_box
{
/* Target location of top-left corner */
int x, y;
/* Width and height of rendered sub-image */
int w, h;
/* Source bounding box (low included, high excluded) */
int left, top;
};
/* Clip the provided box against the input. If, after clipping, the box no
longer intersects the output window, returns false. Otherwise, returns
true. */
bool gint_image_clip_input(image_t const *img, struct gint_image_box *box,
struct dwindow const *window);
/* Clip the provided box against the output. */
void gint_image_clip_output(struct gint_image_box *b,
struct dwindow const *window);
//---
// Internal image rendering routines
//
// The following functions (or non-functions) are implemented in assembler and
// make up the internal interface of the image renderer. If you just want to
// display images, use dimage() and variations; these are only useful if you
// have a different rendering system and wish to use image rendering with
// dynamic effects in it.
//---
/* Renderer command. This structure includes most of the information used by
the image renderer to perform blits. Some of the information on the target
is also passed as direct arguments, which is more convenient and slightly
faster.
Most of the values here can be set with gint_image_mkcmd(). The last two
members, along with the return values of the gint_image_FORMAT_loop()
functions, are used to update the command if one needs to draw *parts* of
the image and resume the rendering later. This is used in Azur. */
struct gint_image_cmd
{
/* Shader ID. This is used in Azur, and ignored in gint */
uint8_t shader_id;
/* Dynamic effects not already dispatched by renderer
Bit 0: VFLIP
Bit 1: HFLIP */
uint8_t effect;
/* Number of pixels to render per line. For formats that force either x
or width alignment (most of them), this is already adjusted to a
suitable multiple (usually a multiple of 2). */
int16_t columns;
/* Stride of the input image (number of pixels between each row), in
pixels, without subtracting the number of columns */
int16_t input_stride;
/* Number of lines in the command. This can be adjusted freely, and is
particularly useful in Azur for fragmented rendering. */
uint8_t lines;
/* [Any effect]: Offset of first edge */
int8_t edge_1;
/* Core loop; this is an internal label of the renderer */
void const *loop;
/* Output pixel array, offset by target x/y */
void const *output;
/* Input pixel array, offset by source x/y. For formats that force x
alignment, this is already adjusted. */
void const *input;
/* Palette, when applicable */
uint16_t const *palette;
/* [Any effect]: Offset of right edge */
int16_t edge_2;
/* [CLEARBG, SWAPCOLOR]: Source color */
uint16_t color_1;
/* [SWAPCOLOR]: Destination color */
uint16_t color_2;
/* Remaining height (for updates between fragments) */
int16_t height;
/* Local x position (for updates between fragments) */
int16_t x;
};
/* gint_image_mkcmd(): Prepare a rendering command with dynamic effects
This function crafts an image renderer command. It loads all the settings
except for effect-dependent parameters: the [.loop] label, the color section
of [.effect], and color effect settings. See the effect-specific functions
to see how they are defined.
The benefit of this approach is that the rendering code does not need to be
linked in unless an effect is actually used, which avoids blowing up the
size of the add-in as the number of support dynamic effects increases.
@box Requested on-screen box (will be clipped depending on effects)
@img Source image
@effects Set of dynamic effects to be applied, as an [IMAGE_*] bitmask
@left_edge Whether to force 2-alignment on the input (box->left)
@right_edge Whether to force 2-alignment on the width
@cmd Command to be filled
@window Rendering window (usually {0, 0, DWIDTH, DHEIGHT})
Returns false if there is nothing to render because of clipping (in which
case [cmd] is unchanged), true otherwise. [*box] is also updated to reflect
the final box after clipping but not accounting for edges. */
bool gint_image_mkcmd(struct gint_image_box *box, image_t const *img,
int effects, bool left_edge, bool right_edge,
struct gint_image_cmd *cmd, struct dwindow const *window);
/* Entry point of the renderers. These functions can be called normally as long
as you can build the commands (eg. by using gint_image_mkcmd() then filling
the effect-specific information). */
void *gint_image_rgb16_loop (int output_width, struct gint_image_cmd *cmd);
void *gint_image_p8_loop (int output_width, struct gint_image_cmd *cmd);
void *gint_image_p4_loop (int output_width, struct gint_image_cmd *cmd);
/* Renderer fragments. The following can absolutely not be called from C code
as they aren't full functions (and this isn't their prototype). These are
continuations to be specified in the [.loop] field of a command before using
one of the functions above. */
void gint_image_rgb16_normal(void);
void gint_image_rgb16_clearbg(void);
void gint_image_rgb16_swapcolor(void);
void gint_image_rgb16_dye(void);
void gint_image_p8_normal(void);
void gint_image_p8_clearbg(void);
void gint_image_p8_swapcolor(void);
void gint_image_p8_dye(void);
void gint_image_p4_normal(void);
void gint_image_p4_clearbg(void);
void gint_image_p4_clearbg_alt(void);
void gint_image_p4_swapcolor(void);
void gint_image_p4_dye(void);
//---
// Image library utilities
//
// The following functions and macros are mostly internal utilities; they are
// exposed here in case user applications want to extend the set of image
// transforms with custom additions.
//---
/* image_target(): Check if an image can be used as target for a transform
This function is used to quickly check whether a transform from [src] to
[dst] is possible. It requires image_valid(src) and image_valid(dst), plus
any optional constraints specified as variadic arguments. These constraints
can be:
* NOT_P4: fails if [dst] is P4.
* DATA_RW: fails if [dst] is not data-writable.
* PALETTE_RW: fails if [dst] is not palette-writable.
* SAME_SIZE: fails if [dst] is not at least as large as [src].
For example, in image_hflip(), we write:
if(!image_target(src, dst, NOT_P4, DATA_RW, SAME_SIZE)) return; */
enum {
IMAGE_TARGET_NONE,
IMAGE_TARGET_NOT_P4,
IMAGE_TARGET_DATA_RW,
IMAGE_TARGET_PALETTE_RW,
IMAGE_TARGET_SAME_SIZE,
IMAGE_TARGET_SAME_FORMAT,
IMAGE_TARGET_SAME_DEPTH,
};
bool image_target(image_t const *src, image_t *dst, ...);
#define image_target(src, dst, ...) \
image_target(src, dst, image_target_arg1(__VA_ARGS__ __VA_OPT__(,) NONE))
#define image_target_arg1(c, ...) \
IMAGE_TARGET_ ## c __VA_OPT__(, image_target_arg2(__VA_ARGS__))
#define image_target_arg2(c, ...) \
IMAGE_TARGET_ ## c __VA_OPT__(, image_target_arg3(__VA_ARGS__))
#define image_target_arg3(c, ...) \
IMAGE_TARGET_ ## c __VA_OPT__(, image_target_arg4(__VA_ARGS__))
#define image_target_arg4(c, ...) \
IMAGE_TARGET_ ## c __VA_OPT__(, image_target_arg5(__VA_ARGS__))
#define image_target_arg5(c, ...) \
IMAGE_TARGET_ ## c __VA_OPT__(, image_target_arg6(__VA_ARGS__))
#define image_target_arg6(c, ...) \
IMAGE_TARGET_ ## c __VA_OPT__(, image_target_too_many_args(__VA_ARGS__))
/* image_alpha_2(): Conditional alpha */
#define image_alpha_2(fmt, copy_alpha) \
((copy_alpha) ? 0x10000 : image_alpha(fmt))
#endif /* GINT_RENDER_RGB */
#ifdef __cplusplus
}
#endif
#endif /* GINT_IMAGE */

View File

@ -1,23 +0,0 @@
#include <cstdlib>
#include <vector>
#include <map>
#include <iostream>
#include "game_data.hpp"
struct texture_t builtin_textures[NB_TEXTURES] = {
{"player_idle_sheet", &img_player_idle_sheet},
{"player_walk_sheet", &img_player_walk_sheet}
};
void load_json_into_game_data(json *json_input, game_data_t *bin_output)
{
}
void write_game_data_as_bin_into_file(game_data_t *game_data, std::ofstream *bin_output_file)
{
}
void free_game_data(game_data_t *game_data)
{
}

View File

@ -1,31 +0,0 @@
#ifndef GAME_DATA_HPP
#define GAME_DATA_HPP
#include <fstream>
#include <gint/display-cg.h>
#include "nlohmann/json/json.hpp"
using nlohmann::json;
extern bopti_image_t img_player_idle_sheet;
extern bopti_image_t img_player_walk_sheet;
typedef struct texture_t {
const char *name;
bopti_image_t *image;
} texture_t;
#define NB_TEXTURES 2
extern struct texture_t builtin_textures[];
typedef struct game_data_t {
texture_t *textures;
} game_data_t;
void load_json_into_game_data(json *json_input, game_data_t *game_data);
void write_game_data_as_bin_into_file(game_data_t *game_data, std::ofstream *bin_output_file);
void free_game_data(game_data_t *game_data);
#endif // GAME_DATA_HPP

View File

@ -0,0 +1,16 @@
#ifndef ANIMATION_SYSTEM_H
#define ANIMATION_SYSTEM_H
#include <stdint.h>
typedef struct animation_system_data_t {
bool play :1;
bool loop :1;
bool reverse :1;
float frame_delay_ms;
uint32_t actual_frame_nb;
uint32_t nb_frames;
} animation_system_data_t;
#endif // SPRITE_COMPONENT_H

View File

@ -0,0 +1,9 @@
#ifndef COMPONENTS_H
#define COMPONENTS_H
#include "transform_component.hpp"
#include "sprite_component.hpp"
#include "animation_system.hpp"
// Add new components header file here
#endif // COMPONENTS_H

31
src/game_data/ecs/ecs.hpp Normal file
View File

@ -0,0 +1,31 @@
#ifndef ECS_H
#define ECS_H
#include <stdint.h>
#include "components.hpp"
typedef enum component_type_t {
TRANSFORM_COMPONENT,
SPRITE_COMPONENT,
ANIMATION_SYSTEM
} component_type_t;
typedef struct component_t {
component_type_t component_type;
union {
transform_component_data_t *transform_component_data;
sprite_component_data_t *sprite_component_data;
animation_system_data_t *animation_system_data;
} component_data;
} component_t;
typedef struct entity_t {
uint16_t id;
unsigned long nb_component;
component_t *components;
} entity_t;
#endif // ECS_H

View File

@ -0,0 +1,8 @@
#ifndef SPRITE_COMPONENT_H
#define SPRITE_COMPONENT_H
typedef struct sprite_component_data_t {
const char *texture_name;
} sprite_component_data_t;
#endif // SPRITE_COMPONENT_H

View File

@ -0,0 +1,10 @@
#ifndef TRANSFORM_COMPONENT_H
#define TRANSFORM_COMPONENT_H
typedef struct transform_component_data_t {
uint32_t x, y;
uint32_t w, h;
float speed;
} transform_component_data_t;
#endif // TRANSFORM_COMPONENT_H

View File

@ -0,0 +1,11 @@
#include <iostream>
#include "game_data.hpp"
void load_game_data(game_data_t *game_data)
{
}
void write_game_data_as_bin_into_file(game_data_t *game_data, std::ofstream *bin_output_file)
{
}

View File

@ -0,0 +1,21 @@
#ifndef GAME_DATA_HPP
#define GAME_DATA_HPP
#include <fstream>
#include "textures.hpp"
#include "maps.hpp"
typedef struct game_data_t {
uint32_t nb_textures;
texture_t *textures;
uint32_t nb_maps;
map_t *maps;
} game_data_t;
void load_game_data(game_data_t *game_data);
void write_game_data_as_bin_into_file(game_data_t *game_data, std::ofstream *bin_output_file);
#endif // GAME_DATA_HPP

29
src/game_data/maps.hpp Normal file
View File

@ -0,0 +1,29 @@
#ifndef MAP_HPP
#define MAP_HPP
#include "ecs/ecs.hpp"
typedef struct map_t {
const char *name;
uint32_t map_width;
uint32_t map_height;
uint16_t *map_background_layer1;
uint16_t *map_background_layer2;
uint16_t *map_background_layer3;
uint16_t *map_foreground;
uint32_t nb_entities;
entity_t *entities;
} map_t;
extern map_t map_example;
static map_t *maps[] = {
&map_example
};
#define NB_MAPS sizeof(maps) / sizeof(map_t)
#endif // MAP_HPP

View File

@ -0,0 +1,25 @@
#ifndef TEXTURES_HPP
#define TEXTURES_HPP
#include <gint/image.h>
typedef struct texture_t {
const char *name;
bopti_image_t *image;
} texture_t;
extern bopti_image_t img_tileset;
extern bopti_image_t img_player_idle_sheet;
extern bopti_image_t img_player_walk_sheet;
extern bopti_image_t img_player_run_sheet;
static texture_t textures[] = {
{"tileset", &img_tileset},
{"player_idle_sheet", &img_player_idle_sheet},
{"player_walk_sheet", &img_player_walk_sheet},
{"player_run_sheet", &img_player_run_sheet}
};
#define NB_TEXTURES sizeof(textures) / sizeof(texture_t)
#endif // TEXTURE_HPP

View File

@ -1,6 +1,6 @@
#include <iostream> #include <iostream>
#include "game_data.hpp" #include "game_data/game_data.hpp"
void error(std::string error); void error(std::string error);
@ -12,13 +12,6 @@ int main(int argc, char *argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} }
std::ifstream json_input_file {argv[1]};
if(!json_input_file)
{
error("Couldn't open input file");
return EXIT_FAILURE;
}
std::ofstream bin_output_file {argv[2], std::ios::binary}; std::ofstream bin_output_file {argv[2], std::ios::binary};
if(!bin_output_file) if(!bin_output_file)
{ {
@ -26,15 +19,12 @@ int main(int argc, char *argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} }
json json_input = json::parse(json_input_file);
game_data_t game_data; game_data_t game_data;
load_json_into_game_data(&json_input, &game_data); load_game_data(&game_data);
write_game_data_as_bin_into_file(&game_data, &bin_output_file); write_game_data_as_bin_into_file(&game_data, &bin_output_file);
free_game_data(&game_data);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -1,14 +0,0 @@
#include <stdio.h>
#include <gint/display-cg.h>
extern bopti_image_t img_tileset;
int main(void)
{
int16_t value = 0;
printf("colorcount:%d, value:%d\n", img_tileset.color_count, value);
printf("width:%d, height:%d\n", img_tileset.width, img_tileset.height);
printf("totalsize:%ld\n", sizeof(img_tileset) + img_tileset.width * img_tileset.height);
return 0;
}