commit 2315a6218366ea6979658b003ca2c1213fe6f0f0 Author: sillysagiri Date: Sun Dec 26 11:36:57 2021 +0700 lets just commit before i break more stuff diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..775a761 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/assets/* +!/assets/convert.sh + +/NDS/nitrofiles/* +!/NDS/nitrofiles/.gitignore +/NDS/cmake +/NDS/compile_commands.json + +/encoder/node_modules + +/temp diff --git a/NDS/CMakeLists.txt b/NDS/CMakeLists.txt new file mode 100644 index 0000000..9e9a84c --- /dev/null +++ b/NDS/CMakeLists.txt @@ -0,0 +1,38 @@ + +# That file is here only to make IDE's happy so they could index all source files. +# Real building happens through Makefile. + +cmake_minimum_required(VERSION 3.10) +project(myProject) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set to your devkitPro's installation dir if environment variable does not exist. +set(DEVKITPRO /opt/devkitpro) + +include(${DEVKITPRO}/cmake/devkitARM.cmake) + +include_directories(${DEVKITPRO}/libnds/lib) +include_directories(${DEVKITPRO}/libnds/include) +include_directories(${DEVKITPRO}/libnds/include/nds) +include_directories(${DEVKITPRO}/libnds/include/nds/arm9) +include_directories(${DEVKITPRO}/devkitARM) +include_directories(${DEVKITPRO}/devkitARM/arm-none-eabi/include) +include_directories(source) +include_directories(fonts) +include_directories(data) +include_directories(build) + +link_directories(${DEVKITPRO}/libnds/lib) +link_directories(${DEVKITPRO}/libnds/include) +link_directories(${DEVKITPRO}/libnds/include/nds) +link_directories(${DEVKITPRO}/libnds/include/nds/arm9) + +add_compile_definitions(ARM9) +add_compile_definitions(ARM7) +add_compile_definitions(iprintf=printf) + +FILE(GLOB_RECURSE src *.cpp *.hpp *.c *.h) + +add_executable(myProject ${src}) \ No newline at end of file diff --git a/NDS/Makefile b/NDS/Makefile new file mode 100644 index 0000000..832b3a7 --- /dev/null +++ b/NDS/Makefile @@ -0,0 +1,222 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +# These set the information text in the nds file +GAME_TITLE := Bad Apple DS +GAME_SUBTITLE1 := Created by Melody +GAME_SUBTITLE2 := https://melody.my.id + +include $(DEVKITARM)/ds_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +# DATA is a list of directories containing binary files embedded using bin2o +# GRAPHICS is a list of directories containing image files to be converted with grit +# AUDIO is a list of directories containing audio to be converted by maxmod +# ICON is the image used to create the game icon, leave blank to use default rule +# NITRO is a directory that will be accessible via NitroFS +#--------------------------------------------------------------------------------- +TARGET := $(shell basename $(CURDIR)) +BUILD := build +DIST := dist +SOURCES := source +INCLUDES := include +DATA := data +GRAPHICS := +AUDIO := maxmod +ICON := + +# specify a directory which contains the nitro filesystem +# this is relative to the Makefile +NITRO := nitrofiles + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -marm -mthumb-interwork -march=armv5te -mtune=arm946e-s + +CFLAGS := -g -Wall -O3\ + $(ARCH) $(INCLUDE) -DARM9 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project (order is important) +#--------------------------------------------------------------------------------- +LIBS := -lnds9 + +# automatigically add libraries for NitroFS +ifneq ($(strip $(NITRO)),) +LIBS := -lfilesystem -lfat $(LIBS) +endif +# automagically add maxmod library +ifneq ($(strip $(AUDIO)),) +LIBS := -lmm9 $(LIBS) +endif + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) $(PORTLIBS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(DIST)/$(TARGET) + +export VPATH := $(CURDIR)/$(subst /,,$(dir $(ICON)))\ + $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))\ + $(foreach dir,$(DATA),$(CURDIR)/$(dir))\ + $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +# prepare NitroFS directory +ifneq ($(strip $(NITRO)),) + export NITRO_FILES := $(CURDIR)/$(NITRO) +endif + +# get audio list for maxmod +ifneq ($(strip $(AUDIO)),) + export MODFILES := $(foreach dir,$(notdir $(wildcard $(AUDIO)/*.*)),$(CURDIR)/$(AUDIO)/$(dir)) + + # place the soundbank file in NitroFS if using it + ifneq ($(strip $(NITRO)),) + export SOUNDBANK := $(NITRO_FILES)/soundbank.bin + + # otherwise, needs to be loaded from memory + else + export SOUNDBANK := soundbank.bin + BINFILES += $(SOUNDBANK) + endif +endif + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) + +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export OFILES := $(PNGFILES:.png=.o) $(OFILES_BIN) $(OFILES_SOURCES) + +export HFILES := $(PNGFILES:.png=.h) $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir))\ + $(foreach dir,$(LIBDIRS),-I$(dir)/include)\ + -I$(CURDIR)/$(BUILD) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +ifeq ($(strip $(ICON)),) + icons := $(wildcard *.bmp) + + ifneq (,$(findstring $(TARGET).bmp,$(icons))) + export GAME_ICON := $(CURDIR)/$(TARGET).bmp + else + ifneq (,$(findstring icon.bmp,$(icons))) + export GAME_ICON := $(CURDIR)/icon.bmp + endif + endif +else + ifeq ($(suffix $(ICON)), .grf) + export GAME_ICON := $(CURDIR)/$(ICON) + else + export GAME_ICON := $(CURDIR)/$(BUILD)/$(notdir $(basename $(ICON))).grf + endif +endif + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @mkdir -p $@ + @mkdir -p $(DIST) + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(SOUNDBANK) $(DIST) + +#--------------------------------------------------------------------------------- +else + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).nds: $(OUTPUT).elf $(NITRO_FILES) $(GAME_ICON) +$(OUTPUT).elf: $(OFILES) + +# source files depend on generated headers +$(OFILES_SOURCES) : $(HFILES) + +# need to build soundbank first +$(OFILES): $(SOUNDBANK) + +#--------------------------------------------------------------------------------- +# rule to build solution from music files +#--------------------------------------------------------------------------------- +$(SOUNDBANK) : $(MODFILES) +#--------------------------------------------------------------------------------- + mmutil $^ -d -o$@ -hsoundbank.h + +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------- +# This rule creates assembly source files using grit +# grit takes an image file and a .grit describing how the file is to be processed +# add additional rules like this for each image extension +# you use in the graphics folders +#--------------------------------------------------------------------------------- +%.s %.h: %.png %.grit +#--------------------------------------------------------------------------------- + grit $< -fts -o$* + +#--------------------------------------------------------------------------------- +# Convert non-GRF game icon to GRF if needed +#--------------------------------------------------------------------------------- +$(GAME_ICON): $(notdir $(ICON)) +#--------------------------------------------------------------------------------- + @echo convert $(notdir $<) + @grit $< -g -gt -gB4 -gT FF00FF -m! -p -pe 16 -fh! -ftr + +-include $(DEPSDIR)/*.d + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/NDS/nitrofiles/.gitignore b/NDS/nitrofiles/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/NDS/source/main.cpp b/NDS/source/main.cpp new file mode 100644 index 0000000..c464884 --- /dev/null +++ b/NDS/source/main.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include + +#define TIMER_SPEED (BUS_CLOCK/1024) + +FILE* file = 0; +std::ifstream in; + +uint16_t blockSize; +char buffer[256*192*2]; +char buffer2[256*256*2]; + +void VBlankProc() { + in.read((char*)&blockSize, sizeof(blockSize)); + in.read(buffer, blockSize); +} + +mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format ) { + if(file){ + size_t samplesize = 1; + switch(format){ + case MM_STREAM_8BIT_MONO: samplesize = 1; break; + case MM_STREAM_8BIT_STEREO: samplesize = 2; break; + case MM_STREAM_16BIT_MONO: samplesize = 2; break; + case MM_STREAM_16BIT_STEREO: samplesize = 4; break; + } + + int res = fread(dest,samplesize,length,file); + if(res){ + length = res; + } else { + mmStreamClose(); + fclose(file); + length = 0; + } + } + return length; +} + +int main(void) { + consoleDebugInit(DebugDevice_NOCASH); + + videoSetMode(MODE_FB0); + vramSetBankA(VRAM_A_LCD); + + std::cerr << "<=== init ===>" << std::endl; + + + // nitrofiles initialization + if (nitroFSInit(NULL)) { + chdir("nitro:/"); + std::cerr << "nitrofs init success" << std::endl; + } else { + consoleDemoInit(); + std::cout << "cannot init nitrofs" << std::endl; + while(1) { + // freezee + } + } + + in.open("output", std::ios::binary); + + uint16_t totalsize; + char buf[256*192*2]; + char buf2[256*256*2]; + + in.read((char*)&totalsize, sizeof(totalsize)); + in.read(buf, totalsize); + + swiDecompressLZSSWram(buf, buf2); + dmaCopyWordsAsynch(3, buf2, VRAM_A, 256*192*2); + + // for (int i=0; i<192*256; i++) { + // VRAM_A[i] = buf[i]; + // } + + while(1) { + // loop + } + + mmInitDefault((char*)"soundbank.bin"); + file = fopen("music.raw","rb"); + + mm_stream mystream; + mystream.sampling_rate = 22050; // sampling rate = 25khz + mystream.buffer_length = 1200; // buffer length = 1200 samples + mystream.callback = on_stream_request; // set callback function + mystream.format = MM_STREAM_16BIT_MONO; // format = stereo 16-bit + mystream.timer = MM_TIMER0; // use hardware timer 0 + mystream.manual = false; // use manual filling + mmStreamOpen( &mystream ); + + irqSet(IRQ_VBLANK, VBlankProc); + + while(1) { + // loop + } + + in.open("data_compress", std::ios::in | std::ios::binary); + + while(1) { + swiDecompressLZSSWram(buffer, buffer2); + dmaCopyWordsAsynch(3, buffer2, VRAM_A, 256*192*2); + + swiWaitForVBlank(); + } + + // crashh + return 0; +} diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..f040350 --- /dev/null +++ b/README.MD @@ -0,0 +1,4 @@ +# my really crappy bad apple port + +contain voodoo and black magic... +check the workflow... im to lazy to explain \ No newline at end of file diff --git a/assets/convert.sh b/assets/convert.sh new file mode 100644 index 0000000..9f8d06b --- /dev/null +++ b/assets/convert.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +palette="palette.png" +video="video.mp4" +output="out.gif" + +filters="fps=30,scale=256x192" +skip="-t 1 -ss 00:8" + +# old +ffmpeg -i $video -vf "$filters,palettegen=max_colors=256:reserve_transparent=" -y $palette +ffmpeg -i $video -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse=dither=none" -y $output + +# unreleased +# ffmpeg -i $video -vf "$filters" out/out_%d.bmp + +# audio +ffmpeg -i $video -f s16le -ac 1 -ar 48000 music.raw \ No newline at end of file diff --git a/encoder/cpp/BMPlib.h b/encoder/cpp/BMPlib.h new file mode 100644 index 0000000..f799d42 --- /dev/null +++ b/encoder/cpp/BMPlib.h @@ -0,0 +1,638 @@ +/* + Author: Leon Etienne + Copyright (c) 2021, Leon Etienne + https://github.com/Leonetienne + https://github.com/Leonetienne/BMPlib + + License: + Don't Be a Jerk: The Open Source Software License. Last Update: Jan, 7, 2021 + This software is free and open source. + Please read the full license: https://github.com/Leonetienne/BMPlib/blob/master/license.txt + + #define BMPLIB_SILENT + if you want bmplib to stop writing exceptions to stderr +*/ + +#pragma once +#include +#include +#include + +#define BMPLIB_VERSION 0.602 + +namespace BMPlib +{ + typedef unsigned char byte; + typedef unsigned short byte2; + typedef unsigned int byte4; + + using bytestring = std::basic_string; + using bytestream = std::basic_stringstream; + + template + // Will convert (int)15 to 0F 00 00 00 and NOT TO 00 00 00 0F + bytestring ToBytes(T t) + { + bytestream toret; + long long sizeofT = (long long)sizeof(T); // Let's make it a signed value to keep the compiler happy with the comparison + byte* bPtr = (byte*)&t; + for (long long i = 0; i < sizeofT; i++) + toret << *(bPtr + i); + + return toret.str(); + } + + template + // Will convert 0F 00 00 00 to 15 and NOT TO 251658240 + std::basic_istream& FromBytes(std::basic_istream& is, T& b) + { + const std::size_t sizeofT = sizeof(T); + b = 0x0; + byte buf; + + for (std::size_t i = 0; i < sizeofT; i++) + { + is.read((ST*)&buf, 1); + T bbuf = buf << (i * 8); + b |= bbuf; + } + + return is; + } + + class BMP + { + public: + enum class COLOR_MODE + { + BW, // This is a special case, since BMP doesn't support 1 channel. It is just RGB, but with a 1-channel pixel buffer + RGB, + RGBA + }; + + BMP() noexcept + { + width = 0; + height = 0; + colorMode = COLOR_MODE::BW; + sizeofPxlbfr = 0; + numChannelsFile = 0; + numChannelsPXBF = 0; + pixelbfr = nullptr; + isInitialized = false; + return; + } + + explicit BMP(const std::size_t& width, const std::size_t& height, const BMP::COLOR_MODE& colorMode = BMP::COLOR_MODE::RGB) + : isInitialized{false} + { + ReInitialize(width, height, colorMode); + return; + } + + void ReInitialize(const std::size_t& width, const std::size_t& height, const BMP::COLOR_MODE& colorMode = BMP::COLOR_MODE::RGB) + { + if ((!width) || (!height)) ThrowException("Bad image dimensions!"); + + // Initialize bunch of stuff + this->width = width; + this->height = height; + this->colorMode = colorMode; + + switch (colorMode) + { + case COLOR_MODE::BW: + numChannelsFile = 3; + numChannelsPXBF = 1; + break; + case COLOR_MODE::RGB: + numChannelsFile = 3; + numChannelsPXBF = 3; + break; + case COLOR_MODE::RGBA: + numChannelsFile = 4; + numChannelsPXBF = 4; + break; + } + + // Delete pixelbuffer if already exists + if (isInitialized) delete[] pixelbfr; + sizeofPxlbfr = sizeof(byte) * width * height * numChannelsPXBF; + + // Try to allocate memory for the pixelbuffer + try + { + pixelbfr = new byte[sizeofPxlbfr]; + } + catch (std::bad_alloc& e) + { + // too bad! + ThrowException(std::string("Can't allocate memory for pixelbuffer!") + e.what()); + } + + // Make image black + memset(pixelbfr, 0, sizeofPxlbfr); + + isInitialized = true; + return; + } + +#ifdef __linux__ +#pragma GCC diagnostic push +// g++ doesn't see the parameters, numPx, and curPx getting used inside the switch... we don't want these false warnings +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + // Will convert between color modes. Set isNonColorData to true to treat pixeldata as raw values rather than color + void ConvertTo(const BMP::COLOR_MODE& convto, bool isNonColorData = false) + { + // Damn this method is one hell of a mess + + if (!isInitialized) + ThrowException("Not initialized!"); + + byte* tmp_pxlbfr; + try + { + tmp_pxlbfr = new byte[sizeofPxlbfr]; + } + catch (std::bad_alloc&e ) + { + // too bad! + ThrowException(std::string("Can't allocate memory for temporary conversion pixelbuffer!") + e.what()); + return; // This won't ever be reached but it satisfies the compiler, soooo... + } + const std::size_t numPx = width * height; + const std::size_t oldPxlbfrSize = sizeofPxlbfr; + const byte* curPx; // Usage may vary on the conversion in question. It's just a pixel cache for a small performance improvement + memcpy(tmp_pxlbfr, pixelbfr, sizeofPxlbfr); + +#ifdef __linux__ +#pragma GCC diagnostic pop // Let's enable these warnings again +#endif + + switch (colorMode) + { + case COLOR_MODE::BW: +#ifndef __linux__ +#pragma region CONVERT_FROM_BW +#endif + switch (convto) + { + case COLOR_MODE::RGB: + // BW -> RGB + + ReInitialize(width, height, COLOR_MODE::RGB); + for (std::size_t i = 0; i < numPx; i++) + { + curPx = tmp_pxlbfr + i; + pixelbfr[i * 3 + 0] = *curPx; + pixelbfr[i * 3 + 1] = *curPx; + pixelbfr[i * 3 + 2] = *curPx; + } + + break; + case COLOR_MODE::RGBA: + // BW -> RGBA + + ReInitialize(width, height, COLOR_MODE::RGBA); + for (std::size_t i = 0; i < numPx; i++) + { + curPx = tmp_pxlbfr + i; + pixelbfr[i * 4 + 0] = *curPx; + pixelbfr[i * 4 + 1] = *curPx; + pixelbfr[i * 4 + 2] = *curPx; + pixelbfr[i * 4 + 3] = 0xFF; + } + break; + + default: + break; + } +#ifndef __linux__ +#pragma endregion +#endif + break; + + case COLOR_MODE::RGB: +#ifndef __linux__ +#pragma region CONVERT_FROM_RGB +#endif + switch (convto) + { + case COLOR_MODE::BW: + // RGB -> BW + + ReInitialize(width, height, COLOR_MODE::BW); + for (std::size_t i = 0; i < numPx; i++) + { + curPx = tmp_pxlbfr + i * 3; + + // Don't ask me why but the compiler hates dereferencing tmp_pxlbfr/curPx via [] and throws false warnings... + if (isNonColorData) + pixelbfr[i] = (byte)(( + *(curPx + 0) + + *(curPx + 1) + + *(curPx + 2)) * 0.33333333); + else + pixelbfr[i] = (byte)( + *(curPx + 0) * 0.3 + + *(curPx + 1) * 0.59 + + *(curPx + 2) * 0.11); + } + break; + + case COLOR_MODE::RGBA: + // RGB -> RGBA + + ReInitialize(width, height, COLOR_MODE::RGBA); + for (std::size_t i = 0; i < numPx; i++) + { + curPx = tmp_pxlbfr + i * 3; + + pixelbfr[i * 4 + 0] = *(curPx + 0); + pixelbfr[i * 4 + 1] = *(curPx + 1); + pixelbfr[i * 4 + 2] = *(curPx + 2); + pixelbfr[i * 4 + 3] = 0xFF; + } + break; + + default: + break; + } +#ifndef __linux__ +#pragma endregion +#endif + break; + + case COLOR_MODE::RGBA: +#ifndef __linux__ +#pragma region CONVERT_FROM_RGBA +#endif + switch (convto) + { + case COLOR_MODE::BW: + // RGBA -> BW + + ReInitialize(width, height, COLOR_MODE::BW); + for (std::size_t i = 0; i < numPx; i++) + { + curPx = tmp_pxlbfr + i * 4; + + if (isNonColorData) + pixelbfr[i] = (byte)(( + *(curPx + 0) + + *(curPx + 1) + + *(curPx + 2)) * 0.33333333); + else + pixelbfr[i] = (byte)( + *(curPx + 0) * 0.3 + + *(curPx + 1) * 0.59 + + *(curPx + 2) * 0.11); + } + break; + + case COLOR_MODE::RGB: + // RGBA -> RGB + + ReInitialize(width, height, COLOR_MODE::RGB); + for (std::size_t i = 0; i < numPx; i++) + { + curPx = tmp_pxlbfr + i * 4; + + pixelbfr[i * 3 + 0] = *(curPx + 0); + pixelbfr[i * 3 + 1] = *(curPx + 1); + pixelbfr[i * 3 + 2] = *(curPx + 2); + } + break; + + default: + break; + } +#ifndef __linux__ +#pragma endregion +#endif + break; + } + + delete[] tmp_pxlbfr; + return; + } + + byte* GetPixelBuffer() noexcept + { + return pixelbfr; + } + + const byte* GetPixelBuffer() const noexcept + { + return pixelbfr; + } + + std::size_t GetWidth() const noexcept + { + return width; + } + + std::size_t GetHeight() const noexcept + { + return height; + } + + COLOR_MODE GetColorMode() const noexcept + { + return colorMode; + } + + bool IsInitialized() const noexcept + { + return isInitialized; + } + + std::size_t CalculatePixelIndex(const std::size_t& x, const std::size_t& y) const + { + if ((x >= width) || (y >= height)) ThrowException("Pixel coordinates out of range!"); + + return numChannelsPXBF * ((y * width) + x); + } + + byte* GetPixel(const std::size_t& x, const std::size_t& y) + { + return pixelbfr + CalculatePixelIndex(x, y); + } + + const byte* GetPixel(const std::size_t& x, const std::size_t& y) const + { + return pixelbfr + CalculatePixelIndex(x, y); + } + + // Sets a pixels color + // If using RGBA, use all + // If using RGB, a gets ignored + // If using BW, use only r + void SetPixel(const std::size_t& x, const std::size_t& y, const byte& r, const byte& g = 0, const byte& b = 0, const byte& a = 0) + { + byte* px = GetPixel(x, y); + + switch (colorMode) + { + case COLOR_MODE::BW: + px[0] = r; + break; + + case COLOR_MODE::RGB: + px[0] = r; + px[1] = g; + px[2] = b; + break; + + case COLOR_MODE::RGBA: + px[0] = r; + px[1] = g; + px[2] = b; + px[3] = a; + break; + } + + return; + } + + // Will write a bmp image + bool Write(const std::string& filename) + { + if (!isInitialized) + return false; + + std::size_t paddingSize = (4 - ((width * numChannelsFile) % 4)) % 4; // number of padding bytes per scanline + byte paddingData[4] = { 0x69,0x69,0x69,0x69 }; // dummy-data for padding + + bytestream data; + data + // BMP Header + << ToBytes(byte2(0x4D42)) // signature + << ToBytes(byte4(0x36 + sizeofPxlbfr + paddingSize * height)) // size of the bmp file (all bytes) + << ToBytes(byte2(0)) // unused + << ToBytes(byte2(0)) // unused + << ToBytes(byte4(0x36)) // Offset where the pixel array begins (size of both headers) + + // DIB Header + << ToBytes(byte4(0x28)) // Number of bytes in DIB header (without this field) + << ToBytes(byte4(width)) // width + << ToBytes(byte4(height)) // height + << ToBytes(byte2(1)) // number of planes used + << ToBytes(byte2(numChannelsFile * 8)) // bit-depth + << ToBytes(byte4(0)) // no compression + << ToBytes(byte4(sizeofPxlbfr + paddingSize * height)) // Size of raw bitmap data (including padding) + << ToBytes(byte4(0xB13)) // print resolution pixels/meter X + << ToBytes(byte4(0xB13)) // print resolution pixels/meter Y + << ToBytes(byte4(0)) // 0 colors in the color palette + << ToBytes(byte4(0)); // 0 means all colors are important + + // Dumbass unusual pixel order of bmp made me do this... + for (long long y = height - 1; y >= 0; y--) + { + for (std::size_t x = 0; x < width; x++) + { + std::size_t idx = CalculatePixelIndex(x, (std::size_t)y); // No precision lost here. I just need a type that can get as large as std::size_t but is also signed (because for y >= 0) + + switch (colorMode) + { + case COLOR_MODE::BW: + // pixelbfr ==> R-G-B ==> B-G-R ==> bmp format + data.write((pixelbfr + idx), 1); // B + data.write((pixelbfr + idx), 1); // G + data.write((pixelbfr + idx), 1); // R + + break; + + case COLOR_MODE::RGB: + // pixelbfr ==> R-G-B ==> B-G-R ==> bmp format + data.write((pixelbfr + idx + 2), 1); // B + data.write((pixelbfr + idx + 1), 1); // G + data.write((pixelbfr + idx + 0), 1); // R + + break; + + case COLOR_MODE::RGBA: + // pixelbfr ==> R-G-B-A ==> B-G-R-A ==> bmp format + data.write((pixelbfr + idx + 2), 1); // B + data.write((pixelbfr + idx + 1), 1); // G + data.write((pixelbfr + idx + 0), 1); // R + data.write((pixelbfr + idx + 3), 1); // A + + break; + } + } + + if ((colorMode == COLOR_MODE::BW) || (colorMode == COLOR_MODE::RGB)) + if (paddingSize > 0) + data.write(paddingData, paddingSize); + } + + + + // write file + std::ofstream bs; + bs.open(filename, std::ofstream::binary); + if (!bs.good()) + return false; + + bytestring bytes = data.str(); + bs.write((const char*)bytes.c_str(), bytes.length()); + bs.flush(); + bs.close(); + + return true; + } + + // Will read a bmp image + bool Read(std::string filename) + { + std::ifstream bs; + bs.open(filename, std::ifstream::binary); + if (!bs.good()) + return false; + + // Check BMP signature + byte2 signature; + FromBytes(bs, signature); + if (signature != 0x4D42) + return false; + + // Gather filesize + byte4 fileLen; + FromBytes(bs, fileLen); + + byte2 unused0; + byte2 unused1; + FromBytes(bs, unused0); + FromBytes(bs, unused1); + + byte4 offsetPixelArray; + FromBytes(bs, offsetPixelArray); + + byte4 dibHeadLen; + FromBytes(bs, dibHeadLen); + + // Gather image dimensions + byte4 imgWidth; + byte4 imgHeight; + FromBytes(bs, imgWidth); + FromBytes(bs, imgHeight); + + byte2 numPlanes; + FromBytes(bs, numPlanes); + + // Gather image bit-depth + byte2 bitDepth; + FromBytes(bs, bitDepth); + switch (bitDepth) + { + // BW is not supported so we can't read a bw image + case 24: + colorMode = COLOR_MODE::RGB; + break; + case 32: + colorMode = COLOR_MODE::RGBA; + } + + byte4 compression; + FromBytes(bs, compression); + + // Gather size of pixel buffer + byte4 sizeofPixelBuffer; + FromBytes(bs, sizeofPixelBuffer); + + byte4 printresX; + byte4 printresY; + FromBytes(bs, printresX); + FromBytes(bs, printresY); + + byte4 colorsInPalette; + byte4 importantColors; + FromBytes(bs, colorsInPalette); + FromBytes(bs, importantColors); + + // Go to the beginning of the pixel array + bs.seekg(offsetPixelArray); + + // Initialize image + ReInitialize(imgWidth, imgHeight, colorMode); + + // Calculate scanline padding size + std::size_t paddingSize = (4 - ((width * numChannelsFile) % 4)) % 4; + paddingSize = paddingSize < 4 ? paddingSize : 0; + + // Dumbass unusual pixel order of bmp made me do this... + for (long long y = imgHeight - 1; y >= 0; y--) + { + std::size_t byteCounter = 0; + for (std::size_t x = 0; x < imgWidth; x++) + { + std::size_t idx = CalculatePixelIndex(x, (std::size_t)y); // No precision lost here. I just need a type that can get as large as std::size_t but is also signed (because for y >= 0) + + switch (colorMode) + { + case COLOR_MODE::RGB: + // bmp format ==> B-G-R ==> R-G-B ==> pixelbfr + bs.read((char*)(pixelbfr + idx + 2), 1); // Read B byte + bs.read((char*)(pixelbfr + idx + 1), 1); // Read G byte + bs.read((char*)(pixelbfr + idx + 0), 1); // Read R byte + byteCounter += 3; + break; + + case COLOR_MODE::RGBA: + // bmp format ==> B-G-R-A ==> R-G-B-A ==> pixelbfr + bs.read((char*)(pixelbfr + idx + 2), 1); // Read B byte + bs.read((char*)(pixelbfr + idx + 1), 1); // Read G byte + bs.read((char*)(pixelbfr + idx + 0), 1); // Read R byte + bs.read((char*)(pixelbfr + idx + 3), 1); // Read A byte + byteCounter += 4; + break; + + default: + break; + } + } + + if ((colorMode == COLOR_MODE::BW) || (colorMode == COLOR_MODE::RGB)) // RGBA will always be a multiple of 4 bytes + if (byteCounter % 4) // If this scan line was not a multiple of 4 bytes long, account for padding + bs.ignore(paddingSize); + } + + bs.close(); + return true; + } + + ~BMP() + { + if (isInitialized) + { + delete[] pixelbfr; + pixelbfr = nullptr; + } + return; + } + + private: + void ThrowException(const std::string msg) const + { + #ifndef BMPLIB_SILENT + #ifdef _IOSTREAM_ + std::cerr << "BMPlib exception: " << msg << std::endl; + #endif + #endif + throw msg; + return; + } + + std::size_t width; + std::size_t height; + std::size_t numChannelsFile; // Num channels of the file format + std::size_t numChannelsPXBF; // Num channels of the pixel buffer + COLOR_MODE colorMode; + bool isInitialized; + byte* pixelbfr; + std::size_t sizeofPxlbfr; // how many bytes the pixelbuffer is long + }; +} diff --git a/encoder/cpp/lzss b/encoder/cpp/lzss new file mode 100755 index 0000000..de2e267 Binary files /dev/null and b/encoder/cpp/lzss differ diff --git a/encoder/cpp/lzss.cpp b/encoder/cpp/lzss.cpp new file mode 100644 index 0000000..945366d --- /dev/null +++ b/encoder/cpp/lzss.cpp @@ -0,0 +1,481 @@ +/*----------------------------------------------------------------------------*/ +/*-- lzss.c - LZSS coding for Nintendo GBA/DS --*/ +/*-- Copyright (C) 2011 CUE --*/ +/*-- --*/ +/*-- 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 . --*/ +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +#include +#include +#include +#include + +/*----------------------------------------------------------------------------*/ +#define CMD_DECODE 0x00 // decode +#define CMD_CODE_10 0x10 // LZSS magic number + +#define LZS_NORMAL 0x00 // normal mode, (0) +#define LZS_FAST 0x80 // fast mode, (1 << 7) +#define LZS_BEST 0x40 // best mode, (1 << 6) + +#define LZS_WRAM 0x00 // VRAM not compatible (LZS_WRAM | LZS_NORMAL) +#define LZS_VRAM 0x01 // VRAM compatible (LZS_VRAM | LZS_NORMAL) +#define LZS_WFAST 0x80 // LZS_WRAM fast (LZS_WRAM | LZS_FAST) +#define LZS_VFAST 0x81 // LZS_VRAM fast (LZS_VRAM | LZS_FAST) +#define LZS_WBEST 0x40 // LZS_WRAM best (LZS_WRAM | LZS_BEST) +#define LZS_VBEST 0x41 // LZS_VRAM best (LZS_VRAM | LZS_BEST) + +#define LZS_SHIFT 1 // bits to shift +#define LZS_MASK 0x80 // bits to check: + // ((((1 << LZS_SHIFT) - 1) << (8 - LZS_SHIFT) + +#define LZS_THRESHOLD 2 // max number of bytes to not encode +#define LZS_N 0x1000 // max offset (1 << 12) +#define LZS_F 0x12 // max coded ((1 << 4) + LZS_THRESHOLD) +#define LZS_NIL LZS_N // index for root of binary search trees + +#define RAW_MINIM 0x00000000 // empty file, 0 bytes +#define RAW_MAXIM 0x00FFFFFF // 3-bytes length, 16MB - 1 + +#define LZS_MINIM 0x00000004 // header only (empty RAW file) +#define LZS_MAXIM 0x01400000 // 0x01200003, padded to 20MB: + // * header, 4 + // * length, RAW_MAXIM + // * flags, (RAW_MAXIM + 7) / 8 + // 4 + 0x00FFFFFF + 0x00200000 + padding + +/*----------------------------------------------------------------------------*/ +unsigned char ring[LZS_N + LZS_F - 1]; +int dad[LZS_N + 1], lson[LZS_N + 1], rson[LZS_N + 1 + 256]; +int pos_ring, len_ring, lzs_vram; + +/*----------------------------------------------------------------------------*/ +#define BREAK(text) { printf(text); return; } +#define EXIT(text) { printf(text); exit(-1); } + +/*----------------------------------------------------------------------------*/ +unsigned char *Load(char *filename, unsigned int *length, int min, int max); +void Save(char *filename, unsigned char *buffer, int length); +unsigned char *Memory(int length, int size); + + +unsigned char *LZS_Code(unsigned char *raw_buffer, int raw_len, unsigned int *new_len, int best); + +unsigned char *LZS_Fast(unsigned char *raw_buffer, int raw_len, unsigned int *new_len); +void LZS_InitTree(void); +void LZS_InsertNode(int r); +void LZS_DeleteNode(int p); + +/*----------------------------------------------------------------------------*/ +// int main(int argc, char **argv) { +// int cmd, mode; +// int arg; + +// if (argc < 2) EXIT("Filename not specified\n"); + +// // for (arg = 2; arg < argc; arg++) LZS_Decode(argv[arg]); +// for (arg = 1; arg < argc; arg++) LZS_Encode(argv[arg], LZS_WFAST); + +// printf("\nDone\n"); + +// return(0); +// } + +/*----------------------------------------------------------------------------*/ +unsigned char *Load(char *filename, unsigned int *length, int min, int max) { + FILE *fp; + int fs; + unsigned char *fb; + + if ((fp = fopen(filename, "rb")) == NULL) EXIT("\nFile open error\n"); + + // fs = filelength(fileno(fp)); + fseek(fp, 0, SEEK_END); + fs = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if ((fs < min) || (fs > max)) EXIT("\nFile size error\n"); + fb = Memory(fs + 3, sizeof(char)); + if (fread(fb, 1, fs, fp) != fs) EXIT("\nFile read error\n"); + if (fclose(fp) == EOF) EXIT("\nFile close error\n"); + + *length = fs; + + return(fb); +} + +/*----------------------------------------------------------------------------*/ +void Save(char *filename, unsigned char *buffer, int length) { + FILE *fp; + + if ((fp = fopen(filename, "wb")) == NULL) EXIT("\nFile create error\n"); + + u_int16_t newLength = length; + fwrite(&newLength, sizeof(newLength), 1, fp); + + if (fwrite(buffer, 1, length, fp) != length) EXIT("\nFile write error\n"); + if (fclose(fp) == EOF) EXIT("\nFile close error\n"); +} + +/*----------------------------------------------------------------------------*/ +unsigned char *Memory(int length, int size) { + unsigned char *fb; + + fb = (unsigned char *) calloc(length, size); + if (fb == NULL) EXIT("\nMemory error\n"); + + return(fb); +} + +/*----------------------------------------------------------------------------*/ +void LZS_Decode(char *filename) { + unsigned char *pak_buffer, *raw_buffer, *pak, *raw, *pak_end, *raw_end; + unsigned int pak_len, raw_len, header, len, pos; + unsigned char flags, mask; + + printf("- decoding '%s'", filename); + + pak_buffer = Load(filename, &pak_len, LZS_MINIM, LZS_MAXIM); + + header = *pak_buffer; + if (header != CMD_CODE_10) { + free(pak_buffer); + BREAK(", WARNING: file is not LZSS encoded!\n"); + } + + raw_len = *(unsigned int *)pak_buffer >> 8; + raw_buffer = (unsigned char *) Memory(raw_len, sizeof(char)); + + pak = pak_buffer + 4; + raw = raw_buffer; + pak_end = pak_buffer + pak_len; + raw_end = raw_buffer + raw_len; + + mask = 0; + + while (raw < raw_end) { + if (!(mask >>= LZS_SHIFT)) { + if (pak == pak_end) break; + flags = *pak++; + mask = LZS_MASK; + } + + if (!(flags & mask)) { + if (pak == pak_end) break; + *raw++ = *pak++; + } else { + if (pak + 1 >= pak_end) break; + pos = *pak++; + pos = (pos << 8) | *pak++; + len = (pos >> 12) + LZS_THRESHOLD + 1; + if (raw + len > raw_end) { + printf(", WARNING: wrong decoded length!"); + len = raw_end - raw; + } + pos = (pos & 0xFFF) + 1; + while (len--) *raw++ = *(raw - pos); + } + } + + raw_len = raw - raw_buffer; + + if (raw != raw_end) printf(", WARNING: unexpected end of encoded file!"); + + Save(filename, raw_buffer, raw_len); + + free(raw_buffer); + free(pak_buffer); + + printf("\n"); +} + +/*----------------------------------------------------------------------------*/ +// void LZS_Encode(char *filename, int mode) { +void LZS_Encode(unsigned char*data, unsigned int length) { + unsigned char *raw_buffer, *pak_buffer, *new_buffer; + unsigned int raw_len, pak_len, new_len; + + int mode = LZS_WFAST; + + lzs_vram = mode & 0xF; + + // raw_buffer = Load(filename, &raw_len, RAW_MINIM, RAW_MAXIM); + raw_buffer = data; + raw_len = length; + + pak_buffer = NULL; + pak_len = LZS_MAXIM + 1; + + if (!(mode & LZS_FAST)) { + mode = mode & LZS_BEST ? 1 : 0; + new_buffer = LZS_Code(raw_buffer, raw_len, &new_len, mode); + } else { + new_buffer = LZS_Fast(raw_buffer, raw_len, &new_len); + } + if (new_len < pak_len) { + if (pak_buffer != NULL) free(pak_buffer); + pak_buffer = new_buffer; + pak_len = new_len; + } + + std::cout << pak_len << "\n"; + + // output = pak_buffer; + // Save("output_new", pak_buffer, pak_len); + + + // free(pak_buffer); + // free(raw_buffer); + + printf("\n"); +} + +/*----------------------------------------------------------------------------*/ +unsigned char *LZS_Code(unsigned char *raw_buffer, int raw_len, unsigned int *new_len, int best) { + unsigned char *pak_buffer, *pak, *raw, *raw_end, *flg; + unsigned int pak_len, len, pos, len_best, pos_best; + unsigned int len_next, pos_next, len_post, pos_post; + unsigned char mask; + +#define SEARCH(l,p) { \ + l = LZS_THRESHOLD; \ + \ + pos = raw - raw_buffer >= LZS_N ? LZS_N : raw - raw_buffer; \ + for ( ; pos > lzs_vram; pos--) { \ + for (len = 0; len < LZS_F; len++) { \ + if (raw + len == raw_end) break; \ + if (*(raw + len) != *(raw + len - pos)) break; \ + } \ + \ + if (len > l) { \ + p = pos; \ + if ((l = len) == LZS_F) break; \ + } \ + } \ +} + + pak_len = 4 + raw_len + ((raw_len + 7) / 8); + pak_buffer = (unsigned char *) Memory(pak_len, sizeof(char)); + + *(unsigned int *)pak_buffer = CMD_CODE_10 | (raw_len << 8); + + pak = pak_buffer + 4; + raw = raw_buffer; + raw_end = raw_buffer + raw_len; + + mask = 0; + + while (raw < raw_end) { + if (!(mask >>= LZS_SHIFT)) { + *(flg = pak++) = 0; + mask = LZS_MASK; + } + + SEARCH(len_best, pos_best); + + // LZ-CUE optimization start + if (best) { + if (len_best > LZS_THRESHOLD) { + if (raw + len_best < raw_end) { + raw += len_best; + SEARCH(len_next, pos_next); + raw -= len_best - 1; + SEARCH(len_post, pos_post); + raw--; + + if (len_next <= LZS_THRESHOLD) len_next = 1; + if (len_post <= LZS_THRESHOLD) len_post = 1; + + if (len_best + len_next <= 1 + len_post) len_best = 1; + } + } + } + // LZ-CUE optimization end + + if (len_best > LZS_THRESHOLD) { + raw += len_best; + *flg |= mask; + *pak++ = ((len_best - (LZS_THRESHOLD + 1)) << 4) | ((pos_best - 1) >> 8); + *pak++ = (pos_best - 1) & 0xFF; + } else { + *pak++ = *raw++; + } + } + + *new_len = pak - pak_buffer; + + return(pak_buffer); +} + +/*----------------------------------------------------------------------------*/ +unsigned char *LZS_Fast(unsigned char *raw_buffer, int raw_len, unsigned int *new_len) { + unsigned char *pak_buffer, *pak, *raw, *raw_end, *flg; + unsigned int pak_len, len, r, s, len_tmp, i; + unsigned char mask; + + pak_len = 4 + raw_len + ((raw_len + 7) / 8); + pak_buffer = (unsigned char *) Memory(pak_len, sizeof(char)); + + *(unsigned int *)pak_buffer = CMD_CODE_10 | (raw_len << 8); + + pak = pak_buffer + 4; + raw = raw_buffer; + raw_end = raw_buffer + raw_len; + + LZS_InitTree(); + + r = s = 0; + + len = raw_len < LZS_F ? raw_len : LZS_F; + while (r < LZS_N - len) ring[r++] = 0; + + for (i = 0; i < len; i++) ring[r + i] = *raw++; + + LZS_InsertNode(r); + + mask = 0; + + while (len) { + if (!(mask >>= LZS_SHIFT)) { + *(flg = pak++) = 0; + mask = LZS_MASK; + } + + if (len_ring > len) len_ring = len; + + if (len_ring > LZS_THRESHOLD) { + *flg |= mask; + pos_ring = ((r - pos_ring) & (LZS_N - 1)) - 1; + *pak++ = ((len_ring - LZS_THRESHOLD - 1) << 4) | (pos_ring >> 8); + *pak++ = pos_ring & 0xFF; + } else { + len_ring = 1; + *pak++ = ring[r]; + } + + len_tmp = len_ring; + for (i = 0; i < len_tmp; i++) { + if (raw == raw_end) break; + LZS_DeleteNode(s); + ring[s] = *raw++; + if (s < LZS_F - 1) ring[s + LZS_N] = ring[s]; + s = (s + 1) & (LZS_N - 1); + r = (r + 1) & (LZS_N - 1); + LZS_InsertNode(r); + } + while (i++ < len_tmp) { + LZS_DeleteNode(s); + s = (s + 1) & (LZS_N - 1); + r = (r + 1) & (LZS_N - 1); + if (--len) LZS_InsertNode(r); + } + } + + *new_len = pak - pak_buffer; + + return(pak_buffer); +} + +/*----------------------------------------------------------------------------*/ +void LZS_InitTree(void) { + int i; + + for (i = LZS_N + 1; i <= LZS_N + 256; i++) + rson[i] = LZS_NIL; + + for (i = 0; i < LZS_N; i++) + dad[i] = LZS_NIL; +} + +/*----------------------------------------------------------------------------*/ +void LZS_InsertNode(int r) { + unsigned char *key; + int i, p, cmp, prev; + + prev = (r - 1) & (LZS_N - 1); + + cmp = 1; + len_ring = 0; + + key = &ring[r]; + p = LZS_N + 1 + key[0]; + + rson[r] = lson[r] = LZS_NIL; + + for ( ; ; ) { + if (cmp >= 0) { + if (rson[p] != LZS_NIL) p = rson[p]; + else { rson[p] = r; dad[r] = p; return; } + } else { + if (lson[p] != LZS_NIL) p = lson[p]; + else { lson[p] = r; dad[r] = p; return; } + } + + for (i = 1; i < LZS_F; i++) + if ((cmp = key[i] - ring[p + i])) break; + + if (i > len_ring) { + if (!lzs_vram || (p != prev)) { + pos_ring = p; + if ((len_ring = i) == LZS_F) break; + } + } + } + + dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p]; + + dad[lson[p]] = r; dad[rson[p]] = r; + + if (rson[dad[p]] == p) rson[dad[p]] = r; + else lson[dad[p]] = r; + + dad[p] = LZS_NIL; +} + +/*----------------------------------------------------------------------------*/ +void LZS_DeleteNode(int p) { + int q; + + if (dad[p] == LZS_NIL) return; + + if (rson[p] == LZS_NIL) { + q = lson[p]; + } else if (lson[p] == LZS_NIL) { + q = rson[p]; + } else { + q = lson[p]; + if (rson[q] != LZS_NIL) { + do { + q = rson[q]; + } while (rson[q] != LZS_NIL); + + rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q]; + lson[q] = lson[p]; dad[lson[p]] = q; + } + + rson[q] = rson[p]; dad[rson[p]] = q; + } + + dad[q] = dad[p]; + + if (rson[dad[p]] == p) rson[dad[p]] = q; + else lson[dad[p]] = q; + + dad[p] = LZS_NIL; +} + +/*----------------------------------------------------------------------------*/ +/*-- EOF Copyright (C) 2011 CUE --*/ +/*----------------------------------------------------------------------------*/ diff --git a/encoder/cpp/lzss.hpp b/encoder/cpp/lzss.hpp new file mode 100644 index 0000000..a98ec93 --- /dev/null +++ b/encoder/cpp/lzss.hpp @@ -0,0 +1 @@ +void LZS_Encode(unsigned char*data, unsigned int length); \ No newline at end of file diff --git a/encoder/cpp/main.cpp b/encoder/cpp/main.cpp new file mode 100644 index 0000000..8beda83 --- /dev/null +++ b/encoder/cpp/main.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include "BMPlib.h" +// #include "lzss.hpp" + +#define RGB8(r,g,b) ((r)>>3) | (((g)>>3)<<5) | (((b)>>3)<<10) +int main() { + + BMPlib::BMP bmp; + bmp.Read("../../assets/out/out_240.bmp"); + + unsigned char* pixel = bmp.GetPixelBuffer(); + uint16_t totalSize = bmp.GetWidth()*bmp.GetHeight(); + + // uint16_t output[totalSize]; + // uint32_t counter = 0; + std::ofstream out("output", std::ios::binary); + + for (int i=0; i>3)|(((g)>>3)<<5)|(((b)>>3)<<10)) +} \ No newline at end of file diff --git a/encoder/package.json b/encoder/package.json new file mode 100644 index 0000000..d734a8d --- /dev/null +++ b/encoder/package.json @@ -0,0 +1,15 @@ +{ + "name": "decoder", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "child-process-promise": "^2.2.1", + "gify-parse": "^1.0.7", + "lz77": "^1.1.0", + "lzma-native": "^8.0.1", + "omggif": "^1.0.10", + "rgb-hex": "^4.0.0", + "write": "^2.0.0" + } +}