diff --git a/graphics/sdl2/sdl2-demo/Makefile b/graphics/sdl2/sdl2-demo/Makefile new file mode 100644 index 0000000..7e15699 --- /dev/null +++ b/graphics/sdl2/sdl2-demo/Makefile @@ -0,0 +1,217 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_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 +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +# +# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .json +# - config.json +# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead +# of a homebrew executable (.nro). This is intended to be used for sysmodules. +# NACP building is skipped as well. +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include +ROMFS := romfs + +APP_TITLE := SDL2+mixer+image Demo +APP_AUTHOR := carstene1ns + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := `$(PREFIX)pkg-config --cflags sdl2 SDL2_mixer SDL2_image` -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := `$(PREFIX)pkg-config --libs sdl2 SDL2_mixer SDL2_image` \ + -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) + + +#--------------------------------------------------------------------------------- +# 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)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(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))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ and libEGL dependent projects +#--------------------------------------------------------------------------------- +export LD := $(CXX) + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +ifeq ($(strip $(ICON)),) + icons := $(wildcard *.jpg) + ifneq (,$(findstring $(TARGET).jpg,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).jpg + else + ifneq (,$(findstring icon.jpg,$(icons))) + export APP_ICON := $(TOPDIR)/icon.jpg + endif + endif +else + export APP_ICON := $(TOPDIR)/$(ICON) +endif + +ifeq ($(strip $(NO_ICON)),) + export NROFLAGS += --icon=$(APP_ICON) +endif + +ifeq ($(strip $(NO_NACP)),) + export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp +endif + +ifneq ($(APP_TITLEID),) + export NACPFLAGS += --titleid=$(APP_TITLEID) +endif + +ifneq ($(ROMFS),) + export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... +ifeq ($(strip $(APP_JSON)),) + @rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf +else + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf +endif + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +ifeq ($(strip $(APP_JSON)),) + +all : $(OUTPUT).nro + +ifeq ($(strip $(NO_NACP)),) +$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp +else +$(OUTPUT).nro : $(OUTPUT).elf +endif + +else + +all : $(OUTPUT).nsp + +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm + +$(OUTPUT).nso : $(OUTPUT).elf + +endif + +$(OUTPUT).elf : $(OFILES) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/graphics/sdl2/sdl2-demo/romfs/data/background.ogg b/graphics/sdl2/sdl2-demo/romfs/data/background.ogg new file mode 100644 index 0000000..dab5f53 Binary files /dev/null and b/graphics/sdl2/sdl2-demo/romfs/data/background.ogg differ diff --git a/graphics/sdl2/sdl2-demo/romfs/data/pop1.wav b/graphics/sdl2/sdl2-demo/romfs/data/pop1.wav new file mode 100644 index 0000000..fd1d88f Binary files /dev/null and b/graphics/sdl2/sdl2-demo/romfs/data/pop1.wav differ diff --git a/graphics/sdl2/sdl2-demo/romfs/data/pop2.wav b/graphics/sdl2/sdl2-demo/romfs/data/pop2.wav new file mode 100644 index 0000000..945dd01 Binary files /dev/null and b/graphics/sdl2/sdl2-demo/romfs/data/pop2.wav differ diff --git a/graphics/sdl2/sdl2-demo/romfs/data/pop3.wav b/graphics/sdl2/sdl2-demo/romfs/data/pop3.wav new file mode 100644 index 0000000..34ee62a Binary files /dev/null and b/graphics/sdl2/sdl2-demo/romfs/data/pop3.wav differ diff --git a/graphics/sdl2/sdl2-demo/romfs/data/pop4.wav b/graphics/sdl2/sdl2-demo/romfs/data/pop4.wav new file mode 100644 index 0000000..a7d3bda Binary files /dev/null and b/graphics/sdl2/sdl2-demo/romfs/data/pop4.wav differ diff --git a/graphics/sdl2/sdl2-demo/romfs/data/sdl.png b/graphics/sdl2/sdl2-demo/romfs/data/sdl.png new file mode 100644 index 0000000..77db555 Binary files /dev/null and b/graphics/sdl2/sdl2-demo/romfs/data/sdl.png differ diff --git a/graphics/sdl2/sdl2-demo/romfs/data/switch.png b/graphics/sdl2/sdl2-demo/romfs/data/switch.png new file mode 100644 index 0000000..d74e5c7 Binary files /dev/null and b/graphics/sdl2/sdl2-demo/romfs/data/switch.png differ diff --git a/graphics/sdl2/sdl2-demo/source/main.c b/graphics/sdl2/sdl2-demo/source/main.c new file mode 100644 index 0000000..caa1b88 --- /dev/null +++ b/graphics/sdl2/sdl2-demo/source/main.c @@ -0,0 +1,218 @@ +/* Mini SDL Demo + * featuring SDL2 + SDL2_mixer + SDL2_image + * on Nintendo Switch using libnx + * + * Copyright 2018 carsten1ns + * 2020 WinterMute + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include + +#include +#include +#include +#include + +// some switch buttons +#define JOY_A 0 +#define JOY_B 1 +#define JOY_X 2 +#define JOY_Y 3 +#define JOY_PLUS 10 +#define JOY_MINUS 11 +#define JOY_LEFT 12 +#define JOY_UP 13 +#define JOY_RIGHT 14 +#define JOY_DOWN 15 + +#define SCREEN_W 1280 +#define SCREEN_H 720 + +int rand_range(int min, int max){ + return min + rand() / (RAND_MAX / (max - min + 1) + 1); +} + + +int main(int argc, char** argv) { + + romfsInit(); + chdir("romfs:/"); + + int exit_requested = 0; + int trail = 0; + int wait = 25; + + SDL_Texture *switchlogo_tex = NULL, *sdllogo_tex = NULL; + SDL_Rect pos = { 0, 0, 0, 0 }, sdl_pos = { 0, 0, 0, 0 }; + Mix_Music *music = NULL; + Mix_Chunk *sound[4] = { NULL }; + SDL_Event event; + + SDL_Color colors[] = { + { 128, 128, 128, 0 }, // gray + { 255, 255, 255, 0 }, // white + { 255, 0, 0, 0 }, // red + { 0, 255, 0, 0 }, // green + { 0, 0, 255, 0 }, // blue + { 255, 255, 0, 0 }, // brown + { 0, 255, 255, 0 }, // cyan + { 255, 0, 255, 0 }, // purple + }; + int col = 0, snd = 0; + + srand(time(NULL)); + int vel_x = rand_range(1, 5); + int vel_y = rand_range(1, 5); + + SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER); + Mix_Init(MIX_INIT_OGG); + IMG_Init(IMG_INIT_PNG); + + SDL_Window* window = SDL_CreateWindow("sdl2+mixer+image demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_W, SCREEN_H, SDL_WINDOW_SHOWN); + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE); + + // load logos from file + SDL_Surface *sdllogo = IMG_Load("data/sdl.png"); + if (sdllogo) { + sdl_pos.w = sdllogo->w; + sdl_pos.h = sdllogo->h; + sdllogo_tex = SDL_CreateTextureFromSurface(renderer, sdllogo); + SDL_FreeSurface(sdllogo); + } + + SDL_Surface *switchlogo = IMG_Load("data/switch.png"); + if (switchlogo) { + pos.x = SCREEN_W / 2 - switchlogo->w / 2; + pos.y = SCREEN_H / 2 - switchlogo->h / 2; + pos.w = switchlogo->w; + pos.h = switchlogo->h; + switchlogo_tex = SDL_CreateTextureFromSurface(renderer, switchlogo); + SDL_FreeSurface(switchlogo); + } + + col = rand_range(0, 7); + + SDL_InitSubSystem(SDL_INIT_JOYSTICK); + SDL_JoystickEventState(SDL_ENABLE); + SDL_JoystickOpen(0); + + SDL_InitSubSystem(SDL_INIT_AUDIO); + Mix_AllocateChannels(5); + Mix_OpenAudio(48000, AUDIO_S16, 2, 4096); + + // load music and sounds from files + music = Mix_LoadMUS("data/background.ogg"); + sound[0] = Mix_LoadWAV("data/pop1.wav"); + sound[1] = Mix_LoadWAV("data/pop2.wav"); + sound[2] = Mix_LoadWAV("data/pop3.wav"); + sound[3] = Mix_LoadWAV("data/pop4.wav"); + if (music) + Mix_PlayMusic(music, -1); + + while (!exit_requested + && appletMainLoop() + ) { + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) + exit_requested = 1; + + // use joystick + if (event.type == SDL_JOYBUTTONDOWN) { + printf("%d\n",event.jbutton.button); + if (event.jbutton.button == JOY_UP) + if (wait > 0) + wait--; + if (event.jbutton.button == JOY_DOWN) + if (wait < 100) + wait++; + + if (event.jbutton.button == JOY_PLUS) + exit_requested = 1; + + if (event.jbutton.button == JOY_B) + trail =! trail; + } + } + + // set position and bounce on the walls + pos.y += vel_y; + pos.x += vel_x; + if (pos.x + pos.w > SCREEN_W) { + pos.x = SCREEN_W - pos.w; + vel_x = -rand_range(1, 5); + col = rand_range(0, 4); + snd = rand_range(0, 3); + if (sound[snd]) + Mix_PlayChannel(-1, sound[snd], 0); + } + if (pos.x < 0) { + pos.x = 0; + vel_x = rand_range(1, 5); + col = rand_range(0, 4); + snd = rand_range(0, 3); + if (sound[snd]) + Mix_PlayChannel(-1, sound[snd], 0); + } + if (pos.y + pos.h > SCREEN_H) { + pos.y = SCREEN_H - pos.h; + vel_y = -rand_range(1, 5); + col = rand_range(0, 4); + snd = rand_range(0, 3); + if (sound[snd]) + Mix_PlayChannel(-1, sound[snd], 0); + } + if (pos.y < 0) { + pos.y = 0; + vel_y = rand_range(1, 5); + col = rand_range(0, 4); + snd = rand_range(0, 3); + if (sound[snd]) + Mix_PlayChannel(-1, sound[snd], 0); + } + + if (!trail) { + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF); + SDL_RenderClear(renderer); + } + + // put logos on screen + if (sdllogo_tex) + SDL_RenderCopy(renderer, sdllogo_tex, NULL, &sdl_pos); + if (switchlogo_tex) { + SDL_SetTextureColorMod(switchlogo_tex, colors[col].r, colors[col].g, colors[col].b); + SDL_RenderCopy(renderer, switchlogo_tex, NULL, &pos); + } + + SDL_RenderPresent(renderer); + + SDL_Delay(wait); + } + + // stop sounds and free loaded data + Mix_HaltChannel(-1); + Mix_FreeMusic(music); + for (snd = 0; snd < 4; snd++) + if (sound[snd]) + Mix_FreeChunk(sound[snd]); + + IMG_Quit(); + Mix_CloseAudio(); + Mix_Quit(); + SDL_Quit(); + romfsExit(); + return 0; +}