Compare commits

..

No commits in common. "f857a9e25878481956c134a52dd8026ea8d8cc26" and "c415f3b2e66a95fb2d078b3cb610e006b163ec9d" have entirely different histories.

23 changed files with 653 additions and 565 deletions

30
.gitignore vendored
View File

@ -1,13 +1,27 @@
/assets/*
/assets/out/*
/assets/*.*
/assets/out/*.bmp
!/assets/convert.sh
/build/*
/build
/build*
/nitrofs/image.bin
/nitrofs/music.raw
/nitrofs/palette.bin
/resource/image.bin
/resource/music.raw
/resource/palette.bin
compile_commands.json
*.nds
/.cache
/NDS/nitrofiles/*
!/NDS/nitrofiles/.gitignore
/NDS/cmake
/NDS/compile_commands.json
/NDS/.cache
/NDS/build
/NDS/dist
/encoder/node_modules
/encoder/data_compress
/encoder/temp
/encoder/cpp/lzss
/temp

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "libs/FastLZ"]
path = libs/FastLZ
url = https://github.com/ariya/FastLZ.git
[submodule "libs/RaylibDS"]
path = libs/RaylibDS
url = https://sillysagiri.my.id/sillysagiri/RaylibDS.git

View File

@ -1,9 +1,5 @@
{
"clangd.arguments": [
"--query-driver=/opt/wonderful/toolchain/gcc-arm-none-eabi/bin/arm-none-eabi-*"
],
"files.exclude": {
".cache": true,
"build": true
}
"--query-driver=/opt/devkitpro/devkitARM/bin/arm-none-eabi-g++"
]
}

48
CMakeLists.txt Executable file
View File

@ -0,0 +1,48 @@
cmake_minimum_required(VERSION 3.27)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(PROJECT_NAME "badapple")
set(NDSTOOL_NAME ${PROJECT_NAME} CACHE BOOL "")
set(NDSTOOL_SUBTITLE1 "Created by sillysagiri" CACHE BOOL "")
set(NDSTOOL_SUBTITLE2 "sillysagiri.my.id" CACHE BOOL "")
set(NDSTOOL_NITROFS "resource" CACHE BOOL "")
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"
${fastlz_SOURCE_DIR}/fastlz.c)
set(PROJECT_INCLUDE
"src"
${fastlz_SOURCE_DIR})
set(PROJECT_VENDOR
"filesystem"
"fat"
"mm9")
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE})
target_link_libraries(${PROJECT_NAME} PUBLIC ${PROJECT_VENDOR})
nds_create_rom(${PROJECT_NAME})
# yeah i know its stupid, but its working!!
add_custom_command(
TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/arm7
COMMAND ${DEVKITPRO}/portlibs/nds/bin/arm-none-eabi-cmake -S ${CMAKE_SOURCE_DIR}/arm7 ${CMAKE_BINARY_DIR}/arm7
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/arm7
)

293
Makefile
View File

@ -1,293 +0,0 @@
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileContributor: Antonio Niño Díaz, 2023
export BLOCKSDS ?= /opt/blocksds/core
export BLOCKSDSEXT ?= /opt/blocksds/external
export WONDERFUL_TOOLCHAIN ?= /opt/wonderful
ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/
# User config
# ===========
NAME := badapple
GAME_TITLE := Bad Apple
GAME_SUBTITLE := Built with BlocksDS
GAME_AUTHOR := sillysagiri
GAME_ICON := icon.bmp
# DLDI and internal SD slot of DSi
# --------------------------------
# Root folder of the SD image
SDROOT := sdroot
# Name of the generated image it "DSi-1.sd" for no$gba in DSi mode
SDIMAGE := image.bin
# Source code paths
# -----------------
SOURCEDIRS := src libs/FastLZ/fastlz.c libs/RaylibDS
INCLUDEDIRS := src libs/FastLZ libs/RaylibDS
GFXDIRS :=
BINDIRS :=
AUDIODIRS :=
# A single directory that is the root of NitroFS:
NITROFSDIR := nitrofs
# Defines passed to all files
# ---------------------------
DEFINES := -DARM9
# Libraries
# ---------
LIBS := -lmm9 -lnds9
LIBDIRS := $(BLOCKSDS)/libs/maxmod \
$(BLOCKSDS)/libs/libnds
# Build artifacts
# ---------------
BUILDDIR := build/$(NAME)
ELF := build/$(NAME).elf
DUMP := build/$(NAME).dump
MAP := build/$(NAME).map
ROM := $(NAME).nds
# If NITROFSDIR is set, the output of mmutil will be placed in that directory
SOUNDBANKINFODIR := $(BUILDDIR)/maxmod
ifeq ($(strip $(NITROFSDIR)),)
SOUNDBANKDIR := $(BUILDDIR)/maxmod
else
SOUNDBANKDIR := $(NITROFSDIR)
endif
# Tools
# -----
PREFIX := $(ARM_NONE_EABI_PATH)arm-none-eabi-
CC := $(PREFIX)gcc
CXX := $(PREFIX)g++
LD := $(PREFIX)gcc
OBJDUMP := $(PREFIX)objdump
MKDIR := mkdir
RM := rm -rf
# Verbose flag
# ------------
ifeq ($(VERBOSE),1)
V :=
else
V := @
endif
# Source files
# ------------
ifneq ($(BINDIRS),)
SOURCES_BIN := $(shell find -L $(BINDIRS) -name "*.bin")
INCLUDEDIRS += $(addprefix $(BUILDDIR)/,$(BINDIRS))
endif
ifneq ($(GFXDIRS),)
SOURCES_PNG := $(shell find -L $(GFXDIRS) -name "*.png")
INCLUDEDIRS += $(addprefix $(BUILDDIR)/,$(GFXDIRS))
endif
ifneq ($(AUDIODIRS),)
SOURCES_AUDIO := $(shell find -L $(AUDIODIRS) -regex '.*\.\(it\|mod\|s3m\|wav\|xm\)')
ifneq ($(SOURCES_AUDIO),)
INCLUDEDIRS += $(SOUNDBANKINFODIR)
endif
endif
SOURCES_S := $(shell find -L $(SOURCEDIRS) -name "*.s")
SOURCES_C := $(shell find -L $(SOURCEDIRS) -name "*.c")
SOURCES_CPP := $(shell find -L $(SOURCEDIRS) -name "*.cpp")
# Compiler and linker flags
# -------------------------
ARCH := -mthumb -mcpu=arm946e-s+nofp
SPECS := $(BLOCKSDS)/sys/crts/ds_arm9.specs
WARNFLAGS := -Wall
ifeq ($(SOURCES_CPP),)
LIBS += -lc
else
LIBS += -lstdc++ -lc
endif
INCLUDEFLAGS := $(foreach path,$(INCLUDEDIRS),-I$(path)) \
$(foreach path,$(LIBDIRS),-I$(path)/include)
LIBDIRSFLAGS := $(foreach path,$(LIBDIRS),-L$(path)/lib)
ASFLAGS += -x assembler-with-cpp $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -ffunction-sections -fdata-sections \
-specs=$(SPECS)
CFLAGS += -std=gnu17 $(WARNFLAGS) $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -O2 -ffunction-sections -fdata-sections \
-specs=$(SPECS)
CXXFLAGS += -std=gnu++17 $(WARNFLAGS) $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -O2 -ffunction-sections -fdata-sections \
-fno-exceptions -fno-rtti \
-specs=$(SPECS)
LDFLAGS := $(ARCH) $(LIBDIRSFLAGS) -Wl,-Map,$(MAP) $(DEFINES) \
-Wl,--start-group $(LIBS) -Wl,--end-group -specs=$(SPECS)
# Intermediate build files
# ------------------------
OBJS_ASSETS := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_PNG)))
HEADERS_ASSETS := $(patsubst %.bin,%_bin.h,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN))) \
$(patsubst %.png,%.h,$(addprefix $(BUILDDIR)/,$(SOURCES_PNG)))
ifneq ($(SOURCES_AUDIO),)
ifeq ($(strip $(NITROFSDIR)),)
OBJS_ASSETS += $(SOUNDBANKDIR)/soundbank.c.o
endif
HEADERS_ASSETS += $(SOUNDBANKINFODIR)/soundbank.h
endif
OBJS_SOURCES := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_S))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_C))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_CPP)))
OBJS := $(OBJS_ASSETS) $(OBJS_SOURCES)
DEPS := $(OBJS:.o=.d)
# Targets
# -------
.PHONY: all clean dump dldipatch sdimage
all: $(ROM)
ifneq ($(strip $(NITROFSDIR)),)
# Additional arguments for ndstool
NDSTOOL_ARGS := -d $(NITROFSDIR)
# Make the NDS ROM depend on the filesystem only if it is needed
$(ROM): $(NITROFSDIR)
endif
# Combine the title strings
ifeq ($(strip $(GAME_SUBTITLE)),)
GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_AUTHOR)
else
GAME_FULL_TITLE := $(GAME_TITLE);$(GAME_SUBTITLE);$(GAME_AUTHOR)
endif
$(ROM): $(ELF)
@echo " NDSTOOL $@"
$(V)$(BLOCKSDS)/tools/ndstool/ndstool -c $@ \
-7 $(BLOCKSDS)/sys/default_arm7/arm7.elf -9 $(ELF) \
-b $(GAME_ICON) "$(GAME_FULL_TITLE)" \
$(NDSTOOL_ARGS)
$(ELF): $(OBJS)
@echo " LD $@"
$(V)$(LD) -o $@ $(OBJS) $(LDFLAGS)
$(DUMP): $(ELF)
@echo " OBJDUMP $@"
$(V)$(OBJDUMP) -h -C -S $< > $@
dump: $(DUMP)
clean:
@echo " CLEAN"
$(V)$(RM) $(ROM) $(DUMP) build $(SDIMAGE) \
$(SOUNDBANKDIR)/soundbank.bin
sdimage:
@echo " MKFATIMG $(SDIMAGE) $(SDROOT)"
$(V)$(BLOCKSDS)/tools/mkfatimg/mkfatimg -t $(SDROOT) $(SDIMAGE)
dldipatch: $(ROM)
@echo " DLDIPATCH $(ROM)"
$(V)$(BLOCKSDS)/tools/dldipatch/dldipatch patch \
$(BLOCKSDS)/sys/dldi_r4/r4tf.dldi $(ROM)
# Rules
# -----
$(BUILDDIR)/%.s.o : %.s
@echo " AS $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(ASFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.c.o : %.c
@echo " CC $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.arm.c.o : %.arm.c
@echo " CC $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -marm -mlong-calls -c -o $@ $<
$(BUILDDIR)/%.cpp.o : %.cpp
@echo " CXX $<"
@$(MKDIR) -p $(@D)
$(V)$(CXX) $(CXXFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.arm.cpp.o : %.arm.cpp
@echo " CXX $<"
@$(MKDIR) -p $(@D)
$(V)$(CXX) $(CXXFLAGS) -MMD -MP -marm -mlong-calls -c -o $@ $<
$(BUILDDIR)/%.bin.o $(BUILDDIR)/%_bin.h : %.bin
@echo " BIN2C $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $< $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.bin.o $(BUILDDIR)/$*_bin.c
$(BUILDDIR)/%.png.o $(BUILDDIR)/%.h : %.png %.grit
@echo " GRIT $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/grit/grit $< -ftc -W1 -o$(BUILDDIR)/$*
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.png.o $(BUILDDIR)/$*.c
$(V)touch $(BUILDDIR)/$*.png.o $(BUILDDIR)/$*.h
ifneq ($(SOURCES_AUDIO),)
$(SOUNDBANKINFODIR)/soundbank.h: $(SOURCES_AUDIO)
@echo " MMUTIL $^"
@$(MKDIR) -p $(@D)
@$(BLOCKSDS)/tools/mmutil/mmutil $^ -d \
-o$(SOUNDBANKDIR)/soundbank.bin -h$(SOUNDBANKINFODIR)/soundbank.h
ifeq ($(strip $(NITROFSDIR)),)
$(SOUNDBANKDIR)/soundbank.c.o: $(SOUNDBANKINFODIR)/soundbank.h
@echo " BIN2C soundbank.bin"
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $(SOUNDBANKDIR)/soundbank.bin \
$(SOUNDBANKDIR)
@echo " CC.9 soundbank_bin.c"
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(SOUNDBANKDIR)/soundbank.c.o \
$(SOUNDBANKDIR)/soundbank_bin.c
endif
endif
# All assets must be built before the source code
# -----------------------------------------------
$(SOURCES_S) $(SOURCES_C) $(SOURCES_CPP): $(HEADERS_ASSETS)
# Include dependency files if they exist
# --------------------------------------
-include $(DEPS)

21
arm7/CMakeLists.txt Executable file
View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# armv5te arm9
# armv4t arm7
set(CMAKE_SYSTEM_PROCESSOR "armv4t")
project(arm7)
set(PROJECT_INCLUDE
"src")
file(GLOB PROJECT_SOURCES CONFIGURE_DEPENDS
"src/*.cpp"
"src/**/*.cpp")
add_executable(arm7 ${PROJECT_SOURCES})
target_include_directories(arm7 PRIVATE ${PROJECT_INCLUDE})
target_link_libraries(arm7 PUBLIC dswifi7 mm7 filesystem fat)

99
arm7/src/main.cpp Executable file
View File

@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------------
default ARM7 core
Copyright (C) 2005 - 2010
Michael Noland (joat)
Jason Rogers (dovoto)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/
#include <nds.h>
#include <dswifi7.h>
#include <maxmod7.h>
#include <filesystem.h>
#include <cstdio>
#include <cstdlib>
#include <nds/debug.h>
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);
REG_SOUNDCNT |= SOUND_ENABLE;
writePowerManagement(PM_CONTROL_REG, ( readPowerManagement(PM_CONTROL_REG) & ~PM_SOUND_MUTE ) | PM_SOUND_AMP );
powerOn(POWER_SOUND);
readUserSettings();
ledBlink(0);
irqInit();
// Start the RTC tracking IRQ
initClockIRQ();
fifoInit();
touchInit();
mmInstall(FIFO_MAXMOD);
SetYtrigger(80);
installWifiFIFO();
installSoundFIFO();
installSystemFIFO();
irqSet(IRQ_VCOUNT, VcountHandler);
irqSet(IRQ_VBLANK, VblankHandler);
irqEnable( IRQ_VBLANK | IRQ_VCOUNT | IRQ_NETWORK);
setPowerButtonCB(powerButtonCB);
// Keep the ARM7 mostly idle
while (!exitflag) {
if ( 0 == (REG_KEYINPUT & (KEY_A | KEY_B))) {
exitflag = true;
}
swiWaitForVBlank();
}
return 0;
}

View File

@ -1,15 +1,18 @@
#!/bin/sh
palette="palette.png"
video="video.webm"
# output="video_out.gif"
video="video.mp4"
output="out/out_%d.bmp"
filters="scale=256x192:flags=lanczos:force_original_aspect_ratio=decrease,pad=256:192:-1:-1:color=black"
filters="fps=60,scale=256x192"
skip="-t 1 -ss 00:8"
# video
ffmpeg -i $video -vf "$filters,palettegen=max_colors=256:reserve_transparent=0:stats_mode=diff" -y $palette
ffmpeg -i $video -i $palette -filter_complex "$filters,setpts=0.8*PTS[x];[x][1:v]paletteuse=dither=none" -y $output
# 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 -filter:a "atempo=1.25" -vn -ac 1 -ar 22050 -y music.raw
ffmpeg -i $video -f s16le -ac 1 -ar 22050 music.raw

View File

@ -9,7 +9,7 @@ project(${PROJECT_NAME})
message(STATUS "Downloading fastlz library")
include(FetchContent)
FetchContent_Declare(fastlz URL https://github.com/ariya/FastLZ/archive/refs/heads/master.zip)
FetchContent_Declare(fastlz URL https://git.sillysagiri.my.id/MirrorRepo/FastLZ/archive/master.zip)
FetchContent_MakeAvailable(fastlz)
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS

View File

@ -1,8 +1,13 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <stdint.h>
#include <string>
#include <vector>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
@ -10,132 +15,177 @@
extern "C" char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len);
#define RGBtoRGB15(r,g,b) (((r >> 3) & 0x1F) | (((g >> 3) & 0x1F) << 5) | (((b >> 3) & 0x1F) << 10))
unsigned short RGB15(int r, int g, int b);
#define ASSETS_PATH "../assets"
#define PALETTE_SIZE 256
#define FRAME_SIZE 256*192
#define CHUNK_SIZE 10
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";
uint16_t palette_buffer[PALETTE_SIZE];
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};
size_t chunk_counter = 0;
size_t chunk_current = 0;
size_t frame_total = 0;
uint8_t frame_buffer[FRAME_SIZE*CHUNK_SIZE];
constexpr int palette_size = 256;
uint16_t palette_map[palette_size];
uint32_t compress_size;
uint32_t compress_size_total;
size_t compress_size_biggest;
uint8_t compress_buffer[FRAME_SIZE*CHUNK_SIZE*2];
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;
void Frame_RAWtoRGB15(unsigned char *frame, unsigned char *dest);
int main()
{
printf("Finding total frame...");
// Find total frame
for (const auto& entry : std::filesystem::directory_iterator(ASSETS_PATH "/out/")) {
for (const auto& entry : std::filesystem::directory_iterator(path_out)) {
if (entry.is_regular_file()) {
std::string filename = entry.path().filename().string();
int extpos = filename.find(".bmp", 4);
if (extpos != std::string::npos)
{
int number = std::stoi(filename.substr(4, extpos-4));
if (number > frame_total) frame_total = number;
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;
}
}
}
}
// Generate palette
printf("Generating palette map...\n");
int pal_w, pal_h, pal_n;
unsigned char *palette_raw = stbi_load(ASSETS_PATH "/palette.png", &pal_w, &pal_h, &pal_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<PALETTE_SIZE; i++)
for (int i=0; i<palette_size; i++)
{
int index = i*3;
unsigned char r = palette_raw[index];
unsigned char g = palette_raw[index + 1];
unsigned char b = palette_raw[index + 2];
palette_buffer[i] = RGBtoRGB15(r, g, b);
palette_map[i] = RGB15(r, g, b);
// printf("%i> %i,%i,%i (%i)\n", i, r, g, b, palette[i]);
}
printf("Writing palette map...\n");
file_out.open(ASSETS_PATH "/palette.bin", std::ios::binary);
file_out.write(reinterpret_cast<const char*>(palette_buffer), sizeof(palette_buffer));
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();
printf("Generating image map...\n");
printf("Generating image map...");
std::stringstream ss;
file_out.open(ASSETS_PATH "/image.bin", std::ios::binary);
int fastlz_total = 0;
int raw_total = 0;
int rle_total = 0;
file_out.open(path_resource + "/image.bin", std::ios::binary);
// Calculate the number of complete iterations needed
int numIterations = frame_total / CHUNK_SIZE;
// Calculate the number of remaining items
int remainingItems = frame_total % CHUNK_SIZE;
for (int i=0; i<numIterations; i++)
for (frame_counter=1; frame_counter<=frame_total; frame_counter++)
{
ss.str("");
ss << path_images << frame_counter << ".bmp";
for (int i_chunk=0; i_chunk<CHUNK_SIZE; i_chunk++) {
// Calculate the index of the current item within the total set
int itemIndex = i * CHUNK_SIZE + i_chunk;
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &temp_w, &temp_h, &temp_n, 3);
ss.str("");
ss << ASSETS_PATH "/out/out_" << itemIndex+1 << ".bmp";
for (int rgb=0; rgb<256*192; rgb++)
{
int index = rgb*3;
unsigned char r = frame_raw[index];
unsigned char g = frame_raw[index + 1];
unsigned char b = frame_raw[index + 2];
// printf("loading %s\n", ss.str().c_str());
uint16_t palette_value = RGB15(r, g, b);
int palette_index = -1;
int frame_w, frame_h, frame_n;
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &frame_w, &frame_h, &frame_n, 3);
for (int i=0; i<256; i++)
{
if (palette_map[i] == palette_value) {
palette_index = i;
break;
}
}
Frame_RAWtoRGB15(frame_raw, &frame_buffer[i_chunk*FRAME_SIZE]);
if (palette_index == -1) printf("frame %i> palette not found!!!\n", frame_counter);
else frame_map[rgb + chunk_counter*frame_size] = palette_index;
}
compress_size = fastlz_compress_level(1, frame_buffer, FRAME_SIZE*CHUNK_SIZE, compress_buffer);
if ((compress_size) > compress_size_biggest) compress_size_biggest = compress_size;
compress_size_total += compress_size;
printf("%i) frame %i/%i (%1.f%s)> done\n", chunk_counter, frame_counter, frame_total, ((float)frame_counter/frame_total)*100, "%");
chunk_counter++;
file_out.write(reinterpret_cast<const char*>(&compress_size), sizeof(uint32_t));
file_out.write(reinterpret_cast<const char*>(compress_buffer), compress_size);
if (chunk_counter >= chunk_size)
{
printf("write chunk %i bytes %i/%i\n", compress_size, i, numIterations-1);
}
bool isRLE = false;
// Handle remaining frame
if (remainingItems > 0) {
memset(frame_buffer, 0, FRAME_SIZE*CHUNK_SIZE);
for (auto y : usingRLE)
if (chunk_current == y)
isRLE = true;
int i_chunk = 0;
for (int k = frame_total-remainingItems; k<frame_total; k++) {
ss.str("");
ss << ASSETS_PATH "/out/out_" << k+1 << ".bmp";
if (isRLE)
{
char *temp = RLE_Code(compress_data, frame_size*chunk_size, (int*)&compress_size);
compress_flag = (compress_size << 2) | 0xfffffffd;
// printf("loading %s\n", ss.str().c_str());
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);
int frame_w, frame_h, frame_n;
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &frame_w, &frame_h, &frame_n, 3);
printf("rle > ");
rle_total++;
}
}
else
{
compress_size = fastlz_compress_level(1, frame_map, frame_size*chunk_size, compress_data);
compress_flag = (compress_size << 2);
Frame_RAWtoRGB15(frame_raw, &frame_buffer[i_chunk*FRAME_SIZE]);
i_chunk++;
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++;
}
}
file_out.write(reinterpret_cast<const char*>(&compress_flag), sizeof(uint32_t));
file_out.write(reinterpret_cast<const char*>(compress_data), compress_size);
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);
chunk_current++;
}
compress_size = fastlz_compress_level(1, frame_buffer, FRAME_SIZE*CHUNK_SIZE, compress_buffer);
if ((compress_size) > compress_size_biggest) compress_size_biggest = compress_size;
compress_size_total += compress_size;
file_out.write(reinterpret_cast<const char*>(&compress_size), sizeof(uint32_t));
file_out.write(reinterpret_cast<const char*>(compress_buffer), compress_size);
printf("write remaining chunk %i bytes\n", compress_size);
}
file_out.close();
@ -143,30 +193,19 @@ int main()
// Print
printf("Total Frame: %i\n", frame_total);
printf("Biggest : %i\n", compress_size_biggest);
printf("Total Size : %1.fmb\n", static_cast<double>(compress_size_total) / (1024*1024));
printf("fastlz : %i\n", fastlz_total);
printf("rle : %i\n", rle_total);
printf("raw : %i\n", raw_total);
}
void Frame_RAWtoRGB15(unsigned char *frame, unsigned char *dest)
{
for (int rgb=0; rgb<FRAME_SIZE; rgb++)
{
int index = rgb*3;
unsigned char r = frame[index];
unsigned char g = frame[index + 1];
unsigned char b = frame[index + 2];
unsigned short RGB15(int r, int g, int b) {
unsigned short rgb15 =
((r >> 3) << 10) |
((g >> 3) << 5) |
(b >> 3);
uint16_t palette_value = RGBtoRGB15(r, g, b);
int palette_index = -1;
// Set the alpha bit to 1
rgb15 |= 1 << 15;
for (int i=0; i<256; i++)
{
if (palette_buffer[i] == palette_value) {
palette_index = i;
break;
}
}
if (palette_index == -1) dest[rgb] = 0;
else dest[rgb] = palette_index;
}
return rgb15;
}

121
encoder/rle.c Normal file
View File

@ -0,0 +1,121 @@
/*----------------------------------------------------------------------------*/
/*-- rle.c - RLE 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 <http://www.gnu.org/licenses/>. --*/
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*----------------------------------------------------------------------------*/
#define CMD_DECODE 0x00 // decode
#define CMD_CODE_30 0x30 // RLE magic number
#define RLE_CHECK 1 // bits to check
#define RLE_MASK 0x80 // bits position:
// ((((1 << RLE_CHECK) - 1) << (8 - RLE_CHECK)
#define RLE_LENGTH 0x7F // length, (0xFF & ~RLE_MASK)
#define RLE_THRESHOLD 2 // max number of bytes to not encode
#define RLE_N 0x80 // max store, (RLE_LENGTH + 1)
#define RLE_F 0x82 // max coded, (RLE_LENGTH + RLE_THRESHOLD + 1)
#define RAW_MINIM 0x00000000 // empty file, 0 bytes
#define RAW_MAXIM 0x00FFFFFF // 3-bytes length, 16MB - 1
#define RLE_MINIM 0x00000004 // header only (empty RAW file)
#define RLE_MAXIM 0x01400000 // 0x01020003, padded to 20MB:
// * header, 4
// * length, RAW_MAXIM
// * flags, (RAW_MAXIM + RLE_N - 1) / RLE_N
// 4 + 0x00FFFFFF + 0x00020000 + padding
/*----------------------------------------------------------------------------*/
#define BREAK(text) { printf(text); return; }
#define EXIT(text) { printf(text); exit(-1); }
/*----------------------------------------------------------------------------*/
void Title(void);
void Usage(void);
char *Load(char *filename, int *length, int min, int max);
void Save(char *filename, char *buffer, int length);
char *Memory(int length, int size);
void RLE_Decode(char *filename);
void RLE_Encode(char *filename);
char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len);
/*----------------------------------------------------------------------------*/
char *Memory(int length, int size) {
char *fb;
fb = (char *) calloc(length, size);
if (fb == NULL) EXIT("\nMemory error\n");
return(fb);
}
/*----------------------------------------------------------------------------*/
char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len) {
unsigned char *pak_buffer, *pak, *raw, *raw_end, store[RLE_N];
unsigned int pak_len, len, store_len, count;
pak_len = 4 + raw_len + ((raw_len + RLE_N - 1) / RLE_N);
pak_buffer = (unsigned char *) Memory(pak_len, sizeof(char));
*(unsigned int *)pak_buffer = CMD_CODE_30 | (raw_len << 8);
pak = pak_buffer + 4;
raw = raw_buffer;
raw_end = raw_buffer + raw_len;
store_len = 0;
while (raw < raw_end) {
for (len = 1; len < RLE_F; len++) {
if (raw + len == raw_end) break;
if (*(raw + len) != *raw) break;
}
if (len <= RLE_THRESHOLD) store[store_len++] = *raw++;
if ((store_len == RLE_N) || (store_len && (len > RLE_THRESHOLD))) {
*pak++ = store_len - 1;
for (count = 0; count < store_len; count++) *pak++ = store[count];
store_len = 0;
}
if (len > RLE_THRESHOLD) {
*pak++ = RLE_MASK | (len - (RLE_THRESHOLD + 1));
*pak++ = *raw;
raw += len;
}
}
if (store_len) {
*pak++ = store_len - 1;
for (count = 0; count < store_len; count++) *pak++ = store[count];
}
*new_len = pak - pak_buffer;
return(pak_buffer);
}
/*----------------------------------------------------------------------------*/
/*-- EOF Copyright (C) 2011 CUE --*/
/*----------------------------------------------------------------------------*/

BIN
icon.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

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

@ -1 +0,0 @@
Subproject commit a55a77fd3e960f472655ee3b9bbe9329202c8a50

View File

View File

@ -1,28 +1,31 @@
#include "fastlz.h"
#include "filesystem.h"
#include "nds/arm9/console.h"
#include "raylibds.hpp"
#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <malloc.h>
#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 PALETTE_SIZE 256
#define FRAME_SIZE 256*192
#define CHUNK_SIZE 10
#define QUEUE_SIZE 6
#define FRAMERATE 30
#define STREAM_CHUNK_SIZE 32000
#define STREAM_QUEUE_SIZE 4
#define MMSTREAM_BUF_SIZE 9600
#define TIMER_SPEED (BUS_CLOCK/1024)
void wait_forever(const char* msg);
size_t LoadFile(const char* file, unsigned char **buffer);
void LoadNextChunk(void *output);
void TimerCallback();
void VBLCallback();
void FrameStep();
int ThreadEntrypoint(void *arg);
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format );
void onVBL();
class CircularQueue {
public:
@ -74,23 +77,48 @@ public:
int ptr_background;
int ptr_subbackground;
FILE *file_image = nullptr;
FILE *file_music = nullptr;
volatile int file_image = -1;
volatile int file_music = -1;
int chunk_current = 0;
volatile bool noQueue = false;
constexpr int queue_size = 6;
uint8_t *frame_decompress;
uint8_t *frame_buffer;
uint8_t *stream_buffer;
constexpr int chunk_size = 10;
volatile int chunk_counter = 0;
volatile int chunk_current = 0;
int stream_index;
int stream_buffer_current;
bool stream_need_update = false;
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);
CircularQueue frame_queue(QUEUE_SIZE);
CircularQueue stream_queue(STREAM_QUEUE_SIZE);
constexpr int music_buffer_size = 4000*16;
int music_buffer_size = 4000*16;
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format ) {
if(file_music){
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 = read(file_music, dest, length*samplesize);
if(res){
length = res/samplesize;
} else {
mmStreamClose();
close(file_music);
length = 0;
}
}
return length;
}
int main(void) {
@ -98,53 +126,74 @@ int main(void) {
videoSetModeSub(MODE_5_2D);
vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankB(VRAM_B_TEXTURE);
vramSetBankC(VRAM_C_SUB_BG);
vramSetBankF(VRAM_F_TEX_PALETTE);
lcdMainOnBottom();
// consoleDemoInit();
consoleDebugInit(DebugDevice_NOCASH);
frame_decompress = (uint8_t*)malloc(FRAME_SIZE*CHUNK_SIZE);
frame_buffer = (uint8_t*)malloc(FRAME_SIZE*CHUNK_SIZE*QUEUE_SIZE);
stream_buffer = (uint8_t*)malloc(STREAM_CHUNK_SIZE*STREAM_QUEUE_SIZE);
nitroFSInit(NULL);
sassert(
frame_buffer != nullptr ||
frame_decompress != nullptr ||
stream_buffer != nullptr,
"failed to allocate memmory");
file_image = open("nitro:/image.bin", O_RDONLY);
if (file_image == -1) wait_forever("cannot load image.bin");
bool nitrofs = nitroFSInit(NULL);
sassert(nitrofs, "error nitrofs");
file_music = open("nitro:/music.raw", O_RDONLY);
if (file_music == -1) wait_forever("cannot load music.raw");
file_image = fopen("nitro:/image.bin", "rb");
sassert(file_image != nullptr, "failed to load image.bin");
file_music = fopen("nitro:/music.raw", "rb");
sassert(file_image != nullptr, "failed to load music.raw");
int pal_len;
unsigned char* pal = Raylib::LoadFile("nitro:/palette.bin", pal_len);
unsigned char* pal = NULL;
size_t pal_len = LoadFile("nitro:/palette.bin", &pal);
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);
DC_FlushRange(pal, pal_len);
dmaCopy(pal, BG_PALETTE, pal_len);
dmaCopy(pal, BG_PALETTE_SUB, pal_len);
free(pal);
// 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();
// fprintf(stderr, "start debug\n");
// int cframe = 0;
// int hframe = 0;
// int ticks = 0;
// while(!feof(in))
// {
// timerStart(0, ClockDivider_1024, 0, NULL);
// readNextBatch(in , chunk);
// ticks = timerStop(0);
// int milis = ((ticks%TIMER_SPEED)*1000) /TIMER_SPEED;
// if (milis > 50) fprintf(stderr, "%i\n", cframe);
// cframe++;
// }
// fprintf(stderr, "%i\n", hframe);
// fseek(in, 0, SEEK_SET);
fprintf(stderr, "preload start\n");
while(!frame_queue.isFull()) {
frame_queue.push();
LoadNextChunk(&frame_buffer[FRAME_SIZE*CHUNK_SIZE*frame_queue.rear]);
LoadNextChunk(&frame_buffer[frame_size*chunk_size*frame_queue.rear]);
}
while(!stream_queue.isFull()) {
stream_queue.push();
fread(&stream_buffer[STREAM_CHUNK_SIZE*stream_queue.rear], sizeof(uint8_t), STREAM_CHUNK_SIZE, file_music);
}
stream_index = 0;
fprintf(stderr, "preload done %i\n", frame_queue.current);
DC_FlushAll();
@ -157,116 +206,115 @@ int main(void) {
mm_stream mystream;
mystream.sampling_rate = 22050;
mystream.buffer_length = MMSTREAM_BUF_SIZE;
mystream.buffer_length = music_buffer_size;
mystream.callback = on_stream_request;
mystream.format = MM_STREAM_16BIT_MONO;
mystream.timer = MM_TIMER2;
mystream.manual = false;
mystream.manual = true;
timerStart(0, ClockDivider_1024, TIMER_FREQ_1024(FRAMERATE), TimerCallback);
cothread_create(ThreadEntrypoint, NULL, 0, COTHREAD_DETACHED);
DC_FlushAll();
mmStreamOpen( &mystream );
free(pal);
while(1) {
cothread_yield_irq(IRQ_VBLANK);
scanKeys();
if (keysUp() & KEY_A) break;
}
irqSet(IRQ_VBLANK, onVBL);
return 0;
}
int ThreadEntrypoint(void *arg)
{
while(1) {
if (!frame_queue.isFull())
{
if (!frame_queue.isFull()) {
frame_queue.push();
LoadNextChunk(&frame_buffer[FRAME_SIZE*CHUNK_SIZE*frame_queue.rear]);
LoadNextChunk(&frame_buffer[frame_size*chunk_size*frame_queue.rear]);
// fprintf(stderr, "read %i\n", queue.rear);
}
cothread_yield();
if (!stream_queue.isFull())
{
stream_queue.push();
fread(stream_buffer+ stream_queue.rear*STREAM_CHUNK_SIZE, sizeof(uint8_t), STREAM_CHUNK_SIZE, file_music);
if (feof(file_music)) {
memset(stream_buffer+ stream_queue.rear*STREAM_CHUNK_SIZE, 0, STREAM_CHUNK_SIZE);
mmStreamClose();
}
}
cothread_yield();
if (!(frame_counter % 4)) mmStreamUpdate();
}
return 0;
}
void FrameStep()
void onVBL()
{
// if (feof(file_image)) return;
// 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);
// }
dmaCopyAsynch(&frame_buffer[FRAME_SIZE*CHUNK_SIZE*frame_queue.front + FRAME_SIZE*chunk_current], bgGetGfxPtr(ptr_background), FRAME_SIZE);
dmaCopyAsynch(&frame_buffer[FRAME_SIZE*CHUNK_SIZE*frame_queue.front + FRAME_SIZE*chunk_current], bgGetGfxPtr(ptr_subbackground), FRAME_SIZE);
chunk_counter++;
frame_counter++;
chunk_current++;
if (chunk_current >= CHUNK_SIZE) {
chunk_current = 0;
frame_queue.pop();
if (chunk_counter >= chunk_size) {
if (!frame_queue.isEmpty()) {
frame_queue.pop();
chunk_counter = 0;
} else {
chunk_counter = chunk_size;
noQueue = true;
fprintf(stderr, "NO QUEUE!!!!!\n");
}
}
}
void TimerCallback()
{
FrameStep();
}
void LoadNextChunk(void *output)
{
uint32_t compress_size;
fread(&compress_size, sizeof(uint32_t), 1, file_image);
read(file_image, &compress_size, sizeof(uint32_t));
fread(frame_decompress, sizeof(uint8_t), compress_size, file_image);
fastlz_decompress(frame_decompress, compress_size, output, FRAME_SIZE*CHUNK_SIZE);
uint32_t flag = compress_size & 0x3;
compress_size = compress_size >> 2;
if (flag == 0x01) // RLE
{
read(file_image, frame_decompress, compress_size);
decompress(frame_decompress, output, RLE);
// fprintf(stderr, "RLE\n");
}
else if (flag == 0x10) // RAW
{
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);
}
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format ) {
size_t LoadFile(const char* file, unsigned char **buffer)
{
FILE *in = fopen(file, "rb");
if (in == NULL) wait_forever("cannot load 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 len = length*samplesize;
fseek(in, 0, SEEK_END);
long file_size = ftell(in);
rewind(in);
if (feof(file_music))
*buffer = (unsigned char*)malloc(file_size);
if (*buffer == NULL) wait_forever("Failed to malloc!");
size_t bytes_read = fread(*buffer, 1, file_size, in);
if (bytes_read != file_size)
{
mmStreamClose();
uint8_t temp[len];
memset(temp, 0, len);
DC_FlushAll();
dmaCopyAsynch(temp, dest, len);
return length;
fclose(in);
free(*buffer);
wait_forever("Failed to read");
}
int bytesToCopy = std::min(len, STREAM_CHUNK_SIZE-stream_index);
dmaCopyAsynch(stream_buffer + stream_queue.front*STREAM_CHUNK_SIZE + stream_index, dest, bytesToCopy);
stream_index += bytesToCopy;
if (stream_index >= STREAM_CHUNK_SIZE)
{
stream_queue.pop();
stream_index = len - bytesToCopy;
// stream_index = 0;
dmaCopyAsynch(stream_buffer + stream_queue.front*STREAM_CHUNK_SIZE, dest+bytesToCopy, stream_index);
}
// return bytesToCopy/2;
return length;
return bytes_read;
}
void wait_forever(const char* msg)
{
fprintf(stderr, "%s\n", msg);
fprintf(stderr, "%s\n", msg);
while (1) swiWaitForVBlank();
}