├── .github
├── FUNDING.yml
├── pull_request_template.md
└── workflows
│ └── autobuild.yml
├── .gitignore
├── Info.plist
├── LICENSE
├── Makefile
├── Makefile.switch
├── Makefile.vita
├── Makefile.wiiu
├── README.md
├── build.gradle
├── com.hydra.noods.desktop
├── com.hydra.noods.yml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── icon
├── icon-linux.png
├── icon-mac.icns
├── icon-switch.jpg
├── icon-vita.png
├── icon-windows.ico
├── icon-windows.rc
└── icon.xpm
├── keystore.jks
├── mac-bundle.sh
├── settings.gradle
└── src
├── action_replay.cpp
├── action_replay.h
├── android
├── AndroidManifest.xml
├── CMakeLists.txt
├── build.gradle
├── cpp
│ └── interface.cpp
├── java
│ └── com
│ │ └── hydra
│ │ └── noods
│ │ ├── BindingsMenu.java
│ │ ├── BindingsPreference.java
│ │ ├── FileAdapter.java
│ │ ├── FileBrowser.java
│ │ ├── NooActivity.java
│ │ ├── NooButton.java
│ │ ├── NooRenderer.java
│ │ └── SettingsMenu.java
├── play-store.patch
└── res
│ ├── drawable-v26
│ ├── icon.xml
│ ├── icon_background.png
│ └── icon_foreground.png
│ ├── drawable
│ ├── abxy.png
│ ├── abxy_pressed1.png
│ ├── abxy_pressed2.png
│ ├── abxy_pressed3.png
│ ├── abxy_pressed4.png
│ ├── abxy_pressed5.png
│ ├── abxy_pressed6.png
│ ├── abxy_pressed7.png
│ ├── abxy_pressed8.png
│ ├── bindings.png
│ ├── dpad.png
│ ├── dpad_pressed1.png
│ ├── dpad_pressed2.png
│ ├── dpad_pressed3.png
│ ├── dpad_pressed4.png
│ ├── dpad_pressed5.png
│ ├── dpad_pressed6.png
│ ├── dpad_pressed7.png
│ ├── dpad_pressed8.png
│ ├── file.png
│ ├── folder.png
│ ├── icon.png
│ ├── info.png
│ ├── l.png
│ ├── l_pressed.png
│ ├── r.png
│ ├── r_pressed.png
│ ├── select.png
│ ├── select_pressed.png
│ ├── settings.png
│ ├── start.png
│ ├── start_pressed.png
│ └── storage.png
│ ├── layout
│ └── file_row.xml
│ ├── menu
│ ├── file_menu.xml
│ ├── noo_menu.xml
│ └── settings_menu.xml
│ ├── values
│ └── arrays.xml
│ └── xml
│ ├── bindings.xml
│ └── settings.xml
├── cartridge.cpp
├── cartridge.h
├── common
├── nds_icon.cpp
├── nds_icon.h
├── screen_layout.cpp
└── screen_layout.h
├── console
├── console_ui.cpp
├── console_ui.h
├── images
│ ├── file_dark.bmp
│ ├── file_light.bmp
│ ├── folder_dark.bmp
│ ├── folder_light.bmp
│ └── font.bmp
├── main_switch.cpp
├── main_vita.cpp
├── main_wiiu.cpp
└── shaders
│ ├── latte-assembler
│ ├── shader_wiiu.gsh
│ ├── shader_wiiu.psh
│ └── shader_wiiu.vsh
├── core.cpp
├── core.h
├── cp15.cpp
├── cp15.h
├── defines.h
├── desktop
├── cheat_dialog.cpp
├── cheat_dialog.h
├── input_dialog.cpp
├── input_dialog.h
├── layout_dialog.cpp
├── layout_dialog.h
├── main.cpp
├── noo_app.cpp
├── noo_app.h
├── noo_canvas.cpp
├── noo_canvas.h
├── noo_frame.cpp
├── noo_frame.h
├── path_dialog.cpp
├── path_dialog.h
├── save_dialog.cpp
└── save_dialog.h
├── div_sqrt.cpp
├── div_sqrt.h
├── dldi.cpp
├── dldi.h
├── dma.cpp
├── dma.h
├── gpu.cpp
├── gpu.h
├── gpu_2d.cpp
├── gpu_2d.h
├── gpu_3d.cpp
├── gpu_3d.h
├── gpu_3d_renderer.cpp
├── gpu_3d_renderer.h
├── hle_arm7.cpp
├── hle_arm7.h
├── hle_bios.cpp
├── hle_bios.h
├── input.cpp
├── input.h
├── interpreter.cpp
├── interpreter.h
├── interpreter_alu.cpp
├── interpreter_branch.cpp
├── interpreter_lookup.cpp
├── interpreter_transfer.cpp
├── ipc.cpp
├── ipc.h
├── memory.cpp
├── memory.h
├── rtc.cpp
├── rtc.h
├── save_states.cpp
├── save_states.h
├── settings.cpp
├── settings.h
├── spi.cpp
├── spi.h
├── spu.cpp
├── spu.h
├── timers.cpp
├── timers.h
├── wifi.cpp
└── wifi.h
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | patreon: Hydr8gon
2 | custom: paypal.me/Hydr8gon
3 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | Pull requests are not accepted for this project; see the contributing section of the readme for more details.
2 |
--------------------------------------------------------------------------------
/.github/workflows/autobuild.yml:
--------------------------------------------------------------------------------
1 | name: Automatic Builds
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build-windows:
10 | runs-on: windows-latest
11 |
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v1
15 | - name: Install MSYS2
16 | uses: msys2/setup-msys2@v2
17 | with:
18 | msystem: MINGW64
19 | update: true
20 | - name: Install build tools, wxWidgets, and PortAudio
21 | run: pacman -S mingw-w64-x86_64-{gcc,pkg-config,wxWidgets,portaudio,jbigkit} make --noconfirm
22 | shell: msys2 {0}
23 | - name: Compile
24 | run: |
25 | make -j$(nproc)
26 | strip noods.exe
27 | shell: msys2 {0}
28 | working-directory: ${{ github.workspace }}
29 | - name: Upload
30 | uses: actions/upload-artifact@v4
31 | with:
32 | name: noods-windows
33 | path: noods.exe
34 |
35 | build-mac:
36 | runs-on: macos-latest
37 |
38 | steps:
39 | - name: Install wxWidgets and PortAudio
40 | run: brew install wxmac portaudio
41 | - name: Checkout
42 | uses: actions/checkout@v1
43 | - name: Compile
44 | run: |
45 | make -j$(sysctl -n hw.logicalcpu)
46 | ./mac-bundle.sh --dmg
47 | - name: Upload
48 | uses: actions/upload-artifact@v4
49 | with:
50 | name: noods-mac
51 | path: NooDS.dmg
52 |
53 | build-linux:
54 | runs-on: ubuntu-latest
55 |
56 | steps:
57 | - name: Install Flatpak and SDK
58 | run: |
59 | sudo apt update
60 | sudo apt install flatpak flatpak-builder -y
61 | sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
62 | sudo flatpak install flathub org.freedesktop.Platform//21.08 org.freedesktop.Sdk//21.08 -y
63 | - name: Checkout
64 | uses: actions/checkout@v1
65 | - name: Compile
66 | run: |
67 | git config --global protocol.file.allow always
68 | make flatpak
69 | - name: Upload
70 | uses: actions/upload-artifact@v4
71 | with:
72 | name: noods-linux
73 | path: noods.flatpak
74 |
75 | build-android:
76 | runs-on: ubuntu-latest
77 |
78 | steps:
79 | - name: Checkout
80 | uses: actions/checkout@v1
81 | - name: Compile
82 | run: |
83 | ./gradlew assembleRelease
84 | mv build-android/outputs/apk/release/android-release-unsigned.apk noods.apk
85 | - name: Sign
86 | run: $ANDROID_SDK_ROOT/build-tools/30.0.2/apksigner sign --ks keystore.jks --ks-pass pass:$KEYSTORE_PASS noods.apk
87 | env:
88 | KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }}
89 | - name: Upload
90 | uses: actions/upload-artifact@v4
91 | with:
92 | name: noods-android
93 | path: noods.apk
94 |
95 | build-switch:
96 | runs-on: ubuntu-latest
97 | container: devkitpro/devkita64:latest
98 |
99 | steps:
100 | - name: Checkout
101 | uses: actions/checkout@v1
102 | - name: Compile
103 | run: make switch -j$(nproc)
104 | - name: Upload
105 | uses: actions/upload-artifact@v4
106 | with:
107 | name: noods-switch
108 | path: noods.nro
109 |
110 | build-wiiu:
111 | runs-on: ubuntu-latest
112 | container: devkitpro/devkitppc:latest
113 |
114 | steps:
115 | - name: Checkout
116 | uses: actions/checkout@v1
117 | - name: Compile
118 | run: make wiiu -j$(nproc)
119 | - name: Upload
120 | uses: actions/upload-artifact@v4
121 | with:
122 | name: noods-wiiu
123 | path: noods.wuhb
124 |
125 | build-vita:
126 | runs-on: ubuntu-latest
127 | container: vitasdk/vitasdk:latest
128 |
129 | steps:
130 | - name: Checkout
131 | uses: actions/checkout@v1
132 | - name: Compile
133 | run: make vita -j$(nproc)
134 | - name: Upload
135 | uses: actions/upload-artifact@v4
136 | with:
137 | name: noods-vita
138 | path: noods.vpk
139 |
140 | update-release:
141 | runs-on: ubuntu-latest
142 | needs: [build-windows, build-mac, build-linux, build-android, build-switch, build-wiiu, build-vita]
143 |
144 | steps:
145 | - name: Delete old release
146 | uses: dev-drprasad/delete-tag-and-release@v0.2.1
147 | with:
148 | delete_release: true
149 | tag_name: release
150 | env:
151 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
152 | - name: Get artifacts
153 | uses: actions/download-artifact@v4
154 | - name: Package artifacts
155 | run: for i in ./*; do zip -r -j ${i}.zip $i; done
156 | - name: Create new release
157 | uses: ncipollo/release-action@v1
158 | with:
159 | name: Rolling Release
160 | body: These are automatically updated builds of the latest commit.
161 | artifacts: "*.zip"
162 | tag: release
163 | token: ${{ secrets.GITHUB_TOKEN }}
164 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /build-android
3 | /build-switch
4 | /build-vita
5 | /build-wiiu
6 | /.gradle
7 | /src/android/.cxx
8 | /eboot.bin
9 | /noods
10 | /noods.aab
11 | /NooDS.app
12 | /NooDS.dmg
13 | /noods.elf
14 | /noods.nacp
15 | /noods.nro
16 | /noods.rpx
17 | /noods.velf
18 | /noods.vpk
19 | /noods.wuhb
20 | /noods.ini
21 | /param.sfo
22 | bios7.bin
23 | bios9.bin
24 | firmware.bin
25 | gba_bios.bin
26 | sd.img
27 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | NooDS
9 | CFBundleGetInfoString
10 |
11 | CFBundleIconFile
12 | NooDS.icns
13 | CFBundleIdentifier
14 | com.github.hydr8gon.NooDS
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | NooDS
19 | CFBundlePackageType
20 | APPL
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | CFBundleShortVersionString
26 | 1.0
27 | CSResourcesFileMapped
28 |
29 | NSHighResolutionCapable
30 |
31 | NSHumanReadableCopyright
32 | Licensed under GPLv3
33 | NSSupportsAutomaticGraphicsSwitching
34 |
35 | NSPrincipalClass
36 | wxNSApplication
37 | NSMicrophoneUsageDescription
38 | This app requires microphone access to emulate the DS microphone.
39 | CFBundleDocumentTypes
40 |
41 |
42 | CFBundleTypeExtensions
43 |
44 | nds
45 | srl
46 |
47 | CFBundleTypeName
48 | Nintendo DS ROM Image
49 | CFBundleTypeRole
50 | Viewer
51 |
52 |
53 | CFBundleTypeExtensions
54 |
55 | gba
56 |
57 | CFBundleTypeName
58 | Game Boy Advance ROM Image
59 | CFBundleTypeRole
60 | Viewer
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | NAME := noods
2 | BUILD := build
3 | SRCS := src src/common src/desktop
4 | ARGS := -Ofast -flto -std=c++11 -DUSE_GL_CANVAS -DLOG_LEVEL=0
5 | LIBS := $(shell pkg-config --libs portaudio-2.0)
6 | INCS := $(shell pkg-config --cflags portaudio-2.0)
7 |
8 | APPNAME := NooDS
9 | PKGNAME := com.hydra.noods
10 | DESTDIR ?= /usr
11 |
12 | ifeq ($(OS),Windows_NT)
13 | ARGS += -static -DWINDOWS
14 | LIBS += $(shell wx-config-static --libs --gl-libs) -lole32 -lsetupapi -lwinmm
15 | INCS += $(shell wx-config-static --cxxflags)
16 | else
17 | LIBS += $(shell wx-config --libs --gl-libs)
18 | INCS += $(shell wx-config --cxxflags)
19 | ifeq ($(shell uname -s),Darwin)
20 | ARGS += -DMACOS
21 | LIBS += -headerpad_max_install_names
22 | else
23 | ARGS += -no-pie
24 | LIBS += -lGL
25 | endif
26 | endif
27 |
28 | CPPFILES := $(foreach dir,$(SRCS),$(wildcard $(dir)/*.cpp))
29 | HFILES := $(foreach dir,$(SRCS),$(wildcard $(dir)/*.h))
30 | OFILES := $(patsubst %.cpp,$(BUILD)/%.o,$(CPPFILES))
31 |
32 | ifeq ($(OS),Windows_NT)
33 | OFILES += $(BUILD)/icon-windows.o
34 | endif
35 |
36 | all: $(NAME)
37 |
38 | ifneq ($(OS),Windows_NT)
39 | ifeq ($(uname -s),Darwin)
40 |
41 | install: $(NAME)
42 | ./mac-bundle.sh
43 | cp -r $(APPNAME).app /Applications/
44 |
45 | uninstall:
46 | rm -rf /Applications/$(APPNAME).app
47 |
48 | else
49 |
50 | flatpak:
51 | flatpak-builder --repo=repo --force-clean build-flatpak $(PKGNAME).yml
52 | flatpak build-bundle repo $(NAME).flatpak $(PKGNAME)
53 |
54 | flatpak-clean:
55 | rm -rf .flatpak-builder
56 | rm -rf build-flatpak
57 | rm -rf repo
58 | rm -f $(NAME).flatpak
59 |
60 | install: $(NAME)
61 | install -Dm755 $(NAME) "$(DESTDIR)/bin/$(NAME)"
62 | install -Dm644 $(PKGNAME).desktop "$(DESTDIR)/share/applications/$(PKGNAME).desktop"
63 | install -Dm644 icon/icon-linux.png "$(DESTDIR)/share/icons/hicolor/64x64/apps/$(PKGNAME).png"
64 |
65 | uninstall:
66 | rm -f "$(DESTDIR)/bin/$(NAME)"
67 | rm -f "$(DESTDIR)/share/applications/$(PKGNAME).desktop"
68 | rm -f "$(DESTDIR)/share/icons/hicolor/64x64/apps/$(PKGNAME).png"
69 |
70 | endif
71 | endif
72 |
73 | $(NAME): $(OFILES)
74 | g++ -o $@ $(ARGS) $^ $(LIBS)
75 |
76 | $(BUILD)/%.o: %.cpp $(HFILES) $(BUILD)
77 | g++ -c -o $@ $(ARGS) $(INCS) $<
78 |
79 | $(BUILD)/icon-windows.o:
80 | windres $(shell wx-config-static --cppflags) icon/icon-windows.rc $@
81 |
82 | $(BUILD):
83 | for dir in $(SRCS); do mkdir -p $(BUILD)/$$dir; done
84 |
85 | android-bundle:
86 | git apply src/android/play-store.patch
87 | ./gradlew bundle
88 | git apply -R src/android/play-store.patch
89 | jarsigner -keystore keystore.jks -signedjar noods.aab build-android/outputs/bundle/release/android-release.aab keystore
90 |
91 | android:
92 | ./gradlew assembleDebug
93 |
94 | switch:
95 | $(MAKE) -f Makefile.switch
96 |
97 | wiiu:
98 | $(MAKE) -f Makefile.wiiu
99 |
100 | vita:
101 | $(MAKE) -f Makefile.vita
102 |
103 | clean:
104 | if [ -d "build-android" ]; then ./gradlew clean; fi
105 | if [ -d "build-switch" ]; then $(MAKE) -f Makefile.switch clean; fi
106 | if [ -d "build-wiiu" ]; then $(MAKE) -f Makefile.wiiu clean; fi
107 | if [ -d "build-vita" ]; then $(MAKE) -f Makefile.vita clean; fi
108 | rm -rf $(BUILD)
109 | rm -f $(NAME)
110 |
--------------------------------------------------------------------------------
/Makefile.switch:
--------------------------------------------------------------------------------
1 | ifeq ($(strip $(DEVKITPRO)),)
2 | $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro")
3 | endif
4 |
5 | include $(DEVKITPRO)/libnx/switch_rules
6 |
7 | NAME := noods
8 | BUILD := build-switch
9 | SRCS := src src/common src/console
10 | DATA := src/console/images
11 | LIBS := -lglad -lEGL -lglapi -ldrm_nouveau -lnx
12 | INCS := $(PORTLIBS) $(LIBNX)
13 |
14 | APP_TITLE := NooDS
15 | APP_AUTHOR := Hydr8gon
16 | APP_VERSION := 0.1
17 | APP_ICON := ../icon/icon-switch.jpg
18 |
19 | ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
20 | CXXFLAGS := -Ofast -flto -std=c++11 -ffunction-sections $(ARCH) $(INCLUDE) -D__SWITCH__ -DNO_FDOPEN -DLOG_LEVEL=0
21 | LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
22 |
23 | ifneq ($(BUILD),$(notdir $(CURDIR)))
24 |
25 | export LD := $(CXX)
26 | export OUTPUT := $(CURDIR)/$(NAME)
27 | export DEPSDIR := $(CURDIR)/$(BUILD)
28 | export LIBPATHS := $(foreach dir,$(INCS),-L$(dir)/lib)
29 | export VPATH := $(foreach dir,$(SRCS),$(CURDIR)/$(dir)) $(foreach dir,$(DATA),$(CURDIR)/$(dir))
30 | export INCLUDE := $(foreach dir,$(SRCS),-I$(CURDIR)/$(dir)) $(foreach dir,$(INCS),-I$(dir)/include)
31 | export NROFLAGS += --icon=$(APP_ICON) --nacp=$(CURDIR)/$(NAME).nacp
32 |
33 | CPPFILES := $(foreach dir,$(SRCS),$(notdir $(wildcard $(dir)/*.cpp)))
34 | BMPFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bmp)))
35 | export OFILES := $(CPPFILES:.cpp=.o) $(BMPFILES:.bmp=.o)
36 |
37 | .PHONY: $(BUILD)
38 | all: $(BUILD)
39 |
40 | $(BUILD):
41 | mkdir -p $@
42 | $(MAKE) -C $(BUILD) -f $(CURDIR)/Makefile.switch
43 |
44 | clean:
45 | rm -rf $(BUILD) $(NAME).nro $(NAME).nacp $(NAME).elf
46 |
47 | else
48 |
49 | all: $(OUTPUT).nro
50 | $(OUTPUT).nro: $(OUTPUT).elf $(OUTPUT).nacp
51 | $(OUTPUT).elf: $(OFILES)
52 |
53 | %.o: %.bmp
54 | @echo $(notdir $<)
55 | @cd ..; $(PREFIX)ld -r -b binary -o $(BUILD)/$@ src/console/images/$*.bmp
56 |
57 | DEPENDS := $(OFILES:.o=.d)
58 | -include $(DEPENDS)
59 |
60 | endif
61 |
--------------------------------------------------------------------------------
/Makefile.vita:
--------------------------------------------------------------------------------
1 | ifeq ($(strip $(VITASDK)),)
2 | $(error "Please define VITASDK to point to your SDK path!")
3 | endif
4 |
5 | NAME := noods
6 | BUILD := build-vita
7 | SRCS := src src/common src/console
8 | DATA := src/console/images
9 | ARGS := -Ofast -flto -std=c++11 -march=armv7-a -mtune=generic-armv7-a -D__VITA__ -DNO_FDOPEN -DLOG_LEVEL=0
10 | LIBS := -Wl,-q -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -lvita2d -lSceAppMgr_stub -lSceAudio_stub \
11 | -lSceCommonDialog_stub -lSceCtrl_stub -lSceDisplay_stub -lSceGxm_stub -lSceSysmodule_stub -lSceTouch_stub \
12 | -lScePower_stub
13 |
14 | APPNAME := NooDS
15 | TITLEID := NOODSVITA
16 |
17 | CPPFILES := $(foreach dir,$(SRCS),$(wildcard $(dir)/*.cpp))
18 | BMPFILES := $(foreach dir,$(DATA),$(wildcard $(dir)/*.bmp))
19 | HFILES := $(foreach dir,$(SRCS),$(wildcard $(dir)/*.h))
20 | OFILES := $(patsubst %.cpp,$(BUILD)/%.o,$(CPPFILES)) $(patsubst %.bmp,$(BUILD)/%.o,$(BMPFILES))
21 |
22 | CXX := $(VITASDK)/bin/arm-vita-eabi-g++
23 | LD := $(VITASDK)/bin/arm-vita-eabi-ld
24 | PACKVPK := $(VITASDK)/bin/vita-pack-vpk
25 | MAKEFSELF := $(VITASDK)/bin/vita-make-fself
26 | MKSFOEX := $(VITASDK)/bin/vita-mksfoex
27 | ELFCREATE := $(VITASDK)/bin/vita-elf-create
28 |
29 | all: $(NAME).vpk
30 |
31 | $(NAME).vpk: eboot.bin param.sfo
32 | $(PACKVPK) -b eboot.bin -s param.sfo --add icon/icon-vita.png=sce_sys/icon0.png $@
33 |
34 | eboot.bin: $(NAME).velf
35 | $(MAKEFSELF) -c $< $@
36 |
37 | param.sfo:
38 | $(MKSFOEX) -s TITLE_ID="$(TITLEID)" "$(APPNAME)" $@
39 |
40 | $(NAME).velf: $(NAME).elf
41 | $(ELFCREATE) -s $< $@
42 |
43 | $(NAME).elf: $(OFILES)
44 | $(CXX) $^ $(LIBS) -o $@
45 |
46 | $(BUILD)/%.o: %.cpp $(HFILES) $(BUILD)
47 | $(CXX) -c -o $@ $(ARGS) $<
48 |
49 | $(BUILD)/%.o: %.bmp $(BUILD)
50 | $(LD) -r -b binary -o $@ $<
51 |
52 | $(BUILD):
53 | for dir in $(SRCS) $(DATA); do mkdir -p $(BUILD)/$$dir; done
54 |
55 | clean:
56 | rm -f $(NAME).velf $(NAME).elf $(NAME).vpk param.sfo eboot.bin
57 | rm -rf $(BUILD)
58 |
--------------------------------------------------------------------------------
/Makefile.wiiu:
--------------------------------------------------------------------------------
1 | ifeq ($(strip $(DEVKITPRO)),)
2 | $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro")
3 | endif
4 |
5 | APP_NAME := NooDS
6 | APP_SHORTNAME := NooDS
7 | APP_AUTHOR := Hydr8gon
8 | APP_ICON := ../icon/icon-vita.png
9 |
10 | include $(DEVKITPRO)/wut/share/wut_rules
11 |
12 | NAME := noods
13 | BUILD := build-wiiu
14 | SRCS := src src/common src/console
15 | DATA := src/console/images src/console/shaders
16 | LIBS := -lwut -lSDL2
17 | INCS := $(PORTLIBS) $(WUT_ROOT)
18 |
19 | CXXFLAGS := -g -Ofast -flto -ffunction-sections $(MACHDEP) $(INCLUDE) \
20 | -D__WIIU__ -D__WUT__ -DENDIAN_BIG -DNO_FDOPEN -DLOG_LEVEL=0
21 | LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map)
22 |
23 | ifneq ($(BUILD),$(notdir $(CURDIR)))
24 |
25 | export LD := $(CXX)
26 | export OUTPUT := $(CURDIR)/$(NAME)
27 | export DEPSDIR := $(CURDIR)/$(BUILD)
28 | export LIBPATHS := $(foreach dir,$(INCS),-L$(dir)/lib)
29 | export VPATH := $(foreach dir,$(SRCS),$(CURDIR)/$(dir)) $(foreach dir,$(DATA),$(CURDIR)/$(dir))
30 | export INCLUDE := $(foreach dir,$(SRCS),-I$(CURDIR)/$(dir)) $(foreach dir,$(INCS),-I$(dir)/include)
31 |
32 | CPPFILES := $(foreach dir,$(SRCS),$(notdir $(wildcard $(dir)/*.cpp)))
33 | BMPFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.bmp)))
34 | GSHFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.gsh)))
35 | export OFILES := $(CPPFILES:.cpp=.o) $(BMPFILES:.bmp=.o) $(addsuffix .o,$(GSHFILES))
36 |
37 | .PHONY: $(BUILD)
38 | all: $(BUILD)
39 |
40 | $(BUILD):
41 | mkdir -p $@
42 | $(MAKE) -C $(BUILD) -f $(CURDIR)/Makefile.wiiu
43 |
44 | build-shader:
45 | cd src/console/shaders; ./latte-assembler compile shader_wiiu.gsh --vsh shader_wiiu.vsh --psh shader_wiiu.psh
46 |
47 | clean:
48 | rm -rf $(BUILD) $(NAME).wuhb $(NAME).rpx $(NAME).elf
49 |
50 | else
51 |
52 | all: $(OUTPUT).wuhb
53 | $(OUTPUT).wuhb: $(OUTPUT).rpx
54 | $(OUTPUT).rpx: $(OUTPUT).elf
55 | $(OUTPUT).elf: $(OFILES)
56 |
57 | %.o: %.bmp
58 | @echo $(notdir $<)
59 | @cd ..; $(PREFIX)ld -r -b binary -o $(BUILD)/$@ src/console/images/$*.bmp
60 |
61 | %.gsh.o: %.gsh
62 | @echo $(notdir $<)
63 | @$(bin2o)
64 |
65 | DEPENDS := $(OFILES:.o=.d)
66 | -include $(DEPENDS)
67 |
68 | endif
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NooDS
2 | A (hopefully!) speedy DS emulator.
3 |
4 | ### Overview
5 | The goal of NooDS is to be a fast and portable DS and GBA emulator. It features accurate software rendering with
6 | upscaling, and can take advantage of multiple cores for better performance. I started working on NooDS for fun and as a
7 | learning experience, and I'd like to keep it that way. If people are interested and get use out of it, that's a bonus!
8 |
9 | ### Downloads
10 | NooDS is available for Windows, macOS, Linux, Android, Switch, Wii U, and Vita. The latest builds are automatically
11 | provided via GitHub Actions, and can be downloaded from the [releases page](https://github.com/Hydr8gon/NooDS/releases).
12 |
13 | ### Usage
14 | NooDS should be able to run most things without any setup. DS BIOS and firmware files must be provided to boot the
15 | system menu, and can be dumped from a DS with [DSBF Dumper](https://archive.org/details/dsbf-dumper). The firmware must
16 | come from an original DS; DSi and 3DS dumps don't contain any boot code. A GBA BIOS file can be optionally provided, and
17 | can be dumped from many systems with [this dumper](https://github.com/mgba-emu/bios-dump). File paths can be configured
18 | in the settings menu. Save types are automatically detected, but this may not always be accurate. If you run something
19 | and it has issues with saving, the save type can be overriden in the file menu.
20 |
21 | ### Contributing
22 | This is a personal project, and I've decided to not review or accept pull requests for it. If you want to help, you can
23 | test things and report issues or provide feedback. If you can afford it, you can also donate to motivate me and allow me
24 | to spend more time on things like this. Nothing is mandatory, and I appreciate any interest in my projects, even if
25 | you're just a user!
26 |
27 | ### Building
28 | **Windows:** Install [MSYS2](https://www.msys2.org) and run the command
29 | `pacman -Syu mingw-w64-x86_64-{gcc,pkg-config,wxWidgets,portaudio,jbigkit} make` to get dependencies. Navigate to the
30 | project root directory and run `make -j$(nproc)` to start building.
31 |
32 | **macOS/Linux:** On the target system, install [wxWidgets](https://www.wxwidgets.org) and
33 | [PortAudio](https://www.portaudio.com). This can be done with the [Homebrew](https://brew.sh) package manager on macOS,
34 | or a built-in package manager on Linux. Run `make -j$(nproc)` in the project root directory to start building.
35 |
36 | **Android:** Install [Android Studio](https://developer.android.com/studio) or the command line tools. Run
37 | `./gradlew assembleDebug` in the project root directory to start building; dependencies will be installed as needed.
38 |
39 | **Switch:** Install [devkitPro](https://devkitpro.org/wiki/Getting_Started) and its `switch-dev` package. Run
40 | `make switch -j$(nproc)` in the project root directory to start building.
41 |
42 | **Wii U:** Install [devkitPro](https://devkitpro.org/wiki/Getting_Started) and its `wiiu-dev` package. Run
43 | `make wiiu -j$(nproc)` in the project root directory to start building.
44 |
45 | **Vita:** Install [Vita SDK](https://vitasdk.org) and run `make vita -j$(nproc)` in the project root directory to
46 | start building.
47 |
48 | ### Hardware References
49 | * [GBATEK](https://problemkaputt.de/gbatek.htm) - The main information source for all things DS and GBA
50 | * [GBATEK Addendum](https://melonds.kuribo64.net/board/thread.php?id=13) - A thread that aims to fill the gaps in GBATEK
51 | * [melonDS Blog](https://melonds.kuribo64.net) - Contains posts that detail various 3D quirks
52 | * [DraStic BIOS](https://drive.google.com/file/d/1dl6xgOXc892r43RzkIJKI6nikYIipzoN/view) - Reference for the DS HLE BIOS
53 | functions
54 | * [Cult of GBA BIOS](https://github.com/Cult-of-GBA/BIOS) - Reference for the GBA HLE BIOS functions
55 |
56 | ### Other Links
57 | * [Hydra's Lair](https://hydr8gon.github.io) - Blog where I may or may not write about things
58 | * [Discord Server](https://discord.gg/JbNz7y4) - A place to chat about my projects and stuff
59 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | buildDir = "build-android"
3 |
4 | repositories {
5 | google()
6 | jcenter()
7 | }
8 |
9 | dependencies {
10 | classpath "com.android.tools.build:gradle:7.0.0"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/com.hydra.noods.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Type=Application
3 | Name=NooDS
4 | Comment=A (hopefully!) speedy NDS emulator
5 | GenericName=Nintendo DS Emulator
6 | Icon=com.hydra.noods
7 | Exec=noods %U
8 | StartupNotify=true
9 | Terminal=false
10 | MimeType=application/x-nintendo-ds-rom;application/x-gba-rom
11 | Categories=Game;Emulator
12 | Keywords=emulator;nintendo;ds;nds
13 |
--------------------------------------------------------------------------------
/com.hydra.noods.yml:
--------------------------------------------------------------------------------
1 | app-id: com.hydra.noods
2 | runtime: org.freedesktop.Platform
3 | runtime-version: '21.08'
4 | sdk: org.freedesktop.Sdk
5 | command: noods
6 |
7 | finish-args:
8 | - --device=all
9 | - --share=ipc
10 | - --socket=x11
11 | - --socket=pulseaudio
12 | - --filesystem=host
13 |
14 | modules:
15 | - name: wxwidgets
16 | buildsystem: cmake-ninja
17 | config-opts:
18 | - -DCMAKE_BUILD_TYPE=Release
19 | sources:
20 | - type: git
21 | url: https://github.com/wxWidgets/wxWidgets.git
22 | tag: v3.1.7
23 | modules:
24 | - name: glu
25 | config-opts:
26 | - --disable-static
27 | sources:
28 | - type: archive
29 | url: https://ftp.osuosl.org/pub/blfs/conglomeration/glu/glu-9.0.2.tar.xz
30 | sha256: 6e7280ff585c6a1d9dfcdf2fca489251634b3377bfc33c29e4002466a38d02d4
31 | cleanup:
32 | - /include
33 | - /lib/*.a
34 | - /lib/*.la
35 | - /lib/pkgconfig
36 | cleanup:
37 | - /bin
38 | - /include
39 | - /lib/wx/include
40 |
41 | - name: portaudio
42 | config-opts:
43 | - --disable-static
44 | - --without-oss
45 | - --without-jack
46 | sources:
47 | - type: git
48 | url: https://github.com/PortAudio/portaudio.git
49 | tag: v19.7.0
50 | cleanup:
51 | - /include
52 | - /lib/*.la
53 | - /lib/pkgconfig
54 |
55 | - name: noods
56 | buildsystem: simple
57 | build-commands:
58 | - DESTDIR=/app make install
59 | sources:
60 | - type: git
61 | url: https://github.com/Hydr8gon/NooDS.git
62 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | android.useAndroidX=true
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 |
88 | @rem Execute Gradle
89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
90 |
91 | :end
92 | @rem End local scope for the variables with windows NT shell
93 | if "%ERRORLEVEL%"=="0" goto mainEnd
94 |
95 | :fail
96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
97 | rem the _cmd.exe /c_ return code!
98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
99 | exit /b 1
100 |
101 | :mainEnd
102 | if "%OS%"=="Windows_NT" endlocal
103 |
104 | :omega
105 |
--------------------------------------------------------------------------------
/icon/icon-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/icon/icon-linux.png
--------------------------------------------------------------------------------
/icon/icon-mac.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/icon/icon-mac.icns
--------------------------------------------------------------------------------
/icon/icon-switch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/icon/icon-switch.jpg
--------------------------------------------------------------------------------
/icon/icon-vita.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/icon/icon-vita.png
--------------------------------------------------------------------------------
/icon/icon-windows.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/icon/icon-windows.ico
--------------------------------------------------------------------------------
/icon/icon-windows.rc:
--------------------------------------------------------------------------------
1 | #define wxUSE_RC_MANIFEST 1
2 | #define wxUSE_DPI_AWARE_MANIFEST 1
3 | #include
4 |
5 | NooDS ICON "icon-windows.ico"
6 |
--------------------------------------------------------------------------------
/icon/icon.xpm:
--------------------------------------------------------------------------------
1 | /* XPM */
2 | const char *icon_xpm[] =
3 | {
4 | "64 64 9 1 ",
5 | " c None",
6 | ". c gray1",
7 | "X c #202020",
8 | "o c #2A2A2A",
9 | "O c #412910",
10 | "+ c #A47B41",
11 | "@ c #FFA4A4",
12 | "# c #E7DED8",
13 | "$ c white",
14 |
15 | " ",
16 | " ",
17 | " ",
18 | " ",
19 | " OOOOOOOOOOOOOOOO ",
20 | " OOOOOOOOOOOOOOOO ",
21 | " OOOO++++++++++++++++OOOO ",
22 | " OOOO++++++++++++++++OOOO ",
23 | " OO++++++++++++++++++++++++OOOO.................... ",
24 | " OO++++++++++++++++++++++++OOOO.................... ",
25 | " OO++++++++OOOOOOOOOOOO++++++++++OOoooooooooooooooooo.. ",
26 | " OO++++++++OOOOOOOOOOOO++++++++++OOoooooooooooooooooo.. ",
27 | " OO++++++OOOOoooo........OO++++..++OO........oooooooooo.. ",
28 | " OO++++++OOOOoooo........OO++++..++OO........oooooooooo.. ",
29 | " OO++++OOoooooooo..$$$$$$OO##++++++++OO$$$$..oooooooooo.. ",
30 | " OO++++OOoooooooo..$$$$$$OO##++++++++OO$$$$..oooooooooo.. ",
31 | "OO++++++OOoooooooo..$$$$$$$$OO####++++OO$$$$..oooooooooo.. ",
32 | "OO++++++OOoooooooo..$$$$$$$$OO####++++OO$$$$..oooooooooo.. ",
33 | "OO++++OOoooooooooo..$$$$$$$$$$OOOO##++OO$$$$..oooooooooo.. ",
34 | "OO++++OOoooooooooo..$$$$$$$$$$OOOO##++OO$$$$..oooooooooo.. ",
35 | "OO++++OOoooooooooo..$$$$$$$$$$$$$$OOOO@@$$$$..oooooooooo.. ",
36 | "OO++++OOoooooooooo..$$$$$$$$$$$$$$OOOO@@$$$$..oooooooooo.. ",
37 | "OO++++OOoooooooooo..$$$$$$$$$$$$$$$$$$$$@@$$..oooooooooo.. ",
38 | "OO++++OOoooooooooo..$$$$$$$$$$$$$$$$$$$$@@$$..oooooooooo.. ",
39 | "OO++++..oooooooooo..$$$$$$$$$$$$$$$$$$$$@@$$..oooooooooo.. ",
40 | "OO++++..oooooooooo..$$$$$$$$$$$$$$$$$$$$@@$$..oooooooooo.. ",
41 | " OO++..oooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$..oooooooooo.. ",
42 | " OO++..oooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$..oooooooooo.. ",
43 | " OO..oooooooooo............................oooooooooo.. ",
44 | " OO..oooooooooo............................oooooooooo.. ",
45 | " ..oooooooooooooooooooooooooooooooooooooooooooooooo..OO ",
46 | " ..oooooooooooooooooooooooooooooooooooooooooooooooo..OO ",
47 | " ................................................++++OO ",
48 | " ................................................++++OO ",
49 | " ....................................................++++OO",
50 | " ....................................................++++OO",
51 | " ..ooooooooooooooooooooooooooooooooooooooooooooooooOO++++OO",
52 | " ..ooooooooooooooooooooooooooooooooooooooooooooooooOO++++OO",
53 | " ..oooooooooo............................ooooooooooOO++++OO",
54 | " ..oooooooooo............................ooooooooooOO++++OO",
55 | " ..oooooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$..ooooooooOO++++++OO",
56 | " ..oooooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$..ooooooooOO++++++OO",
57 | " ..oooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$$$$$..ooOOOO++++++++OO",
58 | " ..oooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$$$$$..ooOOOO++++++++OO",
59 | " ..oooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$$$$$OOOO++++++++++OO ",
60 | " ..oooooooooo..$$$$$$$$$$$$$$$$$$$$$$$$$$$$OOOO++++++++++OO ",
61 | " ..oooooooooooo........................OOOOOO++++++++++++OO.. ",
62 | " ..oooooooooooo........................OOOOOO++++++++++++OO.. ",
63 | " ..ooooooooooooooooooooooooooooooooOOOO++++++++++++++OOOOoo.. ",
64 | " ..ooooooooooooooooooooooooooooooooOOOO++++++++++++++OOOOoo.. ",
65 | " ............................OOOOOO++++++++++++OOOOOO........ ",
66 | " ............................OOOOOO++++++++++++OOOOOO........ ",
67 | " ..XXXXXXXXXXXXXXXXXXXXXXOOOO++++++++++++OOOOOOXXXXXXXXXXXX.. ",
68 | " ..XXXXXXXXXXXXXXXXXXXXXXOOOO++++++++++++OOOOOOXXXXXXXXXXXX.. ",
69 | " ..................OOOO++++++++OOOOOOOO.................. ",
70 | " ..................OOOO++++++++OOOOOOOO.................. ",
71 | " OO++++OOOOOOOO ",
72 | " OO++++OOOOOOOO ",
73 | " OOOOOOOO ",
74 | " OOOOOOOO ",
75 | " ",
76 | " ",
77 | " ",
78 | " "
79 | };
80 |
--------------------------------------------------------------------------------
/keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/keystore.jks
--------------------------------------------------------------------------------
/mac-bundle.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o pipefail
5 |
6 | app=NooDS.app
7 | contents=$app/Contents
8 |
9 | if [[ ! -f noods ]]; then
10 | echo 'Error: NooDS binary was not found.'
11 | echo 'Please run `make` to compile NooDS before bundling.'
12 | exit 1
13 | fi
14 |
15 | if [[ -d "$app" ]]; then
16 | rm -rf "$app"
17 | fi
18 |
19 | install -dm755 "${contents}"/{MacOS,Resources,Frameworks}
20 | install -sm755 noods "${contents}/MacOS/NooDS"
21 | install -m644 Info.plist "$contents/Info.plist"
22 |
23 | # macOS does not have the -f flag for readlink
24 | abspath() {
25 | perl -MCwd -le 'print Cwd::abs_path shift' "$1"
26 | }
27 |
28 | # Recursively copy dependent libraries to the Frameworks directory
29 | # and fix their load paths
30 | fixup_libs() {
31 | local libs=($(otool -L "$1" | grep -vE "/System|/usr/lib|:$" | sed -E 's/'$'\t''(.*) \(.*$/\1/'))
32 |
33 | for lib in "${libs[@]}"; do
34 | # Dereference symlinks to get the actual .dylib as binaries' load
35 | # commands can contain paths to symlinked libraries.
36 | local abslib="$(abspath "$lib")"
37 | local base="$(basename "$abslib")"
38 | local install_path="$contents/Frameworks/$base"
39 |
40 | install_name_tool -change "$lib" "@rpath/$base" "$1"
41 |
42 | if [[ ! -f "$install_path" ]]; then
43 | install -m644 "$abslib" "$install_path"
44 | strip -Sx "$install_path"
45 | fixup_libs "$install_path"
46 | fi
47 | done
48 | }
49 |
50 | install_name_tool -add_rpath "@executable_path/../Frameworks" $contents/MacOS/NooDS
51 |
52 | fixup_libs $contents/MacOS/NooDS
53 |
54 | cp "icon/icon-mac.icns" "$contents/Resources/NooDS.icns"
55 |
56 | codesign --deep -s - NooDS.app
57 |
58 | if [[ $1 == '--dmg' ]]; then
59 | mkdir build/dmg
60 | cp -a NooDS.app build/dmg/
61 | ln -s /Applications build/dmg/Applications
62 | hdiutil create -volname NooDS -srcfolder build/dmg -ov -format UDBZ NooDS.dmg
63 | rm -r build/dmg
64 | fi
65 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':src:android'
2 | rootProject.name = 'NooDS'
3 |
--------------------------------------------------------------------------------
/src/action_replay.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | class Core;
28 |
29 | struct ARCheat {
30 | std::string name;
31 | std::vector code;
32 | bool enabled;
33 | };
34 |
35 | class ActionReplay {
36 | public:
37 | std::vector cheats;
38 |
39 | ActionReplay(Core *core): core(core) {}
40 | void setPath(std::string path);
41 | void setFd(int fd);
42 |
43 | bool loadCheats();
44 | bool saveCheats();
45 | void applyCheats();
46 |
47 | private:
48 | Core *core;
49 | std::mutex mutex;
50 | std::string path;
51 | int fd = -1;
52 |
53 | FILE *openFile(const char *mode);
54 | };
55 |
--------------------------------------------------------------------------------
/src/android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
34 |
35 |
36 |
40 |
41 |
42 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/android/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DLOG_LEVEL=0")
4 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -flto")
5 |
6 | add_library(noods-core SHARED
7 | cpp/interface.cpp
8 | ../common/nds_icon.cpp
9 | ../common/screen_layout.cpp
10 | ../action_replay.cpp
11 | ../cartridge.cpp
12 | ../core.cpp
13 | ../cp15.cpp
14 | ../div_sqrt.cpp
15 | ../dldi.cpp
16 | ../dma.cpp
17 | ../gpu.cpp
18 | ../gpu_2d.cpp
19 | ../gpu_3d.cpp
20 | ../gpu_3d_renderer.cpp
21 | ../hle_arm7.cpp
22 | ../hle_bios.cpp
23 | ../input.cpp
24 | ../interpreter.cpp
25 | ../interpreter_alu.cpp
26 | ../interpreter_branch.cpp
27 | ../interpreter_lookup.cpp
28 | ../interpreter_transfer.cpp
29 | ../ipc.cpp
30 | ../memory.cpp
31 | ../rtc.cpp
32 | ../save_states.cpp
33 | ../settings.cpp
34 | ../spi.cpp
35 | ../spu.cpp
36 | ../timers.cpp
37 | ../wifi.cpp)
38 |
39 | target_link_libraries(noods-core jnigraphics OpenSLES)
40 |
--------------------------------------------------------------------------------
/src/android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | android {
4 | buildDir = "../../build-android"
5 | android.ndkVersion "22.1.7171670"
6 | compileSdkVersion 34
7 |
8 | sourceSets {
9 | main {
10 | manifest.srcFile "AndroidManifest.xml"
11 | java.srcDirs = ["java"]
12 | res.srcDirs = ["res"]
13 | }
14 | }
15 |
16 | defaultConfig {
17 | applicationId "com.hydra.noods"
18 | minSdkVersion 21
19 | targetSdkVersion 34
20 | versionCode "git rev-list HEAD --count".execute().text.toInteger()
21 | versionName "0.1"
22 | }
23 |
24 | buildTypes {
25 | release {
26 | minifyEnabled false
27 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
28 | }
29 | }
30 |
31 | externalNativeBuild {
32 | cmake {
33 | path "CMakeLists.txt"
34 | version "3.10.2"
35 | }
36 | }
37 | }
38 |
39 | dependencies {
40 | implementation 'androidx.appcompat:appcompat:1.1.0'
41 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
42 | implementation 'androidx.preference:preference:1.1.0'
43 | implementation 'androidx.documentfile:documentfile:1.0.1'
44 | implementation 'com.google.android.material:material:1.5.0'
45 | }
46 |
--------------------------------------------------------------------------------
/src/android/java/com/hydra/noods/BindingsMenu.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | package com.hydra.noods;
21 |
22 | import androidx.appcompat.app.AppCompatActivity;
23 | import androidx.preference.PreferenceFragmentCompat;
24 |
25 | import android.os.Bundle;
26 |
27 | public class BindingsMenu extends AppCompatActivity {
28 | public static class BindingsFragment extends PreferenceFragmentCompat {
29 | @Override
30 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
31 | setPreferencesFromResource(R.xml.bindings, rootKey);
32 | }
33 | }
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 |
39 | // Populate the input bindings UI
40 | getSupportFragmentManager().beginTransaction()
41 | .add(android.R.id.content, new BindingsFragment())
42 | .commit();
43 | }
44 |
45 | @Override
46 | public void onBackPressed() {
47 | // Save the bindings and return to the previous activity
48 | SettingsMenu.saveSettings();
49 | finish();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/android/java/com/hydra/noods/BindingsPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | package com.hydra.noods;
21 |
22 | import androidx.appcompat.app.AlertDialog;
23 | import androidx.preference.Preference;
24 |
25 | import android.content.Context;
26 | import android.content.DialogInterface;
27 | import android.util.AttributeSet;
28 | import android.view.KeyEvent;
29 |
30 | public class BindingsPreference extends Preference {
31 | private Context context;
32 | private int index;
33 |
34 | public BindingsPreference(Context context, AttributeSet attrs) {
35 | super(context, attrs);
36 | this.context = context;
37 | index = Integer.parseInt(attrs.getAttributeValue(null, "index"));
38 |
39 | // Set the subtext based on the binding for the key index
40 | int value = getKeyBind(index);
41 | if (value == 0)
42 | setSummary("None");
43 | else
44 | setSummary("Input " + Integer.toString(value - 1));
45 | }
46 |
47 | @Override
48 | protected void onClick() {
49 | // Create the dialog for rebinding an input
50 | AlertDialog.Builder builder = new AlertDialog.Builder(context);
51 | builder.setTitle(getTitle());
52 | builder.setMessage("Press a key to bind it to this input.");
53 | builder.setNegativeButton("Cancel", null);
54 |
55 | builder.setPositiveButton("Clear", new DialogInterface.OnClickListener() {
56 | @Override
57 | public void onClick(DialogInterface dialog, int id) {
58 | // Clear the binding for the key index
59 | setKeyBind(index, 0);
60 | setSummary("None");
61 | }
62 | });
63 |
64 | builder.setOnKeyListener(new DialogInterface.OnKeyListener() {
65 | @Override
66 | public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
67 | // Set the binding for the key index
68 | setKeyBind(index, keyCode + 1);
69 | setSummary("Input " + Integer.toString(keyCode));
70 | dialog.dismiss();
71 | return true;
72 | }
73 | });
74 |
75 | builder.create().show();
76 | }
77 |
78 | public static native int getKeyBind(int index);
79 | public static native void setKeyBind(int index, int value);
80 | }
81 |
--------------------------------------------------------------------------------
/src/android/java/com/hydra/noods/FileAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | package com.hydra.noods;
21 |
22 | import android.content.Context;
23 | import android.graphics.Bitmap;
24 | import android.net.Uri;
25 | import android.view.LayoutInflater;
26 | import android.view.View;
27 | import android.view.ViewGroup;
28 | import android.widget.BaseAdapter;
29 | import android.widget.ImageView;
30 | import android.widget.TextView;
31 |
32 | import java.util.ArrayList;
33 |
34 | public class FileAdapter extends BaseAdapter {
35 | public class FileInfo {
36 | public String name;
37 | public Bitmap icon;
38 | public Uri uri;
39 | }
40 |
41 | private Context context;
42 | private ArrayList info;
43 |
44 | public FileAdapter(Context context) {
45 | this.context = context;
46 | }
47 |
48 | public void setInfo(ArrayList info) {
49 | this.info = info;
50 | }
51 |
52 | @Override
53 | public int getCount() {
54 | return info.size();
55 | }
56 |
57 | @Override
58 | public Object getItem(int position) {
59 | return null;
60 | }
61 |
62 | @Override
63 | public long getItemId(int position) {
64 | return position;
65 | }
66 |
67 | @Override
68 | public View getView(int position, View convertView, ViewGroup parent) {
69 | // Create a new file row
70 | if (convertView == null) {
71 | LayoutInflater inflater = LayoutInflater.from(context);
72 | convertView = inflater.inflate(R.layout.file_row, parent, false);
73 | }
74 |
75 | // Set the file title and icon
76 | TextView title = (TextView)convertView.findViewById(R.id.name);
77 | title.setText(info.get(position).name);
78 | ImageView icon = (ImageView)convertView.findViewById(R.id.icon);
79 | icon.setImageBitmap(info.get(position).icon);
80 | return convertView;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/android/java/com/hydra/noods/NooButton.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | package com.hydra.noods;
21 |
22 | import android.content.Context;
23 | import android.os.Vibrator;
24 | import android.util.AttributeSet;
25 | import android.view.MotionEvent;
26 | import android.view.View;
27 | import android.view.ViewGroup.LayoutParams;
28 | import android.widget.Button;
29 |
30 | public class NooButton extends Button {
31 | private Vibrator vibrator;
32 | private int[] resIds;
33 | private int[] btnIds;
34 | private int state = 0;
35 | private int lastState = 0;
36 |
37 | public static int[] resAbxy = {
38 | R.drawable.abxy, R.drawable.abxy_pressed1, R.drawable.abxy_pressed5, R.drawable.abxy,
39 | R.drawable.abxy_pressed7, R.drawable.abxy_pressed8, R.drawable.abxy_pressed6, R.drawable.abxy,
40 | R.drawable.abxy_pressed3, R.drawable.abxy_pressed2, R.drawable.abxy_pressed4, R.drawable.abxy,
41 | R.drawable.abxy, R.drawable.abxy, R.drawable.abxy, R.drawable.abxy
42 | };
43 |
44 | public static int[] resDpad = {
45 | R.drawable.dpad, R.drawable.dpad_pressed1, R.drawable.dpad_pressed5, R.drawable.dpad,
46 | R.drawable.dpad_pressed7, R.drawable.dpad_pressed8, R.drawable.dpad_pressed6, R.drawable.dpad,
47 | R.drawable.dpad_pressed3, R.drawable.dpad_pressed2, R.drawable.dpad_pressed4, R.drawable.dpad,
48 | R.drawable.dpad, R.drawable.dpad, R.drawable.dpad, R.drawable.dpad
49 | };
50 |
51 | public NooButton(Context context, int[] resIds, int[] btnIds, int x, int y, int width, int height) {
52 | super(context);
53 | vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
54 | this.resIds = resIds;
55 | this.btnIds = btnIds;
56 |
57 | // Set the button parameters
58 | setBackgroundResource(resIds[0]);
59 | setX(x);
60 | setY(y);
61 | setLayoutParams(new LayoutParams(width, height));
62 | setAlpha(0.5f);
63 |
64 | // Handle button touches
65 | if (btnIds.length >= 4) { // D-pad
66 | setOnTouchListener(new Button.OnTouchListener() {
67 | @Override
68 | public boolean onTouch(View view, MotionEvent event) {
69 | switch (event.getAction()) {
70 | case MotionEvent.ACTION_DOWN:
71 | case MotionEvent.ACTION_MOVE:
72 | // Press the right key if in range, otherwise release
73 | if (event.getX() > view.getWidth() * 2 / 3)
74 | pressDKey(0);
75 | else
76 | releaseKey(btnIds[0]);
77 |
78 | // Press the left key if in range, otherwise release
79 | if (event.getX() < view.getWidth() * 1 / 3)
80 | pressDKey(1);
81 | else
82 | releaseKey(btnIds[1]);
83 |
84 | // Press the up key if in range, otherwise release
85 | if (event.getY() < view.getHeight() * 1 / 3)
86 | pressDKey(2);
87 | else
88 | releaseKey(btnIds[2]);
89 |
90 | // Press the down key if in range, otherwise release
91 | if (event.getY() > view.getHeight() * 2 / 3)
92 | pressDKey(3);
93 | else
94 | releaseKey(btnIds[3]);
95 |
96 | // Update the image and vibrate
97 | if (state != lastState)
98 | setBackgroundResource(resIds[state]);
99 | if ((state & ~lastState) != 0)
100 | vibrator.vibrate(SettingsMenu.getVibrateStrength() * 4);
101 | lastState = state;
102 | state = 0;
103 | break;
104 |
105 | case MotionEvent.ACTION_UP:
106 | // Release all directions and update the image
107 | for (int i = 0; i < 4; i++)
108 | releaseKey(btnIds[i]);
109 | setBackgroundResource(resIds[0]);
110 | lastState = state = 0;
111 | break;
112 | }
113 | return true;
114 | }
115 | });
116 | }
117 | else {
118 | setOnTouchListener(new Button.OnTouchListener() {
119 | @Override
120 | public boolean onTouch(View view, MotionEvent event) {
121 | switch (event.getAction()) {
122 | case MotionEvent.ACTION_DOWN:
123 | // Press a key, update the image, and vibrate
124 | pressKey(btnIds[0]);
125 | setBackgroundResource(resIds[1]);
126 | vibrator.vibrate(SettingsMenu.getVibrateStrength() * 4);
127 | break;
128 |
129 | case MotionEvent.ACTION_UP:
130 | // Release a key and update the image
131 | releaseKey(btnIds[0]);
132 | setBackgroundResource(resIds[0]);
133 | break;
134 | }
135 | return true;
136 | }
137 | });
138 | }
139 | }
140 |
141 | private void pressDKey(int key) {
142 | // Press a D-pad key and track the state
143 | pressKey(btnIds[key]);
144 | state |= 1 << key;
145 | }
146 |
147 | public static native void pressKey(int key);
148 | public static native void releaseKey(int key);
149 | }
150 |
--------------------------------------------------------------------------------
/src/android/play-store.patch:
--------------------------------------------------------------------------------
1 | diff --git a/src/android/AndroidManifest.xml b/src/android/AndroidManifest.xml
2 | index 715b448..ccce88e 100644
3 | --- a/src/android/AndroidManifest.xml
4 | +++ b/src/android/AndroidManifest.xml
5 | @@ -6,7 +6,6 @@
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 | diff --git a/src/android/java/com/hydra/noods/FileBrowser.java b/src/android/java/com/hydra/noods/FileBrowser.java
14 | index dffc2d6..455e759 100644
15 | --- a/src/android/java/com/hydra/noods/FileBrowser.java
16 | +++ b/src/android/java/com/hydra/noods/FileBrowser.java
17 | @@ -72,7 +72,7 @@ public class FileBrowser extends AppCompatActivity
18 | System.loadLibrary("noods-core");
19 | }
20 |
21 | - public static final boolean PLAY_STORE = false;
22 | + public static final boolean PLAY_STORE = true;
23 | public static PorterDuffColorFilter iconFilter;
24 |
25 | private ArrayList storagePaths;
26 | diff --git a/src/android/res/menu/file_menu.xml b/src/android/res/menu/file_menu.xml
27 | index 77595be..f8963b8 100644
28 | --- a/src/android/res/menu/file_menu.xml
29 | +++ b/src/android/res/menu/file_menu.xml
30 | @@ -5,7 +5,6 @@
31 |
36 |
37 | -
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/android/res/drawable-v26/icon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable-v26/icon_background.png
--------------------------------------------------------------------------------
/src/android/res/drawable-v26/icon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable-v26/icon_foreground.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed1.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed2.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed3.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed4.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed5.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed6.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed7.png
--------------------------------------------------------------------------------
/src/android/res/drawable/abxy_pressed8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/abxy_pressed8.png
--------------------------------------------------------------------------------
/src/android/res/drawable/bindings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/bindings.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed1.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed2.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed3.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed4.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed5.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed6.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed7.png
--------------------------------------------------------------------------------
/src/android/res/drawable/dpad_pressed8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/dpad_pressed8.png
--------------------------------------------------------------------------------
/src/android/res/drawable/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/file.png
--------------------------------------------------------------------------------
/src/android/res/drawable/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/folder.png
--------------------------------------------------------------------------------
/src/android/res/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/icon.png
--------------------------------------------------------------------------------
/src/android/res/drawable/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/info.png
--------------------------------------------------------------------------------
/src/android/res/drawable/l.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/l.png
--------------------------------------------------------------------------------
/src/android/res/drawable/l_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/l_pressed.png
--------------------------------------------------------------------------------
/src/android/res/drawable/r.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/r.png
--------------------------------------------------------------------------------
/src/android/res/drawable/r_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/r_pressed.png
--------------------------------------------------------------------------------
/src/android/res/drawable/select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/select.png
--------------------------------------------------------------------------------
/src/android/res/drawable/select_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/select_pressed.png
--------------------------------------------------------------------------------
/src/android/res/drawable/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/settings.png
--------------------------------------------------------------------------------
/src/android/res/drawable/start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/start.png
--------------------------------------------------------------------------------
/src/android/res/drawable/start_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/start_pressed.png
--------------------------------------------------------------------------------
/src/android/res/drawable/storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hydr8gon/NooDS/93086be34b9efc3b63b9d4e36a50abe8baeecd55/src/android/res/drawable/storage.png
--------------------------------------------------------------------------------
/src/android/res/layout/file_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/android/res/menu/file_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
--------------------------------------------------------------------------------
/src/android/res/menu/noo_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
--------------------------------------------------------------------------------
/src/android/res/menu/settings_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/src/android/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
- None
6 | - 1 Frame
7 | - 2 Frames
8 | - 3 Frames
9 | - 4 Frames
10 | - 5 Frames
11 |
12 |
13 |
14 | - Disabled
15 | - 1 Thread
16 | - 2 Threads
17 | - 3 Threads
18 | - 4 Threads
19 |
20 |
21 |
22 | - Center
23 | - Top
24 | - Bottom
25 | - Left
26 | - Right
27 |
28 |
29 |
30 | - None
31 | - Clockwise
32 | - Counter-Clockwise
33 |
34 |
35 |
36 | - Automatic
37 | - Vertical
38 | - Horizontal
39 | - Single Screen
40 |
41 |
42 |
43 | - Even
44 | - Enlarge Top
45 | - Enlarge Bottom
46 |
47 |
48 |
49 | - None
50 | - Quarter
51 | - Half
52 | - Full
53 |
54 |
55 |
56 | - Nearest
57 | - Upscaled
58 | - Linear
59 |
60 |
61 |
62 | - Default
63 | - 16:10
64 | - 16:9
65 | - 18:9
66 |
67 |
68 |
69 | - 0
70 | - 1
71 | - 2
72 | - 3
73 | - 4
74 | - 5
75 |
76 |
77 |
78 | - None
79 | - EEPROM 0.5KB
80 | - EEPROM 8KB
81 | - SRAM 32KB
82 | - FLASH 64KB
83 | - FLASH 128KB
84 |
85 |
86 |
87 | - 0
88 | - 0x200
89 | - 0x2000
90 | - 0x8000
91 | - 0x10000
92 | - 0x20000
93 |
94 |
95 |
96 | - None
97 | - EEPROM 0.5KB
98 | - EEPROM 8KB
99 | - EEPROM 64KB
100 | - EEPROM 128KB
101 | - FRAM 32KB
102 | - FLASH 256KB
103 | - FLASH 512KB
104 | - FLASH 1024KB
105 | - FLASH 8192KB
106 |
107 |
108 |
109 | - 0
110 | - 0x200
111 | - 0x2000
112 | - 0x10000
113 | - 0x20000
114 | - 0x8000
115 | - 0x40000
116 | - 0x80000
117 | - 0x100000
118 | - 0x800000
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/src/android/res/xml/bindings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
15 |
16 |
23 |
24 |
31 |
32 |
39 |
40 |
47 |
48 |
55 |
56 |
63 |
64 |
71 |
72 |
79 |
80 |
87 |
88 |
95 |
96 |
103 |
104 |
105 |
108 |
109 |
116 |
117 |
124 |
125 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/src/cartridge.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "defines.h"
28 |
29 | class Core;
30 |
31 | enum NdsCmdMode {
32 | CMD_NONE = 0,
33 | CMD_HEADER,
34 | CMD_CHIP,
35 | CMD_SECURE,
36 | CMD_DATA
37 | };
38 |
39 | class Cartridge {
40 | public:
41 | Cartridge(Core *core): core(core) {}
42 | ~Cartridge();
43 |
44 | bool setRom(std::string romPath, int romFd = -1, int saveFd = -1, int stateFd = -1, int cheatFd = -1);
45 | void writeSave();
46 |
47 | void trimRom();
48 | void resizeSave(int newSize, bool dirty = true);
49 |
50 | int getRomSize() { return romSize; }
51 | int getSaveSize() { return saveSize; }
52 |
53 | protected:
54 | Core *core;
55 |
56 | FILE *romFile = nullptr;
57 | uint8_t *rom = nullptr, *save = nullptr;
58 | int romSize = 0, saveSize = -1;
59 | bool saveDirty = false;
60 | std::mutex mutex;
61 |
62 | std::vector saveSizes;
63 | uint32_t romMask = 0;
64 |
65 | virtual bool loadRom();
66 | void loadRomSection(size_t offset, size_t size);
67 |
68 | private:
69 | std::string romPath, savePath;
70 | int romFd = -1, saveFd = -1;
71 | };
72 |
73 | class CartridgeNds: public Cartridge {
74 | public:
75 | CartridgeNds(Core *core): Cartridge(core) {}
76 | void saveState(FILE *file);
77 | void loadState(FILE *file);
78 |
79 | void directBoot();
80 | void wordReady(bool cpu);
81 |
82 | uint16_t readAuxSpiCnt(bool cpu) { return auxSpiCnt[cpu]; }
83 | uint8_t readAuxSpiData(bool cpu) { return auxSpiData[cpu]; }
84 | uint32_t readRomCtrl(bool cpu) { return romCtrl[cpu]; }
85 | uint32_t readRomDataIn(bool cpu);
86 |
87 | void writeAuxSpiCnt(bool cpu, uint16_t mask, uint16_t value);
88 | void writeAuxSpiData(bool cpu, uint8_t value);
89 | void writeRomCtrl(bool cpu, uint32_t mask, uint32_t value);
90 | void writeRomCmdOutL(bool cpu, uint32_t mask, uint32_t value);
91 | void writeRomCmdOutH(bool cpu, uint32_t mask, uint32_t value);
92 |
93 | private:
94 | uint32_t romCode = 0;
95 | bool romEncrypted = false;
96 | NdsCmdMode cmdMode = CMD_NONE;
97 |
98 | uint32_t encTable[0x412] = {};
99 | uint32_t encCode[3] = {};
100 |
101 | uint32_t romAddrReal[2] = {}, romAddrVirt[2] = {};
102 | uint16_t blockSize[2] = {}, readCount[2] = {};
103 | uint32_t wordCycles[2] = {};
104 | bool encrypted[2] = {};
105 |
106 | uint8_t auxCommand[2] = {};
107 | uint32_t auxAddress[2] = {};
108 | uint32_t auxWriteCount[2] = {};
109 |
110 | uint16_t auxSpiCnt[2] = {};
111 | uint8_t auxSpiData[2] = {};
112 | uint32_t romCtrl[2] = {};
113 | uint64_t romCmdOut[2] = {};
114 |
115 | virtual bool loadRom();
116 |
117 | uint64_t encrypt64(uint64_t value);
118 | uint64_t decrypt64(uint64_t value);
119 | void initKeycode(int level);
120 | void applyKeycode();
121 | };
122 |
123 | class CartridgeGba: public Cartridge {
124 | public:
125 | CartridgeGba(Core *core): Cartridge(core) {}
126 | void saveState(FILE *file);
127 | void loadState(FILE *file);
128 |
129 | uint8_t *getRom(uint32_t address);
130 | bool isEeprom(uint32_t address);
131 |
132 | uint8_t eepromRead();
133 | void eepromWrite(uint8_t value);
134 |
135 | uint8_t sramRead(uint32_t address);
136 | void sramWrite(uint32_t address, uint8_t value);
137 |
138 | private:
139 | uint8_t eepromCount = 0;
140 | uint16_t eepromCmd = 0;
141 | uint64_t eepromData = 0;
142 | bool eepromDone = false;
143 |
144 | uint8_t flashCmd = 0;
145 | bool bankSwap = false;
146 | bool flashErase = false;
147 |
148 | bool findString(std::string string);
149 | virtual bool loadRom();
150 | };
151 |
152 | FORCE_INLINE uint8_t *CartridgeGba::getRom(uint32_t address) {
153 | return ((address &= romMask) < romSize) ? &rom[address] : nullptr;
154 | }
155 |
156 | FORCE_INLINE bool CartridgeGba::isEeprom(uint32_t address) {
157 | return (saveSize == -1 || saveSize == 0x200 || saveSize == 0x2000) && (romSize <= 0x1000000 || address >= 0x0DFFFF00);
158 | }
159 |
--------------------------------------------------------------------------------
/src/common/nds_icon.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | #include
21 |
22 | #include "nds_icon.h"
23 | #include "../defines.h"
24 |
25 | NdsIcon::NdsIcon(std::string path, int fd) {
26 | // Attempt to open the ROM
27 | FILE *rom = (fd == -1) ? fopen(path.c_str(), "rb") : fdopen(fd, "rb");
28 |
29 | // Create an empty icon if ROM loading failed
30 | if (!rom) {
31 | LOG_WARN("Failed to open ROM for icon decoding!\n");
32 | memset(icon, 0, 32 * 32 * sizeof(uint32_t));
33 | return;
34 | }
35 |
36 | // Get the icon offset
37 | uint8_t offset[4];
38 | fseek(rom, 0x68, SEEK_SET);
39 | fread(offset, sizeof(uint8_t), 4, rom);
40 |
41 | // Get the icon data
42 | uint8_t data[512];
43 | fseek(rom, U8TO32(offset, 0) + 0x20, SEEK_SET);
44 | fread(data, sizeof(uint8_t), 512, rom);
45 |
46 | // Get the icon palette
47 | uint8_t palette[32];
48 | fseek(rom, U8TO32(offset, 0) + 0x220, SEEK_SET);
49 | fread(palette, sizeof(uint8_t), 32, rom);
50 | fclose(rom);
51 |
52 | // Get each pixel's 5-bit palette color and convert it to 8-bit
53 | uint32_t tiles[32 * 32];
54 | for (int i = 0; i < 32 * 32; i++) {
55 | uint8_t index = (i & 1) ? ((data[i / 2] & 0xF0) >> 4) : (data[i / 2] & 0x0F);
56 | uint16_t color = index ? U8TO16(palette, index * 2) : 0xFFFF;
57 | uint8_t r = ((color >> 0) & 0x1F) * 255 / 31;
58 | uint8_t g = ((color >> 5) & 0x1F) * 255 / 31;
59 | uint8_t b = ((color >> 10) & 0x1F) * 255 / 31;
60 | tiles[i] = (0xFF << 24) | (b << 16) | (g << 8) | r;
61 | }
62 |
63 | // Rearrange the pixels from 8x8 tiles to a 32x32 icon
64 | for (int i = 0; i < 4; i++) {
65 | for (int j = 0; j < 8; j++) {
66 | for (int k = 0; k < 4; k++)
67 | memcpy(&icon[256 * i + 32 * j + 8 * k], &tiles[256 * i + 8 * j + 64 * k], 8 * sizeof(uint32_t));
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/common/nds_icon.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 |
25 | class NdsIcon {
26 | public:
27 | NdsIcon(std::string path, int fd = -1);
28 | uint32_t *getIcon() { return icon; }
29 |
30 | private:
31 | uint32_t icon[32 * 32];
32 | };
33 |
--------------------------------------------------------------------------------
/src/common/screen_layout.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | class ScreenLayout {
23 | public:
24 | static int screenPosition;
25 | static int screenRotation;
26 | static int screenArrangement;
27 | static int screenSizing;
28 | static int screenGap;
29 | static int aspectRatio;
30 | static int integerScale;
31 | static int gbaCrop;
32 |
33 | int winWidth = 0, winHeight = 0;
34 | int minWidth = 0, minHeight = 0;
35 | int topX = 0, botX = 0;
36 | int topY = 0, botY = 0;
37 | int topWidth = 0, botWidth = 0;
38 | int topHeight = 0, botHeight = 0;
39 |
40 | static void addSettings();
41 | void update(int winWidth, int winHeight, bool gbaMode, bool splitScreens = false);
42 |
43 | int getTouchX(int x, int y);
44 | int getTouchY(int x, int y);
45 | };
46 |
--------------------------------------------------------------------------------
/src/console/console_ui.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019-2025 Hydr8gon
3 |
4 | This file is part of NooDS.
5 |
6 | NooDS is free software: you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | NooDS is distributed in the hope that it will be useful, but
12 | WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with NooDS. If not, see .
18 | */
19 |
20 | #pragma once
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | #include "../common/screen_layout.h"
27 | #include "../core.h"
28 | #include "../defines.h"
29 |
30 | enum MenuInputs {
31 | INPUT_A,
32 | INPUT_B,
33 | INPUT_SELECT,
34 | INPUT_START,
35 | INPUT_RIGHT,
36 | INPUT_LEFT,
37 | INPUT_UP,
38 | INPUT_DOWN,
39 | INPUT_R,
40 | INPUT_L,
41 | INPUT_X,
42 | INPUT_Y,
43 | INPUT_MENU,
44 | INPUT_FAST_HOLD,
45 | INPUT_FAST_TOGG,
46 | INPUT_SCRN_SWAP,
47 | INPUT_MAX
48 | };
49 |
50 | struct MenuTouch {
51 | bool pressed;
52 | float x, y;
53 |
54 | MenuTouch(bool pressed, float x, float y):
55 | pressed(pressed), x(x), y(y) {}
56 | };
57 |
58 | struct MenuItem {
59 | std::string name;
60 | std::string setting;
61 | void *iconTex;
62 | uint8_t iconSize;
63 | bool header;
64 |
65 | MenuItem(std::string name, std::string setting = "", void *iconTex = nullptr, uint8_t iconSize = 0):
66 | name(name), setting(setting), iconTex(iconTex), iconSize(iconSize), header(false) {}
67 | MenuItem(std::string name, bool header):
68 | name(name), setting(""), iconTex(nullptr), iconSize(0), header(header) {}
69 | bool operator<(const MenuItem &item) { return (name < item.name); }
70 | };
71 |
72 | class ConsoleUI {
73 | public:
74 | static Core *core;
75 | static bool running;
76 | static uint32_t framebuffer[256 * 192 * 8];
77 | static ScreenLayout layout;
78 | static bool gbaMode;
79 |
80 | static int showFpsCounter;
81 | static int menuTheme;
82 | static int keyBinds[INPUT_MAX];
83 |
84 | // Data that is defined per-platform
85 | static uint32_t defaultKeys[INPUT_MAX];
86 | static const char *keyNames[32];
87 |
88 | // Functions that are implemented per-platform
89 | static void startFrame(uint32_t color);
90 | static void endFrame();
91 | static void *createTexture(uint32_t *data, int width, int height);
92 | static void destroyTexture(void *texture);
93 | static void drawTexture(void *texture, float tx, float ty, float tw, float th, float x, float y,
94 | float w, float h, bool filter = true, int rotation = 0, uint32_t color = 0xFFFFFFFF);
95 | static uint32_t getInputHeld();
96 | static MenuTouch getInputTouch();
97 |
98 | static void drawRectangle(float x, float y, float w, float h, uint32_t color = 0xFFFFFFFF);
99 | static void drawString(std::string string, float x, float y,
100 | float size, uint32_t color = 0xFFFFFFFF, bool alignRight = false);
101 | static void fillAudioBuffer(uint32_t *buffer, int count, int rate);
102 | static uint32_t getInputPress();
103 |
104 | static void initialize(int width, int height, std::string root, std::string prefix);
105 | static void mainLoop(MenuTouch (*specialTouch)() = nullptr, ScreenLayout *touchLayout = nullptr);
106 | static int setPath(std::string path);
107 | static void fileBrowser();
108 |
109 | private:
110 | static void *fileTextures[2];
111 | static void *folderTextures[2];
112 | static void *fontTexture;
113 |
114 | static const uint32_t *palette;
115 | static uint32_t uiWidth, uiHeight;
116 | static uint32_t lineHeight;
117 | static bool touchMode;
118 |
119 | static std::string ndsPath, gbaPath;
120 | static std::string basePath, curPath;
121 | static bool changed;
122 |
123 | static std::thread *coreThread, *saveThread;
124 | static std::condition_variable cond;
125 | static std::mutex mutex;
126 | static int fpsLimiterBackup;
127 |
128 | static const uint32_t themeColors[];
129 | static const uint8_t charWidths[];
130 |
131 | ConsoleUI() {} // Private to prevent instantiation
132 | static void *bmpToTexture(uint8_t *bmp);
133 | static int stringWidth(std::string &string);
134 |
135 | static uint32_t menu(std::string title, std::vector