diff --git a/.gitignore b/.gitignore index b87e831ff..a20cbba4e 100644 --- a/.gitignore +++ b/.gitignore @@ -23,10 +23,12 @@ android/local.properties # Nintendo Console build results build-3ds/ build-gc/ +build-nds/ build-n64/ build-wii/ build-wiiu/ build-switch/ +classicube.nds # SEGA console build results build-dc/ # Microsoft console build results diff --git a/misc/ds/Makefile b/misc/ds/Makefile index 3da068c46..2cd4a2135 100644 --- a/misc/ds/Makefile +++ b/misc/ds/Makefile @@ -1,9 +1,164 @@ -NAME := classicube -GAME_TITLE := ClassiCube +# SPDX-License-Identifier: CC0-1.0 +# +# SPDX-FileContributor: Antonio Niño Díaz, 2023 +export BLOCKSDS ?= /opt/blocksds/core +export BLOCKSDSEXT ?= /opt/blocksds/external + +NAME := classicube +GAME_TITLE := ClassiCube +GAME_SUBTITLE := Built with BlocksDS +GAME_AUTHOR := UnknownShadow200 +GAME_ICON := misc/ds/icon.bmp SOURCEDIRS := src +INCLUDEDIRS := DEFINES := -DPLAT_NDS -LIBS := -ldswifi9 -lnds9 +LIBS := -ldswifi9 -lnds9 -lc LIBDIRS := $(BLOCKSDS)/libs/dswifi $(BLOCKSDS)/libs/libnds -include $(BLOCKSDS)/sys/default_makefiles/rom_arm9/Makefile + +export WONDERFUL_TOOLCHAIN ?= /opt/wonderful +ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/ + +# 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 + +# Build artifacts +# --------------- + +BUILDDIR := build-nds +ELF := build-nds/$(NAME).elf +DUMP := build-nds/$(NAME).dump +MAP := build-nds/$(NAME).map +ROM := $(NAME).nds + +# 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 +# ------------ + +SOURCES_S := $(foreach dir,$(SOURCEDIRS),$(wildcard $(dir)/*.s)) +SOURCES_C := $(foreach dir,$(SOURCEDIRS),$(wildcard $(dir)/*.c)) + +# Compiler and linker flags +# ------------------------- + +ARCH := -mthumb -mcpu=arm946e-s+nofp + +SPECS := $(BLOCKSDS)/sys/crts/ds_arm9.specs + +WARNFLAGS := -Wall + +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) + +LDFLAGS := $(ARCH) $(LIBDIRSFLAGS) -Wl,-Map,$(MAP) $(DEFINES) \ + -Wl,--start-group $(LIBS) -Wl,--end-group -specs=$(SPECS) + +# Intermediate build files +# ------------------------ +OBJS := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_S))) \ + $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_C))) + +DEPS := $(OBJS:.o=.d) + +# Targets +# ------- + +.PHONY: all clean dump dldipatch sdimage + +all: $(ROM) + +# 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) + +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 $@ $< + +# Include dependency files if they exist +# -------------------------------------- + +-include $(DEPS) + diff --git a/misc/ds/icon.bmp b/misc/ds/icon.bmp new file mode 100644 index 000000000..c5a571c41 Binary files /dev/null and b/misc/ds/icon.bmp differ diff --git a/src/Platform_NDS.c b/src/Platform_NDS.c index e1dc5e382..4d3d1a7f6 100644 --- a/src/Platform_NDS.c +++ b/src/Platform_NDS.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include "_PlatformConsole.h" const cc_result ReturnCode_FileShareViolation = 1000000000; // not used @@ -80,8 +83,8 @@ static void LogNocash(const char* msg, int len) { } void Platform_Log(const char* msg, int len) { - if (!keyboardOpen) LogConsole(msg, len); LogNocash(msg, len); + if (!keyboardOpen) LogConsole(msg, len); } TimeMS DateTime_CurrentUTC(void) { @@ -189,6 +192,12 @@ cc_result File_Length(cc_file file, cc_uint32* len) { } static void InitFilesystem(void) { + // I don't know why I have to call this function, but if I don't, + // then when running in DSi mode AND an SD card is readable, + // fatInitDefault gets stuck somewhere (in disk_initialize it seems) + const DISC_INTERFACE* sd_io = get_io_dsisd(); + if (sd_io) sd_io->startup(); + fat_available = fatInitDefault(); Platform_ReadonlyFilesystem = !fat_available; if (!fat_available) return; @@ -252,6 +261,8 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { /*########################################################################################################################* *---------------------------------------------------------Socket----------------------------------------------------------* *#########################################################################################################################*/ +static cc_bool net_supported = true; + static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* numValidAddrs) { struct hostent* res = gethostbyname(host); struct sockaddr_in* addr4; @@ -286,6 +297,8 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a struct sockaddr_in* addr4 = (struct sockaddr_in*)addrs[0].data; char str[NATIVE_STR_LEN]; String_EncodeUtf8(str, address); + + if (!net_supported) return ERR_NOT_SUPPORTED; *numValidAddrs = 1; if (inet_aton(str, &addr4->sin_addr) > 0) { @@ -302,6 +315,7 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { struct sockaddr* raw = (struct sockaddr*)addr->data; int res; + if (!net_supported) { *s = -1; return ERR_NOT_SUPPORTED; } *s = socket(raw->sa_family, SOCK_STREAM, 0); if (*s < 0) return errno; @@ -366,7 +380,8 @@ cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { static void InitNetworking(void) { if (!Wifi_InitDefault(INIT_ONLY)) { - Platform_LogConst("Initing WIFI failed"); return; + Platform_LogConst("Initing WIFI failed"); + net_supported = false; return; } Wifi_AutoConnect(); @@ -376,11 +391,13 @@ static void InitNetworking(void) { if (status == ASSOCSTATUS_ASSOCIATED) return; if (status == ASSOCSTATUS_CANNOTCONNECT) { - Platform_LogConst("Can't connect to WIFI"); return; + Platform_LogConst("Can't connect to WIFI"); + net_supported = false; return; } swiWaitForVBlank(); } Platform_LogConst("Gave up after 300 tries"); + net_supported = false; }