diff --git a/archive/asset/CMakeLists.txt b/archive/asset/CMakeLists.txt new file mode 100644 index 0000000..f542548 --- /dev/null +++ b/archive/asset/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + asset.c + assetpalette.c + assettileset.c + assetpaletteimage.c +) + +# Compile definitions +target_compile_definitions(${DUSK_TARGET_NAME} + PRIVATE + ASSET_TYPE=wad +) \ No newline at end of file diff --git a/src/asset/asset.c b/archive/asset/asset.c similarity index 100% rename from src/asset/asset.c rename to archive/asset/asset.c diff --git a/src/asset/asset.h b/archive/asset/asset.h similarity index 100% rename from src/asset/asset.h rename to archive/asset/asset.h diff --git a/src/asset/assetpalette.c b/archive/asset/assetpalette.c similarity index 100% rename from src/asset/assetpalette.c rename to archive/asset/assetpalette.c diff --git a/src/asset/assetpalette.h b/archive/asset/assetpalette.h similarity index 100% rename from src/asset/assetpalette.h rename to archive/asset/assetpalette.h diff --git a/src/asset/assetpaletteimage.c b/archive/asset/assetpaletteimage.c similarity index 100% rename from src/asset/assetpaletteimage.c rename to archive/asset/assetpaletteimage.c diff --git a/src/asset/assetpalleteimage.h b/archive/asset/assetpalleteimage.h similarity index 100% rename from src/asset/assetpalleteimage.h rename to archive/asset/assetpalleteimage.h diff --git a/src/asset/assettileset.c b/archive/asset/assettileset.c similarity index 100% rename from src/asset/assettileset.c rename to archive/asset/assettileset.c diff --git a/src/asset/assettileset.h b/archive/asset/assettileset.h similarity index 100% rename from src/asset/assettileset.h rename to archive/asset/assettileset.h diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index 4af287a..a4c04e8 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -4,6 +4,7 @@ # https://opensource.org/licenses/MIT add_asset(PALETTE first.palette.png) +add_asset(IMAGE minogram_6x10.png type=ALPHA) +add_asset(IMAGE entities.png type=PALETTIZED) -# add_asset(TILESET entities.tsx) -# add_asset(IMAGE minogram_6x10.png) \ No newline at end of file +# add_asset(TILESET entities.tsx) \ No newline at end of file diff --git a/src/asset/CMakeLists.txt b/src/asset/CMakeLists.txt index f542548..29b4dbc 100644 --- a/src/asset/CMakeLists.txt +++ b/src/asset/CMakeLists.txt @@ -1,19 +1,10 @@ # Copyright (c) 2025 Dominic Masters -# +# # This software is released under the MIT License. # https://opensource.org/licenses/MIT # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - asset.c - assetpalette.c - assettileset.c - assetpaletteimage.c -) - -# Compile definitions -target_compile_definitions(${DUSK_TARGET_NAME} - PRIVATE - ASSET_TYPE=wad + assetmanager.c ) \ No newline at end of file diff --git a/src/asset/assetmanager.c b/src/asset/assetmanager.c new file mode 100644 index 0000000..893b915 --- /dev/null +++ b/src/asset/assetmanager.c @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assetmanager.h" +#include "util/memory.h" +#include "console/console.h" +#include "util/string.h" +#include "assert/assert.h" + +#define ASSET_ASSET_FILE "dusk.dsk" + +assetmanager_t ASSET_MANAGER; + +errorret_t assetManagerInit(void) { + memoryZero(&ASSET_MANAGER, sizeof(assetmanager_t)); + + // Open zip file + char_t searchPath[FILENAME_MAX]; + consolevar_t *var = consoleVarGet("sys_path"); + const char_t *sysPath = var ? var->value : "."; + for(int32_t i = 0; i < ASSET_MANAGER_SEARCH_PATHS_COUNT; i++) { + sprintf( + searchPath, + ASSET_MANAGER_SEARCH_PATHS[i], + sysPath, + ASSET_ASSET_FILE + ); + + // Try open + ASSET_MANAGER.zip = zip_open(searchPath, ZIP_RDONLY, NULL); + if(ASSET_MANAGER.zip == NULL) continue; + consolePrint("Opened asset file: %s", searchPath); + break; + } + + // Did we open the asset? + if(ASSET_MANAGER.zip == NULL) errorThrow("Failed to open asset file."); + + errorOk(); +} + +void assetManagerDispose(void) { + if(ASSET_MANAGER.zip != NULL) { + zip_close(ASSET_MANAGER.zip); + ASSET_MANAGER.zip = NULL; + } +} \ No newline at end of file diff --git a/src/asset/assetmanager.h b/src/asset/assetmanager.h new file mode 100644 index 0000000..a1cbc34 --- /dev/null +++ b/src/asset/assetmanager.h @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "error/error.h" +#include +#include "display/texture/texture.h" + +#if ASSET_TYPE == wad +#else + #error "Unsupported ASSET_TYPE" +#endif + +static const char_t ASSET_MANAGER_SEARCH_PATHS[][FILENAME_MAX] = { + "%s/%s", + "./%s", + "../%s", + "../../%s", + "data/%s", + "../data/%s", +}; + +#define ASSET_MANAGER_SEARCH_PATHS_COUNT (\ + sizeof(ASSET_MANAGER_SEARCH_PATHS) / FILENAME_MAX\ +) + +typedef struct { + int32_t nothing; + zip_t *zip; +} assetmanager_t; + +extern assetmanager_t ASSET_MANAGER; + +/** + * Initializes the asset system. + */ +errorret_t assetManagerInit(void); + +/** + * Disposes/cleans up the asset system. + */ +void assetManagerDispose(void); \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c index 91dfc7e..6e214f5 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -10,7 +10,7 @@ #include "time/time.h" #include "console/console.h" #include "display/display.h" -#include "asset/asset.h" +#include "asset/assetmanager.h" #include "rpg/rpg.h" engine_t ENGINE; @@ -22,7 +22,7 @@ errorret_t engineInit(void) { // Init systems. Order is important. timeInit(); consoleInit(); - errorChain(assetInit()); + errorChain(assetManagerInit()); errorChain(displayInit()); rpgInit(); @@ -39,7 +39,7 @@ errorret_t engineUpdate(void) { errorret_t engineDispose(void) { errorChain(displayDispose()); - assetDispose(); + assetManagerDispose(); consoleDispose(); errorOk(); diff --git a/tools/assetstool/processasset.py b/tools/assetstool/processasset.py index ef40ec2..cd182e5 100644 --- a/tools/assetstool/processasset.py +++ b/tools/assetstool/processasset.py @@ -1,6 +1,6 @@ import sys # from processtileset import processTileset -# from processimage import processPalette, processImage +from processimage import processImage from processpalette import processPalette processedAssets = [] @@ -15,8 +15,8 @@ def processAsset(asset): t = asset['type'].lower() if t == 'palette': return processPalette(asset) - # elif t == 'image': - # return processImage(asset) + elif t == 'image': + return processImage(asset) # elif t == 'tileset': # return processTileset(asset) else: diff --git a/tools/assetstool/processimage.py b/tools/assetstool/processimage.py new file mode 100644 index 0000000..e852a43 --- /dev/null +++ b/tools/assetstool/processimage.py @@ -0,0 +1,78 @@ +import os +import sys +from PIL import Image +from processpalette import extractPaletteFromImage, palettes +from args import args +from assethelpers import getAssetRelativePath + +images = [] + +def processImage(asset): + type = asset['options'].get('type', 'PALETTIZED').upper() + if type == 'PALETTIZED': + return processPalettizedImage(asset) + elif type == 'ALPHA': + return processAlphaImage(asset) + else: + print(f"Error: Unknown image type {type} for asset {asset['path']}") + sys.exit(1) + +def processPalettizedImage(asset): + assetPath = asset['path'] + + image = Image.open(assetPath) + imagePalette = extractPaletteFromImage(image) + + # Find palette that contains every color + for palette in palettes: + if all(color in palette['pixels'] for color in imagePalette): + break + else: + print(f"No matching palette found for {assetPath}!") + # Find which pixel is missing + for color in imagePalette: + if color not in palette: + print(f"Missing color: {color}") + sys.exit(1) + + print(f"Converting image {assetPath} to use palette") + + paletteIndexes = [] + for pixel in list(image.getdata()): + if pixel[3] == 0: + pixel = (0, 0, 0, 0) + paletteIndex = palette['pixels'].index(pixel) + paletteIndexes.append(paletteIndex) + + data = bytearray() + data.extend(b"DPI") # Dusk Palettized Image + data.extend(image.width.to_bytes(4, 'little')) # Width + data.extend(image.height.to_bytes(4, 'little')) # Height + data.append(palette['paletteIndex']) # Palette index + for paletteIndex in paletteIndexes: + if paletteIndex > 255 or paletteIndex < 0: + print(f"Error: Palette index {paletteIndex} exceeds 255!") + sys.exit(1) + data.append(paletteIndex.to_bytes(1, 'little')[0]) # Pixel index + + relative = getAssetRelativePath(assetPath) + fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0] + outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dpi") + outputFilePath = os.path.join(args.output_assets, outputFileRelative) + os.makedirs(os.path.dirname(outputFilePath), exist_ok=True) + with open(outputFilePath, "wb") as f: + f.write(data) + + outImage = { + "files": [ outputFilePath ], + } + return outImage + +def processAlphaImage(asset): + assetPath = asset['path'] + print(f"Processing alpha image: {assetPath}") + + outImage = { + "files": [] + } + return outImage \ No newline at end of file diff --git a/tools/assetstool/processpalette.py b/tools/assetstool/processpalette.py index 6431098..4d91b97 100644 --- a/tools/assetstool/processpalette.py +++ b/tools/assetstool/processpalette.py @@ -13,7 +13,7 @@ def extractPaletteFromImage(image): pixels = list(image.getdata()) uniqueColors = [] for color in pixels: - # We treat alpha 0 as rgba(0,0,0,0) for palette purposes + # We treat all alpha 0 as rgba(0,0,0,0) for palette purposes if color[3] == 0: color = (0, 0, 0, 0) if color not in uniqueColors: