Compare commits

...

10 Commits

Author SHA1 Message Date
c415f3b2e6 final release 2023-12-31 00:49:12 +07:00
a665fcc7ea remove comment 2023-12-31 00:31:04 +07:00
04b1358957 refactor part 3 2023-12-30 12:27:11 +07:00
95c12d0f02 move vendor to cmakelist 2023-12-30 09:24:41 +07:00
2184c775ac remove submodule 2023-12-30 09:18:42 +07:00
a6f1100470 refactor part 2 2023-12-30 09:03:50 +07:00
37293b6259 refactor part 1 2023-12-29 22:20:32 +07:00
3a5151fed9 idk i broke lots of things 2023-12-29 21:28:51 +07:00
ff27e662c1 remove music.raw loader 2023-12-29 14:24:27 +07:00
255b14345c remove workflow 2023-12-29 14:15:45 +07:00
12 changed files with 253 additions and 657 deletions

View File

@ -1,74 +0,0 @@
name: CI
on:
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-20.04
container: devkitpro/devkitarm
name: "Build with devkitARM"
outputs:
commit_tag: ${{ steps.build.outputs.commit_tag }}
commit_message: ${{ steps.build.outputs.commit_message }}
steps:
- uses: actions/checkout@v2
with:
submodules: true
fetch-depth: 0
- name: Setup NodejS
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependency
run: |
sudo apt update -y
sudo apt upgrade -y
sudo apt install ffmpeg build-essential -y
npm -g install ytdl
- name: Prepare video
run: |
cd assets
ytdl "https://www.youtube.com/watch?v=dQw4w9WgXcQ" -o video.mp4
sh convert.sh
- name: Encode video
run: |
cd encoder
npm install
cd cpp
g++ lzss.cpp -o lzss
cd ..
node .
- name: Build NDS
run: |
cp assets/music.raw NDS/nitrofiles/
cp encoder/data_compress NDS/nitrofiles/
cd NDS
make
- name: Prepare artefact
run: |
cd NDS/dist
mkdir -p dist
tar -czvf dist/${{ github.event.repository.name }}.tar.gz *.nds
curl bashupload.com -T NDS.nds
- name: Upload to basement
uses: SamKirkland/FTP-Deploy-Action@4.0.0
with:
server: ${{ secrets.ftp_server }}
username: ${{ secrets.ftp_username }}
password: ${{ secrets.ftp_password }}
local-dir: ./NDS/dist/dist/
server-dir: ./public_html/basement/${{ github.event.repository.name }}/

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "vendor/FastLZ"]
path = vendor/FastLZ
url = ssh://git@192.168.0.100:3022/MirrorRepo/FastLZ.git

View File

@ -10,26 +10,30 @@ set(NDSTOOL_SUBTITLE1 "Created by sillysagiri" CACHE BOOL "")
set(NDSTOOL_SUBTITLE2 "sillysagiri.my.id" CACHE BOOL "")
set(NDSTOOL_NITROFS "resource" CACHE BOOL "")
# add_subdirectory(arm9)
message(STATUS "Downloading fastlz library")
include(FetchContent)
FetchContent_Declare(fastlz URL https://git.sillysagiri.my.id/MirrorRepo/FastLZ/archive/master.zip)
FetchContent_MakeAvailable(fastlz)
set(NDSTOOL_ARM7 "${CMAKE_BINARY_DIR}/arm7/arm7.elf" CACHE BOOL "")
# set(NDSTOOL_ARM9 arm9 CACHE BOOL "")
project(${PROJECT_NAME})
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "src/*.cpp")
file(GLOB VENDOR_SOURCES CONFIGURE_DEPENDS "vendor/FastLZ/fastlz.c")
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS
"src/*.cpp"
${fastlz_SOURCE_DIR}/fastlz.c)
set(PROJECT_INCLUDE
"src"
"vendor/FastLZ")
${fastlz_SOURCE_DIR})
set(PROJECT_VENDOR
"filesystem"
"fat"
"mm9")
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES} ${VENDOR_SOURCES})
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE})
target_link_libraries(${PROJECT_NAME} PUBLIC ${PROJECT_VENDOR})

View File

@ -1,38 +0,0 @@
# 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})

View File

@ -1,222 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
# These set the information text in the nds file
GAME_TITLE := Rune Factory 5 Lite
GAME_SUBTITLE1 := Version 1.0.2b
GAME_SUBTITLE2 := Created by Melody
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
#---------------------------------------------------------------------------------------

View File

View File

@ -1,116 +0,0 @@
#include <nds.h>
#include <filesystem.h>
#include <iostream>
#include <fstream>
#include <maxmod9.h>
#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];
bool shouldDraw = false;
bool queueAvaible = false;
void VBlankProc() {
mmStreamUpdate();
if (shouldDraw) {
shouldDraw = false;
if (queueAvaible) {
queueAvaible = false;
dmaCopyWordsAsynch(3, buffer2, VRAM_A, 256*192*2);
}
}
}
void TimerTick() {
shouldDraw = true;
}
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) {
consoleDemoInit();
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 << "failed to init nitrofs" << std::endl;
std::cout << "Please launch the game\nfrom nds-bootstrap from twilightmenu" << std::endl;
while(1) {
// freezee
}
}
mmInitDefault((char*)"soundbank.bin");
file = fopen("music.raw","rb");
mm_stream mystream;
mystream.sampling_rate = 22050; // sampling rate = 25khz
mystream.buffer_length = 2400; // 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 = true; // use manual filling
mmStreamOpen( &mystream );
// quick hack... sometime it need to update once?
mmStreamUpdate(); mmStreamUpdate();
irqSet(IRQ_VBLANK, VBlankProc);
timerStart(2, ClockDivider_1024, TIMER_FREQ_1024(30), TimerTick);
in.open("data_compress", std::ios::in | std::ios::binary);
while(true) {
timerElapsed(1);
if (!in.eof() && !queueAvaible) {
in.read((char*)&blockSize, sizeof(blockSize));
in.read(buffer, blockSize);
swiDecompressLZSSWram(buffer, buffer2);
queueAvaible = true;
}
// swiWaitForVBlank();
}
// crashh
return 0;
}

View File

@ -38,32 +38,24 @@
static FILE *in_music = NULL;
//---------------------------------------------------------------------------------
void VblankHandler(void) {
//---------------------------------------------------------------------------------
Wifi_Update();
}
//---------------------------------------------------------------------------------
void VcountHandler() {
//---------------------------------------------------------------------------------
inputGetAndSend();
}
volatile bool exitflag = false;
//---------------------------------------------------------------------------------
void powerButtonCB() {
//---------------------------------------------------------------------------------
exitflag = true;
}
//---------------------------------------------------------------------------------
int main() {
//---------------------------------------------------------------------------------
// clear sound registers
dmaFillWords(0, (void*)0x04000400, 0x100);

View File

@ -7,12 +7,18 @@ set(PROJECT_NAME "encoder")
project(${PROJECT_NAME})
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "*.cpp" "*.c")
file(GLOB VENDOR_SOURCES CONFIGURE_DEPENDS "../vendor/FastLZ/fastlz.c")
message(STATUS "Downloading fastlz library")
include(FetchContent)
FetchContent_Declare(fastlz URL https://git.sillysagiri.my.id/MirrorRepo/FastLZ/archive/master.zip)
FetchContent_MakeAvailable(fastlz)
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS
"*.cpp" "*.c"
${fastlz_SOURCE_DIR}/fastlz.c)
set(PROJECT_INCLUDE
"encoder"
"../vendor/FastLZ")
${fastlz_SOURCE_DIR})
set(PROJECT_VENDOR
"")

View File

@ -15,40 +15,47 @@
extern "C" char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len);
unsigned short RGB15(int r, int g, int b) {
unsigned short rgb15 =
((r >> 3) << 10) | // 5 bits for red
((g >> 3) << 5) | // 5 bits for green
(b >> 3); // 5 bits for blue
unsigned short RGB15(int r, int g, int b);
// Set the alpha bit to 1
rgb15 |= 1 << 15;
return rgb15;
}
std::string path_out = "../assets/out/";
std::string path_palette = "../assets/palette.png";
std::string path_resource = "../resource";
std::string path_images = "../assets/out/out_";
std::string path_test = "../assets/out/out_3667.bmp";
std::vector<int> usingRLE = {999999};
// std::vector<int> usingRLE = {840, 841, 842, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1041, 1459, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1626, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1664, 1666, 1719, 1720, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 3191, 3192, 3193, 3196, 3197, 3198, 3225, 3227, 3228, 3229};
constexpr int palette_size = 256;
uint16_t palette_map[palette_size];
constexpr int chunk_size = 10;
volatile int chunk_counter = 0;
volatile int chunk_current = 0;
constexpr int frame_size = 256*192;
volatile int frame_total = -1;
volatile int frame_counter = 0;
uint8_t frame_map[frame_size*chunk_size];
uint32_t compress_size, compress_flag;
volatile int compress_size_biggest;
uint8_t compress_data[frame_size*chunk_size*2];
std::ofstream file_out;
int main()
{
std::string path_out = "../assets/out/";
std::string path_palette = "../assets/palette.png";
std::string path_resource = "../resource";
std::string path_images = "../assets/out/out_";
std::string path_test = "../assets/out/out_3667.bmp";
std::vector<int> usingRLE = {177, 178, 179, 220, 231, 232, 237, 238, 239, 240, 241, 263, 264, 409, 681, 682, 735, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 770, 771, 772, 773, 774, 775, 776, 777, 779, 780, 783, 784, 785, 786, 787, 788, 789, 790, 791, 798, 799, 800, 801, 802, 803, 804, 805, 807, 808, 809, 811, 812, 813, 814, 815, 816, 817, 818, 819, 821, 822, 823, 824, 825, 826, 827, 828, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 897, 898, 899, 900, 908, 909, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 925, 926, 927, 928, 929, 930, 931, 934, 935, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1154, 1155, 1156, 1157, 1158, 1245, 1247, 1248, 1249, 1250, 1251, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1459, 1460, 1461, 1462, 1463, 1465, 1466, 1467, 1468, 1469, 1470, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1493, 1494, 1495, 1496, 1501, 1504, 1507, 1510, 1513, 1515, 1516, 1517, 1520, 1521, 1522, 1524, 1525, 1526, 1528, 1529, 1530, 1531, 1532, 1533, 1535, 1536, 1537, 1538, 1539, 1541, 1542, 1547, 1549, 1551, 1552, 1553, 1554, 1555, 1557, 1559, 1560, 1561, 1562, 1563, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1582, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1699, 1701, 1702, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1763, 1764, 1765, 1766, 1787, 1789, 1808, 1809, 1810, 1823, 1834, 1835, 1836, 1837, 1843, 1876, 1892, 1893, 1894, 1897, 1901, 1904, 1905, 1906, 1907, 1908, 1910, 1911, 1969, 2090, 2091, 2092, 2128, 2129, 2180, 2181, 2182, 2195, 2196, 2197, 2199, 2201, 2281, 2282, 2286, 2287, 2295, 2300, 2309, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2343, 2345, 2346, 2347, 2349, 2670, 2727, 2729, 2730, 2812, 2831, 2833, 2850, 2851, 3140, 3141, 3142, 3143, 3144, 3146, 3147, 3148, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3182, 3183, 3184, 3185, 3186, 3187, 3189, 3190, 3255};
int frame_total = -1;
std::stringstream ss;
std::ofstream out;
printf("Finding total frame...");
// Find total frame
for (const auto& entry : std::filesystem::directory_iterator(path_out)) {
if (entry.is_regular_file()) {
std::string fileName = entry.path().filename().string();
std::string filename = entry.path().filename().string();
if (fileName.substr(0, 4) == "out_" && fileName.substr(fileName.size() - 4) == ".bmp") {
int number = std::stoi(fileName.substr(4, fileName.size() - 8));
if (filename.substr(0, 4) == "out_" && filename.substr(filename.size() - 4) == ".bmp") {
int number = std::stoi(filename.substr(4, filename.size() - 8));
if (number > frame_total) {
frame_total = number;
@ -58,122 +65,147 @@ int main()
}
// Generate palette
uint16_t palette[256];
int palette_w = -1;
int palette_h = -1;
int palette_n = -1;
unsigned char *palette_data = stbi_load(path_palette.c_str(), &palette_w, &palette_h, &palette_n, 3);
printf("Generating palette map...");
int temp_w, temp_h, temp_n;
unsigned char *palette_raw = stbi_load(path_palette.c_str(), &temp_w, &temp_h, &temp_n, 3);
for (int i=0; i<256; i++)
for (int i=0; i<palette_size; i++)
{
int index = i*3;
unsigned char r = palette_data[index];
unsigned char g = palette_data[index + 1];
unsigned char b = palette_data[index + 2];
unsigned char r = palette_raw[index];
unsigned char g = palette_raw[index + 1];
unsigned char b = palette_raw[index + 2];
palette[i] = RGB15(r, g, b);
palette_map[i] = RGB15(r, g, b);
// printf("%i> %i,%i,%i (%i)\n", i, r, g, b, palette[i]);
}
out.open(path_resource + "/palette.bin", std::ios::binary);
out.write(reinterpret_cast<const char*>(palette), sizeof(palette));
out.close();
out.open(path_resource + "/image.bin", std::ios::binary);
printf("Writing palette map...");
file_out.open(path_resource + "/palette.bin", std::ios::binary);
file_out.write(reinterpret_cast<const char*>(palette_map), sizeof(palette_map));
file_out.close();
uint8_t batch_map[256*192*4];
int batch_counter = 0;
int batch_biggest = 0;
int batch_num = 0;
for (int frame_counter=1; frame_counter<=frame_total; frame_counter++)
printf("Generating image map...");
std::stringstream ss;
int fastlz_total = 0;
int raw_total = 0;
int rle_total = 0;
file_out.open(path_resource + "/image.bin", std::ios::binary);
for (frame_counter=1; frame_counter<=frame_total; frame_counter++)
{
ss.str("");
ss << path_images << frame_counter << ".bmp";
int frame_w = -1;
int frame_h = -1;
int frame_n = -1;
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &frame_w, &frame_h, &frame_n, 3);
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &temp_w, &temp_h, &temp_n, 3);
for (int i=0; i<256*192; i++)
for (int rgb=0; rgb<256*192; rgb++)
{
int index = i*3;
int index = rgb*3;
unsigned char r = frame_raw[index];
unsigned char g = frame_raw[index + 1];
unsigned char b = frame_raw[index + 2];
uint16_t pixel_pal = RGB15(r, g, b);
int pixel_index = -1;
uint16_t palette_value = RGB15(r, g, b);
int palette_index = -1;
for (int i2=0; i2<256; i2++)
for (int i=0; i<256; i++)
{
if (palette[i2] == pixel_pal) {
pixel_index = i2;
if (palette_map[i] == palette_value) {
palette_index = i;
break;
}
}
if (pixel_index == -1) printf("%i> %i palette not found!!!\n", i, pixel_index);
else batch_map[i+ batch_counter*256*192] = pixel_index;
if (palette_index == -1) printf("frame %i> palette not found!!!\n", frame_counter);
else frame_map[rgb + chunk_counter*frame_size] = palette_index;
}
// printf("%i) frame %i/%i (%1.f%s)> done\n", batch_counter, frame_counter, frame_total, ((float)frame_counter/frame_total)*100, "%");
batch_counter++;
printf("%i) frame %i/%i (%1.f%s)> done\n", chunk_counter, frame_counter, frame_total, ((float)frame_counter/frame_total)*100, "%");
chunk_counter++;
// int size;
// char *batch_map_compress = LZS_Fast(batch_map, 256*192, &size);
// out.write(reinterpret_cast<const char*>(&size), sizeof(size));
// out.write(batch_map_compress, size);
if (batch_counter >= 4)
if (chunk_counter >= chunk_size)
{
bool isRLE = false;
for (auto y : usingRLE)
if (batch_num == y)
if (chunk_current == y)
isRLE = true;
uint32_t size, size2;
uint8_t *batch_map_compress = (uint8_t*)malloc(256*192*4*2);
if (isRLE)
{
char *temp = RLE_Code(batch_map, 256*192*4, (int*)&size);
size2 = (size << 1) | 0x01;
memcpy(batch_map_compress, temp, size);
free(temp);
char *temp = RLE_Code(compress_data, frame_size*chunk_size, (int*)&compress_size);
compress_flag = (compress_size << 2) | 0xfffffffd;
if (compress_size > frame_size*chunk_size)
{
free(temp);
compress_size = frame_size*chunk_size;
compress_flag = (compress_size << 2) | 0xfffffffe;
memcpy(compress_data, frame_map, compress_size);
printf("raw > ");
raw_total++;
}
else
{
memcpy(compress_data, temp, compress_size);
free(temp);
printf("rle > ");
printf("rle > ");
rle_total++;
}
}
else
{
size = fastlz_compress_level(1, batch_map, 256*192*4, batch_map_compress);
size2 = (size << 1);
compress_size = fastlz_compress_level(1, frame_map, frame_size*chunk_size, compress_data);
compress_flag = (compress_size << 2);
printf("fastlz > ");
if (compress_size > frame_size*chunk_size)
{
compress_size = frame_size*chunk_size;
compress_flag = (compress_size << 2) | 0xfffffffe;
memcpy(compress_data, frame_map, compress_size);
printf("raw > ");
raw_total++;
}
else
{
printf("fastlz > ");
fastlz_total++;
}
}
out.write(reinterpret_cast<const char*>(&size2), sizeof(uint32_t));
out.write(reinterpret_cast<const char*>(batch_map_compress), size);
file_out.write(reinterpret_cast<const char*>(&compress_flag), sizeof(uint32_t));
file_out.write(reinterpret_cast<const char*>(compress_data), compress_size);
batch_counter = 0;
if ((size) > batch_biggest) batch_biggest = (size);
printf("write batch %i %i/%i\n", size, batch_num, frame_total/4);
chunk_counter = 0;
if ((compress_size) > compress_size_biggest) compress_size_biggest = compress_size;
printf("write batch %i %i/%i\n", compress_size, chunk_current, frame_total/chunk_size);
free(batch_map_compress);
batch_num++;
chunk_current++;
}
}
out.close();
file_out.close();
// Print
printf("Total Frame: %i\n", frame_total);
printf("Biggest: %i\n", batch_biggest);
printf("Biggest : %i\n", compress_size_biggest);
printf("fastlz : %i\n", fastlz_total);
printf("rle : %i\n", rle_total);
printf("raw : %i\n", raw_total);
}
unsigned short RGB15(int r, int g, int b) {
unsigned short rgb15 =
((r >> 3) << 10) |
((g >> 3) << 5) |
(b >> 3);
// Set the alpha bit to 1
rgb15 |= 1 << 15;
return rgb15;
}

View File

@ -5,22 +5,27 @@
#include <mm_types.h>
#include <nds.h>
#include <filesystem.h>
#include <nds/arm9/background.h>
#include <nds/arm9/cache.h>
#include <nds/arm9/decompress.h>
#include <nds/arm9/video.h>
#include <nds/arm9/videoGL.h>
#include <nds/bios.h>
#include <nds/debug.h>
#include <nds/dma.h>
#include <nds/system.h>
#include <nds/timers.h>
#include <stdio.h>
#include <maxmod9.h>
#include <fcntl.h>
#include <gl2d.h>
#define TIMER_SPEED (BUS_CLOCK/1024)
void wait_forever(const char* msg);
size_t LoadFile(const char* file, unsigned char **buffer);
void readNextBatch(FILE *input, void *output);
void readNextMusic(FILE *input, void *output);
void vbl_handler();
void LoadNextChunk(void *output);
void onVBL();
class CircularQueue {
public:
@ -70,20 +75,28 @@ public:
}
};
int ptr_background;
int ptr_subbackground;
volatile int file_image = -1;
volatile int file_music = -1;
volatile bool noQueue = false;
constexpr int queue_size = 6;
static uint8_t chunk[256*192*4*7];
static int chunk_counter = 0;
static CircularQueue queue(7);
static FILE *in = NULL;
static FILE *in_music = NULL;
static int bgp;
constexpr int chunk_size = 10;
volatile int chunk_counter = 0;
volatile int chunk_current = 0;
static uint8_t music_buffer[1024*1000];
static CircularQueue music_queue(1000);
constexpr int frame_size = 256*192;
volatile int frame_counter = 0;
uint8_t frame_decompress[frame_size*chunk_size];
uint8_t frame_buffer[frame_size*chunk_size*queue_size];
CircularQueue frame_queue(queue_size);
constexpr int music_buffer_size = 4000*16;
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format ) {
if(in_music){
if(file_music){
size_t samplesize = 1;
switch(format){
case MM_STREAM_8BIT_MONO: samplesize = 1; break;
@ -92,23 +105,16 @@ mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats forma
case MM_STREAM_16BIT_STEREO: samplesize = 4; break;
}
dmaCopy(&music_buffer[1024*music_queue.front], dest, 1024);
music_queue.pop();
int res = read(file_music, dest, length*samplesize);
fprintf(stderr, "music %i/%i\n", music_queue.front, music_queue.current);
if(res){
length = res/samplesize;
} else {
mmStreamClose();
close(file_music);
length = 0;
}
// fprintf(stderr, "%i %p %i\n", length, dest, format);
// int res = fread(music_buffer, 1, length, in_music);
// dmaCopy(music_buffer, dest, res);
// DC_FlushRange(music_buffer, 1024);
// if(res){
// length = res;
// } else {
// mmStreamClose();
// fclose(in_music);
// length = 0;
// }
}
return length;
@ -117,34 +123,49 @@ mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats forma
int main(void) {
videoSetMode(MODE_5_3D);
videoSetModeSub(MODE_0_2D);
videoSetModeSub(MODE_5_2D);
vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankB(VRAM_B_TEXTURE);
vramSetBankC(VRAM_C_SUB_BG);
vramSetBankF(VRAM_F_TEX_PALETTE);
consoleDemoInit();
lcdMainOnBottom();
// consoleDemoInit();
consoleDebugInit(DebugDevice_NOCASH);
nitroFSInit(NULL);
in = fopen("nitro:/image.bin", "rb");
if (in == NULL) wait_forever("cannot load image.bin");
file_image = open("nitro:/image.bin", O_RDONLY);
if (file_image == -1) wait_forever("cannot load image.bin");
in_music = fopen("nitro:/music.raw", "rb");
if (in_music == NULL) wait_forever("cannot load music.raw");
file_music = open("nitro:/music.raw", O_RDONLY);
if (file_music == -1) wait_forever("cannot load music.raw");
unsigned char* pal = NULL;
size_t pal_len = LoadFile("nitro:/palette.bin", &pal);
bgp = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0);
ptr_background = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0);
ptr_subbackground = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, VRAM_C_SUB_BG, 0);
dmaCopy(pal, BG_PALETTE, pal_len);
dmaCopy(pal, BG_PALETTE_SUB, pal_len);
// glScreen2D();
// glLoadTileSet(
// img_washer,
// 512, 512,
// 512, 521,
// GL_RGB256,
// TEXTURE_SIZE_512, TEXTURE_SIZE_512,
// GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT,
// 8,
// (u16*)sagiri_washer_pal,
// (u8*)sagiri_washer);
// DC_FlushAll();
// timerStart(1, ClockDivider_1024, TIMER_FREQ_1024(30), music);
// fprintf(stderr, "start debug\n");
// int cframe = 0;
// int hframe = 0;
@ -158,26 +179,21 @@ int main(void) {
// ticks = timerStop(0);
// int milis = ((ticks%TIMER_SPEED)*1000) /TIMER_SPEED;
// if (milis > 60) fprintf(stderr, "%i\n", cframe);
// if (milis > 50) fprintf(stderr, "%i\n", cframe);
// cframe++;
// }
// fprintf(stderr, "%i\n", hframe);
fseek(in, 0, SEEK_SET);
// fseek(in, 0, SEEK_SET);
fprintf(stderr, "read\n");
while(!queue.isFull()) {
queue.push();
readNextBatch(in, &chunk[256*192*4 * queue.rear]);
fprintf(stderr, "read %i\n", queue.rear);
}
while(!music_queue.isFull()) {
music_queue.push();
readNextMusic(in_music, &music_buffer[1024 * music_queue.rear]);
fprintf(stderr, "preload start\n");
while(!frame_queue.isFull()) {
frame_queue.push();
LoadNextChunk(&frame_buffer[frame_size*chunk_size*frame_queue.rear]);
}
fprintf(stderr, "preload done %i\n", frame_queue.current);
DC_FlushAll();
@ -188,89 +204,89 @@ int main(void) {
sys.fifo_channel = FIFO_MAXMOD;
mmInit( &sys );
mm_stream mystream;
mystream.sampling_rate = 1000;
mystream.buffer_length = 1024;
mystream.sampling_rate = 22050;
mystream.buffer_length = music_buffer_size;
mystream.callback = on_stream_request;
mystream.format = MM_STREAM_16BIT_MONO;
mystream.timer = MM_TIMER2;
mystream.manual = true;
// mmStreamOpen( &mystream );
DC_FlushAll();
mmStreamOpen( &mystream );
free(pal);
while(1) {
irqSet(IRQ_VBLANK, vbl_handler);
irqSet(IRQ_VBLANK, onVBL);
if (!queue.isFull()) {
queue.push();
readNextBatch(in, &chunk[256*192*4 * queue.rear]);
if (!frame_queue.isFull()) {
frame_queue.push();
LoadNextChunk(&frame_buffer[frame_size*chunk_size*frame_queue.rear]);
// fprintf(stderr, "read %i\n", queue.rear);
}
if (!music_queue.isFull()) {
music_queue.push();
readNextMusic(in_music, &music_buffer[1024 * music_queue.rear]);
fprintf(stderr, "read music %i\n", music_queue.rear);
}
if (!(frame_counter % 4)) mmStreamUpdate();
}
return 0;
}
void vbl_handler()
void onVBL()
{
mmStreamUpdate();
// DC_FlushRange(&chunk[256*192*4 * queue.front + 256*192*chunk_counter], 256*192*4);
dmaCopyAsynch(&frame_buffer[frame_size*chunk_size*frame_queue.front + frame_size*chunk_counter], bgGetGfxPtr(ptr_subbackground), frame_size);
// if (frame_queue.current < frame_queue.size*0.4) {
// fprintf(stderr, "%i\n ", chunk_counter);
// fprintf(stderr, "count: %i, %i\n ", chunk_counter, frame_queue.current);
// }
if (queue.isEmpty() && chunk_counter == 0) {
return;
fprintf(stderr, "NO QUEUE!!!!!\n");
}
DC_FlushRange(&chunk[256*192*4 * queue.front + 256*192*chunk_counter], 256*192*4);
dmaCopy(&chunk[256*192*4 * queue.front + 256*192*chunk_counter], bgGetGfxPtr(bgp), 256*192);
// fprintf(stderr, "count: %i, %i\n ", chunk_counter, queue.current);
chunk_counter++;
frame_counter++;
if (chunk_counter >= 4) {
if (!queue.isEmpty()) {
queue.pop();
if (chunk_counter >= chunk_size) {
if (!frame_queue.isEmpty()) {
frame_queue.pop();
chunk_counter = 0;
} else {
chunk_counter = 4;
chunk_counter = chunk_size;
noQueue = true;
fprintf(stderr, "NO QUEUE!!!!!\n");
}
}
}
static void *buffer = malloc(256*192*4);
void readNextMusic(FILE *input, void *output)
void LoadNextChunk(void *output)
{
fread(output, 1024, 1, input);
}
uint32_t compress_size;
read(file_image, &compress_size, sizeof(uint32_t));
uint32_t flag = compress_size & 0x3;
compress_size = compress_size >> 2;
void readNextBatch(FILE *input, void *output)
{
uint32_t chunk_len;
fread(&chunk_len, sizeof(uint32_t), 1, input);
bool isRLE = chunk_len & 0x01;
chunk_len = chunk_len >> 1;
fread(buffer, 1, chunk_len, input);
DC_FlushRange(buffer, 256*192*4);
if (isRLE)
if (flag == 0x01) // RLE
{
decompress(buffer, output, RLE);
read(file_image, frame_decompress, compress_size);
decompress(frame_decompress, output, RLE);
// fprintf(stderr, "RLE\n");
}
else
else if (flag == 0x10) // RAW
{
fastlz_decompress(buffer, chunk_len, output, 256*192*4);
read(file_image, output, compress_size);
// fprintf(stderr, "RAW\n");
}
else if (flag == 0x00) // fastlz
{
read(file_image, frame_decompress, compress_size);
fastlz_decompress(frame_decompress, compress_size, output, frame_size*chunk_size);
// fprintf(stderr, "fastlz\n");
}
chunk_current++;
noQueue = false;
// DC_FlushRange(output, 256*192*4);
}
size_t LoadFile(const char* file, unsigned char **buffer)
@ -298,7 +314,7 @@ size_t LoadFile(const char* file, unsigned char **buffer)
void wait_forever(const char* msg)
{
fprintf(stdout, "%s\n", msg);
fprintf(stderr, "%s\n", msg);
fprintf(stderr, "%s\n", msg);
while (1) swiWaitForVBlank();
}

1
vendor/FastLZ vendored

@ -1 +0,0 @@
Subproject commit 344eb4025f9ae866ebf7a2ec48850f7113a97a42