├── .gitignore ├── .gitmodules ├── .vscode ├── c_cpp_properties.json ├── launch.json └── tasks.json ├── Docs └── ngpctech.txt ├── History.txt ├── Makefile ├── NGPDS.code-workspace ├── NGPDS.pnproj ├── NGPDS.pnps ├── NGPDS.pnws ├── NGPDS.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ └── NGPDS.xcscheme ├── NGPDS_todo.txt ├── NGPLogo.bmp ├── README.md ├── copytodsx.bat ├── graphics ├── NGPBorder.grit ├── NGPBorder.png ├── NGPHW.grit └── NGPHW.png ├── logo.png └── source ├── AsmHleBios.s ├── Cart.h ├── Cart.s ├── Emubase.h ├── FileHandling.c ├── FileHandling.h ├── GameInfo.s ├── Gfx.h ├── Gfx.s ├── Gui.c ├── Gui.h ├── Main.c ├── Main.h ├── Memory.h ├── Memory.s ├── NGPHeader.h ├── NeoGeoPocket.c ├── NeoGeoPocket.h ├── Sound.h ├── Sound.s ├── SpeedHacks.s ├── bios.c ├── bios.h ├── biosHLE.c ├── cpu.h ├── cpu.s ├── io.h └── io.s /.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | UserInterfaceState.xcuserstate 3 | contents.xcworkspacedata 4 | *.ngp 5 | *.ngc 6 | build 7 | *.elf 8 | *.nds 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "source/K2Audio"] 2 | path = source/K2Audio 3 | url = https://github.com/FluBBaOfWard/K2Audio.git 4 | [submodule "source/K2GE"] 5 | path = source/K2GE 6 | url = https://github.com/FluBBaOfWard/K2GE.git 7 | [submodule "source/TLCS900H"] 8 | path = source/TLCS900H 9 | url = https://github.com/FluBBaOfWard/TLCS900H.git 10 | [submodule "source/ARMZ80"] 11 | path = source/ARMZ80 12 | url = https://github.com/FluBBaOfWard/ARMZ80.git 13 | [submodule "source/Shared"] 14 | path = source/Shared 15 | url = https://github.com/FluBBaOfWard/NDS_Shared.git 16 | [submodule "source/NGPFlash"] 17 | path = source/NGPFlash 18 | url = https://github.com/FluBBaOfWard/NGPFlash.git 19 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "/usr/local/include", 7 | "${workspaceFolder}", 8 | "${workspaceFolder}/include", 9 | "${workspaceFolder}/build", 10 | "/opt/devkitPro/libnds/include", 11 | "/opt/devkitPro/devkitARM/arm-none-eabi/include", 12 | "/opt/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 13 | ], 14 | "defines": [], 15 | "intelliSenseMode": "clang-x64", 16 | "browse": { 17 | "path": [ 18 | "/usr/local/include", 19 | "${workspaceFolder}", 20 | "${workspaceFolder}/include", 21 | "/opt/devkitPro/libnds/include", 22 | "/opt/devkitPro/devkitARM/arm-none-eabi/include", 23 | "/opt/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 24 | ], 25 | "limitSymbolsToIncludedHeaders": true, 26 | "databaseFilename": "" 27 | }, 28 | "macFrameworkPath": [ 29 | "/System/Library/Frameworks", 30 | "/Library/Frameworks" 31 | ] 32 | }, 33 | { 34 | "name": "Linux", 35 | "includePath": [ 36 | "/usr/include", 37 | "/usr/local/include", 38 | "${workspaceFolder}/include" 39 | ], 40 | "defines": [], 41 | "intelliSenseMode": "clang-x64", 42 | "browse": { 43 | "path": [ 44 | "/usr/include", 45 | "/usr/local/include", 46 | "${workspaceFolder}/include" 47 | ], 48 | "limitSymbolsToIncludedHeaders": true, 49 | "databaseFilename": "" 50 | } 51 | }, 52 | { 53 | "name": "Win32", 54 | "includePath": [ 55 | "${workspaceFolder}", 56 | "${workspaceFolder}/include", 57 | "C:/devkitPro/devkitARM/arm-none-eabi/include", 58 | "C:/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 59 | ], 60 | "defines": [ 61 | "_DEBUG", 62 | "UNICODE", 63 | "_UNICODE", 64 | "ARM7", 65 | "WIN32" 66 | ], 67 | "intelliSenseMode": "msvc-x64", 68 | "browse": { 69 | "path": [ 70 | "${workspaceFolder}", 71 | "${workspaceFolder}/include", 72 | "C:/devkitPro/devkitARM/arm-none-eabi/include", 73 | "C:/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 74 | ], 75 | "limitSymbolsToIncludedHeaders": true, 76 | "databaseFilename": "" 77 | }, 78 | "cStandard": "c11", 79 | "cppStandard": "c++17" 80 | } 81 | ], 82 | "version": 4 83 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "2.0.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "preLaunchTask": "gdb-debug", 12 | "postDebugTask": "stop emulation", 13 | "serverLaunchTimeout": 10000, 14 | "stopAtEntry": true, 15 | "program": "${workspaceFolder}/${workspaceFolderBasename}.elf", 16 | "MIMode": "gdb", 17 | "externalConsole": true, 18 | "cwd": "${workspaceFolder}", 19 | "targetArchitecture": "arm", 20 | "miDebuggerServerAddress": "localhost:2345", 21 | "windows": { 22 | "miDebuggerPath": "C:/devkitPro/devkitARM/bin/arm-none-eabi-gdb.exe", 23 | "setupCommands": [ 24 | { 25 | "description": "Enable pretty-printing for gdb", 26 | "ignoreFailures": true, 27 | "text": "file ${workspaceFolder}/${workspaceFolderBasename}.elf -enable-pretty-printing" 28 | }] 29 | }, 30 | "osx":{ 31 | "miDebuggerPath": "/opt/devkitPro/devkitARM/bin/arm-none-eabi-gdb", 32 | "setupCommands": [ 33 | { 34 | "description": "Enable pretty-printing for gdb", 35 | "ignoreFailures": true, 36 | "text": "file ${workspaceFolder}/${workspaceFolderBasename}.elf -enable-pretty-printing" 37 | }] 38 | }, 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "stop emulation", 8 | "type": "shell", 9 | "windows": { 10 | "command": "taskkill /im mGBA.exe /F" 11 | }, 12 | "osx": { 13 | "command": "killall mGBA" 14 | } 15 | }, 16 | { 17 | "label": "make debug", 18 | "type": "process", 19 | "command": "make", 20 | "args": [ 21 | "DEBUG=1" 22 | ], 23 | "problemMatcher": [] 24 | }, 25 | { 26 | "label": "make release", 27 | "type": "process", 28 | "command": "make", 29 | "args": [ 30 | "DEBUG=0" 31 | ], 32 | "problemMatcher": [], 33 | "group": { 34 | "kind": "build", 35 | "isDefault": true 36 | } 37 | }, 38 | { 39 | "label": "clean", 40 | "type": "shell", 41 | "command": "make clean" 42 | }, 43 | { 44 | "label": "gdb-debug", 45 | "type": "shell", 46 | "dependsOn": [ 47 | "make debug" 48 | ], 49 | "isBackground": false, 50 | "windows": { 51 | "command": "C:/mGBA/mGBA.exe -g ${workspaceFolder}/${workspaceFolderBasename}.nds;sleep 5;echo debuggerReady" 52 | }, 53 | "osx": { 54 | "command": "/Applications/desmume.app/Contents/MacOS/desmume", 55 | "args": [ 56 | "-g", 57 | "${workspaceFolder}/${workspaceFolderBasename}.nds" 58 | ] 59 | }, 60 | "presentation": { 61 | "clear": true, 62 | "reveal": "always", 63 | "panel": "new" 64 | }, 65 | "command": "debuggerReady", 66 | "problemMatcher": { 67 | "background": { 68 | "activeOnStart": true, 69 | "beginsPattern": "^.*debuggerReady.*$", 70 | "endsPattern": "^.*debuggerReady.*$" 71 | } 72 | } 73 | }, 74 | { 75 | "label": "run", 76 | "type": "shell", 77 | "isBackground": true, 78 | "command": "C:/NO$GBADebugger/NO$GBA.exe ${workspaceFolder}/${workspaceFolderBasename}.elf", 79 | "problemMatcher": [] 80 | } 81 | ] 82 | } -------------------------------------------------------------------------------- /History.txt: -------------------------------------------------------------------------------- 1 | NGPDS revision history 2 | -=-=-=-=-=-=-=-=-=-=-=- 3 | 4 | 5 | V0.5.8 - 2024-09-11 (FluBBa) 6 | Optimized BS1B opcode. 7 | 8 | V0.5.7 - 2024-01-24 (FluBBa) 9 | Added warning for low battery in the NGP. 10 | Added support for sample playing. 11 | Fixed IRQ & Micro DMA handling. 12 | Fixed BG priority updates mid screen (Rockman). 13 | Fixed start of game from TWiLight. 14 | Fixed HLE BIOS some more. 15 | Fixed save states a bit. 16 | More optimizations. 17 | 18 | V0.5.6 - 2023-12-20 (FluBBa) 19 | Added SLOT-2 RAM support. 20 | Fixed Color/Mono selection. 21 | Linked NDS battery to NGP battery. 22 | Optimized cpu core. 23 | 24 | V0.5.5 - 2022-11-02 (FluBBa) 25 | Fixed writing to scroll registers. 26 | Optimized K2GE access. 27 | Added speedhack for Big Bang Pro Wrestling. 28 | More games should work without a BIOS. 29 | 30 | V0.5.4 - 2022-10-19 (FluBBa) 31 | Optimized Z80 communication. 32 | Fixed savestates. 33 | 34 | V0.5.3 - 2022-10-18 (FluBBa) 35 | Fixed savestates. 36 | 37 | V0.5.2 - 2022-10-15 (FluBBa) 38 | Added new debug menu. 39 | Added Z80 CPU slow down menu item. 40 | Added Quit Emulator menu item if supported. 41 | Better menu traversing. 42 | 43 | V0.5.1 - 2021-10-10 (FluBBa) 44 | Fixed timers, interrupts and scrolling. 45 | Fixed DAA opcode. 46 | Completed port to GBA devkitPro. 47 | 48 | V0.5.0 - 2021-09-29 (FluBBa) 49 | Fixed sound mute handling. 50 | 51 | V0.4.9 - 2021-09-28 (FluBBa) 52 | Better flash emulation/saving/loading. 53 | Fixed save/load state. 54 | 55 | V0.4.8 - 2021-09-11 (FluBBa) 56 | Added stereo sound. 57 | Added speed hacks. 58 | Optimized VRAM transfers a bit. 59 | Optimized memory accesses a bit. 60 | 61 | V0.4.7 - 2021-08-29 (FluBBa) 62 | Various cpu fixes. 63 | Fixed auto power on/off. 64 | 65 | V0.4.6 - 2021-08-22 (FluBBa) 66 | Added a new border on game screen. 67 | Added new setting to lower emulated cpu speed. 68 | Tweaked cpu register usage. 69 | Fixed MULA opcode. 70 | 71 | V0.4.5 - 2021-06-28 (FluBBa) 72 | CPU working. 73 | Memory working. 74 | Graphics working. 75 | Sound working. 76 | 77 | V0.4.0 - 2021-05-18 (FluBBa) 78 | Started port to Nintendo DS & devkitPro. 79 | 80 | V0.3.0 - 2008-10-01 (FluBBa) 81 | Fixed copy protection in "Metal Slug 2" (SNK logo in VRAM). 82 | Fixed control problem in "Rockman Battle & Fighters" (MIRR opcode). 83 | Fixed background glitch in "Memories of Pure" (HCount register). 84 | Fixed problems with DMA probably affecting many games. 85 | 86 | V0.2.0 - 2008-09-04 (FluBBa) 87 | Added speedhacks for a lot of games. 88 | Added emulation of batteries & sub battery. 89 | Added RTC alarm. 90 | Added power button (SELECT). 91 | Added D button (R) (check "Doko Demo Mahjong"). 92 | Fixed a couple of cpu bugs affecting "Metal Slug 1" and a couple of other games. 93 | 94 | V0.1.0 - 2008-07-04 (FluBBa) 95 | Initial GBA release (NGPAdvance). 96 | 97 | V0.0.0 - 2008-04-02 (FluBBa) 98 | Started Coding. 99 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | GAME_TITLE := NGPDS 10 | GAME_SUBTITLE1 := NeoGeo Pocket Emulator 11 | GAME_SUBTITLE2 := www.ndsretro.com 12 | GAME_ICON := $(CURDIR)/../NGPLogo.bmp 13 | 14 | include $(DEVKITARM)/ds_rules 15 | 16 | #--------------------------------------------------------------------------------- 17 | # TARGET is the name of the output 18 | # BUILD is the directory where object files & intermediate files will be placed 19 | # SOURCES is a list of directories containing source code 20 | # INCLUDES is a list of directories containing extra header files 21 | # DATA is a list of directories containing binary files 22 | # GRAPHICS is a list of directories containing files to be processed by grit 23 | # all directories are relative to this makefile 24 | #--------------------------------------------------------------------------------- 25 | TARGET := $(shell basename $(CURDIR)) 26 | BUILD := build 27 | SOURCES := source \ 28 | source/Shared \ 29 | source/Shared/Unzip \ 30 | source/TLCS900H \ 31 | source/ARMZ80 \ 32 | source/K2GE \ 33 | source/K2Audio \ 34 | source/NGPFlash 35 | DATA := data 36 | INCLUDES := include 37 | GRAPHICS := graphics \ 38 | source/Shared/graphics 39 | 40 | #--------------------------------------------------------------------------------- 41 | # options for code generation 42 | #--------------------------------------------------------------------------------- 43 | ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork 44 | FLAGS := -DARM9 -DNDS 45 | 46 | ifeq ($(DEBUG),1) 47 | CFLAGS := -gdwarf-2 -Wall -ffast-math $(ARCH) 48 | else 49 | CFLAGS := -g -Wall -O3 -fomit-frame-pointer -ffast-math $(ARCH) 50 | endif 51 | 52 | CFLAGS += $(INCLUDE) $(FLAGS) 53 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions 54 | 55 | ASFLAGS := -g $(ARCH) $(INCLUDE) $(FLAGS) 56 | LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 57 | 58 | #--------------------------------------------------------------------------------- 59 | # any extra libraries we wish to link with the project 60 | #--------------------------------------------------------------------------------- 61 | LIBS := -lfat -lmm9 -lnds9 62 | 63 | 64 | #--------------------------------------------------------------------------------- 65 | # list of directories containing libraries, this must be the top level containing 66 | # include and lib 67 | #--------------------------------------------------------------------------------- 68 | LIBDIRS := $(LIBNDS) 69 | 70 | #--------------------------------------------------------------------------------- 71 | # no real need to edit anything past this point unless you need to add additional 72 | # rules for different file extensions 73 | #--------------------------------------------------------------------------------- 74 | ifneq ($(BUILD),$(notdir $(CURDIR))) 75 | #--------------------------------------------------------------------------------- 76 | 77 | export OUTPUT := $(CURDIR)/$(TARGET) 78 | 79 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 80 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ 81 | $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) 82 | 83 | 84 | export DEPSDIR := $(CURDIR)/$(BUILD) 85 | 86 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 87 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 88 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 89 | PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) 90 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 91 | 92 | #--------------------------------------------------------------------------------- 93 | # use CXX for linking C++ projects, CC for standard C 94 | #--------------------------------------------------------------------------------- 95 | ifeq ($(strip $(CPPFILES)),) 96 | #--------------------------------------------------------------------------------- 97 | export LD := $(CC) 98 | #--------------------------------------------------------------------------------- 99 | else 100 | #--------------------------------------------------------------------------------- 101 | export LD := $(CXX) 102 | #--------------------------------------------------------------------------------- 103 | endif 104 | #--------------------------------------------------------------------------------- 105 | 106 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 107 | $(PNGFILES:.png=.o) \ 108 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 109 | 110 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 111 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 112 | -I$(CURDIR)/$(BUILD) 113 | 114 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 115 | 116 | .PHONY: $(BUILD) clean 117 | 118 | #--------------------------------------------------------------------------------- 119 | $(BUILD): 120 | @[ -d $@ ] || mkdir -p $@ 121 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 122 | 123 | #--------------------------------------------------------------------------------- 124 | clean: 125 | @echo clean ... 126 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).arm9 $(TARGET).ds.gba 127 | 128 | 129 | #--------------------------------------------------------------------------------- 130 | else 131 | 132 | DEPENDS := $(OFILES:.o=.d) 133 | 134 | #--------------------------------------------------------------------------------- 135 | # main targets 136 | #--------------------------------------------------------------------------------- 137 | $(OUTPUT).nds : $(OUTPUT).elf 138 | $(OUTPUT).elf : $(OFILES) 139 | 140 | #--------------------------------------------------------------------------------- 141 | %.pcx.o : %.pcx 142 | #--------------------------------------------------------------------------------- 143 | @echo $(notdir $<) 144 | @$(bin2o) 145 | 146 | #--------------------------------------------------------------------------------- 147 | %.s %.h : %.png %.grit 148 | #--------------------------------------------------------------------------------- 149 | grit $< -fts -o$* 150 | 151 | 152 | -include $(DEPENDS) 153 | 154 | #--------------------------------------------------------------------------------------- 155 | endif 156 | #--------------------------------------------------------------------------------------- 157 | -------------------------------------------------------------------------------- /NGPDS.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "files.associations": { 9 | "*.s": "arm", 10 | "fat.h": "c" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /NGPDS.pnproj: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NGPDS.pnps: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NGPDS.pnws: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NGPDS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NGPDS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NGPDS.xcodeproj/xcshareddata/xcschemes/NGPDS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 47 | 48 | 49 | 55 | 56 | 57 | 58 | 61 | 62 | 63 | 64 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /NGPDS_todo.txt: -------------------------------------------------------------------------------- 1 | NGPDS Todo 2 | 3 | Save language and machine in settings. #11 4 | Use CLZ for memory mapping. 5 | Save settings for Swap A-B. 6 | Emulate second flash chip! 7 | 8 | Add SWI & Interrupt to BiosHLE. 9 | Rewrite BiosHLE to asm? 10 | Keep disassemblying BIOS from 0xFF476C. 11 | 12 | Convert BIOS font to png. Done. 13 | 14 | GFX: 15 | Optimize color transfer? 16 | 17 | GUI: 18 | 19 | Mem: 20 | 21 | CPU: 22 | See TLCS900H Todo. 23 | 24 | Sound T6W28: 25 | Sample Darkarms from HW. 26 | 27 | 28 | Misc: 29 | Starting at 0xFF1800 Skips power button check. 30 | ... 31 | 32 | Games Non Working: 33 | 34 | Games With Glitches: 35 | Memories of - Pure: Glitches everywhere. 36 | Neo Poke Pro Yakyuu: Sprite multiplexing doesn't work. 37 | Pachi-Slot Aruze Oukoku Pocket - Azteca (J): Palette glitches. 38 | Pachi-Slot Aruze Oukoku Pocket - Dekahel 2 (J): Palette glitches. 39 | Pachi-Slot Aruze Oukoku Pocket - Delsol 2 (J): Palette glitches. 40 | Pachi-Slot Aruze Oukoku Pocket - e-Cup (J): Palette glitches. 41 | Pachi-Slot Aruze Oukoku Pocket - Hanabi (J) (v1.02): Palette glitches. 42 | Pachi-Slot Aruze Oukoku Pocket - Hanabi (J) (v1.04): Palette glitches. 43 | Pachi-Slot Aruze Oukoku Pocket - Oohanabi (J): Palette glitches. 44 | Pachi-Slot Aruze Oukoku Pocket - Porcano 2 (J): Palette glitches. 45 | Pachi-Slot Aruze Oukoku Pocket - Ward of Lights (J): Palette glitches. 46 | Puzzle Link/Puzzle Link 2 (USA, EU): sometimes softlocks when a level ends. 47 | Sonic The Hedgehog: First boss sometimes disappear. 48 | Super Real Mahjong - Premium Collection: Sprite multiplexing & palette updates doesn't' work, game play locks up. 49 | 50 | Games With Glitches Fixed: 51 | Densetsu no Ogre Battle Gaiden - Zenobia no Ouji (J): Uses top 8 bits of address. 52 | Rockman - Battle & Fighters (J): Changes BG priority mid screen. 53 | 54 | Speedhacks: 55 | "Bakumatsu Rouman Tokubetsu" - JR (0x65,0xF8) @0x2002 56 | "Baseball Stars" - JR (0x67,0xF4) @0x2001 57 | "Baseball Stars Color" - JR (0x67,0xF4) @0x2001 58 | "Big Bang Pro Wrestling" - JR (0x66,0xF7) @0x2001 ??? 59 | "Bikkuriman 2000" - JR (0x7E,0xFFF4) @0x2001 ??? 60 | "Bio Motor Unitron" - JR (0x6E,0xF9) @0x2001 61 | "Bust a Move Pocket" - JR (0x66,0xF8) @0x2001 62 | "Cool Boarders Pocket" - ??? 63 | "Cool Cool Jam" - JR (0x6F,0xF9) @0x2001 64 | "Cool Cool Jam Sample" - JR (0x68,0xF7) @0x2001 65 | "Crush Roller" - JR (0x6B,0xF3) @0x2001 66 | "Dark Arms" - JR (0x61,0xF4) @0x200 67 | "Delta Warp" - ??? 68 | "Densetsu no Ogre Battle Gaiden" - JR (0x66,0xF9) @0x2001 69 | "Densha de Go 2" - JR (0x66,0xFA) @0x2001 70 | "Dive Alert" - ??? 71 | "Dokodemo Mahjong" - JR (0x66,0xF9) @0x200 72 | "Dynamite Slugger" - JR (0x66,0xF6) @0x200 73 | "Evolution Eternal Dungeons" - JR (0x66,0xF5) @0x200 74 | "Faselei" - JR (0x66,0xF8) @0x200 75 | "Fatal Fury" - JR (0x66,0xF8) @0x200 76 | "Ganbare Neo Poke-kun" - JR (0x66,0xF9) @0x20021A 77 | "Infinity Cure" - JR (0x66,0xF8) @0x200 78 | "Kikou Seiki Unitron" - JR (0x6E,0xF9) @0x200 79 | "King of Fighter R1" - JR (0x6E,0xF8) @0x200152 80 | "King of Fighter R2" - JR (0x6E,0xF8) @0x200170 81 | "KoF, Battle De Paradise" - JR (0x61,0xF8) @0x20052D 82 | - JR (0x67,0xF9) @0x203495 83 | "Koi Koi Mahjong" - JR (0x66,0xF9) @0x200 84 | "Last Blade" - JR (0x65,0xF8) @0x20021F 85 | "Magical Drop Pocket" - JR (0x66,0xF8) @0x200 86 | "Melon-chan no Seichou Nikki" - JR (0x76,0xFFF5) @0x200 ??? 87 | "Memories of Pure" - JR (0x68,0xF5) @0x200 88 | - JR (0x61,0xF7) @0x200 ??? 89 | "Metal Slug 1st" - JR (0x6E,0xF9) @0x2001 90 | - JR (0x6A,0xF9) @0x200 91 | "Metal Slug - 2nd Mission" - JR (0x66,0xF9) @0x2001 92 | "Mezase! Kanji Ou" - JR (0x66,0xF9) @0x2001 93 | "Mizuki Shigeru no Youkai Shas" - JR (0x66,0xF9) @0x2001 94 | - JR (0x6A,0xF9) @0x2001 95 | "Neo 21 - Real Casino Series" - JR (0x68,0xF8) @0x2001 96 | "Neo Baccarat - Real Casino Series" - JR (0x6E,0xF8) @0x2001 97 | "Neo Cherry Master - Real Casino S" - JR (0x68,0xF8) @0x2001 98 | "Neo Cherry Master Color - Real Ca" - JR (0x68,0xF8) @0x2001 99 | "Neo Derby Champ Daiyosou" - JR (0x67,0xF8) @0x2001 100 | "Neo Dragons Wild" - JR (0x66,0xFC) @0x2001 101 | "Neo Geo Cup '98 Special" - JR (0x66,0xF3) @0x2001 102 | "Neo Mystery Bonus - Real Casino S" - JR (0x68,0xF8) @0x2001 103 | "Neo Poke Pro Yakyuu" - JR (0x66,0xF6) @0x200 104 | "Neo Turf Masters" - JR (0x65,0xF8) @0x200 105 | "Nigeronpa" - JR (0x6E,0xF8) @0x200 106 | "Oekaki Puzzle" - JR (0x66,0xF5) @0x200 107 | "Pachinko Hisshou Guide - Pocket" - JR (0x66,0xF9) @0x200 108 | "Pachi-slot Aruze Oukoku Pocket " - JR (0x66,0xF9) @0x200 109 | "Pacman" - JP (0xF2,0x20018F) 110 | "Party Mail" - JR (0x66,0xF6) @0x200 111 | "Picture Puzzle" - JR (0x66,0xF5) @0x200 112 | "Pocket Love If" - JR (0x66,0xF8) @0x200 113 | "Pocket Reversi" - JR (0x66,0xF5) @0x200 114 | "Pocket Tennis" - JP (0xF2,0x2001EA) 115 | "Pocket Tennis Color" - JP (0xF2,0x200050) 116 | "Puyo Pop" - JR (0x66,0xF9) @0x200 117 | "Puzzle Booble Mini (V1.09)" - JR (0x66,0xF8) @0x200 118 | "Puzzle Booble Mini (V1.10)" - JR (0x65,0xF8) @0x200 119 | "Rockman Battle & Fighters" - JR (0x66,0xF8) @0x200 120 | "Samurai Shodown! - Pocket Fightin" - JR (0x66,0xF9) @0x200 121 | "Samurai Shodown! 2 - Pocket Fight" - JR (0x67,0xF8) @0x200 122 | "Shanghai Mini" - JR (0x66,0xF5) @0x200 123 | "Shinki Sekai Evolution - Hate" - JR (0x66,0xF5) @0x200 124 | "Shougi no Tatsujin" - JR (0x66,0xF8) @0x200 125 | "Shougi no Tatsujin Color" - JR (0x66,0xF8) @0x200 126 | "SNK Gals Fighters" - JR (0x66,0xF8) @0x200 127 | "SNK vs Capcom - Card Fighters Cap" - JR (0x6E,0xF9) @0x200 128 | "SNK vs Capcom - Card Fighters SNK" - JR (0x6E,0xF9) @0x200 129 | "SNK vs Capcom - Card Fighters 2" - JR (0x6E,0xF9) @0x200100 130 | "SNK vs Capcom - The Match of The " - JR (0x6E,0xF8) @0x200 131 | "Sonic The Hedgehog - Pocket Adven" - JR (0x66,0xF9) @0x200 132 | "Sonic The Hedgehog - Poc - Sample" - JR (0x67,0xFA) @0x200 133 | "Soreike!! Hanafuda Doujou" - JR (0x66,0xF8) @0x200 134 | "Super Real Mahjong - Premium" - JR (0x61,0xF8) @0x200 135 | "Tsunagete Pon! 2" - JR (0x6E,0xF9) @0x200 136 | "Wrestling Madness" - ??? 137 | 138 | "BIOS" - JR (0x67,0xF9) @0xFF 139 | - JR (0x6E,0xF9) @0xFF 140 | 141 | Metal Slug - 2nd Mission: 142 | See 0x28dd04 143 | It checks for a 64 byte long pattern (SNK logo) in VRAM. 144 | 145 | 146 | Puyo Pop: 147 | See 0x215BE9 148 | Loads value from 0xFFFE40 (0xFF2BBD) 149 | VECT_COMINIT 150 | VECT_COMRECEIVESTART 151 | VECT_COMOFFRTS 152 | VECT_COMONRTS 153 | VBLIRQ_Entry 154 | 155 | 156 | 157 | i = 0x2772; 158 | ngpc_bios[i] = 0x17; i++; ngpc_bios[i] = 0x03; i++; // ldf 3 159 | ngpc_bios[i] = 0x3C; i++; // push XIX 160 | ngpc_bios[i] = 0xC8; i++; ngpc_bios[i] = 0xCC; i++; // and w,1F 161 | ngpc_bios[i] = 0x1F; i++; 162 | ngpc_bios[i] = 0xC8; i++; ngpc_bios[i] = 0x80; i++; // add w,w 163 | ngpc_bios[i] = 0xC8; i++; ngpc_bios[i] = 0x80; i++; // add w,w 164 | ngpc_bios[i] = 0x44; i++; ngpc_bios[i] = 0x00; i++; // ld XIX,0xFFFE00 165 | ngpc_bios[i] = 0xFE; i++; ngpc_bios[i] = 0xFF; i++; // 166 | ngpc_bios[i] = 0x00; i++; // 167 | ngpc_bios[i] = 0xE3; i++; ngpc_bios[i] = 0x03; i++; // ld XIX,(XIX+W) 168 | ngpc_bios[i] = 0xF0; i++; ngpc_bios[i] = 0xE1; i++; // 169 | ngpc_bios[i] = 0x24; i++; // 170 | ngpc_bios[i] = 0xB4; i++; ngpc_bios[i] = 0xE8; i++; // call XIX 171 | ngpc_bios[i] = 0x5C; i++; // pop XIX 172 | ngpc_bios[i] = 0x07; i++; // reti 173 | 174 | 175 | 176 | 177 | orr r0,r0,r0,lsl#10 178 | ldr r1,=0x2211000 179 | and r2,r1,r0,lsl#9 ;@ bit __6___2___3___7 180 | and r0,r1,r0,lsl#11 ;@ bit __4___0___5___1 181 | orr r0,r2,r0,lsl#2 ;@ bit 4_6_0_2_5_3_1_7 182 | add r2,r0,r0,lsl#8 183 | add r2,r2,r0,lsl#16 184 | mov r0,r2,lsr#24 185 | 186 | orr r0,r0,r0,lsl#10 187 | mov r1,r0,lsl#17 188 | orr r0,r1,r0,lsr#3 189 | ldr r1,=0x88442211 190 | and r0,r1,r0 191 | orr r0,r0,r0,ror#16 192 | orr r0,r0,r0,ror#8 193 | mov r0,r0,lsr#4 194 | 195 | orr r0,r0,r0,lsl#8 196 | and r1,r0,#0x330 197 | and r2,r0,#0xCC0 198 | orr r0,r1,r2,lsr#4 199 | and r1,r0,#0x154 200 | and r2,r0,#0x2A8 201 | orr r0,r1,r2,lsr#2 202 | mov r0,r0,lsr#1 203 | 204 | 205 | unsigned char b; // reverse this byte 206 | 207 | b = ((b * 0x80200802ULL) & 0x884422110ULL) * 0x0101010101ULL >> 32; 208 | 209 | b = ((b * 0x40100401ULL) & 0x442211088UL) * 0x0202020202ULL >> 32; 210 | 211 | 212 | 43210__76543210__76543210__76543 213 | OoooOooooOoooOooooOoooOooooOoooO 214 | 215 | 43210__76543210__76543210__76543210 216 | OoooOooooOoooOooooOoooOooooOoooO 217 | . . . . 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /NGPLogo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/NGPDS/4dc21dc76fdef1931c1cab7ed09e4bf37244bcb7/NGPLogo.bmp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NGPDS V0.5.8 2 | 3 | 4 | 5 | This is a SNK Neogeo Pocket (Color) emulator for the Nintendo DS(i)/3DS. 6 | 7 | ## How to use 8 | 9 | 1. Create a folder named "ngpds" in either the root of your flash card or in 10 | the data folder. This is where settings and save files end up. 11 | 2. Now put game/bios files into a folder where you have (NGP) roms, max 12 | 768 games per folder, filenames must not be longer than 127 chars. You can use 13 | zip-files (as long as they use the deflate compression). CAUTION! Games that 14 | require SLOT-2 RAM can not be used with zip-files! 15 | 3. Depending on your flashcart you might have to DLDI patch the emulator. 16 | 17 | Note! You need a bios to be able to save in game. 18 | The save file should be compatible with most other NeoGeo Pocket emulators. 19 | 20 | When the emulator starts, you can either press L+R or tap on the screen to open 21 | up the menu. 22 | Now you can use the cross or touchscreen to navigate the menus, A or double tap 23 | to select an option, B or the top of the screen to go back a step. 24 | 25 | To select between the tabs use R & L or the touchscreen. 26 | 27 | Since the DS/DS Lite only has 4MB of RAM you will need a SLOT-2/GBA cart with 28 | RAM on these devices to play games larger than 2MB. 29 | 30 | ## Menu 31 | 32 | ### File 33 | 34 | * Load Game: Select a game to load. 35 | * Load State: Load a previously saved state of the currently running game. 36 | * Save State: Save a state of the currently running game. 37 | * Load Flash: Load flash ram for the currently running game. 38 | * Save Flash: Save flash ram for the currently running game. 39 | * Save Settings: Save the current settings. 40 | * Eject Game: Remove the game, can be used to enter bios settings. 41 | * Reset Console: Reset the console. 42 | * Quit Emulator: (If supported.) 43 | 44 | ### Options 45 | 46 | * Controller: 47 | * B Autofire: Select if you want autofire on button B. 48 | * A Autofire: Select if you want autofire on button A. 49 | * Swap A-B: Swap which NDS button is mapped to which NGP button. 50 | * Display: 51 | * Gamma: Lets you change the gamma ("brightness"). 52 | * B&W Palette: Here you can select the palette for B & W games. 53 | * Machine: 54 | * Language: Select between Japanese and English. 55 | * Machine: Select the emulated machine. 56 | * Change Batteries: Change to new main batteries (AA/LR6). 57 | * Change Sub Battery: Change to a new sub battery (CR2032). 58 | * Cpu Speed Hacks: Allow speed hacks. 59 | * Z80 Clock: You can underclock to get better speed on the DS. 60 | * Select BnW Bios: Load a real NGP Bios, recommended. 61 | * Select Color Bios: Load a real NGPC Bios, recommended. 62 | * Settings: 63 | * Speed: Switch between speed modes. 64 | * Normal: Game runs at it's normal speed. 65 | * 200%: Game runs at double speed. 66 | * Max: Games can run up to 4 times normal speed (might change). 67 | * 50%: Game runs at half speed. 68 | * Autoload State: Toggle Savestate autoloading. Automagically load the savestate associated with the current game. 69 | * Autoload Flash RAM: Toggle flash/save ram autoloading. Automagically load the flash ram associated with the current game. 70 | * Autosave Settings: This will save settings when leaving menu if any changes are made. 71 | * Autopause Game: Toggle if the game should pause when opening the menu. 72 | * Powersave 2nd Screen: If graphics/light should be turned off for the GUI screen when menu is not active. 73 | * Emulator on Bottom: Select if top or bottom screen should be used for emulator, when menu is active emulator screen is allways on top. 74 | * Autosleep: Doesn't work. 75 | * Debug: 76 | * Debug Output: Show FPS and logged text. 77 | * Disable Foreground: Turn on/off foreground rendering. 78 | * Disable Background: Turn on/off background rendering. 79 | * Disable Sprites: Turn on/off sprite rendering. 80 | * Step Frame: Emulate one frame. 81 | 82 | ### About 83 | 84 | Some dumb info about the game and emulator... 85 | 86 | ## Controls 87 | 88 | * NDS A & B buttons are mapped to NeoGeo Pocket B & A. 89 | * NDS Start & X is mapped to NeoGeo Pocket Option. 90 | * NDS Select & Y is mapped to NeoGeo Pocket Power. 91 | * NDS d-pad is mapped to NeoGeo Pocket d-pad. 92 | * NDS L button is mapped to NeoGeo Pocket D (debug). 93 | 94 | ## Games 95 | 96 | * Memories of - Pure: Glitches everywhere. 97 | * Neo Poke Pro Yakyuu: Sprite multiplexing doesn't work. 98 | * Pachi-Slot Aruze Oukoku Pocket - Azteca (J) : Palette glitches. 99 | * Pachi-Slot Aruze Oukoku Pocket - Dekahel 2 (J) : Palette glitches. 100 | * Pachi-Slot Aruze Oukoku Pocket - Delsol 2 (J) : Palette glitches. 101 | * Pachi-Slot Aruze Oukoku Pocket - e-Cup (J) : Palette glitches. 102 | * Pachi-Slot Aruze Oukoku Pocket - Hanabi (J) (v1.02) : Palette glitches. 103 | * Pachi-Slot Aruze Oukoku Pocket - Hanabi (J) (v1.04) : Palette glitches. 104 | * Pachi-Slot Aruze Oukoku Pocket - Oohanabi (J) : Palette glitches. 105 | * Pachi-Slot Aruze Oukoku Pocket - Porcano 2 (J) : Palette glitches. 106 | * Pachi-Slot Aruze Oukoku Pocket - Ward of Lights (J) : Palette glitches. 107 | * Sonic The Hedgehog: First boss sometimes disappear, try to use a save state soon before the boss and reload and try again. 108 | * Super Real Mahjong - Premium Collection: Sprite multiplexing & palette updates doesn't' work, game play locks up. 109 | 110 | ## Credits 111 | 112 | ```text 113 | Huge thanks to Loopy for the incredible PocketNES, without it this emu would 114 | probably never have been made. 115 | Thanks to: 116 | Flavor & Koyote for NGP info. 117 | Dwedit for help and inspiration with a lot of things. 118 | ``` 119 | 120 | Fredrik Ahlström 121 | 122 | X/Twitter @TheRealFluBBa 123 | 124 | 125 | -------------------------------------------------------------------------------- /copytodsx.bat: -------------------------------------------------------------------------------- 1 | copy NGPDS.nds h:\apps -------------------------------------------------------------------------------- /graphics/NGPBorder.grit: -------------------------------------------------------------------------------- 1 | 2 | -gB 8 3 | 4 | # use lz77 compression 5 | -gzl 6 | 7 | # map output, lz77 compression 8 | -mzl 9 | 10 | # standard 8bpp tilereduction 11 | -mR8 12 | -------------------------------------------------------------------------------- /graphics/NGPBorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/NGPDS/4dc21dc76fdef1931c1cab7ed09e4bf37244bcb7/graphics/NGPBorder.png -------------------------------------------------------------------------------- /graphics/NGPHW.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 13 | 14 | #palette options 15 | -pn32 -------------------------------------------------------------------------------- /graphics/NGPHW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/NGPDS/4dc21dc76fdef1931c1cab7ed09e4bf37244bcb7/graphics/NGPHW.png -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/NGPDS/4dc21dc76fdef1931c1cab7ed09e4bf37244bcb7/logo.png -------------------------------------------------------------------------------- /source/AsmHleBios.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "TLCS900H/TLCS900H_mac.h" 4 | 5 | .global sngBIOSHLE 6 | 7 | .syntax unified 8 | .arm 9 | 10 | .section .text 11 | ;@---------------------------------------------------------------------------- 12 | callCFunc: ;@ r0 = arg0, r1 = arg1, r2 = function. 13 | ;@---------------------------------------------------------------------------- 14 | stmfd sp!,{r0-r2,lr} 15 | bl storeTLCS900 16 | ldmfd sp!,{r0-r2} 17 | adr lr,callcRet 18 | bx r2 19 | callcRet: 20 | bl loadTLCS900 21 | ldmfd sp!,{lr} 22 | bx lr 23 | 24 | ;@---------------------------------------------------------------------------- 25 | sngBIOSHLE: 26 | ;@---------------------------------------------------------------------------- 27 | ldr r0,[t9ptr,#tlcsLastBank] 28 | sub r0,t9pc,r0 29 | and r0,r0,#0xFF0000 30 | cmp r0,#0xFF0000 31 | bne notBios 32 | 33 | ldrb r0,[t9pc],#1 34 | tst r0,#0x40 35 | bne asmBiosHLE 36 | ldr r2,=iBIOSHLE 37 | bl callCFunc ;@ r0 = arg0, r1 = arg1, r2 = function. 38 | t9fetch 8 39 | notBios: 40 | mov r11,r11 41 | t9fetch 8 42 | 43 | ;@---------------------------------------------------------------------------- 44 | asmBiosHLE: 45 | ;@---------------------------------------------------------------------------- 46 | cmp r0,#0x40 47 | beq BiosReset 48 | cmp r0,#0x41 49 | beq BiosSWI_1 50 | cmp r0,#0x4B 51 | beq BiosIRQ_VBlank 52 | cmp r0,#0x4C 53 | beq BiosIRQ_Z80 54 | cmp r0,#0x61 55 | bmi BiosIRQ_User 56 | t9fetch 24 57 | 58 | ;@---------------------------------------------------------------------------- 59 | BiosReset: 60 | ;@---------------------------------------------------------------------------- 61 | mov r0,#0x6C00 62 | str r0,[t9gprBank,#RXSP] 63 | bl t9LoadL ;@ 0x6C00 Should also have the game start vector. 64 | bl encode_r0_pc 65 | t9fetch 24 66 | 67 | ;@---------------------------------------------------------------------------- 68 | BiosSWI_1: 69 | ;@---------------------------------------------------------------------------- 70 | ldr r0,[t9ptr,#tlcsLastBank] 71 | sub r0,t9pc,r0 72 | bl push32 73 | add r2,t9ptr,#tlcsGprBanks 74 | ldrb r0,[r2,#0x20*3+1] 75 | ldr r1,=0xFFFE00 76 | add r0,r1,r0,lsl#2 77 | bl t9LoadL 78 | bl encode_r0_pc 79 | t9fetch 24 80 | 81 | ;@---------------------------------------------------------------------------- 82 | BiosIRQ_Z80: ;@ Extra work for Puyo Pop 83 | ;@---------------------------------------------------------------------------- 84 | ldr r1,=ngpRAM+0x2F83 ;@ User Z80 IRQ allowed? 85 | ldrb r2,[r1] 86 | tst r2,#0x40 87 | bne BiosIRQ_User 88 | 89 | ldr r1,=ngpRAM+0x2DA2 ;@ Z80 IRQ done? 90 | ldrb r0,[r1] 91 | tst r0,#0x80 92 | bne not3reset 93 | orr r0,r0,#0x80 94 | strb r0,[r1] 95 | 96 | mov r0,#0x28 97 | bl t9LoadB 98 | and r0,r0,#0x33 99 | orr r0,r0,#0x04 100 | mov t9Mem,#0x28 101 | bl t9StoreB_mem 102 | 103 | mov r0,#0x25 104 | bl t9LoadB 105 | and r0,r0,#0x0F 106 | orr r0,r0,#0xB0 107 | mov t9Mem,#0x25 108 | bl t9StoreB_mem 109 | 110 | mov r0,#0x62 111 | mov t9Mem,#0x27 112 | bl t9StoreB_mem 113 | 114 | mov r0,#0x20 115 | bl t9LoadB 116 | orr r0,r0,#0x88 117 | mov t9Mem,#0x20 118 | bl t9StoreB_mem 119 | 120 | not3reset: 121 | t9fetch 24 122 | ;@---------------------------------------------------------------------------- 123 | BiosIRQ_VBlank: 124 | ;@---------------------------------------------------------------------------- 125 | ldr r1,=systemMemory+0xB0 ;@ HW joypad 126 | ldrb r2,[r1] 127 | ldr r1,=ngpRAM+0x2F82 ;@ BIOS joypad 128 | strb r2,[r1] 129 | ldr r1,=ngpRAM+0x2C5F ;@ BIOS joypad backup 130 | strb r2,[r1] 131 | ;@---------------------------------------------------------------------------- 132 | BiosIRQ_User: 133 | ;@---------------------------------------------------------------------------- 134 | and r0,r0,#0x3F 135 | adr r1,IndexConv 136 | ldrb r0,[r1,r0] 137 | ldr r1,=0x6FB8 138 | add r0,r1,r0,lsl#2 139 | bl t9LoadL 140 | bl encode_r0_pc 141 | t9fetch 24 142 | ;@---------------------------------------------------------------------------- 143 | IndexConv: 144 | .byte 0,0,0,0,1,2,3,0,0,0,4,5,6,0,0,0, 7,8,9,10,0,0,0,0,11,12,0,0,0,14,15,16, 17 145 | 146 | ;@---------------------------------------------------------------------------- 147 | 148 | #endif // #ifdef __arm__ 149 | -------------------------------------------------------------------------------- /source/Cart.h: -------------------------------------------------------------------------------- 1 | #ifndef CART_HEADER 2 | #define CART_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "NGPHeader.h" 9 | 10 | extern u32 gRomSize; 11 | extern u32 maxRomSize; 12 | extern u32 allocatedRomMemSize; 13 | extern u32 emuFlags; 14 | extern u8 gConfig; 15 | extern u8 gMachineSet; 16 | extern u8 gMachine; 17 | extern u8 gSOC; 18 | extern u8 gLang; 19 | extern u8 gPaletteBank; 20 | 21 | extern u8 ngpRAM[0x4000]; 22 | extern u8 biosSpace[0x10000]; 23 | extern u8 biosSpaceColor[0x10000]; 24 | extern u8 *romSpacePtr; 25 | extern u8 *allocatedRomMem; 26 | extern const NgpHeader *ngpHeader; 27 | extern const void *g_BIOSBASE_COLOR; 28 | extern const void *g_BIOSBASE_BNW; 29 | 30 | void machineInit(void); 31 | void loadCart(int emuFlags); 32 | void tlcs9000MemInit(u8 *romPtr); 33 | 34 | #ifdef __cplusplus 35 | } // extern "C" 36 | #endif 37 | 38 | #endif // CART_HEADER 39 | -------------------------------------------------------------------------------- /source/Cart.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "TLCS900H/TLCS900H.i" 4 | #include "ARMZ80/ARMZ80.i" 5 | #include "K2GE/K2GE.i" 6 | 7 | .extern reset ;@ from bios.c 8 | 9 | .global gRomSize 10 | .global maxRomSize 11 | .global allocatedRomMemSize 12 | .global emuFlags 13 | .global gConfig 14 | .global gMachineSet 15 | .global gMachine 16 | .global gSOC 17 | .global gLang 18 | .global gPaletteBank 19 | 20 | .global ngpRAM 21 | .global biosSpace 22 | .global biosSpaceColor 23 | .global romSpacePtr 24 | .global allocatedRomMem 25 | .global ngpHeader 26 | .global g_BIOSBASE_COLOR 27 | .global g_BIOSBASE_BNW 28 | .global cartFlags 29 | .global romStart 30 | .global isBiosLoaded 31 | 32 | .global machineInit 33 | .global loadCart 34 | .global tlcs9000MemInit 35 | 36 | 37 | .syntax unified 38 | .arm 39 | 40 | .section .rodata 41 | .align 2 42 | 43 | ROM_Space: 44 | // .incbin "ngproms/Bust-A-Move Pocket (U).ngc" 45 | // .incbin "ngproms/Cool Boarders Pocket (JE) (M2).ngc" 46 | // .incbin "ngproms/Dark Arms - Beast Buster 1999 (JUE) (M2).ngc" 47 | // .incbin "ngproms/Evolution - Eternal Dungeons (E).ngc" 48 | // .incbin "ngproms/Fantastic Night Dreams Cotton (E).ngc" 49 | // .incbin "ngproms/Fatal Fury F-Contact (JUE) (M2).ngc" 50 | // .incbin "ngproms/King of Fighters R-2 (JUE) (M2).ngc" 51 | // .incbin "ngproms/Last Blade, The - Beyond the Destiny (E).ngc" 52 | // .incbin "ngproms/Metal Slug - 1st Mission (JUE) (M2).ngc" 53 | // .incbin "ngproms/SNK Gals' Fighters (UE).ngc" 54 | // .incbin "ngproms/Sonic the Hedgehog - Pocket Adventure (JUE).ngc" 55 | //biosSpace: 56 | // .incbin "ngproms/[BIOS] SNK Neo Geo Pocket (J).ngp" 57 | // .incbin "ngproms/[BIOS] SNK Neo Geo Pocket Color (JE).ngp" 58 | 59 | .align 2 60 | ;@---------------------------------------------------------------------------- 61 | machineInit: ;@ Called from C 62 | .type machineInit STT_FUNC 63 | ;@---------------------------------------------------------------------------- 64 | stmfd sp!,{r4,t9ptr,lr} 65 | 66 | ldr r1,=romSpacePtr 67 | // ldr r0,=ROM_Space 68 | // str r0,[r1] 69 | ldr r0,[r1] 70 | 71 | bl tlcs9000MemInit 72 | 73 | ldr r4,=gMachine 74 | ldrb r4,[r4] 75 | cmp r4,#HW_NGPMONO 76 | ldreq r0,=biosSpace 77 | ldrne r0,=biosSpaceColor 78 | ldr t9ptr,=tlcs900HState 79 | sub r0,r0,#0xFF0000 80 | str r0,[t9ptr,#biosBase] 81 | 82 | bl gfxInit 83 | // bl ioInit 84 | bl soundInit 85 | bl z80MemInit 86 | // bl cpuInit 87 | 88 | bl gfxReset 89 | bl ioReset 90 | bl soundReset 91 | bl cpuReset 92 | 93 | cmp r4,#HW_NGPMONO 94 | ldreq r0,=g_BIOSBASE_BNW 95 | ldrne r0,=g_BIOSBASE_COLOR 96 | ldr r0,[r0] 97 | cmp r0,#0 98 | beq skipBiosSettings 99 | 100 | bl run ;@ Settings are cleared when new batteries are inserted. 101 | bl transferTime ;@ So set up time 102 | ldr r1,=fixBiosSettings ;@ And Bios settings after the first run. 103 | blx r1 104 | skipBiosSettings: 105 | ldmfd sp!,{r4,t9ptr,lr} 106 | bx lr 107 | 108 | .section .ewram,"ax" 109 | .align 2 110 | ;@---------------------------------------------------------------------------- 111 | loadCart: ;@ Called from C: r0=emuflags 112 | .type loadCart STT_FUNC 113 | ;@---------------------------------------------------------------------------- 114 | stmfd sp!,{lr} 115 | str r0,emuFlags 116 | 117 | ldr r0,gRomSize 118 | ldr r1,romSpacePtr 119 | bl ngpFlashReset 120 | bl hacksInit 121 | 122 | ldr r1,=gMachine 123 | ldrb r1,[r1] 124 | cmp r1,#HW_NGPMONO 125 | ldreq r0,g_BIOSBASE_BNW 126 | ldrne r0,g_BIOSBASE_COLOR 127 | cmp r0,#0 128 | bne skipHWSetup 129 | 130 | bl gfxReset 131 | bl ioReset 132 | bl soundReset 133 | bl cpuReset 134 | ldr r0,ngpHeader ;@ First argument 135 | ldr r1,=resetHleBios 136 | blx r1 137 | skipHWSetup: 138 | ldmfd sp!,{lr} 139 | bx lr 140 | 141 | ;@---------------------------------------------------------------------------- 142 | tlcs9000MemInit: ;@ Called from C: r0=rombase address 143 | .type tlcs9000MemInit STT_FUNC 144 | ;@---------------------------------------------------------------------------- 145 | ldr r1,=tlcs900HState 146 | sub r2,r0,#0x200000 ;@ First bank is @ 0x200000 147 | str r2,[r1,#romBaseLo] 148 | add r0,r0,#0x200000-0x800000 ;@ Second Bank @ 0x800000 149 | str r0,[r1,#romBaseHi] 150 | bx lr 151 | ;@---------------------------------------------------------------------------- 152 | z80MemInit: 153 | ;@---------------------------------------------------------------------------- 154 | stmfd sp!,{z80ptr} 155 | ldr z80ptr,=Z80OpTable 156 | add r0,z80ptr,#z80ReadTbl 157 | ldr r1,=empty_R 158 | ldr r2,=empty_W 159 | mov r3,#8 160 | z80MemLoop0: 161 | str r2,[r0,#32] ;@ z80WriteTbl 162 | str r1,[r0],#4 163 | subs r3,r3,#1 164 | bne z80MemLoop0 165 | 166 | add r0,z80ptr,#z80ReadTbl 167 | ldr r1,=z80RamR 168 | str r1,[r0] ;@ 0x0000-0x1FFF 169 | ldr r1,=z80LatchR 170 | str r1,[r0,#16] ;@ 0x8000-0x9FFF 171 | 172 | add r0,z80ptr,#z80WriteTbl 173 | ldr r1,=z80RamW 174 | str r1,[r0] ;@ 0x0000-0x1FFF 175 | ldr r1,=z80SoundW 176 | str r1,[r0,#8] ;@ 0x4000-0x5FFF 177 | ldr r1,=z80LatchW 178 | str r1,[r0,#16] ;@ 0x8000-0x9FFF 179 | ldr r1,=z80IrqW 180 | str r1,[r0,#24] ;@ 0xC000-0xDFFF 181 | 182 | ldr r0,=ngpRAM+0x3000 ;@ Shared Z80/TLCS-900H RAM. 183 | add r1,z80ptr,#z80MemTbl 184 | mov r2,#8 185 | z80MemLoop1: 186 | str r0,[r1],#4 ;@ z80MemTbl 187 | subs r2,r2,#1 188 | bne z80MemLoop1 189 | 190 | ldmfd sp!,{z80ptr} 191 | bx lr 192 | 193 | 194 | ;@---------------------------------------------------------------------------- 195 | 196 | romInfo: ;@ 197 | emuFlags: 198 | .byte 0 ;@ emuflags (label this so GUI.c can take a peek) see EmuSettings.h for bitfields 199 | //scaling: 200 | .byte 0 ;@ (display type) 201 | .byte 0,0 ;@ (sprite follow val) 202 | cartFlags: 203 | .byte 0 ;@ cartflags 204 | gConfig: 205 | .byte 0 ;@ Config, bit 7=BIOS on/off 206 | gMachineSet: 207 | .byte HW_AUTO 208 | gMachine: 209 | .byte HW_NGPCOLOR 210 | gSOC: 211 | .byte SOC_K2GE 212 | gLang: 213 | .byte 1 ;@ language 214 | gPaletteBank: 215 | .byte 0 ;@ palettebank 216 | isBiosLoaded: 217 | .byte 0 218 | // .space 1 ;@ alignment. 219 | 220 | allocatedRomMem: 221 | .long 0 222 | allocatedRomMemSize: 223 | .long 0 224 | ngpHeader: 225 | romSpacePtr: 226 | .long 0 227 | g_BIOSBASE_COLOR: 228 | .long 0 229 | g_BIOSBASE_BNW: 230 | .long 0 231 | gRomSize: 232 | romSize: 233 | .long 0 234 | maxRomSize: 235 | .long 0 236 | 237 | .section .bss 238 | ngpRAM: 239 | .space 0x4000 240 | biosSpace: 241 | .space 0x10000 242 | biosSpaceColor: 243 | .space 0x10000 244 | ;@---------------------------------------------------------------------------- 245 | .end 246 | #endif // #ifdef __arm__ 247 | -------------------------------------------------------------------------------- /source/Emubase.h: -------------------------------------------------------------------------------- 1 | #ifndef EMUBASE 2 | #define EMUBASE 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct { //(config struct) 9 | char magic[4]; //="CFG",0 10 | int emuSettings; 11 | int sleepTime; // autoSleepTime 12 | u8 gammaValue; // from gfx.s 13 | u8 sprites; // from gfx.s 14 | u8 config; // from cart.s 15 | u8 controller; // from io.s 16 | u8 alarmHour; 17 | u8 alarmMinute; 18 | u8 birthDay; 19 | u8 birthMonth; 20 | u8 birthYear; 21 | u8 language; 22 | u8 palette; 23 | char currentPath[256]; 24 | char biosPath[256]; 25 | char biosPathColor[256]; 26 | } ConfigData; 27 | 28 | #ifdef __cplusplus 29 | } // extern "C" 30 | #endif 31 | 32 | #endif // EMUBASE 33 | -------------------------------------------------------------------------------- /source/FileHandling.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "FileHandling.h" 6 | #include "Shared/EmuMenu.h" 7 | #include "Shared/EmuSettings.h" 8 | #include "Shared/FileHelper.h" 9 | #include "Shared/AsmExtra.h" 10 | #include "Shared/CartridgeRAM.h" 11 | #include "Main.h" 12 | #include "Gui.h" 13 | #include "Cart.h" 14 | #include "cpu.h" 15 | #include "Gfx.h" 16 | #include "io.h" 17 | #include "Memory.h" 18 | #include "NGPHeader.h" 19 | #include "NGPFlash/NGPFlash.h" 20 | 21 | static const char *const folderName = "ngpds"; 22 | static const char *const settingName = "settings.cfg"; 23 | 24 | ConfigData cfg; 25 | 26 | //--------------------------------------------------------------------------------- 27 | int initSettings() { 28 | cfg.gammaValue = 0; 29 | cfg.emuSettings = AUTOPAUSE_EMULATION | AUTOLOAD_NVRAM; 30 | cfg.sleepTime = 60*60*5; 31 | cfg.controller = 0; // Don't swap A/B 32 | cfg.alarmHour = PersonalData->alarmHour; 33 | cfg.alarmMinute = PersonalData->alarmMinute; 34 | cfg.birthDay = PersonalData->birthDay; 35 | cfg.birthMonth = PersonalData->birthMonth; 36 | cfg.birthYear = 99; 37 | cfg.language = (PersonalData->language == 0) ? 0 : 1; 38 | int col = 0; // Black n White 39 | switch (PersonalData->theme & 0xF) { 40 | case 1: 41 | case 4: 42 | col = 4; // Brown 43 | break; 44 | case 2: 45 | case 3: 46 | case 15: 47 | col = 1; // Red 48 | break; 49 | case 6: 50 | case 7: 51 | case 8: 52 | col = 2; // Green 53 | break; 54 | case 10: 55 | case 11: 56 | case 12: 57 | col = 3; // Blue 58 | break; 59 | default: 60 | break; 61 | } 62 | cfg.palette = col; 63 | gPaletteBank = col; 64 | return 0; 65 | } 66 | 67 | bool updateSettingsFromNGP() { 68 | int val; 69 | bool changed = false; 70 | if (g_BIOSBASE_COLOR == NULL && g_BIOSBASE_BNW == NULL) { 71 | return changed; 72 | } 73 | 74 | val = t9LoadBX(0x6F8B); 75 | if (cfg.birthYear != val) { 76 | cfg.birthYear = val; 77 | changed = true; 78 | } 79 | val = t9LoadBX(0x6F8C); 80 | if (cfg.birthMonth != val) { 81 | cfg.birthMonth = val; 82 | changed = true; 83 | } 84 | val = t9LoadBX(0x6F8D); 85 | if (cfg.birthDay != val) { 86 | cfg.birthDay = val; 87 | changed = true; 88 | } 89 | 90 | val = t9LoadBX(0x6C34); 91 | if (cfg.alarmHour != val) { 92 | cfg.alarmHour = val; 93 | changed = true; 94 | } 95 | val = t9LoadBX(0x6C35); 96 | if (cfg.alarmMinute != val) { 97 | cfg.alarmMinute = val; 98 | changed = true; 99 | } 100 | 101 | val = t9LoadBX(0x6F87) & 1; 102 | if (cfg.language != val) { 103 | cfg.language = val; 104 | gLang = val; 105 | changed = true; 106 | } 107 | if (gMachine == HW_NGPCOLOR) { 108 | val = t9LoadBX(0x6F94) & 7; 109 | if (cfg.palette != val) { 110 | cfg.palette = val; 111 | gPaletteBank = val; 112 | changed = true; 113 | } 114 | } 115 | settingsChanged |= changed; 116 | 117 | return changed; 118 | } 119 | 120 | int loadSettings() { 121 | FILE *file; 122 | 123 | if (findFolder(folderName)) { 124 | return 1; 125 | } 126 | if ( (file = fopen(settingName, "r")) ) { 127 | fread(&cfg, 1, sizeof(ConfigData), file); 128 | fclose(file); 129 | if (!strstr(cfg.magic,"cfg")) { 130 | infoOutput("Error in settings file."); 131 | return 1; 132 | } 133 | } 134 | else { 135 | infoOutput("Couldn't open file:"); 136 | infoOutput(settingName); 137 | return 1; 138 | } 139 | 140 | gGammaValue = cfg.gammaValue; 141 | emuSettings = cfg.emuSettings & ~EMUSPEED_MASK; // Clear speed setting. 142 | sleepTime = cfg.sleepTime; 143 | joyCfg = (joyCfg & ~0x400)|((cfg.controller & 1)<<10); 144 | strlcpy(currentDir, cfg.currentPath, sizeof(currentDir)); 145 | 146 | infoOutput("Settings loaded."); 147 | return 0; 148 | } 149 | 150 | void saveSettings() { 151 | FILE *file; 152 | 153 | strcpy(cfg.magic,"cfg"); 154 | cfg.gammaValue = gGammaValue; 155 | cfg.emuSettings = emuSettings & ~EMUSPEED_MASK; // Clear speed setting. 156 | cfg.sleepTime = sleepTime; 157 | cfg.controller = (joyCfg>>10)&1; 158 | strlcpy(cfg.currentPath, currentDir, sizeof(cfg.currentPath)); 159 | 160 | if (findFolder(folderName)) { 161 | return; 162 | } 163 | if ( (file = fopen(settingName, "w")) ) { 164 | fwrite(&cfg, 1, sizeof(ConfigData), file); 165 | fclose(file); 166 | infoOutput("Settings saved."); 167 | } 168 | else { 169 | infoOutput("Couldn't open file:"); 170 | infoOutput(settingName); 171 | } 172 | } 173 | 174 | void loadNVRAM() { 175 | // Find the .fla file and read it in 176 | FILE *ngfFile; 177 | int i; 178 | NgfHeader header; 179 | NgfBlock block; 180 | char flashName[FILENAME_MAX_LENGTH]; 181 | bool canCopy; 182 | 183 | if (findFolder(folderName)) { 184 | return; 185 | } 186 | setFileExtension(flashName, currentFilename, ".fla", sizeof(flashName)); 187 | if ( !(ngfFile = fopen(flashName, "r")) ) { 188 | infoOutput("Couldn't open flash file:"); 189 | infoOutput(flashName); 190 | return; 191 | } 192 | 193 | if (fread(&header, 1, sizeof(NgfHeader), ngfFile) != sizeof(NgfHeader)) { 194 | infoOutput("Bad flash file:"); 195 | infoOutput(flashName); 196 | fclose(ngfFile); 197 | return; 198 | } 199 | 200 | if (header.version != 0x53) { 201 | infoOutput("Bad flash file version:"); 202 | infoOutput(flashName); 203 | fclose(ngfFile); 204 | return; 205 | } 206 | 207 | if (header.blockCount > MAX_BLOCKS) { 208 | infoOutput("Too many blocks in flash file:"); 209 | infoOutput(flashName); 210 | fclose(ngfFile); 211 | return; 212 | } 213 | 214 | // Loop through the blocks and insert them into mainrom 215 | for (i=0; i < header.blockCount; i++) { 216 | if (fread(&block, 1, sizeof(NgfBlock), ngfFile) != sizeof(NgfBlock)) { 217 | infoOutput("Couldn't read correct number of header bytes."); 218 | fclose(ngfFile); 219 | return; 220 | } 221 | 222 | canCopy = false; 223 | if ((block.ngpAddr >= 0x800000 && block.ngpAddr < 0xA00000)) { 224 | block.ngpAddr &= 0x1FFFFF; 225 | canCopy = markBlockDirty(1, getBlockFromAddress(block.ngpAddr)); 226 | block.ngpAddr += 0x200000; 227 | } 228 | else if ((block.ngpAddr >= 0x200000 && block.ngpAddr < 0x400000)) { 229 | block.ngpAddr &= 0x1FFFFF; 230 | canCopy = markBlockDirty(0, getBlockFromAddress(block.ngpAddr)); 231 | } 232 | if (!canCopy) { 233 | fseek(ngfFile, block.len, SEEK_CUR); 234 | infoOutput("Invalid block header in flash."); 235 | continue; 236 | } 237 | if (fread(&romSpacePtr[block.ngpAddr], 1, block.len, ngfFile) != block.len) { 238 | infoOutput("Couldn't read correct number of block bytes."); 239 | fclose(ngfFile); 240 | return; 241 | } 242 | } 243 | 244 | infoOutput("Loaded flash."); 245 | fclose(ngfFile); 246 | } 247 | 248 | void saveNVRAM() { 249 | // Find the dirty blocks and write them to the .fla file 250 | FILE *ngfFile; 251 | int totalBlocks = MAX_BLOCKS; 252 | int i; 253 | int chip; 254 | char flashName[FILENAME_MAX_LENGTH]; 255 | 256 | int bytes; 257 | int chipCount = (flashSize != 0x400000) ? 1 : 2; 258 | NgfHeader header; 259 | NgfBlock block; 260 | 261 | cls(0); 262 | drawText(" Saving flash...", 11, 0); 263 | 264 | header.version = 0x53; 265 | header.blockCount = 0; 266 | header.fileLen = sizeof(NgfHeader); 267 | 268 | // Add them all up, first 269 | for (chip=0; chipmode != 0 || strstr(fileExt, ".ngc")) { 441 | newMachine = HW_NGPCOLOR; 442 | } 443 | else { 444 | newMachine = HW_NGPMONO; 445 | } 446 | } 447 | if (gMachine != newMachine) { 448 | gMachine = newMachine; 449 | if (gMachine == HW_NGPMONO) { 450 | gSOC = SOC_K1GE; 451 | } 452 | else { 453 | gSOC = SOC_K2GE; 454 | } 455 | machineInit(); 456 | } 457 | } 458 | 459 | //--------------------------------------------------------------------------------- 460 | void ejectCart() { 461 | gRomSize = 0x200000; 462 | memset(romSpacePtr, -1, gRomSize); 463 | gameInserted = false; 464 | } 465 | 466 | //--------------------------------------------------------------------------------- 467 | static int loadBIOS(void *dest, const char *fPath, const int size) { 468 | char tempString[FILEPATH_MAX_LENGTH]; 469 | char *sPtr; 470 | 471 | cls(0); 472 | strlcpy(tempString, fPath, sizeof(tempString)); 473 | if ( (sPtr = strrchr(tempString, '/')) ) { 474 | sPtr[0] = 0; 475 | sPtr += 1; 476 | chdir("/"); 477 | chdir(tempString); 478 | bool result = loadROM(allocatedRomMem, sPtr, allocatedRomMemSize); 479 | memcpy(dest, allocatedRomMem, size); 480 | return result; 481 | } 482 | return 0; 483 | } 484 | 485 | int loadColorBIOS(void) { 486 | if ( loadBIOS(biosSpaceColor, cfg.biosPathColor, sizeof(biosSpaceColor)) ) { 487 | g_BIOSBASE_COLOR = biosSpaceColor; 488 | return 1; 489 | } 490 | g_BIOSBASE_COLOR = NULL; 491 | return 0; 492 | } 493 | 494 | int loadBnWBIOS(void) { 495 | if ( loadBIOS(biosSpace, cfg.biosPath, sizeof(biosSpace)) ) { 496 | g_BIOSBASE_BNW = biosSpace; 497 | return 1; 498 | } 499 | g_BIOSBASE_BNW = NULL; 500 | return 0; 501 | } 502 | 503 | static bool selectBios(char *dest, const char *fileTypes) { 504 | const char *biosName = browseForFileType(fileTypes); 505 | 506 | if ( biosName ) { 507 | strlcpy(dest, currentDir, FILEPATH_MAX_LENGTH); 508 | strlcat(dest, "/", FILEPATH_MAX_LENGTH); 509 | strlcat(dest, biosName, FILEPATH_MAX_LENGTH); 510 | return true; 511 | } 512 | return false; 513 | } 514 | 515 | void selectColorBios() { 516 | pauseEmulation = true; 517 | if ( selectBios(cfg.biosPathColor, ".ngp.ngc.zip") ) { 518 | loadColorBIOS(); 519 | machineInit(); 520 | } 521 | cls(0); 522 | } 523 | 524 | void selectBnWBios() { 525 | if ( selectBios(cfg.biosPath, ".ngp.ngc.zip") ) { 526 | loadBnWBIOS(); 527 | machineInit(); 528 | } 529 | cls(0); 530 | } 531 | -------------------------------------------------------------------------------- /source/FileHandling.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEHANDLING_HEADER 2 | #define FILEHANDLING_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "Emubase.h" 9 | #include "NeoGeoPocket.h" 10 | 11 | #define FILEEXTENSIONS ".ngp.ngc.ngpc" 12 | #define NGPF_MAGIC (0x4650474e) 13 | 14 | typedef struct 15 | { 16 | unsigned short version; // Always 0x53? 17 | unsigned short blockCount; // How many blocks are in the file 18 | unsigned long fileLen; // Length of the file in bytes 19 | } NgfHeader; 20 | 21 | typedef struct 22 | { 23 | unsigned long ngpAddr; // Where this block starts (in NGP memory map) 24 | unsigned long len; // Length of following data in bytes. 25 | } NgfBlock; 26 | 27 | /// NgpFlashFile 28 | typedef struct 29 | { 30 | u32 magic; // NGPF 31 | u8 blocksLOInfo[36]; // Flash low blocks 32 | u8 blocksHIInfo[36]; // Flash high blocks 33 | u32 addressLO; // Start address of flash low blocks in bytes 34 | u32 sizeLO; // Length of flash low blocks in bytes 35 | u32 addressHI; // Start address of flash high blocks in bytes 36 | u32 sizeHI; // Length of flash high blocks in bytes 37 | } NgpFlashFile; 38 | 39 | 40 | extern ConfigData cfg; 41 | 42 | int initSettings(void); 43 | bool updateSettingsFromNGP(void); 44 | int loadSettings(void); 45 | void saveSettings(void); 46 | bool loadGame(const char *gameName); 47 | void checkMachine(void); 48 | void loadNVRAM(void); 49 | void saveNVRAM(void); 50 | void loadState(void); 51 | void saveState(void); 52 | void ejectCart(void); 53 | void selectGame(void); 54 | void selectColorBios(void); 55 | void selectBnWBios(void); 56 | int loadColorBIOS(void); 57 | int loadBnWBIOS(void); 58 | 59 | #ifdef __cplusplus 60 | } // extern "C" 61 | #endif 62 | 63 | #endif // FILEHANDLING_HEADER 64 | -------------------------------------------------------------------------------- /source/GameInfo.s: -------------------------------------------------------------------------------- 1 | // 2 | // GameInfo.s 3 | // NGPDS 4 | // 5 | // Created by Fredrik Ahlström on 2021-09-22. 6 | // 7 | 8 | /* 9 | [KOF R1 ] 10 | 0x0001 11 | 0x0A 12 | 13 | 32 14 | 33 15 | 34 16 | 17 | 18 | [NeoGeo Cup98] 19 | 0x0002 20 | 0x08 21 | 22 | 16 23 | 17 24 | 18 25 | 26 | 27 | [MELON ] 28 | 0x0004 29 | 0x02 30 | 31 | 17 32 | 18 33 | 34 | 35 | [shogi ] 36 | 0x0005 37 | 0x03 38 | 39 | 8 40 | 9 41 | 10 42 | 43 | 44 | [BASEBALL1.10] 45 | 0x0007 46 | 0x03 47 | 48 | 14 49 | 15 50 | 16 51 | 17 52 | 18 53 | 54 | 55 | [SAMURAI v010] 56 | 0x0008 57 | 0x0A 58 | 59 | 34 60 | 61 | 62 | [PocketTennis] 63 | 0x0009 64 | 0x50 65 | 66 | 9 67 | 10 68 | 69 | 70 | [RB_F_CONTACT] 71 | 0x0011 72 | 0x90 73 | 74 | 33 75 | 34 76 | 77 | 78 | [DRAGONS WILD] 79 | 0x0015 80 | 0x13 81 | 82 | 15 83 | 18 84 | 85 | 86 | [N.Mystery B.] 87 | 0x0016 88 | 0x12 89 | 90 | 16 91 | 17 92 | 18 93 | 94 | 95 | [N.DerbyChamp] 96 | 0x0017 97 | 0x13 98 | 99 | 28 100 | 29 101 | 30 102 | 34 103 | 104 | 105 | [N.Twenty One] 106 | 0x0018 107 | 0x11 108 | 109 | 14 110 | 15 111 | 16 112 | 18 113 | 114 | 115 | [Neo Bacarrat] 116 | 0x0019 117 | 0x11 118 | 119 | 14 120 | 15 121 | 16 122 | 18 123 | 124 | 125 | [PUZZLE MINI] 126 | 0x0020 127 | 0x10 128 | 129 | 6 130 | 7 131 | 18 132 | 133 | 134 | [METALSLUG1ST] 135 | 0x0021 136 | 0x15 137 | 138 | 30 139 | 31 140 | 32 141 | 33 142 | 34 143 | 144 | 145 | [KOF R2 ] 146 | 0x0023 147 | 0x15 148 | 149 | 32 150 | 33 151 | 34 152 | 153 | 154 | [N.C.M.color ] 155 | 0x0024 156 | 0x10 157 | 158 | 16 159 | 17 160 | 18 161 | 162 | 163 | [BASEBALL2.10] 164 | 0x0025 165 | 0x07 166 | 167 | 14 168 | 15 169 | 16 170 | 17 171 | 18 172 | 173 | 174 | [NGP YAKYUU] 175 | 0x0026 176 | 0x1F 177 | 178 | 16 179 | 17 180 | 18 181 | 182 | 183 | [shogi color ] 184 | 0x0027 185 | 0x04 186 | 187 | 8 188 | 9 189 | 10 190 | 191 | 192 | [PTennisColor] 193 | 0x0028 194 | 0x30 195 | 196 | 9 197 | 10 198 | 199 | 200 | [TUNAGETE COL] 201 | 0x0029 202 | 0x30 203 | 204 | 6 205 | 7 206 | 10 207 | 208 | 209 | [SAMURAI2v000] 210 | 0x0030 211 | 0x1A 212 | 213 | 31 214 | 32 215 | 33 216 | 34 217 | 218 | 219 | [party mail ] 220 | 0x0032 221 | 0x15 222 | 223 | 16 224 | 17 225 | 18 226 | 227 | 228 | [Mahjong K2 ] 229 | 0x0033 230 | 0x21 231 | 232 | 8 233 | 9 234 | 10 235 | 236 | 237 | [B_T_GOLF ] 238 | 0x0035 239 | 0x11 240 | 241 | 30 242 | 31 243 | 32 244 | 33 245 | 34 246 | 247 | 248 | [DIVE ALERT B] 249 | 0x0036 250 | 0x03 251 | 252 | 30 253 | 34 254 | 255 | 256 | [DIVE ALERT R] 257 | 0x0037 258 | 0x03 259 | 260 | 30 261 | 34 262 | 263 | 264 | [CRUSH ROLLER] 265 | 0x0038 266 | 0x00 267 | 268 | 16 269 | 17 270 | 18 271 | 272 | 273 | [NGC98+COLOR ] 274 | 0x0039 275 | 0x10 276 | 277 | 16 278 | 17 279 | 18 280 | 281 | 282 | [SHANGHAIMINI] 283 | 0x0040 284 | 0x03 285 | 286 | 18 287 | 288 | 289 | [SHANGHAIMINI] 290 | 0x0040 291 | 0x04 292 | 293 | 18 294 | 295 | 296 | [PUYOPUYO2 ] 297 | 0x0041 298 | 0x06 299 | 300 | 17 301 | 18 302 | 303 | 304 | [PocketLoveIf] 305 | 0x0044 306 | 0x08 307 | 308 | 28 309 | 29 310 | 30 311 | 31 312 | 32 313 | 33 314 | 34 315 | 316 | 317 | [BEAST BUSTER] 318 | 0x0045 319 | 0x14 320 | 321 | 29 322 | 30 323 | 31 324 | 32 325 | 33 326 | 34 327 | 328 | 329 | [JV PACHI V01] 330 | 0x0046 331 | 0x02 332 | 333 | 13 334 | 14 335 | 15 336 | 16 337 | 17 338 | 18 339 | 340 | 341 | [magical drop] 342 | 0x0048 343 | 0x04 344 | 345 | 15 346 | 18 347 | 348 | 349 | [TSUNAGETE P2] 350 | 0x0049 351 | 0x50 352 | 353 | 16 354 | 17 355 | 18 356 | 357 | 358 | [B.M.Unitron2] 359 | 0x0050 360 | 0x60 361 | 362 | 30 363 | 31 364 | 32 365 | 33 366 | 34 367 | 368 | 369 | [FASELEI! ] 370 | 0x0051 371 | 0x09 372 | 373 | 30 374 | 31 375 | 32 376 | 33 377 | 34 378 | 379 | 380 | [HANABI 1.02 ] 381 | 0x0052 382 | 0x03 383 | 384 | 6 385 | 7 386 | 8 387 | 9 388 | 10 389 | 390 | 391 | [B.M.Unitron1] 392 | 0x0053 393 | 0x00 394 | 395 | 17 396 | 18 397 | 398 | 399 | [PUZZLE LINK ] 400 | 0x0054 401 | 0x20 402 | 403 | 6 404 | 7 405 | 10 406 | 407 | 408 | [PACMAN ] 409 | 0x0055 410 | 0x80 411 | 412 | 10 413 | 414 | 415 | [CARD FIGHTER] 416 | 0x0056 417 | 0x07 418 | 419 | 31 420 | 32 421 | 33 422 | 34 423 | 424 | 425 | [CARD FIGHTER] 426 | 0x0057 427 | 0x07 428 | 429 | 31 430 | 32 431 | 33 432 | 34 433 | 434 | 435 | [magical drop] 436 | 0x0058 437 | 0x04 438 | 439 | 15 440 | 18 441 | 442 | 443 | [SONIC POCKET] 444 | 0x0059 445 | 0x04 446 | 447 | 32 448 | 33 449 | 34 450 | 451 | 452 | [SONIC POCKET] 453 | 0x0059 454 | 0x05 455 | 456 | 32 457 | 33 458 | 34 459 | 460 | 461 | [DENSHADEGO2 ] 462 | 32 463 | 2 464 | 0x0060 465 | 0x50 466 | 467 | 468 | 31 469 | 32 470 | 33 471 | 34 472 | 473 | 474 | 475 | 476 | 34 477 | 478 | 479 | 480 | [METALSLUG2ND] 481 | 32 482 | 2 483 | 0x0061 484 | 0x04 485 | 486 | 487 | 33 488 | 34 489 | 490 | 491 | 492 | 493 | 34 494 | 495 | 496 | 497 | [YOUKAISYASIN] 498 | 0x0062 499 | 0x03 500 | 501 | 28 502 | 29 503 | 30 504 | 31 505 | 32 506 | 33 507 | 34 508 | 509 | 510 | [MEZASE!KANJI] 511 | 0x0063 512 | 0x06 513 | 514 | 30 515 | 34 516 | 517 | 518 | [GEKKAv1.1F00] 519 | 0x0064 520 | 0x1F 521 | 522 | 31 523 | 32 524 | 33 525 | 34 526 | 527 | 528 | [GalsFighters] 529 | 0x0065 530 | 0x30 531 | 532 | 32 533 | 33 534 | 34 535 | 536 | 537 | [BBPROWRESTLE] 538 | 0x0066 539 | 0x02 540 | 541 | 30 542 | 31 543 | 32 544 | 33 545 | 34 546 | 547 | 548 | [CARD FIGHT E] 549 | 0x0067 550 | 0x03 551 | 552 | 31 553 | 32 554 | 33 555 | 34 556 | 557 | 558 | [CARD FIGHT E] 559 | 0x0068 560 | 0x03 561 | 562 | 31 563 | 32 564 | 33 565 | 34 566 | 567 | 568 | [SNKvsCAPCOM1] 569 | 32 570 | 2 571 | 0x0069 572 | 0x15 573 | 574 | 575 | 32 576 | 33 577 | 34 578 | 579 | 580 | 581 | 582 | 34 583 | 584 | 585 | 586 | [N.Twenty One] 587 | 0x0070 588 | 0x20 589 | 590 | 14 591 | 15 592 | 18 593 | 594 | 595 | [NGP BBall] 596 | 0x0071 597 | 0x10 598 | 599 | 16 600 | 17 601 | 18 602 | 603 | 604 | [AZTECA 1.03 ] 605 | 0x0074 606 | 0x04 607 | 608 | 6 609 | 7 610 | 8 611 | 9 612 | 10 613 | 11 614 | 12 615 | 13 616 | 14 617 | 15 618 | 16 619 | 17 620 | 18 621 | 622 | 623 | [AZTECA 1.04 ] 624 | 0x0074 625 | 0x06 626 | 627 | 6 628 | 7 629 | 8 630 | 9 631 | 10 632 | 11 633 | 12 634 | 13 635 | 14 636 | 15 637 | 16 638 | 17 639 | 18 640 | 641 | 642 | [COOLBOARDERS] 643 | 0x0075 644 | 0x02 645 | 646 | 16 647 | 18 648 | 649 | 650 | [PUZZLE LINK2] 651 | 0x0076 652 | 0x30 653 | 654 | 16 655 | 17 656 | 18 657 | 658 | 659 | [HANAFUDA DJ ] 660 | 0x0078 661 | 0x03 662 | 663 | 9 664 | 10 665 | 666 | 667 | [OEKAKIPAZURU] 668 | 0x0081 669 | 0x0B 670 | 671 | 7 672 | 8 673 | 10 674 | 675 | 676 | [BM2000 ] 677 | 0x0083 678 | 0x04 679 | 680 | 17 681 | 18 682 | 683 | 684 | [WARD 1.02 ] 685 | 0x0084 686 | 0x03 687 | 688 | 6 689 | 7 690 | 8 691 | 9 692 | 10 693 | 694 | 695 | [OGRE_BATTLE ] 696 | 0x0085 697 | 0x08 698 | 699 | 27 700 | 28 701 | 29 702 | 30 703 | 34 704 | 705 | 706 | [MEMORIES OFF] 707 | 0x0087 708 | 0x07 709 | 710 | 16 711 | 17 712 | 18 713 | 714 | 715 | [DIVEALERT ME] 716 | 0x0088 717 | 0x02 718 | 719 | 30 720 | 34 721 | 722 | 723 | [DIVEALERT BE] 724 | 0x0089 725 | 0x02 726 | 727 | 30 728 | 34 729 | 730 | 731 | [FASELEI!(E) ] 732 | 0x0090 733 | 0x03 734 | 735 | 30 736 | 31 737 | 32 738 | 33 739 | 34 740 | 741 | 742 | [KOIKOIMARJAN] 743 | 0x0091 744 | 0x08 745 | 746 | 9 747 | 10 748 | 749 | 750 | [BATTLEDEPARA] 751 | 0x0092 752 | 0x05 753 | 754 | 32 755 | 33 756 | 34 757 | 758 | 759 | [GalsFighters] 760 | 0x0093 761 | 0x30 762 | 763 | 32 764 | 33 765 | 34 766 | 767 | 768 | [ROCKMAN ] 769 | 0x0094 770 | 0x04 771 | 772 | 32 773 | 33 774 | 34 775 | 776 | 777 | [LASTBLADE124] 778 | 0x0095 779 | 0x24 780 | 781 | 31 782 | 32 783 | 33 784 | 34 785 | 786 | 787 | [ NIGE-RONPA ] 788 | 0x0096 789 | 0x18 790 | 791 | 16 792 | 17 793 | 18 794 | 795 | 796 | [NEOPOKE KUN ] 797 | 0x0097 798 | 0x02 799 | 800 | 32 801 | 33 802 | 34 803 | 804 | 805 | [EVOLUTION US] 806 | 0x0099 807 | 0x03 808 | 809 | 31 810 | 32 811 | 33 812 | 34 813 | 814 | 815 | [CoolCoolJAM ] 816 | 0x0100 817 | 0x35 818 | 819 | 31 820 | 32 821 | 33 822 | 34 823 | 824 | 825 | [PORCANO 1.01] 826 | 0x0102 827 | 0x02 828 | 829 | 6 830 | 7 831 | 8 832 | 9 833 | 10 834 | 11 835 | 12 836 | 13 837 | 14 838 | 15 839 | 16 840 | 17 841 | 18 842 | 843 | 844 | [DELTA WARP ] 845 | 0x0103 846 | 0x05 847 | 848 | 8 849 | 9 850 | 10 851 | 11 852 | 12 853 | 13 854 | 14 855 | 15 856 | 16 857 | 17 858 | 18 859 | 860 | 861 | [COTTON-NGP/C] 862 | 0x0105 863 | 0x03 864 | 865 | 17 866 | 18 867 | 868 | 869 | [DELSOL2 ] 870 | 0x0107 871 | 0x03 872 | 873 | 14 874 | 15 875 | 16 876 | 17 877 | 18 878 | 879 | 880 | [DH2 DEKAHEL ] 881 | 0x0108 882 | 0x01 883 | 884 | 14 885 | 15 886 | 16 887 | 17 888 | 18 889 | 890 | 891 | [InfinityCure] 892 | 0x0109 893 | 0x22 894 | 895 | 17 896 | 18 897 | 898 | 899 | [OHANABI ] 900 | 0x0110 901 | 0x01 902 | 903 | 14 904 | 15 905 | 16 906 | 17 907 | 18 908 | 909 | 910 | [S-REAL-MAJAN] 911 | 0x0111 912 | 0x02 913 | 914 | 33 915 | 34 916 | 917 | 918 | [e-cup ] 919 | 0x0112 920 | 0x03 921 | 922 | 14 923 | 15 924 | 16 925 | 17 926 | 18 927 | 928 | 929 | [CARD FIGHT 2] 930 | 0x0116 931 | 0x06 932 | 933 | 32 934 | 33 935 | 34 936 | 937 | */ 938 | -------------------------------------------------------------------------------- /source/Gfx.h: -------------------------------------------------------------------------------- 1 | #ifndef GFX_HEADER 2 | #define GFX_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "K2GE/K2GE.h" 9 | 10 | extern u8 gFlicker; 11 | extern u8 gTwitch; 12 | extern u8 gScaling; 13 | extern u8 gGfxMask; 14 | extern u8 gBufferEnable; 15 | 16 | extern K2GE k2GE_0; 17 | extern u16 EMUPALBUFF[0x200]; 18 | extern u32 GFX_DISPCNT; 19 | extern u16 GFX_BG0CNT; 20 | extern u16 GFX_BG1CNT; 21 | 22 | void gfxInit(void); 23 | void vblIrqHandler(void); 24 | void monoPalInit(void); 25 | void paletteInit(u8 gammaVal); 26 | void paletteTxAll(void); 27 | void refreshGfx(void); 28 | 29 | /** 30 | * Enables/disables buffered VRAM mode. 31 | * @param enable: Enable buffered VRAM mode. 32 | */ 33 | void k2GE_0EnableBufferMode(bool enable); 34 | 35 | #ifdef __cplusplus 36 | } // extern "C" 37 | #endif 38 | 39 | #endif // GFX_HEADER 40 | -------------------------------------------------------------------------------- /source/Gfx.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "Shared/nds_asm.h" 4 | #include "TLCS900H/TLCS900H.i" 5 | #include "K2GE/K2GE.i" 6 | 7 | .global gfxInit 8 | .global gfxReset 9 | .global monoPalInit 10 | .global paletteInit 11 | .global paletteTxAll 12 | .global refreshGfx 13 | .global endFrameGfx 14 | .global vblIrqHandler 15 | 16 | .global gFlicker 17 | .global gTwitch 18 | .global gScaling 19 | .global gGfxMask 20 | .global gBufferEnable 21 | .global GFX_DISPCNT 22 | .global GFX_BG0CNT 23 | .global GFX_BG1CNT 24 | .global EMUPALBUFF 25 | .global tmpOamBuffer 26 | 27 | 28 | .global k2GE_0 29 | .global k2GE_0R 30 | .global k2GE_0R_W 31 | .global k2GE_0W 32 | .global k2GE_0W_W 33 | .global k2GE_0EnableBufferMode 34 | .global k2geRAM 35 | .global DIRTYTILES 36 | .global DIRTYTILES2 37 | 38 | 39 | .syntax unified 40 | .arm 41 | 42 | .section .text 43 | .align 2 44 | ;@---------------------------------------------------------------------------- 45 | gfxInit: ;@ Called from machineInit 46 | ;@---------------------------------------------------------------------------- 47 | stmfd sp!,{lr} 48 | 49 | ldr r0,=OAM_BUFFER1 ;@ No stray sprites please 50 | mov r1,#0x200+SCREEN_HEIGHT 51 | mov r2,#0x100 52 | bl memset_ 53 | 54 | bl k2GEInit 55 | 56 | ldmfd sp!,{pc} 57 | 58 | ;@---------------------------------------------------------------------------- 59 | gfxReset: ;@ Called with CPU reset 60 | ;@---------------------------------------------------------------------------- 61 | stmfd sp!,{lr} 62 | 63 | ldr r0,=k2geRAM 64 | ldr r1,=0x6960/4 ;@ VRAM and dirty tiles 65 | bl memclr_ ;@ Clear GFX regs 66 | 67 | mov r1,#REG_BASE 68 | ;@ Horizontal start-end 69 | ldr r0,=(((SCREEN_WIDTH-GAME_WIDTH)/2)<<8)+(SCREEN_WIDTH+GAME_WIDTH)/2 70 | strh r0,[r1,#REG_WIN0H] 71 | ;@ Vertical start-end 72 | ldr r0,=(((SCREEN_HEIGHT-GAME_HEIGHT)/2)<<8)+(SCREEN_HEIGHT+GAME_HEIGHT)/2 73 | strh r0,[r1,#REG_WIN0V] 74 | 75 | mov r0,#0x003F ;@ WinIN0, Everything enabled inside Win0 76 | orr r0,r0,#0x2800 ;@ WinIN1, Only BG3 & COL inside Win1 77 | strh r0,[r1,#REG_WININ] 78 | mov r0,#0x002C ;@ WinOUT, BG2, BG3 & COL enabled outside Windows. 79 | strh r0,[r1,#REG_WINOUT] 80 | ldr r0,=0x14AC30D0 81 | strh r0,[r1,#REG_WIN1H] 82 | mov r0,r0,lsr#16 83 | strh r0,[r1,#REG_WIN1V] 84 | 85 | ldr r0,=setVBlankInterrupt 86 | ldr r1,=clockTimer0 87 | ldr r2,=k2geRAM 88 | ldr r3,=gSOC 89 | ldrb r3,[r3] 90 | bl k2GEReset0 91 | ldrb r0,gBufferEnable 92 | bl k2GEEnableBufferMode 93 | bl monoPalInit 94 | 95 | ldr r0,=gGammaValue 96 | ldrb r0,[r0] 97 | bl paletteInit ;@ Do palette mapping 98 | bl paletteTxAll ;@ Transfer it 99 | bl updateLED 100 | 101 | ldmfd sp!,{pc} 102 | 103 | ;@---------------------------------------------------------------------------- 104 | monoPalInit: 105 | .type monoPalInit STT_FUNC 106 | ;@---------------------------------------------------------------------------- 107 | ldr geptr,=k2GE_0 108 | stmfd sp!,{r4-r6,lr} 109 | ldr r0,=gPaletteBank 110 | ldrb r0,[r0] 111 | adr r1,monoPalette 112 | add r1,r1,r0,lsl#4 113 | ldr r0,[geptr,#paletteRAM] 114 | add r0,r0,#0x180 115 | 116 | mov r2,#8 117 | ldmia r1,{r3-r6} 118 | monoPalLoop: 119 | stmia r0!,{r3-r6} 120 | subs r2,r2,#1 121 | bne monoPalLoop 122 | 123 | ldmfd sp!,{r4-r6,lr} 124 | bx lr 125 | ;@---------------------------------------------------------------------------- 126 | monoPalette: 127 | ;@ .short 0xFFF,0xDCD,0xBAB,0x979,0x767,0x535,0x313,0x000 128 | ;@ .short 0xFFF,0xDDC,0xBBA,0x997,0x775,0x553,0x331,0x000 129 | ;@ .short 0xFFF,0xCDD,0xABB,0x799,0x577,0x355,0x133,0x000 130 | ;@ .short 0xFFF,0xCCD,0xAAB,0x779,0x557,0x335,0x113,0x000 131 | ;@ .short 0xFFF,0xDCC,0xBAA,0x977,0x755,0x533,0x311,0x000 132 | ;@ .short 0xFFF,0xCDC,0xABA,0x797,0x575,0x353,0x131,0x000 133 | ;@ .short 0xFFF,0xDDD,0xBBB,0x999,0x777,0x555,0x333,0x000 134 | ;@ .short 0xFFF,0xDDD,0xBBB,0x999,0x777,0x555,0x333,0x000 135 | 136 | ;@ Black & White 137 | .short 0xFFF,0xDDD,0xBBB,0x999,0x777,0x444,0x333,0x000 138 | ;@ Red 139 | .short 0xFFF,0xCCF,0x99F,0x55F,0x11D,0x009,0x006,0x000 140 | ;@ Green 141 | .short 0xFFF,0xBFB,0x7F7,0x3D3,0x0B0,0x080,0x050,0x000 142 | ;@ Blue 143 | .short 0xFFF,0xFCC,0xFAA,0xF88,0xE55,0xB22,0x700,0x000 144 | ;@ Classic 145 | .short 0xFFF,0xADE,0x8BD,0x59B,0x379,0x157,0x034,0x000 146 | ;@---------------------------------------------------------------------------- 147 | paletteInit: ;@ r0-r3 modified. 148 | .type paletteInit STT_FUNC 149 | ;@ Called by ui.c: void paletteInit(gammaVal); 150 | ;@---------------------------------------------------------------------------- 151 | stmfd sp!,{r4-r7,lr} 152 | mov r1,r0 ;@ Gamma value = 0 -> 4 153 | mov r7,#0xF ;@ mask 154 | ldr r6,=MAPPED_RGB 155 | mov r4,#4096*2 156 | sub r4,r4,#2 157 | noMap: ;@ Map 0000bbbbggggrrrr -> 0bbbbbgggggrrrrr 158 | and r0,r7,r4,lsr#9 ;@ Blue ready 159 | bl gPrefix 160 | mov r5,r0 161 | 162 | and r0,r7,r4,lsr#5 ;@ Green ready 163 | bl gPrefix 164 | orr r5,r0,r5,lsl#5 165 | 166 | and r0,r7,r4,lsr#1 ;@ Red ready 167 | bl gPrefix 168 | orr r5,r0,r5,lsl#5 169 | 170 | strh r5,[r6,r4] 171 | subs r4,r4,#2 172 | bpl noMap 173 | 174 | ldmfd sp!,{r4-r7,lr} 175 | bx lr 176 | 177 | ;@---------------------------------------------------------------------------- 178 | gPrefix: 179 | orr r0,r0,r0,lsl#4 180 | ;@---------------------------------------------------------------------------- 181 | gammaConvert: ;@ Takes value in r0(0-0xFF), gamma in r1(0-4),returns new value in r0=0x1F 182 | ;@---------------------------------------------------------------------------- 183 | rsb r2,r0,#0x100 184 | mul r3,r2,r2 185 | rsbs r2,r3,#0x10000 186 | rsb r3,r1,#4 187 | orr r0,r0,r0,lsl#8 188 | mul r2,r1,r2 189 | mla r0,r3,r0,r2 190 | mov r0,r0,lsr#13 191 | 192 | bx lr 193 | ;@---------------------------------------------------------------------------- 194 | paletteTxAll: ;@ Called from ui.c 195 | .type paletteTxAll STT_FUNC 196 | ;@---------------------------------------------------------------------------- 197 | stmfd sp!,{r4-r11,lr} 198 | adr geptr,k2GE_0 199 | ldr r2,=0x1FFE 200 | ldr r3,[geptr,#paletteRAM] ;@ Colour palette 201 | ldr r7,[geptr,#paletteMonoRAM] ;@ Mono palette 202 | ldr r4,=MAPPED_RGB 203 | ldr r5,=EMUPALBUFF 204 | add r6,r5,#0x200 ;@ Sprite palette 205 | 206 | ldrb r8,[geptr,#kgeMode] ;@ Mono or color mode. 207 | eor r8,r8,#0x80 208 | ldrb r0,[geptr,#kgeBGCol] 209 | ands r9,r0,#0x80 ;@ Invert colors? 210 | orrne r9,r2,r2,lsl#16 211 | mov r1,#0 212 | 213 | txLoop0: ;@ Transfer starts with spr and continues with bgr0. 214 | tst r8,#0x80 ;@ !!! inverted at start !!! 215 | tsteq r1,#0x70 216 | add r1,r1,#2 217 | ldrh r0,[r3,r1] ;@ NGP palette 218 | eor r0,r9,r0,lsl#1 219 | and r0,r2,r0 220 | ldrh r0,[r4,r0] ;@ Pal lut 221 | strhne r0,[r6,r1] ;@ GBA/NDS palette 222 | add r1,r1,#2 223 | 224 | ldr r0,[r3,r1] ;@ NGP palette 225 | eor r0,r9,r0,lsl#1 226 | and r11,r2,r0 227 | ldrh r11,[r4,r11] ;@ Pal lut 228 | and r0,r2,r0,lsr#16 229 | ldrh r0,[r4,r0] ;@ Pal lut 230 | orr r0,r11,r0,lsl#16 231 | strne r0,[r6,r1] ;@ GBA/NDS palette 232 | 233 | add r1,r1,#4 234 | add r6,r6,#0x18 235 | tst r1,#0x7E 236 | bne txLoop0 237 | 238 | sub r6,r6,#512-8 239 | cmp r1,#0x80 240 | subeq r6,r5,#0x80 241 | cmp r1,#0x180 ;@ Also show mono replacement palette? 0x180/0x200. 242 | bne txLoop0 243 | 244 | tst r8,#0x80 ;@ !!! inverted at start !!! 245 | beq TxMonoPalette 246 | TxBackground: 247 | ldrb r0,[geptr,#kgeBGCol] ;@ Out of window color 248 | and r0,r0,#0x07 249 | mov r0,r0,lsl#1 250 | add r0,r0,#0x1F0 251 | ldrh r0,[r3,r0] 252 | eor r0,r9,r0,lsl#1 253 | and r0,r2,r0 254 | ldrh r0,[r4,r0] 255 | strh r0,[r5] 256 | mov r0,#0 257 | strh r0,[r5,#0x20] ;@ Border color (internal) 258 | 259 | ldrb r1,[r7,#0x18] ;@ Background color 260 | and r0,r1,#0x07 261 | mov r0,r0,lsl#1 262 | add r0,r0,#0x1E0 263 | ldrh r0,[r3,r0] 264 | // and r1,r1,#0xC0 265 | // cmp r1,#0x80 266 | // movne r0,#0 ;@ Black background if not 0x80 267 | eor r0,r9,r0,lsl#1 268 | and r0,r2,r0 269 | ldrh r0,[r4,r0] 270 | strh r0,[r5,#0x40] 271 | 272 | ldmfd sp!,{r4-r11,lr} 273 | bx lr 274 | 275 | TxMonoPalette: 276 | add r6,r5,#0x200 ;@ Sprite palette 277 | mov r1,#0 278 | add r8,r3,#0x180 ;@ Mono palette 279 | txLoop1: 280 | tst r1,#0x06 281 | ldrbne r0,[r7,r1,lsr#1] ;@ NGP mono lut 282 | eorne r0,r9,r0,lsl#1 283 | andne r0,r0,#0x0E 284 | ldrhne r0,[r8,r0] ;@ NGP palette 285 | andne r0,r2,r0,lsl#1 286 | ldrhne r0,[r4,r0] ;@ Pal lut 287 | strhne r0,[r6,r1] ;@ GBA/NDS palette 288 | 289 | add r1,r1,#2 290 | tst r1,#0x6 291 | addeq r6,r6,#0x18 292 | addeq r8,r8,#0x10 293 | tst r1,#0x0E 294 | bne txLoop1 295 | 296 | sub r6,r6,#64-8 297 | cmp r1,#0x10 298 | subeq r6,r5,#0x10 299 | cmp r1,#0x30 300 | bne txLoop1 301 | 302 | b TxBackground 303 | 304 | ;@---------------------------------------------------------------------------- 305 | updateLED: 306 | ;@---------------------------------------------------------------------------- 307 | ldrb r0,[geptr,#kgeLedOnOff] 308 | tst r0,#0x01 309 | ldr r0,=BG_GFX+0x1000 310 | ldr r1,[r0,#64*24] 311 | movne r1,r1,ror#16 312 | add r0,r0,#0x104 313 | strh r1,[r0] 314 | bx lr 315 | 316 | ;@---------------------------------------------------------------------------- 317 | vblIrqHandler: 318 | .type vblIrqHandler STT_FUNC 319 | ;@---------------------------------------------------------------------------- 320 | stmfd sp!,{r4-r8,lr} 321 | bl calculateFPS 322 | 323 | mov r6,#REG_BASE 324 | strh r6,[r6,#REG_DMA0CNT_H] ;@ DMA0 stop 325 | 326 | add r1,r6,#REG_DMA0SAD 327 | ldr r2,dmaScroll ;@ Setup DMA buffer for scrolling: 328 | ldmia r2!,{r4-r5} ;@ Read 329 | add r3,r6,#REG_BG0HOFS ;@ DMA0 always goes here 330 | stmia r3,{r4-r5} ;@ Set 1st value manually, HBL is AFTER 1st line 331 | ldr r4,=0x96600002 ;@ noIRQ hblank 32bit repeat incsrc inc_reloaddst, 2 word 332 | stmia r1,{r2-r4} ;@ DMA0 go 333 | 334 | add r1,r6,#REG_DMA3SAD 335 | 336 | ldr r2,dmaOamBuffer ;@ DMA3 src, OAM transfer: 337 | mov r3,#OAM ;@ DMA3 dst 338 | mov r4,#0x84000000 ;@ noIRQ 32bit incsrc incdst 339 | orr r4,r4,#64*2 ;@ 64 sprites * 2 longwords 340 | stmia r1,{r2-r4} ;@ DMA3 go 341 | 342 | ldr r2,=EMUPALBUFF ;@ DMA3 src, Palette transfer: 343 | mov r3,#BG_PALETTE ;@ DMA3 dst 344 | mov r4,#0x84000000 ;@ noIRQ 32bit incsrc incdst 345 | orr r4,r4,#0x100 ;@ 256 words (1024 bytes) 346 | stmia r1,{r2-r4} ;@ DMA3 go 347 | 348 | ldr r0,=GFX_DISPCNT 349 | ldr r0,[r0] 350 | ldrb r2,gGfxMask 351 | bic r0,r0,r2,lsl#8 352 | strh r0,[r6,#REG_DISPCNT] 353 | 354 | adr geptr,k2GE_0 355 | ldr r0,[geptr,#windowData] 356 | strh r0,[r6,#REG_WIN0H] 357 | mov r0,r0,lsr#16 358 | strh r0,[r6,#REG_WIN0V] 359 | 360 | ldrb r0,frameDone 361 | cmp r0,#0 362 | beq nothingNew 363 | bl k2GEConvertTiles 364 | mov r0,#BG_GFX 365 | bl k2GEConvertTileMaps 366 | mov r0,#0 367 | strb r0,frameDone 368 | nothingNew: 369 | 370 | blx scanKeys 371 | ldmfd sp!,{r4-r8,pc} 372 | 373 | 374 | ;@---------------------------------------------------------------------------- 375 | gFlicker: .byte 1 376 | .space 2 377 | gTwitch: .byte 0 378 | 379 | gScaling: .byte 0 380 | gGfxMask: .byte 0 381 | gBufferEnable: .byte 1 382 | frameDone: .byte 0 383 | ;@---------------------------------------------------------------------------- 384 | refreshGfx: ;@ Called from C when changing scaling. 385 | .type refreshGfx STT_FUNC 386 | ;@---------------------------------------------------------------------------- 387 | adr geptr,k2GE_0 388 | ;@---------------------------------------------------------------------------- 389 | endFrameGfx: ;@ Called just before screen end (~line 152) (r0-r3 safe to use) 390 | ;@---------------------------------------------------------------------------- 391 | stmfd sp!,{lr} 392 | 393 | bl updateSlowIO ;@ RTC/Alarm and more 394 | bl updateLED 395 | ldr r0,tmpScroll 396 | bl copyScrollValues 397 | bl paletteTxAll 398 | ;@-------------------------- 399 | 400 | ldr r0,dmaOamBuffer 401 | ldr r1,tmpOamBuffer 402 | str r0,tmpOamBuffer 403 | str r1,dmaOamBuffer 404 | 405 | ldr r0,dmaScroll 406 | ldr r1,tmpScroll 407 | str r0,tmpScroll 408 | str r1,dmaScroll 409 | 410 | mov r0,#1 411 | strb r0,frameDone 412 | 413 | ldmfd sp!,{lr} 414 | bx lr 415 | 416 | ;@---------------------------------------------------------------------------- 417 | DMA0BUFPTR: .long 0 418 | 419 | tmpOamBuffer: .long OAM_BUFFER1 420 | dmaOamBuffer: .long OAM_BUFFER2 421 | tmpScroll: .long SCROLLBUFF1 422 | dmaScroll: .long SCROLLBUFF2 423 | 424 | ;@---------------------------------------------------------------------------- 425 | k2GEReset0: ;@ r0=frameIrqFunc, r1=hblankIrqFunc, r2=frame2IrqFunc, r3=model 426 | ;@---------------------------------------------------------------------------- 427 | adr geptr,k2GE_0 428 | b k2GEReset 429 | ;@---------------------------------------------------------------------------- 430 | k2GE_0R: ;@ K2GE read byte, 0x8000-0x8FFF 431 | ;@---------------------------------------------------------------------------- 432 | adr geptr,k2GE_0 433 | b k2GE_R 434 | ;@---------------------------------------------------------------------------- 435 | k2GE_0R_W: ;@ K2GE read word, 0x8000-0x8FFF 436 | ;@---------------------------------------------------------------------------- 437 | adr geptr,k2GE_0 438 | b k2GE_R_W 439 | 440 | ;@---------------------------------------------------------------------------- 441 | k2GE_0W: ;@ K2GE write byte, 0x8000-0x8FFF 442 | ;@---------------------------------------------------------------------------- 443 | mov r1,t9Mem 444 | adr geptr,k2GE_0 445 | b k2GE_W 446 | ;@---------------------------------------------------------------------------- 447 | k2GE_0W_W: ;@ K2GE write word, 0x8000-0x8FFF 448 | ;@---------------------------------------------------------------------------- 449 | mov r1,t9Mem 450 | adr geptr,k2GE_0 451 | b k2GE_W_W 452 | ;@---------------------------------------------------------------------------- 453 | k2GE_0EnableBufferMode: ;@ K2GE Enable/disable buffer mode 454 | .type k2GE_0EnableBufferMode STT_FUNC 455 | ;@---------------------------------------------------------------------------- 456 | adr geptr,k2GE_0 457 | b k2GEEnableBufferMode 458 | 459 | k2GE_0: 460 | .space k2GESize 461 | ;@---------------------------------------------------------------------------- 462 | GFX_DISPCNT: 463 | .long 0 464 | GFX_BG0CNT: 465 | .short 0 466 | GFX_BG1CNT: 467 | .short 0 468 | 469 | #ifdef GBA 470 | .section .sbss ;@ For the GBA 471 | #else 472 | .section .bss 473 | #endif 474 | .align 2 475 | 476 | OAM_BUFFER1: 477 | .space 0x400 478 | OAM_BUFFER2: 479 | .space 0x400 480 | SCROLLBUFF1: 481 | .space 0x100*8 ;@ Scrollbuffer. 482 | SCROLLBUFF2: 483 | .space 0x100*8 ;@ Scrollbuffer. 484 | MAPPED_RGB: 485 | .space 0x2000 ;@ 4096*2 486 | EMUPALBUFF: 487 | .space 0x400 488 | k2geRAM: 489 | .space 0x3360 ;@ 0x3000+0x200+0x140+0x20 490 | .space 0x3000 ;@ backbuffer 491 | DIRTYTILES: 492 | .space 0x300 493 | DIRTYTILES2: 494 | .space 0x300 495 | 496 | ;@---------------------------------------------------------------------------- 497 | .end 498 | #endif // #ifdef __arm__ 499 | -------------------------------------------------------------------------------- /source/Gui.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Gui.h" 4 | #include "Shared/EmuMenu.h" 5 | #include "Shared/EmuSettings.h" 6 | #include "Main.h" 7 | #include "FileHandling.h" 8 | #include "Cart.h" 9 | #include "Gfx.h" 10 | #include "io.h" 11 | #include "cpu.h" 12 | #include "bios.h" 13 | #include "TLCS900H/Version.h" 14 | #include "ARMZ80/Version.h" 15 | #include "K2GE/Version.h" 16 | #include "K2Audio/Version.h" 17 | 18 | #define EMUVERSION "V0.5.7 2024-09-11" 19 | 20 | #define ALLOW_SPEED_HACKS (1<<17) 21 | 22 | void hacksInit(void); 23 | 24 | static void paletteChange(void); 25 | static void bufferModeSet(void); 26 | static void languageSet(void); 27 | static void machineSet(void); 28 | static void batteryChange(void); 29 | static void subBatteryChange(void); 30 | static void speedHackSet(void); 31 | static void z80SpeedSet(void); 32 | 33 | static void uiMachine(void); 34 | static void uiDebug(void); 35 | static void updateGameInfo(void); 36 | static void checkBattery(void); 37 | 38 | 39 | const MItem fnList0[] = {{"",uiDummy}}; 40 | const MItem fnList1[] = { 41 | {"Load Game",selectGame}, 42 | {"Load State",loadState}, 43 | {"Save State",saveState}, 44 | {"Load Flash",loadNVRAM}, 45 | {"Save Flash",saveNVRAM}, 46 | {"Save Settings",saveSettings}, 47 | {"Eject Game",ejectGame}, 48 | {"Reset Console",resetConsole}, 49 | {"Quit Emulator",ui9}}; 50 | const MItem fnList2[] = { 51 | {"Controller",ui4}, 52 | {"Display",ui5}, 53 | {"Machine",ui6}, 54 | {"Settings",ui7}, 55 | {"Debug",ui8}}; 56 | const MItem fnList4[] = {{"",autoBSet}, {"",autoASet}, {"",swapABSet}}; 57 | const MItem fnList5[] = {{"",gammaSet}, {"",paletteChange}, {"",bufferModeSet}}; 58 | const MItem fnList6[] = {{"",languageSet}, {"",machineSet}, {"",batteryChange}, {"",subBatteryChange}, {"",speedHackSet}, {"",z80SpeedSet}, {"",selectBnWBios}, {"",selectColorBios}}; 59 | const MItem fnList7[] = {{"",speedSet}, {"",autoStateSet}, {"",autoNVRAMSet}, {"",autoSettingsSet}, {"",autoPauseGameSet}, {"",powerSaveSet}, {"",screenSwapSet}, {"",sleepSet}}; 60 | const MItem fnList8[] = {{"",debugTextSet}, {"",fgrLayerSet}, {"",bgrLayerSet}, {"",sprLayerSet}, {"",stepFrame}}; 61 | const MItem fnList9[] = {{"Yes ",exitEmulator}, {"No ",backOutOfMenu}}; 62 | 63 | const Menu menu0 = MENU_M("", uiNullNormal, fnList0); 64 | Menu menu1 = MENU_M("", uiAuto, fnList1); 65 | const Menu menu2 = MENU_M("", uiAuto, fnList2); 66 | const Menu menu3 = MENU_M("", uiAbout, fnList0); 67 | const Menu menu4 = MENU_M("Controller Settings", uiController, fnList4); 68 | const Menu menu5 = MENU_M("Display Settings", uiDisplay, fnList5); 69 | const Menu menu6 = MENU_M("Machine Settings", uiMachine, fnList6); 70 | const Menu menu7 = MENU_M("Settings", uiSettings, fnList7); 71 | const Menu menu8 = MENU_M("Debug", uiDebug, fnList8); 72 | const Menu menu9 = MENU_M("Quit Emulator?", uiAuto, fnList9); 73 | const Menu menu10 = MENU_M("", uiDummy, fnList0); 74 | 75 | const Menu *const menus[] = {&menu0, &menu1, &menu2, &menu3, &menu4, &menu5, &menu6, &menu7, &menu8, &menu9, &menu10 }; 76 | 77 | static int oldBattery; 78 | u8 gGammaValue = 0; 79 | u8 gZ80Speed = 0; 80 | char gameInfoString[32]; 81 | 82 | const char *const autoTxt[] = {"Off", "On", "With R"}; 83 | const char *const speedTxt[] = {"Normal", "200%", "Max", "50%"}; 84 | const char *const brighTxt[] = {"I", "II", "III", "IIII", "IIIII"}; 85 | const char *const sleepTxt[] = {"5min", "10min", "30min", "Off"}; 86 | const char *const ctrlTxt[] = {"1P", "2P"}; 87 | const char *const dispTxt[] = {"Unscaled", "Scaled"}; 88 | const char *const flickTxt[] = {"No Flicker", "Flicker"}; 89 | 90 | const char *const machTxt[] = {"Auto", "NeoGeo Pocket", "NeoGeo Pocket Color"}; 91 | const char *const bordTxt[] = {"Black", "Border Color", "None"}; 92 | const char *const palTxt[] = {"Black & White", "Red", "Green", "Blue", "Classic"}; 93 | const char *const langTxt[] = {"Japanese", "English"}; 94 | const char *const cpuSpeedTxt[] = {"Full Speed", "Half Speed", "1/4 Speed", "1/8 Speed", "1/16 Speed"}; 95 | 96 | /// This is called at the start of the emulator 97 | void setupGUI() { 98 | emuSettings = AUTOPAUSE_EMULATION | AUTOLOAD_NVRAM | ALLOW_SPEED_HACKS | AUTOSLEEP_OFF; 99 | keysSetRepeat(25, 4); // Delay, repeat. 100 | menu1.itemCount = ARRSIZE(fnList1) - (enableExit?0:1); 101 | openMenu(); 102 | } 103 | 104 | /// This is called when going from emu to ui. 105 | void enterGUI() { 106 | if (updateSettingsFromNGP() && (emuSettings & AUTOSAVE_SETTINGS)) { 107 | saveSettings(); 108 | settingsChanged = false; 109 | } 110 | } 111 | 112 | /// This is called going from ui to emu. 113 | void exitGUI() { 114 | } 115 | 116 | void quickSelectGame(void) { 117 | openMenu(); 118 | selectGame(); 119 | closeMenu(); 120 | } 121 | 122 | void uiNullNormal() { 123 | uiNullDefault(); 124 | oldBattery = 0; 125 | } 126 | 127 | void uiAbout() { 128 | cls(1); 129 | updateGameInfo(); 130 | drawTabs(); 131 | drawMenuText("B: NGP A button", 4, 0); 132 | drawMenuText("A: NGP B button", 5, 0); 133 | drawMenuText("L: NGP D button", 6, 0); 134 | drawMenuText("X/Start: Option button", 7, 0); 135 | drawMenuText("Y/Select: Power button", 8, 0); 136 | drawMenuText("DPad: Joystick", 9, 0); 137 | 138 | drawMenuText(gameInfoString, 11, 0); 139 | 140 | drawMenuText("NGPDS " EMUVERSION, 19, 0); 141 | drawMenuText("ARMZ80 " ARMZ80VERSION, 20, 0); 142 | drawMenuText("ARMTLCS-900H " TLCS900VERSION, 21, 0); 143 | drawMenuText("ARMK2GE " K2GEVERSION, 22, 0); 144 | drawMenuText("ARMK2Audio " ARMK2AUDIOVERSION, 23, 0); 145 | } 146 | 147 | void uiController() { 148 | setupSubMenuText(); 149 | drawSubItem("B Autofire:", autoTxt[autoB]); 150 | drawSubItem("A Autofire:", autoTxt[autoA]); 151 | drawSubItem("Swap A-B: ", autoTxt[(joyCfg>>10)&1]); 152 | } 153 | 154 | void uiDisplay() { 155 | setupSubMenuText(); 156 | drawSubItem("Gamma:", brighTxt[gGammaValue]); 157 | drawSubItem("B&W Palette:", palTxt[gPaletteBank]); 158 | drawSubItem("VRAM Double Buffer:", autoTxt[gBufferEnable]); 159 | } 160 | 161 | static void uiMachine() { 162 | setupSubMenuText(); 163 | drawSubItem("Language:", langTxt[gLang]); 164 | drawSubItem("Machine:", machTxt[gMachineSet]); 165 | drawSubItem("Change Batteries", NULL); 166 | drawSubItem("Change Sub Battery", NULL); 167 | drawSubItem("Cpu Speed Hacks:", autoTxt[(emuSettings&ALLOW_SPEED_HACKS)>>17]); 168 | drawSubItem("Z80 Clock:", cpuSpeedTxt[gZ80Speed&7]); 169 | drawSubItem("Select BnW Bios", NULL); 170 | drawSubItem("Select Color Bios", NULL); 171 | } 172 | 173 | void uiSettings() { 174 | setupSubMenuText(); 175 | drawSubItem("Speed:", speedTxt[(emuSettings>>6)&3]); 176 | drawSubItem("Autoload State:", autoTxt[(emuSettings>>2)&1]); 177 | drawSubItem("Autoload Flash RAM:", autoTxt[(emuSettings>>10)&1]); 178 | drawSubItem("Autosave Settings:", autoTxt[(emuSettings>>9)&1]); 179 | drawSubItem("Autopause Game:", autoTxt[emuSettings&1]); 180 | drawSubItem("Powersave 2nd Screen:", autoTxt[(emuSettings>>1)&1]); 181 | drawSubItem("Emulator on Bottom:", autoTxt[(emuSettings>>8)&1]); 182 | drawSubItem("Autosleep:", sleepTxt[(emuSettings>>4)&3]); 183 | } 184 | 185 | void uiDebug() { 186 | setupSubMenuText(); 187 | drawSubItem("Debug Output:", autoTxt[gDebugSet&1]); 188 | drawSubItem("Disable Foreground:", autoTxt[gGfxMask&1]); 189 | drawSubItem("Disable Background:", autoTxt[(gGfxMask>>1)&1]); 190 | drawSubItem("Disable Sprites:", autoTxt[(gGfxMask>>4)&1]); 191 | drawSubItem("Step Frame", NULL); 192 | } 193 | 194 | void checkBattery() { 195 | if (oldBattery != batteryLevel) { 196 | oldBattery = batteryLevel; 197 | if (batteryLevel < 0x8400) { 198 | drawText(" Batteries low in the NGP!", 15, 0); 199 | } 200 | else { 201 | drawText("", 15, 0); 202 | } 203 | } 204 | } 205 | 206 | void nullUINormal(int key) { 207 | checkBattery(); 208 | if (key & KEY_TOUCH) { 209 | openMenu(); 210 | } 211 | } 212 | 213 | void nullUIDebug(int key) { 214 | checkBattery(); 215 | if (key & KEY_TOUCH) { 216 | openMenu(); 217 | } 218 | } 219 | 220 | void ejectGame() { 221 | ejectCart(); 222 | } 223 | 224 | void resetConsole() { 225 | checkMachine(); 226 | machineInit(); 227 | loadCart(0); 228 | } 229 | 230 | void updateGameInfo() { 231 | char catalog[8]; 232 | strlMerge(gameInfoString, "Game Name: ", ngpHeader->name, sizeof(gameInfoString)); 233 | strlcat(gameInfoString, " #", sizeof(gameInfoString)); 234 | short2HexStr(catalog, ngpHeader->catalog); 235 | strlcat(gameInfoString, catalog, sizeof(gameInfoString)); 236 | } 237 | //--------------------------------------------------------------------------------- 238 | void debugIO(u16 port, u8 val, const char *message) { 239 | char debugString[32]; 240 | 241 | debugString[0] = 0; 242 | strlcat(debugString, message, sizeof(debugString)); 243 | short2HexStr(&debugString[strlen(debugString)], port); 244 | strlcat(debugString, " val:", sizeof(debugString)); 245 | char2HexStr(&debugString[strlen(debugString)], val); 246 | debugOutput(debugString); 247 | } 248 | //--------------------------------------------------------------------------------- 249 | void debugIOUnimplR(u16 port) { 250 | debugIO(port, 0, "Unimpl R port:"); 251 | } 252 | void debugIOUnimplW(u8 val, u16 port) { 253 | debugIO(port, val, "Unimpl W port:"); 254 | } 255 | void debugDivideError() { 256 | debugOutput("Divide Error."); 257 | } 258 | void debugUndefinedInstruction() { 259 | debugOutput("Undefined Instruction."); 260 | } 261 | void debugCrashInstruction() { 262 | debugOutput("CPU Crash!"); 263 | } 264 | 265 | //--------------------------------------------------------------------------------- 266 | /// Swap A & B buttons 267 | void swapABSet() { 268 | joyCfg ^= 0x400; 269 | } 270 | 271 | /// Change gamma (brightness) 272 | void gammaSet() { 273 | gGammaValue++; 274 | if (gGammaValue > 4) gGammaValue = 0; 275 | paletteInit(gGammaValue); 276 | paletteTxAll(); // Make new palette visible 277 | setupMenuPalette(); 278 | settingsChanged = true; 279 | } 280 | 281 | /// Turn on/off rendering of foreground 282 | void fgrLayerSet(){ 283 | gGfxMask ^= 0x01; 284 | } 285 | /// Turn on/off rendering of background 286 | void bgrLayerSet(){ 287 | gGfxMask ^= 0x02; 288 | } 289 | /// Turn on/off rendering of sprites 290 | void sprLayerSet(){ 291 | gGfxMask ^= 0x10; 292 | } 293 | 294 | void paletteChange() { 295 | gPaletteBank++; 296 | if (gPaletteBank > 4) { 297 | gPaletteBank = 0; 298 | } 299 | monoPalInit(); 300 | paletteTxAll(); 301 | fixBiosSettings(); 302 | settingsChanged = true; 303 | } 304 | void bufferModeSet() { 305 | gBufferEnable ^= 0x01; 306 | k2GE_0EnableBufferMode(gBufferEnable); 307 | } 308 | /* 309 | void borderSet() { 310 | bcolor++; 311 | if (bcolor > 2) { 312 | bcolor = 0; 313 | } 314 | makeborder(); 315 | } 316 | */ 317 | void languageSet() { 318 | gLang ^= 0x01; 319 | fixBiosSettings(); 320 | } 321 | 322 | void machineSet() { 323 | gMachineSet++; 324 | if (gMachineSet >= HW_SELECT_END) { 325 | gMachineSet = 0; 326 | } 327 | } 328 | 329 | void batteryChange() { 330 | batteryLevel = 0xFFFF; // 0xFFFF for 2 days battery? 331 | } 332 | 333 | void subBatteryChange() { 334 | gSubBatteryLevel = 0x3FFFFFF; // 0x3FFFFFF for 2 years battery? 335 | } 336 | 337 | void speedHackSet() { 338 | emuSettings ^= ALLOW_SPEED_HACKS; 339 | hacksInit(); 340 | } 341 | 342 | void z80SpeedSet() { 343 | gZ80Speed++; 344 | if (gZ80Speed >= 5) { 345 | gZ80Speed = 0; 346 | } 347 | tweakZ80Speed(gZ80Speed); 348 | } 349 | -------------------------------------------------------------------------------- /source/Gui.h: -------------------------------------------------------------------------------- 1 | #ifndef GUI_HEADER 2 | #define GUI_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern u8 gGammaValue; 9 | 10 | void setupGUI(void); 11 | void enterGUI(void); 12 | void exitGUI(void); 13 | void quickSelectGame(void); 14 | void nullUINormal(int key); 15 | void nullUIDebug(int key); 16 | void resetConsole(void); 17 | void ejectGame(void); 18 | 19 | void uiNullNormal(void); 20 | void uiFile(void); 21 | void uiSettings(void); 22 | void uiAbout(void); 23 | void uiOptions(void); 24 | void uiController(void); 25 | void uiDisplay(void); 26 | 27 | void debugIOUnimplR(u16 port); 28 | void debugIOUnimplW(u8 val, u16 port); 29 | void debugDivideError(void); 30 | void debugUndefinedInstruction(void); 31 | void debugCrashInstruction(void); 32 | 33 | void controllerSet(void); 34 | void swapABSet(void); 35 | 36 | void scalingSet(void); 37 | void gammaSet(void); 38 | void fgrLayerSet(void); 39 | void bgrLayerSet(void); 40 | void sprLayerSet(void); 41 | 42 | #ifdef __cplusplus 43 | } // extern "C" 44 | #endif 45 | 46 | #endif // GUI_HEADER 47 | -------------------------------------------------------------------------------- /source/Main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Main.h" 5 | #include "Shared/EmuMenu.h" 6 | #include "Shared/FileHelper.h" 7 | #include "Shared/AsmExtra.h" 8 | #include "Gui.h" 9 | #include "FileHandling.h" 10 | #include "EmuFont.h" 11 | #include "NGPBorder.h" 12 | #include "Cart.h" 13 | #include "cpu.h" 14 | #include "Gfx.h" 15 | #include "io.h" 16 | #include "Sound.h" 17 | #include "bios.h" 18 | 19 | static void checkTimeOut(void); 20 | static void setupGraphics(void); 21 | static void setupStream(void); 22 | 23 | bool gameInserted = false; 24 | static int sleepTimer = 60*60*5; // 5 min 25 | static bool vBlankOverflow = false; 26 | 27 | static mm_ds_system sys; 28 | static mm_stream myStream; 29 | 30 | u16 *map0sub; 31 | u16 *map1sub; 32 | 33 | static const u8 guiPalette[] = { 34 | 0x00,0x00,0xC0, 0x00,0x00,0x00, 0x81,0x81,0x81, 0x93,0x93,0x93, 0xA5,0xA5,0xA5, 0xB7,0xB7,0xB7, 0xC9,0xC9,0xC9, 0xDB,0xDB,0xDB, 35 | 0xED,0xED,0xED, 0xFF,0xFF,0xFF, 0x00,0x00,0xC0, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 36 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x50,0x78,0x78, 0x60,0x90,0x90, 0x78,0xB0,0xB0, 0x88,0xC8,0xC8, 0x90,0xE0,0xE0, 0xA0,0xF0,0xF0, 37 | 0xB8,0xF8,0xF8, 0xEF,0xFF,0xFF, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 38 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x21,0x21,0x21, 0x33,0x33,0x33, 0x45,0x45,0x45, 0x47,0x47,0x47, 0x59,0x59,0x59, 0x6B,0x6B,0x6B, 39 | 0x7D,0x7D,0x7D, 0x8F,0x8F,0x8F, 0x20,0x20,0xE0, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 40 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x81,0x81,0x81, 0x93,0x93,0x93, 0xA5,0xA5,0xA5, 0xB7,0xB7,0xB7, 0xC9,0xC9,0xC9, 0xDB,0xDB,0xDB, 41 | 0xED,0xED,0xED, 0xFF,0xFF,0xFF, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 42 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x70,0x70,0x20, 0x88,0x88,0x40, 0xA0,0xA0,0x60, 0xB8,0xB8,0x80, 0xD0,0xD0,0x90, 0xE8,0xE8,0xA0, 43 | 0xF7,0xF7,0xC0, 0xFF,0xFF,0xE0, 0x00,0x00,0x60, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 44 | }; 45 | 46 | //--------------------------------------------------------------------------------- 47 | void myVblank(void) { 48 | //--------------------------------------------------------------------------------- 49 | vBlankOverflow = true; 50 | // DC_FlushRange(EMUPALBUFF, 0x400); 51 | vblIrqHandler(); 52 | } 53 | 54 | //--------------------------------------------------------------------------------- 55 | int main(int argc, char **argv) { 56 | //--------------------------------------------------------------------------------- 57 | if (argc > 1) { 58 | enableExit = true; 59 | } 60 | // Try to allocate 4MB on DSi 61 | allocatedRomMemSize = 0x400000 + 0x1000; 62 | allocatedRomMem = malloc(allocatedRomMemSize); 63 | if (allocatedRomMem == NULL) { 64 | // Try to allocate 2MB on DS 65 | allocatedRomMemSize = 0x200000 + 0x1000; 66 | allocatedRomMem = malloc(allocatedRomMemSize); 67 | } 68 | maxRomSize = allocatedRomMemSize; 69 | romSpacePtr = allocatedRomMem; 70 | setupGraphics(); 71 | 72 | setupStream(); 73 | irqSet(IRQ_VBLANK, myVblank); 74 | setupGUI(); 75 | getInput(); 76 | initSettings(); 77 | if (initFileHelper()) { 78 | loadSettings(); 79 | loadBnWBIOS(); 80 | loadColorBIOS(); 81 | redrawUI(); 82 | } 83 | else { 84 | infoOutput("fatInitDefault() failure."); 85 | } 86 | if (g_BIOSBASE_BNW == NULL) { 87 | installHleBios(biosSpace); 88 | } 89 | if (g_BIOSBASE_COLOR == NULL) { 90 | installHleBios(biosSpaceColor); 91 | } 92 | checkMachine(); 93 | machineInit(); 94 | if (argc > 1) { 95 | loadGame(argv[1]); 96 | setMuteSoundGUI(); 97 | } 98 | 99 | while (1) { 100 | waitVBlank(); 101 | checkTimeOut(); 102 | guiRunLoop(); 103 | if (!pauseEmulation) { 104 | run(); 105 | } 106 | } 107 | return 0; 108 | } 109 | 110 | //--------------------------------------------------------------------------------- 111 | void pausVBlank(int count) { 112 | //--------------------------------------------------------------------------------- 113 | while (--count) { 114 | waitVBlank(); 115 | } 116 | } 117 | 118 | //--------------------------------------------------------------------------------- 119 | void waitVBlank() { 120 | //--------------------------------------------------------------------------------- 121 | // Workaround for bug in Bios. 122 | if (!vBlankOverflow) { 123 | swiIntrWait(1, IRQ_VBLANK); 124 | } 125 | vBlankOverflow = false; 126 | } 127 | 128 | //--------------------------------------------------------------------------------- 129 | static void checkTimeOut() { 130 | //--------------------------------------------------------------------------------- 131 | if (EMUinput) { 132 | sleepTimer = sleepTime; 133 | } 134 | else { 135 | sleepTimer--; 136 | if (sleepTimer < 0) { 137 | sleepTimer = sleepTime; 138 | // systemSleep doesn't work as expected. 139 | //systemSleep(); 140 | } 141 | } 142 | } 143 | 144 | //--------------------------------------------------------------------------------- 145 | void setEmuSpeed(int speed) { 146 | //--------------------------------------------------------------------------------- 147 | if (speed == 0) { // Normal Speed 148 | waitMaskIn = 0x00; 149 | waitMaskOut = 0x00; 150 | } 151 | else if (speed == 1) { // Double speed 152 | waitMaskIn = 0x00; 153 | waitMaskOut = 0x01; 154 | } 155 | else if (speed == 2) { // Max speed (4x) 156 | waitMaskIn = 0x00; 157 | waitMaskOut = 0x03; 158 | } 159 | else if (speed == 3) { // 50% speed 160 | waitMaskIn = 0x01; 161 | waitMaskOut = 0x00; 162 | } 163 | } 164 | 165 | //--------------------------------------------------------------------------------- 166 | static void setupGraphics() { 167 | //--------------------------------------------------------------------------------- 168 | 169 | vramSetBankA(VRAM_A_MAIN_BG); 170 | vramSetBankB(VRAM_B_MAIN_BG_0x06020000); 171 | vramSetBankC(VRAM_C_MAIN_BG_0x06040000); 172 | vramSetBankD(VRAM_D_MAIN_BG_0x06060000); 173 | vramSetBankE(VRAM_E_MAIN_SPRITE); 174 | vramSetBankF(VRAM_F_LCD); 175 | vramSetBankG(VRAM_G_LCD); 176 | vramSetBankH(VRAM_H_SUB_BG); 177 | vramSetBankI(VRAM_I_SUB_SPRITE); 178 | 179 | // Set up the main display 180 | GFX_DISPCNT = MODE_0_2D 181 | | DISPLAY_BG0_ACTIVE 182 | | DISPLAY_BG1_ACTIVE 183 | | DISPLAY_BG2_ACTIVE 184 | | DISPLAY_SPR_ACTIVE 185 | | DISPLAY_WIN0_ON 186 | | DISPLAY_WIN1_ON 187 | ; 188 | videoSetMode(GFX_DISPCNT); 189 | GFX_BG0CNT = BG_32x64 | BG_MAP_BASE(0) | BG_COLOR_16 | BG_TILE_BASE(2) | BG_PRIORITY(0); 190 | GFX_BG1CNT = BG_32x64 | BG_MAP_BASE(0) | BG_COLOR_16 | BG_TILE_BASE(2) | BG_PRIORITY(1); 191 | REG_BG0CNT = GFX_BG0CNT; 192 | REG_BG1CNT = GFX_BG1CNT; 193 | // Background 2 for border 194 | REG_BG2CNT = BG_32x32 | BG_MAP_BASE(2) | BG_COLOR_256 | BG_TILE_BASE(1) | BG_PRIORITY(2); 195 | 196 | // Set up the sub display 197 | videoSetModeSub(MODE_0_2D 198 | | DISPLAY_BG0_ACTIVE 199 | | DISPLAY_BG1_ACTIVE 200 | ); 201 | // Set up two backgrounds for menu 202 | REG_BG0CNT_SUB = BG_COLOR_16 | BG_MAP_BASE(0); 203 | REG_BG1CNT_SUB = BG_COLOR_16 | BG_MAP_BASE(1); 204 | REG_BG1HOFS_SUB = 0; 205 | REG_BG1VOFS_SUB = 0; 206 | map0sub = BG_MAP_RAM_SUB(0); 207 | map1sub = BG_MAP_RAM_SUB(1); 208 | 209 | decompress(NGPBorderTiles, BG_TILE_RAM(1), LZ77Vram); 210 | decompress(NGPBorderMap, BG_MAP_RAM(2), LZ77Vram); 211 | memcpy(EMUPALBUFF, NGPBorderPal, NGPBorderPalLen); 212 | decompress(EmuFontTiles, BG_GFX_SUB+0x1200, LZ77Vram); 213 | setupMenuPalette(); 214 | } 215 | 216 | void setupMenuPalette() { 217 | convertPalette(BG_PALETTE_SUB, guiPalette, sizeof(guiPalette)/3, gGammaValue); 218 | } 219 | 220 | //--------------------------------------------------------------------------------- 221 | static void setupStream(void) { 222 | //--------------------------------------------------------------------------------- 223 | 224 | //---------------------------------------------------------------- 225 | // initialize maxmod without any soundbank (unusual setup) 226 | //---------------------------------------------------------------- 227 | sys.mod_count = 0; 228 | sys.samp_count = 0; 229 | sys.mem_bank = 0; 230 | sys.fifo_channel = FIFO_MAXMOD; 231 | mmInit( &sys ); 232 | 233 | //---------------------------------------------------------------- 234 | // open stream 235 | //---------------------------------------------------------------- 236 | myStream.sampling_rate = sample_rate; // sampling rate = 237 | myStream.buffer_length = buffer_size; // buffer length = 238 | myStream.callback = VblSound2; // set callback function 239 | myStream.format = MM_STREAM_16BIT_STEREO; // format = stereo 16-bit 240 | myStream.timer = MM_TIMER0; // use hardware timer 0 241 | myStream.manual = false; // use manual filling 242 | mmStreamOpen( &myStream ); 243 | 244 | //---------------------------------------------------------------- 245 | // when using 'automatic' filling, your callback will be triggered 246 | // every time half of the wave buffer is processed. 247 | // 248 | // so: 249 | // 25000 (rate) 250 | // ----- = ~21 Hz for a full pass, and ~42hz for half pass 251 | // 1200 (length) 252 | //---------------------------------------------------------------- 253 | // with 'manual' filling, you must call mmStreamUpdate 254 | // periodically (and often enough to avoid buffer underruns) 255 | //---------------------------------------------------------------- 256 | } 257 | -------------------------------------------------------------------------------- /source/Main.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_HEADER 2 | #define MAIN_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern bool gameInserted; 9 | extern u16 *map0sub; 10 | 11 | void waitVBlank(void); 12 | 13 | /** 14 | * Waits the specified number of frames before returning. 15 | * @param count: Number of frames to wait. 16 | * @deprecated Don't use, solve it some other way. 17 | */ 18 | void pausVBlank(int count); 19 | 20 | void setEmuSpeed(int speed); 21 | void setupMenuPalette(void); 22 | 23 | #ifdef __cplusplus 24 | } // extern "C" 25 | #endif 26 | 27 | #endif // MAIN_HEADER 28 | -------------------------------------------------------------------------------- /source/Memory.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_HEADER 2 | #define MEMORY_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | u8 t9LoadBX(u32 address); 9 | u16 t9LoadWX(u32 address); 10 | u32 t9LoadLX(u32 address); 11 | 12 | void t9StoreBX(u8 data, u32 address); 13 | void t9StoreWX(u16 data, u32 address); 14 | void t9StoreLX(u32 data, u32 address); 15 | 16 | #ifdef __cplusplus 17 | } // extern "C" 18 | #endif 19 | 20 | #endif // MEMORY_HEADER 21 | -------------------------------------------------------------------------------- /source/Memory.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "TLCS900H/TLCS900H_mac.h" 4 | #include "ARMZ80/ARMZ80.i" 5 | 6 | .global empty_IO_R 7 | .global empty_IO_W 8 | .global empty_R 9 | .global empty_W 10 | .global rom_W 11 | .global t9StoreBX 12 | .global t9StoreWX 13 | .global t9StoreLX 14 | .global t9LoadBX 15 | .global t9LoadWX 16 | .global t9LoadLX 17 | .global push8 18 | .global t9StoreB_mem 19 | .global push16 20 | .global t9StoreW_mem 21 | .global push32 22 | .global t9StoreL_mem 23 | .global srcExB 24 | .global t9LoadB_mem 25 | .global t9LoadB 26 | .global srcExW 27 | .global t9LoadW_mem 28 | .global t9LoadW 29 | .global srcExL 30 | .global t9LoadL_mem 31 | .global t9LoadL 32 | .global z80RamW 33 | .global z80SoundW 34 | .global z80IrqW 35 | .global z80RamR 36 | 37 | 38 | .syntax unified 39 | .arm 40 | 41 | .section .text 42 | .align 2 43 | ;@---------------------------------------------------------------------------- 44 | empty_IO_R: ;@ Read bad IO address (error) 45 | ;@---------------------------------------------------------------------------- 46 | mov r11,r11 ;@ No$GBA breakpoint 47 | mov r0,#0x10 48 | bx lr 49 | ;@---------------------------------------------------------------------------- 50 | empty_IO_W: ;@ Write bad IO address (error) 51 | ;@---------------------------------------------------------------------------- 52 | mov r11,r11 ;@ No$GBA breakpoint 53 | mov r0,#0x18 54 | bx lr 55 | ;@---------------------------------------------------------------------------- 56 | empty_R: ;@ Read bad address (error) 57 | ;@---------------------------------------------------------------------------- 58 | mov r11,r11 ;@ No$GBA breakpoint 59 | mov r0,#0 60 | mov r1,#0 61 | bx lr 62 | ;@---------------------------------------------------------------------------- 63 | empty_W: ;@ Write bad address (error) 64 | ;@---------------------------------------------------------------------------- 65 | mov r11,r11 ;@ No$GBA breakpoint 66 | mov r0,#0xBA 67 | bx lr 68 | ;@---------------------------------------------------------------------------- 69 | rom_W: ;@ Write ROM address (error) 70 | ;@---------------------------------------------------------------------------- 71 | tst t9Mem,#0xFF000000 72 | bicne t9Mem,t9Mem,#0xFF000000 73 | bne t9StoreB_mem 74 | mov r11,r11 ;@ No$GBA breakpoint 75 | mov r0,#0xB0 76 | bx lr 77 | ;@---------------------------------------------------------------------------- 78 | t9StoreBX: ;@ r0=value, r1=address 79 | .type t9StoreBX STT_FUNC 80 | ;@---------------------------------------------------------------------------- 81 | stmfd sp!,{t9Mem,t9ptr,lr} 82 | ldr t9ptr,=tlcs900HState 83 | mov t9Mem,r1 84 | bl t9StoreB_mem 85 | ldmfd sp!,{t9Mem,t9ptr,lr} 86 | bx lr 87 | ;@---------------------------------------------------------------------------- 88 | t9StoreWX: ;@ r0=value, r1=address 89 | .type t9StoreWX STT_FUNC 90 | ;@---------------------------------------------------------------------------- 91 | stmfd sp!,{t9Mem,t9cycles,t9ptr,lr} 92 | ldr t9ptr,=tlcs900HState 93 | mov t9Mem,r1 94 | bl t9StoreW_mem 95 | ldmfd sp!,{t9Mem,t9cycles,t9ptr,lr} 96 | bx lr 97 | ;@---------------------------------------------------------------------------- 98 | t9StoreLX: ;@ r0=value, r1=address 99 | .type t9StoreLX STT_FUNC 100 | ;@---------------------------------------------------------------------------- 101 | stmfd sp!,{t9Mem,t9cycles,t9ptr,lr} 102 | ldr t9ptr,=tlcs900HState 103 | mov t9Mem,r1 104 | bl t9StoreL_mem 105 | ldmfd sp!,{t9Mem,t9cycles,t9ptr,lr} 106 | bx lr 107 | ;@---------------------------------------------------------------------------- 108 | t9LoadBX: ;@ r0=address 109 | .type t9LoadBX STT_FUNC 110 | ;@---------------------------------------------------------------------------- 111 | stmfd sp!,{t9ptr,lr} 112 | ldr t9ptr,=tlcs900HState 113 | bl t9LoadB 114 | ldmfd sp!,{t9ptr,lr} 115 | bx lr 116 | ;@---------------------------------------------------------------------------- 117 | t9LoadWX: ;@ r0=address 118 | .type t9LoadWX STT_FUNC 119 | ;@---------------------------------------------------------------------------- 120 | stmfd sp!,{t9cycles,t9ptr,lr} 121 | ldr t9ptr,=tlcs900HState 122 | bl t9LoadW 123 | ldmfd sp!,{t9cycles,t9ptr,lr} 124 | bx lr 125 | ;@---------------------------------------------------------------------------- 126 | t9LoadLX: ;@ r0=address 127 | .type t9LoadLX STT_FUNC 128 | ;@---------------------------------------------------------------------------- 129 | stmfd sp!,{t9cycles,t9ptr,lr} 130 | ldr t9ptr,=tlcs900HState 131 | bl t9LoadL 132 | ldmfd sp!,{t9cycles,t9ptr,lr} 133 | bx lr 134 | ;@---------------------------------------------------------------------------- 135 | 136 | #ifdef NDS 137 | .section .itcm ;@ For the NDS ARM9 138 | #elif GBA 139 | .section .iwram, "ax", %progbits ;@ For the GBA 140 | #endif 141 | .align 2 142 | ;@---------------------------------------------------------------------------- 143 | push8: 144 | ;@---------------------------------------------------------------------------- 145 | ldr t9Mem,[t9gprBank,#RXSP] 146 | sub t9Mem,t9Mem,#1 147 | str t9Mem,[t9gprBank,#RXSP] 148 | ;@---------------------------------------------------------------------------- 149 | t9StoreB_mem: ;@ r0=value, t9Mem=address 150 | ;@---------------------------------------------------------------------------- 151 | movs r2,t9Mem,lsr#8 152 | beq t9StoreB_Low 153 | movs r2,r2,lsr#6 154 | cmp r2,#1 155 | beq t9StoreB_ram 156 | cmp r2,#2 157 | beq t9StoreB_vram 158 | mov r2,r2,lsr#7 159 | cmp r2,#1 160 | beq FlashWriteLO 161 | cmp r2,#4 162 | beq FlashWriteHI 163 | bhi rom_W 164 | b empty_W 165 | ;@---------------------------------------------------------------------------- 166 | push16: 167 | ;@---------------------------------------------------------------------------- 168 | ldr t9Mem,[t9gprBank,#RXSP] 169 | sub t9Mem,t9Mem,#2 170 | str t9Mem,[t9gprBank,#RXSP] 171 | ;@---------------------------------------------------------------------------- 172 | t9StoreW_mem: ;@ r0=value, t9Mem=address 173 | ;@---------------------------------------------------------------------------- 174 | tst t9Mem,#1 175 | bne t9StoreUnevenW 176 | t9StoreW_even: 177 | mov r2,t9Mem,lsr#14 178 | cmp r2,#1 179 | beq t9StoreW_ram 180 | cmp r2,#2 181 | beq t9StoreW_vram 182 | 183 | tst t9Mem,#0xFF000000 184 | bicne t9Mem,t9Mem,#0xFF000000 185 | bne t9StoreW_even 186 | ;@---------------------------------------------------------------------------- 187 | t9StoreUnevenW: 188 | ;@---------------------------------------------------------------------------- 189 | t9eatcycles 1 190 | stmfd sp!,{r0,lr} 191 | bl t9StoreB_mem 192 | ldmfd sp!,{r0,lr} 193 | mov r0,r0,lsr#8 194 | add t9Mem,t9Mem,#1 195 | b t9StoreB_mem 196 | ;@---------------------------------------------------------------------------- 197 | push32: ;@ Also used from interrupt 198 | ;@---------------------------------------------------------------------------- 199 | ldr t9Mem,[t9gprBank,#RXSP] 200 | sub t9Mem,t9Mem,#4 201 | str t9Mem,[t9gprBank,#RXSP] 202 | ;@---------------------------------------------------------------------------- 203 | t9StoreL_mem: ;@ r0=value, t9Mem=address 204 | ;@---------------------------------------------------------------------------- 205 | stmfd sp!,{r0,t9Mem,lr} 206 | tst t9Mem,#1 207 | bne t9StoreUnevenL 208 | bl t9StoreW_even 209 | ldmfd sp!,{r0,t9Mem,lr} 210 | mov r0,r0,lsr#16 211 | add t9Mem,t9Mem,#2 212 | b t9StoreW_even 213 | ;@---------------------------------------------------------------------------- 214 | t9StoreUnevenL: 215 | ;@---------------------------------------------------------------------------- 216 | t9eatcycles 1 217 | bl t9StoreB_mem 218 | ldmfd sp,{r0} 219 | mov r0,r0,lsr#8 220 | add t9Mem,t9Mem,#1 221 | bl t9StoreW_even 222 | ldmfd sp!,{r0,t9Mem,lr} 223 | mov r0,r0,lsr#24 224 | add t9Mem,t9Mem,#3 225 | b t9StoreB_mem 226 | ;@---------------------------------------------------------------------------- 227 | t9StoreB_ram: ;@ Write RAM byte (0x004000-0x007FFF) 228 | ;@---------------------------------------------------------------------------- 229 | ldr r2,=ngpRAM-0x4000 230 | strb r0,[r2,t9Mem] 231 | bx lr 232 | ;@---------------------------------------------------------------------------- 233 | t9StoreB_vram: ;@ Write VRAM byte (0x009000-0x00BFFF) 234 | ;@---------------------------------------------------------------------------- 235 | tst t9Mem,#0x007000 236 | beq k2GE_0W 237 | ldr r2,=k2geRAM-0x9000 238 | strb r0,[r2,t9Mem] 239 | ldr r2,=DIRTYTILES-0x900 240 | mov r1,#0 241 | strb r1,[r2,t9Mem,lsr#4] ;@ Each dirty byte is 0x10 VRAM bytes 242 | bx lr 243 | ;@---------------------------------------------------------------------------- 244 | t9StoreW_ram: ;@ Write RAM word (0x004000-0x007FFF) 245 | ;@---------------------------------------------------------------------------- 246 | ldr r2,=ngpRAM-0x4000 247 | strh r0,[r2,t9Mem] 248 | bx lr 249 | ;@---------------------------------------------------------------------------- 250 | t9StoreW_vram: ;@ Write VRAM word (0x009000-0x00BFFF) 251 | ;@---------------------------------------------------------------------------- 252 | tst t9Mem,#0x007000 253 | beq k2GE_0W_W 254 | ldr r2,=k2geRAM-0x9000 255 | strh r0,[r2,t9Mem] 256 | ldr r2,=DIRTYTILES-0x900 257 | mov r1,#0 258 | strb r1,[r2,t9Mem,lsr#4] ;@ Each dirty byte is 0x10 VRAM bytes 259 | bx lr 260 | ;@---------------------------------------------------------------------------- 261 | //srcExB: 262 | ;@---------------------------------------------------------------------------- 263 | // Room for most used srcExB code 264 | ;@---------------------------------------------------------------------------- 265 | srcExB: 266 | ;@---------------------------------------------------------------------------- 267 | ldrb r0,[t9pc],#1 268 | add r1,t9ptr,#tlcsSrcOpCodesB 269 | and t9Reg,r0,#0x07 270 | ldr lr,[r1,r0,lsl#2] 271 | ;@---------------------------------------------------------------------------- 272 | t9LoadB_mem: 273 | ;@---------------------------------------------------------------------------- 274 | bic r0,t9Mem,#0xFF000000 275 | ;@---------------------------------------------------------------------------- 276 | t9LoadB: ;@ r0=address 277 | ;@---------------------------------------------------------------------------- 278 | movs r2,r0,lsr#8 279 | beq t9LoadB_Low 280 | movs r2,r2,lsr#6 281 | cmp r2,#1 282 | beq tlcs_ram_R 283 | cmp r2,#2 284 | beq tlcs_vram_R 285 | mov r2,r2,lsr#7 286 | cmp r2,#1 287 | beq FlashReadByteLo 288 | cmp r2,#4 289 | beq FlashReadByteHi 290 | cmp r2,#7 291 | beq tlcs_bios_R 292 | b empty_R 293 | ;@---------------------------------------------------------------------------- 294 | //srcExW: 295 | ;@---------------------------------------------------------------------------- 296 | // Room for most used srcExW code 297 | ;@---------------------------------------------------------------------------- 298 | srcExW: 299 | ;@---------------------------------------------------------------------------- 300 | ldrb r0,[t9pc],#1 301 | add r1,t9ptr,#tlcsSrcOpCodesW 302 | and t9Reg,r0,#0x07 303 | ldr lr,[r1,r0,lsl#2] 304 | ;@---------------------------------------------------------------------------- 305 | t9LoadW_mem: 306 | ;@---------------------------------------------------------------------------- 307 | bic r0,t9Mem,#0xFF000000 308 | ;@---------------------------------------------------------------------------- 309 | t9LoadW: ;@ r0=address 310 | ;@---------------------------------------------------------------------------- 311 | tst r0,#1 312 | bne t9LoadUnevenW 313 | t9LoadEvenW: ;@ r0=address 314 | movs r2,r0,lsr#8 315 | beq t9LoadWAsB 316 | movs r2,r2,lsr#6 317 | cmp r2,#1 318 | beq tlcs_ram_W_R 319 | cmp r2,#2 320 | beq tlcs_vram_W_R 321 | mov r2,r2,lsr#7 322 | cmp r2,#1 323 | beq FlashReadWordLo 324 | cmp r2,#4 325 | beq FlashReadWordHi 326 | cmp r2,#7 327 | beq tlcs_bios_W_R 328 | b t9LoadWAsB 329 | ;@---------------------------------------------------------------------------- 330 | t9LoadUnevenW: ;@ r0=address 331 | ;@---------------------------------------------------------------------------- 332 | t9eatcycles 1 333 | ;@---------------------------------------------------------------------------- 334 | t9LoadWAsB: ;@ r0=address 335 | ;@---------------------------------------------------------------------------- 336 | stmfd sp!,{r4,lr} 337 | mov r3,r0 338 | bl t9LoadB 339 | mov r4,r0 340 | add r0,r3,#1 341 | bl t9LoadB 342 | orr r0,r4,r0,lsl#8 343 | ldmfd sp!,{r4,lr} 344 | bx lr 345 | ;@---------------------------------------------------------------------------- 346 | //srcExL: 347 | ;@---------------------------------------------------------------------------- 348 | // Room for most used srcExL code 349 | ;@---------------------------------------------------------------------------- 350 | srcExL: 351 | ;@---------------------------------------------------------------------------- 352 | ldrb r0,[t9pc],#1 353 | add r1,t9ptr,#tlcsSrcOpCodesL 354 | and t9Reg,r0,#0x07 355 | ldr lr,[r1,r0,lsl#2] 356 | ;@---------------------------------------------------------------------------- 357 | t9LoadL_mem: 358 | ;@---------------------------------------------------------------------------- 359 | bic r0,t9Mem,#0xFF000000 360 | ;@---------------------------------------------------------------------------- 361 | t9LoadL: ;@ r0=address 362 | ;@---------------------------------------------------------------------------- 363 | stmfd sp!,{r4,r5,lr} 364 | tst r0,#1 365 | bne t9LoadUnevenL 366 | mov r5,r0 367 | bl t9LoadEvenW 368 | mov r4,r0 369 | add r0,r5,#2 370 | bl t9LoadEvenW 371 | orr r0,r4,r0,lsl#16 372 | ldmfd sp!,{r4,r5,lr} 373 | bx lr 374 | ;@---------------------------------------------------------------------------- 375 | t9LoadUnevenL: ;@ r0=address 376 | ;@---------------------------------------------------------------------------- 377 | t9eatcycles 1 378 | mov r5,r0 379 | bl t9LoadB 380 | mov r4,r0 381 | add r0,r5,#1 382 | bl t9LoadEvenW 383 | orr r4,r4,r0,lsl#8 384 | add r0,r5,#3 385 | bl t9LoadB 386 | orr r0,r4,r0,lsl#24 387 | ldmfd sp!,{r4,r5,lr} 388 | bx lr 389 | ;@---------------------------------------------------------------------------- 390 | tlcs_ram_R: ;@ Read RAM byte (0x004000-0x007FFF) 391 | ;@---------------------------------------------------------------------------- 392 | ldr r1,=ngpRAM-0x4000 393 | ldrb r0,[r1,r0]! 394 | bx lr 395 | ;@---------------------------------------------------------------------------- 396 | tlcs_vram_R: ;@ Read VRAM byte (0x009000-0x00BFFF) 397 | ;@---------------------------------------------------------------------------- 398 | tst r0,#0x007000 399 | beq k2GE_0R 400 | ldr r1,=k2geRAM-0x9000 401 | ldrb r0,[r1,r0]! 402 | bx lr 403 | ;@---------------------------------------------------------------------------- 404 | tlcs_bios_R: ;@ Read BIOS byte (0xFF0000-0xFFFFFF) 405 | ;@---------------------------------------------------------------------------- 406 | ldr r1,[t9ptr,#biosBase] 407 | ldrb r0,[r1,r0]! 408 | bx lr 409 | 410 | ;@---------------------------------------------------------------------------- 411 | tlcs_ram_W_R: ;@ Read RAM word (0x004000-0x007FFF) 412 | ;@---------------------------------------------------------------------------- 413 | ldr r1,=ngpRAM-0x4000 414 | ldrh r0,[r1,r0] 415 | bx lr 416 | ;@---------------------------------------------------------------------------- 417 | tlcs_vram_W_R: ;@ Read VRAM word (0x009000-0x00BFFF) 418 | ;@---------------------------------------------------------------------------- 419 | tst r0,#0x007000 420 | beq k2GE_0R_W 421 | ldr r1,=k2geRAM-0x9000 422 | ldrh r0,[r1,r0] 423 | bx lr 424 | ;@---------------------------------------------------------------------------- 425 | tlcs_bios_W_R: ;@ Read BIOS word (0xFF0000-0xFFFFFF) 426 | ;@---------------------------------------------------------------------------- 427 | ldr r1,[t9ptr,#biosBase] 428 | ldrh r0,[r1,r0] 429 | bx lr 430 | 431 | ;@---------------------------------------------------------------------------- 432 | z80RamW: ;@ Write mem (0x0000-0x0FFF) 433 | ;@---------------------------------------------------------------------------- 434 | cmp addy,#0x1000 435 | ldrmi r1,=ngpRAM+0x3000 436 | strbmi r0,[r1,addy] 437 | bxmi lr 438 | b empty_W 439 | ;@---------------------------------------------------------------------------- 440 | z80RamR: ;@ Read Ram (0x0000-0x0FFF) 441 | ;@---------------------------------------------------------------------------- 442 | cmp addy,#0x1000 443 | ldrmi r1,=ngpRAM+0x3000 444 | ldrbmi r0,[r1,addy] 445 | bxmi lr 446 | b empty_R 447 | ;@---------------------------------------------------------------------------- 448 | z80SoundW: ;@ Write mem (0x4000-0x4001) 449 | ;@---------------------------------------------------------------------------- 450 | mov r1,#0x4000 451 | cmp addy,r1 ;@ 0x4000, sound Right 452 | beq T6W28_R_W 453 | add r1,r1,#1 ;@ 0x4001, sound Left 454 | cmp addy,r1 455 | beq T6W28_L_W 456 | b empty_W 457 | ;@---------------------------------------------------------------------------- 458 | z80IrqW: ;@ Write mem (0xC000) 459 | ;@---------------------------------------------------------------------------- 460 | cmp addy,#0xC000 461 | bne empty_W 462 | stmfd sp!,{r3,lr} 463 | mov r0,#0x0C ;@ This must load up tlcs900 regs before executing. 464 | bl setInterruptExternal 465 | ldmfd sp!,{r3,lr} 466 | bx lr 467 | 468 | ;@---------------------------------------------------------------------------- 469 | .end 470 | #endif // #ifdef __arm__ 471 | -------------------------------------------------------------------------------- /source/NGPHeader.h: -------------------------------------------------------------------------------- 1 | #ifndef NGPHEADER 2 | #define NGPHEADER 3 | 4 | /// NgpHeader 5 | typedef struct 6 | { 7 | const char licence[28]; // 0x00 - 0x1B 8 | const u32 startPC; // 0x1C - 0x1F 9 | const u16 catalog; // 0x20 - 0x21 10 | const u8 subCatalog; // 0x22 11 | const u8 mode; // 0x23, 0x00 = B&W, 0x10 = Color. 12 | const char name[12]; // 0x24 - 0x2F 13 | 14 | const u32 reserved1; // 0x30 - 0x33 15 | const u32 reserved2; // 0x34 - 0x37 16 | const u32 reserved3; // 0x38 - 0x3B 17 | const u32 reserved4; // 0x3C - 0x3F 18 | } NgpHeader; 19 | 20 | #endif // NGPHEADER 21 | -------------------------------------------------------------------------------- /source/NeoGeoPocket.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "NeoGeoPocket.h" 4 | #include "Cart.h" 5 | #include "Gfx.h" 6 | #include "Sound.h" 7 | #include "io.h" 8 | #include "TLCS900H/TLCS900H.h" 9 | #include "ARMZ80/ARMZ80.h" 10 | 11 | 12 | int packState(void *statePtr) { 13 | int size = 0; 14 | memcpy(statePtr+size, ngpRAM, sizeof(ngpRAM)); 15 | size += sizeof(ngpRAM); 16 | size += ioSaveState(statePtr+size); 17 | size += sn76496SaveState(statePtr+size, &k2Audio_0); 18 | size += k2GESaveState(statePtr+size, &k2GE_0); 19 | size += Z80SaveState(statePtr+size, &Z80OpTable); 20 | size += tlcs900HSaveState(statePtr+size, &tlcs900HState); 21 | return size; 22 | } 23 | 24 | void unpackState(const void *statePtr) { 25 | int size = 0; 26 | memcpy(ngpRAM, statePtr+size, sizeof(ngpRAM)); 27 | size += sizeof(ngpRAM); 28 | size += ioLoadState(statePtr+size); 29 | size += sn76496LoadState(&k2Audio_0, statePtr+size); 30 | size += k2GELoadState(&k2GE_0, statePtr+size); 31 | size += Z80LoadState(&Z80OpTable, statePtr+size); 32 | tlcs900HLoadState(&tlcs900HState, statePtr+size); 33 | } 34 | 35 | int getStateSize() { 36 | int size = 0; 37 | size += sizeof(ngpRAM); 38 | size += ioGetStateSize(); 39 | size += sn76496GetStateSize(); 40 | size += k2GEGetStateSize(); 41 | size += Z80GetStateSize(); 42 | size += tlcs900HGetStateSize(); 43 | return size; 44 | } 45 | -------------------------------------------------------------------------------- /source/NeoGeoPocket.h: -------------------------------------------------------------------------------- 1 | #ifndef NEOGEOPOCKET_HEADER 2 | #define NEOGEOPOCKET_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /// This runs all save state functions for each chip. 9 | int packState(void *statePtr); 10 | 11 | /// This runs all load state functions for each chip. 12 | void unpackState(const void *statePtr); 13 | 14 | /// Gets the total state size in bytes. 15 | int getStateSize(void); 16 | 17 | #ifdef __cplusplus 18 | } // extern "C" 19 | #endif 20 | 21 | #endif // NEOGEOPOCKET_HEADER 22 | -------------------------------------------------------------------------------- /source/Sound.h: -------------------------------------------------------------------------------- 1 | #ifndef SOUND_HEADER 2 | #define SOUND_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "K2Audio/SN76496.h" 10 | 11 | #define sample_rate 48000 12 | #define buffer_size (800*2) 13 | 14 | extern SN76496 k2Audio_0; 15 | 16 | void soundInit(void); 17 | void setMuteSoundGUI(void); 18 | mm_word VblSound2(mm_word length, mm_addr dest, mm_stream_formats format); 19 | 20 | #ifdef __cplusplus 21 | } // extern "C" 22 | #endif 23 | 24 | #endif // SOUND_HEADER 25 | -------------------------------------------------------------------------------- /source/Sound.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "K2Audio/SN76496.i" 4 | 5 | .extern pauseEmulation 6 | 7 | .global k2Audio_0 8 | 9 | .global soundInit 10 | .global soundReset 11 | .global VblSound2 12 | .global setMuteSoundGUI 13 | .global setMuteT6W28 14 | .global soundUpdate 15 | .global T6W28_R_W 16 | .global T6W28_L_W 17 | .global T6W28_DAC_L_W 18 | .global T6W28_DAC_R_W 19 | 20 | #define WAV_BUFFER_SIZE (0x800) 21 | #define SHIFTVAL (21) 22 | 23 | ;@---------------------------------------------------------------------------- 24 | 25 | .syntax unified 26 | .arm 27 | 28 | .section .text 29 | .align 2 30 | ;@---------------------------------------------------------------------------- 31 | soundInit: 32 | .type soundInit STT_FUNC 33 | ;@---------------------------------------------------------------------------- 34 | // stmfd sp!,{lr} 35 | 36 | // ldmfd sp!,{lr} 37 | // bx lr 38 | 39 | ;@---------------------------------------------------------------------------- 40 | soundReset: 41 | ;@---------------------------------------------------------------------------- 42 | stmfd sp!,{lr} 43 | ldr r0,=k2Audio_0 44 | bl sn76496Reset ;@ sound 45 | ldmfd sp!,{lr} 46 | bx lr 47 | 48 | ;@---------------------------------------------------------------------------- 49 | setMuteSoundGUI: 50 | .type setMuteSoundGUI STT_FUNC 51 | ;@---------------------------------------------------------------------------- 52 | ldr r1,=pauseEmulation ;@ Output silence when emulation paused. 53 | ldrb r0,[r1] 54 | strb r0,muteSoundGUI 55 | bx lr 56 | ;@---------------------------------------------------------------------------- 57 | setMuteT6W28: 58 | ;@---------------------------------------------------------------------------- 59 | and r0,r0,#0xFF 60 | cmp r0,#0xAA 61 | cmpne r0,#0x55 62 | andeq r0,r0,#0xAA 63 | strbeq r0,muteSoundChip 64 | bx lr 65 | ;@---------------------------------------------------------------------------- 66 | VblSound2: ;@ r0=length, r1=pointer 67 | ;@---------------------------------------------------------------------------- 68 | ;@ mov r11,r11 69 | ldr r2,muteSound 70 | tst r2,#0x00FF 71 | bne silenceMix 72 | tst r2,#0xFF00 73 | bne playSamples 74 | 75 | stmfd sp!,{r0,lr} 76 | ldr r2,=k2Audio_0 77 | bl sn76496Mixer 78 | ldmfd sp!,{r0,lr} 79 | bx lr 80 | 81 | playSamples: 82 | stmfd sp!,{r0,lr} 83 | ldr r12,pcmWritePtr 84 | sub r12,r12,r0,lsr#2 85 | ldr r2,=WAVBUFFER 86 | mov r12,r12,lsl#SHIFTVAL 87 | wavLoop: 88 | ldrb r3,[r2,r12,lsr#SHIFTVAL-1] 89 | // ldrb lr,[r2,r12,lsr#SHIFTVAL-1] 90 | eor r3,r3,#0x80 91 | mov r3,r3,lsl#8 92 | orr r3,r3,r3,lsl#16 93 | str r3,[r1],#4 94 | str r3,[r1],#4 95 | str r3,[r1],#4 96 | str r3,[r1],#4 97 | add r12,r12,#1< 10 | 11 | #include "Memory.h" 12 | #include "Cart.h" 13 | #include "bios.h" 14 | #include "K2GE/K2GE.h" 15 | #include "Shared/EmuMenu.h" 16 | #include "FileHandling.h" 17 | #include "TLCS900H/TLCS900H.h" 18 | 19 | extern void sngBIOSHLE(void); // From AsmHleBios.s 20 | 21 | //============================================================================= 22 | 23 | static const u8 font[0x800] = { 24 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 25 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 26 | 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00, 27 | 0x00,0x00,0x00,0xF8,0xF8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 28 | 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, 29 | 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, 30 | 0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, 31 | 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 32 | 33 | 0x20,0x30,0x38,0x3C,0x38,0x30,0x20,0x00,0x04,0x0C,0x1C,0x3C,0x1C,0x0C,0x04,0x00, 34 | 0x00,0x00,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x00,0x00, 35 | 0x20,0x3C,0x08,0x3C,0x28,0x7E,0x08,0x00,0x3C,0x24,0x3C,0x24,0x3C,0x24,0x24,0x00, 36 | 0x3C,0x24,0x24,0x3C,0x24,0x24,0x3C,0x00,0x10,0x10,0x54,0x54,0x10,0x28,0xC6,0x00, 37 | 0x10,0x12,0xD4,0x58,0x54,0x92,0x10,0x00,0x10,0x10,0x7C,0x10,0x38,0x54,0x92,0x00, 38 | 0x10,0x28,0x7C,0x92,0x38,0x54,0xFE,0x00,0x10,0x10,0x10,0x7C,0x10,0x10,0xFE,0x00, 39 | 0x7F,0xFF,0xE0,0xFF,0x7F,0x01,0xFF,0xFF,0xDC,0xDE,0x1F,0x9F,0xDF,0xDD,0xDC,0x9C, 40 | 0x3B,0x3B,0x3B,0xBB,0xFB,0xFB,0xFB,0x7B,0x8F,0x9E,0xBC,0xF8,0xF8,0xBC,0x9E,0x8F, 41 | 42 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x08,0x10,0x00,0x18,0x00, 43 | 0x6C,0x6C,0x24,0x48,0x00,0x00,0x00,0x00,0x14,0x14,0xFE,0x28,0xFE,0x50,0x50,0x00, 44 | 0x10,0x7C,0x90,0x7C,0x12,0xFC,0x10,0x00,0x42,0xA4,0xA8,0x54,0x2A,0x4A,0x84,0x00, 45 | 0x30,0x48,0x38,0x62,0x94,0x88,0x76,0x00,0x18,0x18,0x08,0x10,0x00,0x00,0x00,0x00, 46 | 0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00,0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00, 47 | 0x10,0x92,0x54,0x38,0x38,0x54,0x92,0x00,0x10,0x10,0x10,0xFE,0x10,0x10,0x10,0x00, 48 | 0x00,0x00,0x00,0x30,0x30,0x10,0x20,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00, 49 | 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00, 50 | 51 | 0x3C,0x42,0x46,0x5A,0x62,0x42,0x3C,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x00, 52 | 0x3C,0x42,0x42,0x0C,0x30,0x40,0x7E,0x00,0x3C,0x42,0x02,0x1C,0x02,0x42,0x3C,0x00, 53 | 0x0C,0x14,0x24,0x44,0x7E,0x04,0x04,0x00,0x7E,0x40,0x7C,0x02,0x02,0x42,0x3C,0x00, 54 | 0x3C,0x40,0x7C,0x42,0x42,0x42,0x3C,0x00,0x7E,0x02,0x04,0x08,0x08,0x10,0x10,0x00, 55 | 0x3C,0x42,0x42,0x3C,0x42,0x42,0x3C,0x00,0x3C,0x42,0x42,0x42,0x3E,0x02,0x3C,0x00, 56 | 0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x08,0x10,0x00, 57 | 0x00,0x08,0x10,0x20,0x10,0x08,0x00,0x00,0x00,0x00,0x3C,0x00,0x3C,0x00,0x00,0x00, 58 | 0x00,0x10,0x08,0x04,0x08,0x10,0x00,0x00,0x3C,0x62,0x62,0x0C,0x18,0x00,0x18,0x00, 59 | 60 | 0x7C,0x82,0xBA,0xA2,0xBA,0x82,0x7C,0x00,0x10,0x28,0x28,0x44,0x7C,0x82,0x82,0x00, 61 | 0x7C,0x42,0x42,0x7C,0x42,0x42,0x7C,0x00,0x1C,0x22,0x40,0x40,0x40,0x22,0x1C,0x00, 62 | 0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x00,0x7E,0x40,0x40,0x7E,0x40,0x40,0x7E,0x00, 63 | 0x7E,0x40,0x40,0x7C,0x40,0x40,0x40,0x00,0x3C,0x42,0x80,0x9E,0x82,0x46,0x3A,0x00, 64 | 0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, 65 | 0x02,0x02,0x02,0x02,0x42,0x42,0x3C,0x00,0x42,0x44,0x48,0x50,0x68,0x44,0x42,0x00, 66 | 0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x82,0xC6,0xAA,0x92,0x82,0x82,0x82,0x00, 67 | 0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x00,0x38,0x44,0x82,0x82,0x82,0x44,0x38,0x00, 68 | 69 | 0x7C,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x38,0x44,0x82,0x82,0x8A,0x44,0x3A,0x00, 70 | 0x7C,0x42,0x42,0x7C,0x48,0x44,0x42,0x00,0x3C,0x42,0x40,0x3C,0x02,0x42,0x3C,0x00, 71 | 0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00, 72 | 0x82,0x82,0x44,0x44,0x28,0x28,0x10,0x00,0x82,0x92,0x92,0xAA,0xAA,0x44,0x44,0x00, 73 | 0x82,0x44,0x28,0x10,0x28,0x44,0x82,0x00,0x82,0x44,0x28,0x10,0x10,0x10,0x10,0x00, 74 | 0x7E,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x18,0x10,0x10,0x10,0x10,0x10,0x18,0x00, 75 | 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x18,0x00, 76 | 0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00, 77 | 78 | 0x08,0x10,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x78,0x04,0x7C,0x84,0x84,0x7E,0x00, 79 | 0x40,0x40,0x7C,0x42,0x42,0x42,0x3C,0x00,0x00,0x00,0x3C,0x42,0x40,0x42,0x3C,0x00, 80 | 0x02,0x02,0x3E,0x42,0x42,0x42,0x3C,0x00,0x00,0x00,0x3C,0x42,0x7E,0x40,0x3E,0x00, 81 | 0x0C,0x10,0x3E,0x10,0x10,0x10,0x10,0x00,0x00,0x3C,0x42,0x42,0x3E,0x02,0x7C,0x00, 82 | 0x40,0x40,0x7C,0x42,0x42,0x42,0x42,0x00,0x18,0x18,0x00,0x08,0x08,0x08,0x08,0x00, 83 | 0x06,0x06,0x00,0x02,0x42,0x42,0x3C,0x00,0x20,0x20,0x26,0x28,0x30,0x28,0x26,0x00, 84 | 0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x80,0xEC,0x92,0x92,0x92,0x92,0x00, 85 | 0x00,0x40,0x78,0x44,0x44,0x44,0x44,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x00, 86 | 87 | 0x00,0x3C,0x42,0x42,0x7C,0x40,0x40,0x00,0x00,0x78,0x84,0x84,0x7C,0x04,0x06,0x00, 88 | 0x00,0x00,0x5C,0x62,0x40,0x40,0x40,0x00,0x00,0x00,0x3E,0x40,0x3C,0x02,0x7C,0x00, 89 | 0x00,0x10,0x7C,0x10,0x10,0x10,0x0E,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x3F,0x00, 90 | 0x00,0x00,0x42,0x42,0x24,0x24,0x18,0x00,0x00,0x00,0x92,0x92,0x92,0x92,0x6C,0x00, 91 | 0x00,0x00,0x42,0x24,0x18,0x24,0x42,0x00,0x00,0x00,0x42,0x42,0x3E,0x02,0x7C,0x00, 92 | 0x00,0x00,0x7E,0x02,0x3C,0x40,0x7E,0x00,0x08,0x10,0x10,0x20,0x10,0x10,0x08,0x00, 93 | 0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x00,0x20,0x10,0x10,0x08,0x10,0x10,0x20,0x00, 94 | 0x00,0x00,0x60,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 95 | 96 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x90,0x90,0x60,0x00, 97 | 0x1E,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0xF0,0x00, 98 | 0x00,0x00,0x00,0x80,0x40,0x60,0x60,0x00,0x00,0x00,0x00,0x30,0x78,0x30,0x00,0x00, 99 | 0x20,0xF8,0x26,0x78,0xD0,0x80,0x7C,0x00,0x00,0x10,0x3A,0x1C,0x36,0x5A,0x36,0x00, 100 | 0x00,0x00,0x44,0x42,0x42,0x42,0x30,0x00,0x00,0x3C,0x00,0x3C,0x42,0x02,0x3C,0x00, 101 | 0x00,0x3C,0x00,0x7C,0x08,0x38,0x66,0x00,0x00,0x14,0x72,0x1C,0x32,0x52,0x34,0x00, 102 | 0x00,0x28,0x2C,0x3A,0x62,0x16,0x10,0x00,0x00,0x08,0x5C,0x6A,0x4A,0x0C,0x18,0x00, 103 | 0x00,0x08,0x0C,0x38,0x4C,0x4A,0x38,0x00,0x00,0x00,0x00,0x1C,0x62,0x02,0x1C,0x00, 104 | 105 | 0x00,0x00,0x80,0x7E,0x00,0x00,0x00,0x00,0x28,0xF2,0x3C,0x6A,0xAA,0xB6,0xEC,0x00, 106 | 0x80,0x88,0x84,0x84,0x82,0x92,0x70,0x00,0x78,0x00,0x3C,0xC2,0x02,0x04,0x78,0x00, 107 | 0x78,0x00,0xFC,0x08,0x30,0x50,0x9E,0x00,0x2C,0xF2,0x20,0x7C,0xA2,0xA2,0xE4,0x00, 108 | 0x28,0xF4,0x2A,0x4A,0x4A,0x88,0xB0,0x00,0x20,0xFC,0x12,0xFC,0x08,0xC2,0x7C,0x00, 109 | 0x04,0x18,0x60,0x80,0xC0,0x30,0x0E,0x00,0x84,0xBE,0x84,0x84,0x84,0x84,0x58,0x00, 110 | 0x00,0x7C,0x02,0x00,0x80,0x82,0x7E,0x00,0x20,0xFE,0x10,0x78,0x8C,0xC0,0x7C,0x00, 111 | 0x80,0x80,0x80,0x80,0x82,0x84,0x78,0x00,0x04,0xFE,0x3C,0x44,0x7C,0x04,0x78,0x00, 112 | 0x44,0x5E,0xF4,0x44,0x48,0x40,0x3E,0x00,0x44,0x58,0xE0,0x3E,0xC0,0x40,0x3C,0x00, 113 | 114 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x90,0x90,0x60,0x00, 115 | 0x1E,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0xF0,0x00, 116 | 0x00,0x00,0x00,0x80,0x40,0x60,0x60,0x00,0x00,0x00,0x00,0x30,0x78,0x30,0x00,0x00, 117 | 0x1E,0x62,0x1E,0x62,0x04,0x0C,0x30,0x00,0x00,0x00,0x1E,0x6A,0x0E,0x08,0x18,0x00, 118 | 0x00,0x00,0x06,0x18,0x68,0x08,0x08,0x00,0x00,0x10,0x1C,0x72,0x42,0x04,0x38,0x00, 119 | 0x00,0x00,0x0C,0x78,0x10,0x10,0x7E,0x00,0x00,0x08,0x08,0x7C,0x18,0x28,0x48,0x00, 120 | 0x00,0x00,0x26,0x1A,0x72,0x10,0x08,0x00,0x00,0x00,0x0C,0x34,0x04,0x08,0x7E,0x00, 121 | 0x00,0x00,0x78,0x04,0x3C,0x04,0x78,0x00,0x00,0x00,0x52,0x4A,0x22,0x04,0x38,0x00, 122 | 123 | 0x00,0x00,0x80,0x7E,0x00,0x00,0x00,0x00,0x3C,0xC2,0x14,0x1C,0x10,0x30,0x60,0x00, 124 | 0x02,0x0C,0x38,0xC8,0x08,0x08,0x08,0x00,0x60,0x3C,0xE2,0x82,0x82,0x04,0x38,0x00, 125 | 0x00,0x1C,0x70,0x10,0x10,0x1C,0xE2,0x00,0x08,0xFE,0x18,0x38,0x68,0xC8,0x18,0x00, 126 | 0x10,0x3E,0xD2,0x12,0x22,0x62,0xCC,0x00,0x20,0x3C,0xF0,0x1E,0xF0,0x08,0x08,0x00, 127 | 0x10,0x3E,0x62,0xC2,0x04,0x0C,0x70,0x00,0x40,0x7E,0x44,0x84,0x84,0x08,0x30,0x00, 128 | 0x3E,0xC2,0x02,0x02,0x02,0x02,0xFC,0x00,0x44,0x5E,0xE4,0x44,0x44,0x08,0xF0,0x00, 129 | 0x60,0x12,0xC2,0x22,0x04,0x04,0xF8,0x00,0x3C,0xC6,0x0C,0x08,0x38,0x6C,0xC6,0x00, 130 | 0x40,0x4E,0x72,0xC4,0x4C,0x40,0x3E,0x00,0x82,0x42,0x62,0x04,0x04,0x08,0x70,0x00, 131 | 132 | 0x3C,0x42,0x72,0x8A,0x04,0x0C,0x70,0x00,0x0C,0xF8,0x10,0xFE,0x10,0x10,0x60,0x00, 133 | 0x22,0xA2,0x92,0x42,0x04,0x08,0x70,0x00,0x3C,0x40,0x1E,0xE8,0x08,0x10,0x60,0x00, 134 | 0x40,0x40,0x70,0x4C,0x42,0x40,0x40,0x00,0x08,0x3E,0xC8,0x08,0x08,0x18,0x70,0x00, 135 | 0x00,0x1C,0x60,0x00,0x00,0x3C,0xC2,0x00,0x3C,0xC2,0x26,0x38,0x1C,0x36,0xE2,0x00, 136 | 0x10,0x3C,0xC6,0x1C,0x38,0xD6,0x12,0x00,0x02,0x02,0x02,0x06,0x04,0x1C,0xF0,0x00, 137 | 0x18,0x4C,0x44,0x46,0x42,0x82,0x82,0x00,0x80,0x86,0xBC,0xE0,0x80,0x80,0x7E,0x00, 138 | 0x3C,0xC2,0x02,0x02,0x04,0x08,0x30,0x00,0x30,0x48,0x4C,0x84,0x86,0x02,0x02,0x00, 139 | 0x10,0xFE,0x10,0x54,0x52,0x92,0x92,0x00,0x3C,0xC2,0x02,0x44,0x28,0x10,0x0C,0x00, 140 | 141 | 0x70,0x0C,0x60,0x18,0xC4,0x30,0x0E,0x00,0x30,0x40,0x4C,0x84,0x8E,0xBA,0x62,0x00, 142 | 0x04,0x04,0x64,0x18,0x0C,0x16,0xE2,0x00,0x1C,0xE0,0x3E,0xE0,0x20,0x20,0x1E,0x00, 143 | 0x4E,0x52,0x62,0xE4,0x20,0x10,0x18,0x00,0x1C,0x64,0x04,0x08,0x08,0x10,0xFE,0x00, 144 | 0x1C,0x62,0x02,0x3E,0x02,0x02,0x7C,0x00,0x3C,0xC0,0x3E,0xC2,0x02,0x04,0x78,0x00, 145 | 0x44,0x42,0x42,0x42,0x22,0x04,0x78,0x00,0x50,0x50,0x52,0x52,0x52,0x54,0x88,0x00, 146 | 0x80,0x80,0x82,0x82,0x84,0x88,0xF0,0x00,0x1C,0xE2,0x82,0x82,0x82,0x4C,0x74,0x00, 147 | 0x3C,0xC2,0x82,0x82,0x02,0x04,0x38,0x00,0xC0,0x62,0x22,0x02,0x04,0x08,0xF0,0x00, 148 | 0x00,0x00,0x00,0x00,0x0A,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x02,0x00, 149 | 150 | 0x20,0xF8,0x40,0x5E,0x80,0xA0,0x9E,0x00,0x20,0xFE,0x40,0x7C,0xC2,0x86,0x3C,0x00, 151 | 0x00,0x3C,0xC6,0x02,0x02,0x0C,0x38,0x00,0x0E,0xF8,0x10,0x20,0x20,0x10,0x0E,0x00, 152 | 0x40,0x4C,0x30,0x40,0x80,0x80,0x7E,0x00,0x44,0xF2,0x4A,0x9C,0xA4,0xA6,0x3A,0x00, 153 | 0x40,0x5C,0x82,0x80,0xA0,0xA0,0x9E,0x00,0x48,0x7C,0x52,0xB2,0xBE,0xAA,0x4C,0x00, 154 | 0x20,0xFC,0x32,0x62,0xEE,0xAA,0x2C,0x00,0x38,0x54,0x92,0x92,0xB2,0xA2,0x4C,0x00, 155 | 0x44,0x5E,0x84,0x9C,0xA4,0xA6,0x9C,0x00,0x28,0xEE,0x44,0x84,0x84,0x44,0x38,0x00, 156 | 0x78,0x10,0x64,0x34,0x8A,0x8A,0x30,0x00,0x30,0x58,0x48,0x84,0x84,0x02,0x02,0x00, 157 | 0xBC,0x88,0xBE,0x84,0xBC,0xA6,0x9C,0x00,0x68,0x1E,0x68,0x1E,0x78,0x8C,0x7A,0x00, 158 | 159 | 0x70,0x14,0x7C,0x96,0x94,0x94,0x68,0x00,0x2C,0xF2,0x60,0xA0,0xA2,0xC2,0x7C,0x00, 160 | 0x48,0x7C,0x6A,0xAA,0xB2,0xB2,0x6C,0x00,0x10,0xF8,0x20,0xF8,0x22,0x22,0x1C,0x00, 161 | 0x48,0x5C,0x6A,0xC2,0x64,0x20,0x18,0x00,0x10,0xBC,0xD6,0xCA,0xAA,0x1C,0x70,0x00, 162 | 0x10,0x1C,0x12,0x70,0x9C,0x92,0x70,0x00,0xE0,0x18,0x40,0x7C,0xC2,0x82,0x3C,0x00, 163 | 0x44,0x42,0x82,0xA2,0x62,0x04,0x78,0x00,0x7C,0x38,0x7C,0xC2,0xBA,0x26,0x3C,0x00, 164 | 0x48,0xD4,0x64,0x64,0xC4,0xC4,0x46,0x00,0x7C,0x30,0x7C,0xC2,0x82,0x06,0x3C,0x00, 165 | 0x20,0xFC,0x32,0x62,0xE2,0xA2,0x2C,0x00,0x10,0x30,0x60,0x72,0xD2,0x92,0x9C,0x00, 166 | 0x00,0x00,0x00,0x00,0x0A,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x02,0x00 167 | }; 168 | 169 | static const u8 snkLogo[0x40] = { 170 | 0xFF,0x3F,0xFF,0xFF,0x00,0xFC,0xFF,0xFF,0xFF,0x3F,0x03,0x00,0xFF,0xFF,0xFF,0xFF, 171 | 0xF0,0xF3,0xFC,0xF3,0xFF,0x03,0xFF,0xC3,0xFF,0xF3,0xF3,0xF3,0xF0,0xF3,0xF0,0xC3, 172 | 0xCF,0x0F,0xCF,0x0F,0xCF,0x0F,0xCF,0xCF,0xCF,0xFF,0xCF,0xFF,0xCF,0xFF,0xCF,0x3F, 173 | 0xFF,0xC0,0xFC,0xC3,0xF0,0xCF,0xC0,0xFF,0xC0,0xFF,0xF0,0xCF,0xFC,0xC3,0xFF,0xC0 174 | }; 175 | 176 | static const u16 callTable[0x1B] = { 177 | 0x27A2, // 0x00 VECT_SHUTDOWN 178 | 0x1034, // 0x01 VECT_CLOCKGEARSET 179 | 0x1440, // 0x02 VECT_RTCGET 180 | 0x12B4, // 0x03 VECT_RTCSET 181 | 0x1222, // 0x04 VECT_INTLVSET 182 | 0x8D8A, // 0x05 VECT_SYSFONTSET 183 | 0x6FD8, // 0x06 VECT_FLASHWRITE 184 | 0x7042, // 0x07 VECT_FLASHALLERS 185 | 0x7082, // 0x08 VECT_FLASHERS 186 | 0x149B, // 0x09 VECT_ALARMSET 187 | 0x1033, // 0x0A Reserved (just RET) 188 | 0x1487, // 0x0B VECT_ALARMDOWNSET 189 | 0x731F, // 0x0C Another FLASHPROTECT? 190 | 0x70CA, // 0x0D VECT_FLASHPROTECT 191 | 0x17C4, // 0x0E VECT_GEMODESET 192 | 0x1032, // 0x0F Reserved (just RET) 193 | 194 | 0x2BBD, // 0x10 VECT_COMINIT 195 | 0x2C0C, // 0x11 VECT_COMSENDSTART 196 | 0x2C44, // 0x12 VECT_COMRECIVESTART 197 | 0x2C86, // 0x13 VECT_COMCREATEDATA 198 | 0x2CB4, // 0x14 VECT_COMGETDATA 199 | 0x2D27, // 0x15 VECT_COMONRTS 200 | 0x2D33, // 0x16 VECT_COMOFFRTS 201 | 0x2D3A, // 0x17 VECT_COMSENDSTATUS 202 | 0x2D4E, // 0x18 VECT_COMRECIVESTATUS 203 | 0x2D6C, // 0x19 VECT_COMCREATEBUFDATA 204 | 0x2D85, // 0x1A VECT_COMGETBUFDATA 205 | }; 206 | 207 | static const u16 irqTable[0x21] = { 208 | 0x204A, // 0x00 SWI_0, Reset 209 | 0x2772, // 0x01 SWI_1, Call handler 210 | 0x2305, // 0x02 SWI_2, Illegal instruction interrupt 211 | 0x2202, // 0x03 SWI_3, User controlled 212 | 0x220B, // 0x04 SWI_4, User controlled 213 | 0x2214, // 0x05 SWI_5, User controlled 214 | 0x221D, // 0x06 SWI_6, User controlled 215 | 0x2226, // 0x07 SWI_7, ? 216 | 0x1898, // 0x08 NMI_PowerButton 217 | 0x2D98, // 0x09 NMI_WatchDogTimer 218 | 0x2856, // 0x0A IRQ_RTCAlarm 219 | 0x2163, // 0x0B IRQ_VerticalBlanking 220 | 0x2282, // 0x0C IRQ_Z80 221 | 0x2B25, // 0x0D IRQ_INT6? unused 222 | 0x2DB6, // 0x0E IRQ_INT7? joypad interrupt? 223 | 0x22A4, // 0x0F IRQ_??? unused 224 | 225 | 0x22A5, // 0x10 IRQ_Timer0 226 | 0x22AE, // 0x11 IRQ_Timer1 227 | 0x22B7, // 0x12 IRQ_Timer2 228 | 0x22C0, // 0x13 IRQ_Timer3 229 | 0x22C9, // 0x14 IRQ_Timer4, unused 230 | 0x22CA, // 0x15 IRQ_Timer5, unused 231 | 0x22CB, // 0x16 IRQ_Timer6, unused 232 | 0x22CC, // 0x17 IRQ_Timer7, unused 233 | 0x22CD, // 0x18 IRQ_SerialTX0 234 | 0x22D6, // 0x19 IRQ_SerialRX0 235 | 0x22DF, // 0x1A IRQ_SerialTX1, unused 236 | 0x22E0, // 0x1B IRQ_SerialRX1, unused 237 | 0x2DCE, // 0x1C IRQ_INTAD, battery measure 238 | 0x22E1, // 0x1D IRQ_DMA0End 239 | 0x22EA, // 0x1E IRQ_DMA1End 240 | 0x22F3, // 0x1F IRQ_DMA2End 241 | 0x22FC, // 0x20 IRQ_DMA3End 242 | }; 243 | 244 | bool installHleBios(u8 *ngpBios) { 245 | int i; 246 | // System Call Table, install iBIOSHLE instructions 247 | for (i = 0; i < ARRSIZE(callTable); i++) { 248 | *(u32 *)(ngpBios + 0xFE00 + (i * 4)) = 0xFF0000 + callTable[i]; 249 | ngpBios[callTable[i]] = 0x1F; // iBIOSHLE 250 | ngpBios[callTable[i] + 1] = i; // iBIOSHLE num 251 | ngpBios[callTable[i] + 2] = 0x0E; // RET 252 | } 253 | 254 | // IRQ vector Table, install interrupt vectors 255 | for (i = 0; i < ARRSIZE(irqTable); i++) { 256 | *(u32 *)(ngpBios + 0xFF00 + (i * 4)) = 0xFF0000 + irqTable[i]; 257 | ngpBios[irqTable[i]] = 0x1F; // iBIOSHLE 258 | ngpBios[irqTable[i] + 1] = i + 0x40; // iBIOSHLE num 259 | ngpBios[irqTable[i] + 2] = 0x07; // RETI 260 | } 261 | 262 | // System Font 263 | memcpy(ngpBios + 0x8DCF, font, sizeof(font)); 264 | 265 | // Default Interrupt handler 266 | ngpBios[0x23DF] = 0x07; // RETI 267 | // System calls patch 268 | ngpBios[0x1032] = 0x0E; // RET 269 | ngpBios[0x1033] = 0x0E; // RET 270 | ngpBios[0x27A4] = 0x68; // - JR 0xFE (Infinite loop!) VECT_SHUTDOWN 271 | ngpBios[0x27A5] = 0xFE; 272 | // IRQ Vector patch 273 | ngpBios[0x2305] = 0x68; // - JR 0xFE (Infinite loop!) SWI_2 Illegal instruction interrupt 274 | ngpBios[0x2306] = 0xFE; 275 | ngpBios[0x2226] = 0x68; // - JR 0xFE (Infinite loop!) SWI_7 ??? 276 | ngpBios[0x2227] = 0xFE; 277 | ngpBios[0x1898] = 0x07; // RETI 278 | ngpBios[0x2D98] = 0x07; // RETI 279 | ngpBios[0x2B25] = 0x07; // RETI 280 | ngpBios[0x2DB6] = 0x07; // RETI 281 | ngpBios[0x22A4] = 0x07; // RETI 282 | ngpBios[0x22C9] = 0x07; // RETI 283 | ngpBios[0x22CA] = 0x07; // RETI 284 | ngpBios[0x22CB] = 0x07; // RETI 285 | ngpBios[0x22CC] = 0x07; // RETI 286 | ngpBios[0x22DF] = 0x07; // RETI 287 | ngpBios[0x22E0] = 0x07; // RETI 288 | ngpBios[0x2DCE] = 0x07; // RETI 289 | 290 | tlcs900HRedirectOpcode(0x1F, &sngBIOSHLE); 291 | return true; // Success 292 | } 293 | 294 | void resetHleBios(NgpHeader *cartHeader) { 295 | int i; 296 | // Clear all RAM first 297 | for (i = 0; i < 0x1000; i++) { 298 | t9StoreLX(0, 0x4000 + i*4); 299 | } 300 | 301 | //============================================================================= 302 | //006C00 -> 006FFF BIOS Workspace 303 | //================================== 304 | 305 | t9StoreLX(cartHeader->startPC, 0x6C00); // Start 306 | 307 | t9StoreWX(cartHeader->catalog, 0x6C04); 308 | t9StoreWX(cartHeader->catalog, 0x6E82); 309 | 310 | t9StoreBX(cartHeader->subCatalog, 0x6C06); 311 | t9StoreBX(cartHeader->subCatalog, 0x6E84); 312 | 313 | for (i = 0; i < 12; i++) { 314 | t9StoreBX(cartHeader->name[i], 0x6C08 + i); 315 | } 316 | 317 | t9StoreBX(0x01, 0x6C58); 318 | t9StoreBX(0x00, 0x6C59); 319 | // 32MBit cart? 320 | if (gRomSize > 0x200000) { 321 | t9StoreBX(0x03, 0x6C58); 322 | t9StoreBX(0x03, 0x6C59); 323 | } 324 | else if (gRomSize > 0x100000) { 325 | t9StoreBX(0x03, 0x6C58); 326 | } 327 | else if (gRomSize > 0x080000) { 328 | t9StoreBX(0x02, 0x6C58); 329 | } 330 | 331 | t9StoreBX(0x01, 0x6C55); // 0x01 = Commercial game 332 | 333 | t9StoreWX(0x03FF, 0x6F80); // Lots of battery power! 334 | 335 | t9StoreBX(0x40, 0x6F84); // "Power On" startup 336 | t9StoreBX(0x00, 0x6F85); // No shutdown request 337 | t9StoreBX(0x00, 0x6F86); // No user answer (?) 338 | 339 | t9StoreWX(0xA5A5, 0x6C7A); // Running mode 340 | t9StoreWX(0x5AA5, 0x6C7C); // Running mode 341 | 342 | // Language: 0 = Japanese, 1 = English 343 | if (gLang) { 344 | t9StoreBX(0x01, 0x6F87); 345 | } 346 | else { 347 | t9StoreBX(0x00, 0x6F87); 348 | } 349 | t9StoreBX(gPaletteBank, 0x6F94); 350 | 351 | // Color Mode Selection: 0x00 = B&W, 0x10 = Colour 352 | int color = cartHeader->mode; 353 | if (gMachine == HW_NGPMONO) { 354 | color = 0; 355 | } 356 | t9StoreBX(color, 0x6F90); // Game Displaymode 357 | t9StoreBX(color, 0x6F95); // Current Displaymode 358 | t9StoreBX(color, 0x6F91); // Machine 359 | if (gMachine == HW_NGPCOLOR) { 360 | t9StoreBX(0x10, 0x6F91); // Machine 361 | } 362 | // User Interrupt table 363 | for (i = 0; i < 0x12; i++) { 364 | t9StoreLX(0xFF23DF, 0x6FB8 + i * 4); 365 | } 366 | 367 | //============================================================================= 368 | //008000 -> 00BFFF Video RAM 369 | //============================= 370 | 371 | t9StoreBX(0xAA, 0x87F0); 372 | t9StoreBX(color ? 0x00 : 0x80, 0x87E2); 373 | t9StoreBX(0x55, 0x87F0); 374 | 375 | // Clear some tiles, (Cool Cool Jam in B&W) 376 | for (i = 0; i < 0x20; i++) { 377 | t9StoreBX(0, 0xA000 + i); 378 | } 379 | 380 | // Copy SNK logo to VRAM, Metal Slug 2 checks this unless run in debug mode. 381 | for (i = 0; i < 0x40; i++) { 382 | t9StoreBX(snkLogo[i], 0xA1C0 + i); 383 | } 384 | 385 | t9StoreBX(0xF3, 0x7000); // Z80 DI 386 | t9StoreBX(0x31, 0x7001); // Z80 LD SP 0x0FFF 387 | t9StoreBX(0xFF, 0x7002); 388 | t9StoreBX(0x0F, 0x7003); 389 | t9StoreBX(0x18, 0x7004); // Z80 JR -2 390 | t9StoreBX(0xFE, 0x7005); 391 | 392 | // Enable Z80 393 | t9StoreBX(0x55, 0xB9); 394 | 395 | // Turn on LED 396 | t9StoreBX(0xFF, 0x8400); 397 | 398 | // Do some setup for the interrupt priorities. 399 | for (i = 0; i < 0x8; i++) { 400 | t9StoreBX(0, 0x6C24 + i); 401 | } 402 | for (i = 0; i < 0xB; i++) { 403 | t9StoreBX(0, 0x70 + i); 404 | } 405 | t9StoreBX(0x0A, 0x6C24); 406 | t9StoreBX(0xDC, 0x6C25); 407 | t9StoreBX(0x0A, 0x70); 408 | t9StoreBX(0xDC, 0x71); 409 | } 410 | 411 | void fixBiosSettings(void) { 412 | // Setup alarm from config 413 | t9StoreBX(cfg.alarmHour, 0x6C34); 414 | t9StoreBX(cfg.alarmMinute, 0x6C35); 415 | 416 | t9StoreBX(0x4E, 0x6E96); // N 417 | t9StoreBX(0x50, 0x6E95); // P 418 | t9StoreBX(0x00, 0x6F83); 419 | 420 | // Setup birth day from config 421 | t9StoreBX(cfg.birthYear, 0x6F8B); 422 | t9StoreBX(cfg.birthMonth, 0x6F8C); 423 | t9StoreBX(cfg.birthDay, 0x6F8D); 424 | 425 | int check = gLang ? 0x01 : 0x00; 426 | // Language: 0 = Japanese, 1 = English 427 | t9StoreBX(check, 0x6F87); 428 | if (gMachine == HW_NGPCOLOR) { 429 | t9StoreBX(gPaletteBank, 0x6F94); 430 | check += gPaletteBank; 431 | } 432 | else { 433 | // Required by mono BIOS to skip setup. 434 | t9StoreBX(0xDC, 0x6C25); 435 | } 436 | check += 0xDC; // Actualy addition of all IRQ priorities. 437 | t9StoreWX(check, 0x6C14); 438 | } 439 | 440 | //============================================================================= 441 | -------------------------------------------------------------------------------- /source/bios.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __BIOS__ 3 | #define __BIOS__ 4 | 5 | #include "NGPHeader.h" 6 | 7 | /** Fill the bios rom area with a HLE BIOS. Call once at program start */ 8 | bool installHleBios(u8 *ngpBios); 9 | 10 | void resetHleBios(NgpHeader *cartHeader); 11 | 12 | void fixBiosSettings(void); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /source/biosHLE.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "io.h" 5 | #include "cpu.h" 6 | #include "Memory.h" 7 | #include "NGPFlash/NGPFlash.h" 8 | 9 | #define rCodeB(r) (*((u8 *)getRegAdr(r))) 10 | #define rCodeW(r) (*((u16 *)getRegAdr((r) & ~1))) 11 | #define rCodeL(r) (*((u32 *)getRegAdr((r) & ~3))) 12 | 13 | /** 14 | * 15 | */ 16 | void iBIOSHLE(int vector) { 17 | switch (vector) { 18 | 19 | // VECT_SHUTDOWN (0xFF27A2) 20 | case 0x00: 21 | return; 22 | 23 | // VECT_CLOCKGEARSET (0xFF1034) 24 | case 0x01: 25 | t9StoreBX(rCodeL(0x3C), 0x80); 26 | break; 27 | 28 | // VECT_RTCGET (0xFF1440) 29 | case 0x02: { 30 | // Copy time from hardware area 31 | u32 adr = rCodeL(0x3C); 32 | t9StoreBX(t9LoadBX(0x91), adr + 0); 33 | t9StoreWX(t9LoadWX(0x92), adr + 1); 34 | t9StoreWX(t9LoadWX(0x94), adr + 3); 35 | t9StoreWX(t9LoadWX(0x96), adr + 5); 36 | break; 37 | } 38 | // VECT_RTCSET (0xFF12B4) 39 | //case 0x03: 40 | // break; 41 | 42 | // VECT_INTLVSET (0xFF1222) 43 | case 0x04: { 44 | 45 | u8 level = rCodeB(0x35) & 0x0F; // RB 46 | u8 interrupt = rCodeB(0x34); // RC 47 | 48 | switch(interrupt) { 49 | case 0x00: // Interrupt from RTC alarm 50 | level |= t9LoadBX(0x6C24) & 0xf0; 51 | t9StoreBX(level, 0x6C24); 52 | t9StoreBX(level, 0x70); 53 | break; 54 | case 0x01: // Interrupt from the Z80 CPU 55 | level = (level<<4) | (t9LoadBX(0x6C25) & 0x0f); 56 | t9StoreBX(level, 0x6C25); 57 | t9StoreBX(level, 0x71); 58 | break; 59 | case 0x02: // Interrupt from Timer 0 60 | level |= t9LoadBX(0x6C27) & 0xf0; 61 | t9StoreBX(level, 0x6C27); 62 | t9StoreBX(level, 0x73); 63 | break; 64 | case 0x03: // Interrupt from Timer 1 65 | level = (level<<4) | (t9LoadBX(0x6C27) & 0x0f); 66 | t9StoreBX(level, 0x6C27); 67 | t9StoreBX(level, 0x73); 68 | break; 69 | case 0x04: // Interrupt from Timer 2 70 | level |= t9LoadBX(0x6C28) & 0xf0; 71 | t9StoreBX(level, 0x6C28); 72 | t9StoreBX(level, 0x74); 73 | break; 74 | case 0x05: // Interrupt from Timer 3 75 | level = (level<<4) | (t9LoadBX(0x6C28) & 0x0f); 76 | t9StoreBX(level, 0x6C28); 77 | t9StoreBX(level, 0x74); 78 | break; 79 | case 0x06: // End of transfer interrupt from DMA channel 0 80 | level |= t9LoadBX(0x6C2A) & 0xf0; 81 | t9StoreBX(level, 0x6C2A); 82 | t9StoreBX(level, 0x79); 83 | break; 84 | case 0x07: // End of transfer interrupt from DMA channel 1 85 | level = (level<<4) | (t9LoadBX(0x6C2A) & 0x0f); 86 | t9StoreBX(level, 0x6C2A); 87 | t9StoreBX(level, 0x79); 88 | break; 89 | case 0x08: // End of transfer interrupt from DMA channel 2 90 | level |= (t9LoadBX(0x6C2B) & 0xf0); 91 | t9StoreBX(level, 0x6C2B); 92 | t9StoreBX(level, 0x7A); 93 | break; 94 | case 0x09: // End of transfer interrupt from DMA channel 3 95 | level = (level<<4) | (t9LoadBX(0x6C2B) & 0x0f); 96 | t9StoreBX(level, 0x6C2B); 97 | t9StoreBX(level, 0x7A); 98 | break; 99 | default: 100 | break; 101 | } 102 | } 103 | break; 104 | 105 | // VECT_SYSFONTSET (0xFF8D8A) 106 | case 0x05: { 107 | int j, i, dst = 0xA000; 108 | 109 | u8 a = rCodeB(0x30); 110 | u8 b = a >> 4; 111 | a &= 3; 112 | 113 | for (i = 0; i < 0x800; i++) { 114 | u8 c = t9LoadBX(0xFF8DCF + i); 115 | 116 | u16 data16 = t9LoadWX(dst); 117 | for (j = 0; j < 8; j++, c <<= 1) { 118 | data16 <<= 2; 119 | data16 |= (c & 0x80)?a:b; 120 | } 121 | t9StoreWX(data16, dst); 122 | dst += 2; 123 | } 124 | } 125 | break; 126 | 127 | // VECT_FLASHWRITE (0xFF6FD8) 128 | case 0x06: { 129 | int i, bank = 0x200000; 130 | 131 | // Select HI rom 132 | if (rCodeB(0x30) == 1) { 133 | bank = 0x800000; 134 | } 135 | int destination = rCodeL(0x38) + bank; 136 | int source = rCodeL(0x3C) + bank; 137 | 138 | int count = rCodeW(0x34) * 256; 139 | for (i = 0; i < count; i++) { 140 | t9StoreBX(0xAA, bank + 0x5555); 141 | t9StoreBX(0x55, bank + 0x2AAA); 142 | t9StoreBX(0xA0, bank + 0x5555); 143 | t9StoreBX(t9LoadBX(source + i), destination + i); 144 | } 145 | int block = getBlockFromAddress(destination); 146 | markBlockDirty(rCodeB(0x30), block); 147 | 148 | rCodeB(0x30) = 0; // RA3 = SYS_SUCCESS 149 | } 150 | break; 151 | 152 | // VECT_FLASHALLERS (0xFF7042) 153 | case 0x07: 154 | // TODO 155 | rCodeB(0x30) = 0; // RA3 = SYS_SUCCESS 156 | break; 157 | // VECT_FLASHERS (0xFF7082) 158 | case 0x08: { 159 | u32 address = 0x200000; 160 | // Select HI rom? 161 | if (rCodeB(0x30) == 1) { 162 | address = 0x800000; 163 | } 164 | address += getBlockOffset(rCodeB(0x34)); 165 | 166 | t9StoreBX(0xAA, address + 0x5555); 167 | t9StoreBX(0x55, address + 0x2AAA); 168 | t9StoreBX(0x80, address + 0x5555); 169 | t9StoreBX(0xAA, address + 0x5555); 170 | t9StoreBX(0x55, address + 0x2AAA); 171 | rCodeB(0x30) = 0; // RA3 = SYS_SUCCESS 172 | } 173 | break; 174 | 175 | // VECT_ALARMSET (0xFF149B) 176 | case 0x09: 177 | // TODO 178 | rCodeB(0x30) = 0; // RA3 = SYS_SUCCESS 179 | break; 180 | 181 | // Reserved (just RET) (0xFF1033) 182 | //case 0x0A: break; 183 | 184 | // VECT_ALARMDOWNSET (0xFF1487) 185 | case 0x0B: 186 | // TODO 187 | rCodeB(0x30) = 0; // RA3 = SYS_SUCCESS 188 | break; 189 | 190 | // ? (0xFF731F) 191 | //case 0x0C: break; 192 | 193 | // VECT_FLASHPROTECT (0xFF70CA) 194 | case 0x0D: 195 | // TODO 196 | rCodeB(0x30) = 0; // RA3 = SYS_SUCCESS 197 | break; 198 | 199 | // VECT_GEMODESET (0xFF17C4) 200 | case 0x0E: 201 | t9StoreBX(0xAA, 0x87F0); // Allow GE MODE registers to be written to 202 | if (rCodeB(0x30) < 0x10) { // Current A register. 203 | // set B/W mode 204 | t9StoreBX(0x80, 0x87E2); 205 | t9StoreBX(0x00, 0x6F95); 206 | } 207 | else { 208 | // set color mode 209 | t9StoreBX(0x00, 0x87E2); 210 | t9StoreBX(0x10, 0x6F95); 211 | } 212 | t9StoreBX(0x55, 0x87F0); // Disallow GE MODE registers to be written to 213 | break; 214 | 215 | // Reserved (just RET) (0xFF1032) 216 | //case 0x0F: break; 217 | 218 | // VECT_COMINIT (0xFF2BBD) 219 | case 0x10: 220 | // Nothing to do. 221 | break; 222 | 223 | // VECT_COMSENDSTART (0xFF2C0C) 224 | case 0x11: 225 | // Nothing to do. 226 | break; 227 | 228 | // VECT_COMRECEIVESTART (0xFF2C44) 229 | case 0x12: 230 | // Nothing to do. 231 | break; 232 | 233 | // VECT_COMCREATEDATA (0xFF2C86) 234 | case 0x13: { 235 | // Write the byte 236 | u8 data = rCodeB(0x35); 237 | system_comms_write(data); 238 | // Always COM_BUF_OK because the write call always succeeds. 239 | rCodeB(0x30) = 0; // RA3 = COM_BUF_OK 240 | } 241 | setInterruptExternal(0x18); 242 | break; 243 | 244 | // VECT_COMGETDATA (0xFF2CB4) 245 | case 0x14: { 246 | u8 data; 247 | if (system_comms_read(&data)) { 248 | rCodeB(0x30) = 0; // COM_BUF_OK 249 | rCodeB(0x35) = data; 250 | // Comms. Read interrupt 251 | t9StoreBX(data, 0x50); 252 | 253 | setInterruptExternal(0x19); 254 | } 255 | else { 256 | rCodeB(0x30) = 1; // COM_BUF_EMPTY 257 | } 258 | } 259 | break; 260 | 261 | // VECT_COMONRTS (0xFF2D27) 262 | case 0x15: 263 | t9StoreBX(t9LoadBX(0xB2) & 0xFE, 0xB2); 264 | break; 265 | 266 | // VECT_COMOFFRTS (0xFF2D33) 267 | case 0x16: 268 | t9StoreBX(t9LoadBX(0xB2) | 0x01, 0xB2); 269 | break; 270 | 271 | // VECT_COMSENDSTATUS (0xFF2D3A) 272 | case 0x17: 273 | // Nothing to do. 274 | rCodeW(0x30) = 0; // Send Buffer Count, never any pending data! 275 | break; 276 | 277 | // VECT_COMRECEIVESTATUS (0xFF2D4E) 278 | case 0x18: 279 | // Receive Buffer Count 280 | rCodeW(0x30) = system_comms_read(NULL); 281 | break; 282 | 283 | // VECT_COMCREATEBUFDATA (0xFF2D6C) 284 | case 0x19: { 285 | u8 count = rCodeB(0x35); 286 | u32 index = rCodeL(0x3C); 287 | while(count > 0) { 288 | u8 data = t9LoadBX(index); 289 | // Write data from (XHL3++) 290 | system_comms_write(data); 291 | index++; // Next data 292 | count--; // RB3 = Count Left 293 | } 294 | rCodeL(0x3C) = index; 295 | rCodeB(0x35) = count; 296 | setInterruptExternal(0x18); 297 | } 298 | break; 299 | 300 | // VECT_COMGETBUFDATA (0xFF2D85) 301 | case 0x1A: { 302 | u8 count = rCodeB(0x35); 303 | u32 index = rCodeL(0x3C); 304 | while(count > 0) { 305 | u8 data; 306 | if (system_comms_read(&data)) { 307 | // Read data into (XHL3++) 308 | t9StoreBX(data, index); 309 | index++; // Next data 310 | count--; // RB3 = Count Left 311 | 312 | // Comms. Read interrupt 313 | t9StoreBX(data, 0x50); 314 | setInterruptExternal(0x19); 315 | } 316 | else { 317 | break; 318 | } 319 | } 320 | rCodeL(0x3C) = index; 321 | rCodeB(0x35) = count; 322 | } 323 | break; 324 | } 325 | 326 | } 327 | -------------------------------------------------------------------------------- /source/cpu.h: -------------------------------------------------------------------------------- 1 | #ifndef CPU_HEADER 2 | #define CPU_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern u8 waitMaskIn; 9 | extern u8 waitMaskOut; 10 | 11 | void run(void); 12 | void stepFrame(void); 13 | void cpuReset(void); 14 | bool isConsoleRunning(void); 15 | bool isConsoleSleeping(void); 16 | 17 | void setInterruptExternal(int index); 18 | 19 | /** 20 | * Change z80 cpu speed, can make emulation less power demanding. 21 | * @param downShift: How many times the speed is shifted down. 22 | */ 23 | void tweakZ80Speed(int downShift); 24 | 25 | /** 26 | * Get the address of cpu register 27 | */ 28 | void *getRegAdr(int reg); 29 | 30 | #ifdef __cplusplus 31 | } // extern "C" 32 | #endif 33 | 34 | #endif // CPU_HEADER 35 | -------------------------------------------------------------------------------- /source/cpu.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "TLCS900H/TLCS900H.i" 4 | #include "ARMZ80/ARMZ80.i" 5 | #include "K2GE/K2GE.i" 6 | 7 | .global frameTotal 8 | .global waitMaskIn 9 | .global waitMaskOut 10 | 11 | .global run 12 | .global stepFrame 13 | .global cpuReset 14 | .global isConsoleRunning 15 | .global isConsoleSleeping 16 | .global tweakZ80Speed 17 | .global setInterruptExternal 18 | .global Z80_SetEnable 19 | .global Z80_nmi_do 20 | .global getRegAdr 21 | 22 | .syntax unified 23 | .arm 24 | 25 | #ifdef GBA 26 | .section .ewram, "ax", %progbits ;@ For the GBA 27 | #else 28 | .section .text ;@ For anything else 29 | #endif 30 | .align 2 31 | ;@---------------------------------------------------------------------------- 32 | run: ;@ Return after X frame(s) 33 | .type run STT_FUNC 34 | ;@---------------------------------------------------------------------------- 35 | ldrh r0,waitCountIn 36 | add r0,r0,#1 37 | ands r0,r0,r0,lsr#8 38 | strb r0,waitCountIn 39 | bxne lr 40 | stmfd sp!,{r4-r11,lr} 41 | 42 | ;@---------------------------------------------------------------------------- 43 | runStart: 44 | ;@---------------------------------------------------------------------------- 45 | ldr r0,=EMUinput 46 | ldr r0,[r0] 47 | ldr r3,joyClick 48 | eor r3,r3,r0 49 | and r3,r3,r0 50 | str r0,joyClick 51 | 52 | tst r3,#0x04 ;@ NDS Select? 53 | tsteq r3,#0x800 ;@ NDS Y? 54 | ldrne r2,=systemMemory+0xB3 55 | ldrbne r2,[r2] 56 | tstne r2,#4 ;@ Power button NMI enabled? 57 | movne r0,#0x08 ;@ 0x08 = Power button on NGP 58 | blne setInterruptExternal 59 | 60 | bl refreshEMUjoypads ;@ Z=1 if communication ok 61 | 62 | ;@---------------------------------------------------------------------------- 63 | ngpFrameLoop: 64 | ;@---------------------------------------------------------------------------- 65 | ldrb r0,z80Enabled 66 | cmp r0,#0 67 | beq NoZ80Now 68 | 69 | ldr z80ptr,=Z80OpTable 70 | ldr r0,z80CyclesPerScanline 71 | bl Z80RestoreAndRunXCycles 72 | add r0,z80ptr,#z80Regs 73 | stmia r0,{z80f-z80pc,z80sp} ;@ Save Z80 state 74 | NoZ80Now: 75 | ;@-------------------------------------- 76 | ldr t9ptr,=tlcs900HState 77 | ldr r0,tlcs900hCyclesPerScanline 78 | bl tlcsRestoreAndRunXCycles 79 | ;@-------------------------------------- 80 | bl soundUpdate 81 | ldr geptr,=k2GE_0 82 | bl k2GEDoScanline 83 | cmp r0,#0 84 | bne ngpFrameLoop 85 | ;@---------------------------------------------------------------------------- 86 | 87 | ldr r1,=fpsValue 88 | ldr r0,[r1] 89 | add r0,r0,#1 90 | str r0,[r1] 91 | 92 | ldr r1,frameTotal 93 | add r1,r1,#1 94 | str r1,frameTotal 95 | 96 | ldrh r0,waitCountOut 97 | add r0,r0,#1 98 | ands r0,r0,r0,lsr#8 99 | strb r0,waitCountOut 100 | ldmfdeq sp!,{r4-r11,lr} ;@ Exit here if doing single frame: 101 | bxeq lr ;@ Return to rommenu() 102 | b runStart 103 | 104 | ;@---------------------------------------------------------------------------- 105 | tlcs900hCyclesPerScanline: .long 0 106 | z80CyclesPerScanline: .long 0 107 | joyClick: .long 0 108 | frameTotal: .long 0 ;@ Let Gui.c see frame count for savestates 109 | waitCountIn: .byte 0 110 | waitMaskIn: .byte 0 111 | waitCountOut: .byte 0 112 | waitMaskOut: .byte 0 113 | 114 | z80Enabled: .byte 0 115 | .byte 0,0,0 116 | 117 | ;@---------------------------------------------------------------------------- 118 | stepFrame: ;@ Return after 1 frame 119 | .type stepFrame STT_FUNC 120 | ;@---------------------------------------------------------------------------- 121 | stmfd sp!,{r4-r11,lr} 122 | ;@---------------------------------------------------------------------------- 123 | ngpStepLoop: 124 | ;@---------------------------------------------------------------------------- 125 | ldrb r0,z80Enabled 126 | cmp r0,#0 127 | beq NoZ80Step 128 | 129 | ldr z80ptr,=Z80OpTable 130 | ldr r0,z80CyclesPerScanline 131 | bl Z80RestoreAndRunXCycles 132 | add r0,z80ptr,#z80Regs 133 | stmia r0,{z80f-z80pc,z80sp} ;@ Save Z80 state 134 | NoZ80Step: 135 | ;@-------------------------------------- 136 | ldr t9ptr,=tlcs900HState 137 | ldr r0,tlcs900hCyclesPerScanline 138 | bl tlcsRestoreAndRunXCycles 139 | ;@-------------------------------------- 140 | ldr geptr,=k2GE_0 141 | bl k2GEDoScanline 142 | cmp r0,#0 143 | bne ngpStepLoop 144 | ;@---------------------------------------------------------------------------- 145 | 146 | ldr r1,frameTotal 147 | add r1,r1,#1 148 | str r1,frameTotal 149 | 150 | ldmfd sp!,{r4-r11,lr} 151 | bx lr 152 | ;@---------------------------------------------------------------------------- 153 | isConsoleRunning: 154 | .type isConsoleRunning STT_FUNC 155 | ;@---------------------------------------------------------------------------- 156 | ldr r1,=ngpRAM+0x2C7C 157 | ldrh r0,[r1] 158 | ldr r1,=0x5AA5 159 | cmp r0,r1 160 | moveq r0,#1 161 | movne r0,#0 162 | bx lr 163 | ;@---------------------------------------------------------------------------- 164 | isConsoleSleeping: 165 | .type isConsoleSleeping STT_FUNC 166 | ;@---------------------------------------------------------------------------- 167 | ldr r1,=ngpRAM+0x2C7C 168 | ldrh r0,[r1] 169 | ldr r1,=0xA55A 170 | cmp r0,r1 171 | moveq r0,#1 172 | movne r0,#0 173 | bx lr 174 | ;@--------------------------------------------------------------------------- 175 | setInterruptExternal: ;@ r0 = index 176 | .type setInterruptExternal STT_FUNC 177 | ;@--------------------------------------------------------------------------- 178 | stmfd sp!,{t9ptr,lr} 179 | ldr t9ptr,=tlcs900HState 180 | bl setInterrupt 181 | ldmfd sp!,{t9ptr,lr} 182 | bx lr 183 | ;@---------------------------------------------------------------------------- 184 | Z80_SetEnable: ;@ Address 0xB9 of the TLCS-900H, r0=enabled 185 | ;@---------------------------------------------------------------------------- 186 | cmp r0,#0x55 ;@ On 187 | cmpne r0,#0xAA ;@ Off 188 | bxne lr 189 | and r0,r0,#1 190 | strb r0,z80Enabled 191 | eor r0,r0,#1 192 | ldr r1,=Z80OpTable 193 | b Z80SetResetPin 194 | ;@---------------------------------------------------------------------------- 195 | Z80_nmi_do: ;@ Address 0xBA of the TLCS-900H 196 | ;@---------------------------------------------------------------------------- 197 | ldrb r1,z80Enabled 198 | cmp r1,#0 199 | bxeq lr 200 | ldr r1,=Z80OpTable 201 | mov r0,#1 202 | b Z80SetNMIPin 203 | ;@---------------------------------------------------------------------------- 204 | cpu1SetIRQ: ;@ r0=pin state 205 | ;@---------------------------------------------------------------------------- 206 | ldr r1,=Z80OpTable 207 | b Z80SetIRQPin 208 | ;@---------------------------------------------------------------------------- 209 | getRegAdr: ;@ r0=register, 0x00-0xFF 210 | .type getRegAdr STT_FUNC 211 | ;@---------------------------------------------------------------------------- 212 | ldr r1,=tlcs900HState 213 | ldr r2,[r1,#tlcsCurrentMapBank] 214 | ldrsb r0,[r2,r0] 215 | ldr r2,[r1,#tlcsCurrentGprBank] 216 | add r0,r2,r0 217 | bx lr 218 | ;@---------------------------------------------------------------------------- 219 | setCpuSpeed: ;@ 220 | ;@---------------------------------------------------------------------------- 221 | ;@---Speed - 6.144MHz / 59.95Hz / 199 lines ;NGP TLCS-900H. 222 | ldr r0,=T9_HINT_RATE ;@ 515 223 | str r0,tlcs900hCyclesPerScanline 224 | ;@---Speed - 3.072MHz / 59.95Hz / 199 lines ;NGP Z80. 225 | mov r0,r0,lsr#1 226 | str r0,z80CyclesPerScanline 227 | bx lr 228 | ;@---------------------------------------------------------------------------- 229 | tweakZ80Speed: ;@ in r0=0 normal, 1=half speed, 2=1/4 speed... 230 | .type tweakZ80Speed STT_FUNC 231 | ;@---------------------------------------------------------------------------- 232 | ;@---Speed - 3.072MHz / 59.95Hz / 199 lines ;NGP Z80. 233 | ldr r1,=T9_HINT_RATE/2 ;@ 515/2 234 | mov r1,r1,lsr r0 235 | str r1,z80CyclesPerScanline 236 | bx lr 237 | ;@---------------------------------------------------------------------------- 238 | cpuReset: ;@ Called by loadCart/resetGame 239 | ;@---------------------------------------------------------------------------- 240 | stmfd sp!,{lr} 241 | 242 | bl setCpuSpeed 243 | 244 | ldr r0,=tlcs900HState 245 | adr r1,cpu1SetIRQ 246 | bl tlcs900HReset 247 | 248 | ;@-------------------------------------- 249 | ldr r0,=gZ80Speed 250 | ldrb r0,[r0] 251 | and r0,r0,#7 252 | bl tweakZ80Speed 253 | 254 | ldr r0,=Z80OpTable 255 | mov r1,#0 256 | bl Z80Reset 257 | 258 | ldmfd sp!,{lr} 259 | bx lr 260 | ;@---------------------------------------------------------------------------- 261 | .end 262 | #endif // #ifdef __arm__ 263 | -------------------------------------------------------------------------------- /source/io.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_HEADER 2 | #define IO_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern u32 joyCfg; 9 | extern u32 EMUinput; 10 | extern u32 gSubBatteryLevel; 11 | extern u32 batteryLevel; 12 | 13 | /** 14 | * Copies the time from the NDS RTC to the NGP RTC. 15 | */ 16 | void transferTime(void); 17 | 18 | /** 19 | * Saves the state of io to the destination. 20 | * @param *destination: Where to save the state. 21 | * @return The size of the state. 22 | */ 23 | int ioSaveState(void *destination); 24 | 25 | /** 26 | * Loads the state of io from the source. 27 | * @param *source: Where to load the state from. 28 | * @return The size of the state. 29 | */ 30 | int ioLoadState(const void *source); 31 | 32 | /** 33 | * Gets the state size of an io state. 34 | * @return The size of the state. 35 | */ 36 | int ioGetStateSize(void); 37 | 38 | /** 39 | * Convert device input keys to target keys. 40 | * @param input NDS/GBA keys 41 | * @return The converted input. 42 | */ 43 | int convertInput(int input); 44 | 45 | /** 46 | * Reads a byte from the other system. If no data is available or no 47 | * high-level communications have been established, then return FALSE. 48 | * If buffer is NULL, then no data is read, only status is returned 49 | */ 50 | bool system_comms_read(u8 *buffer); 51 | 52 | /** 53 | * Writes a byte from the other system. This function should block until 54 | * the data is written. USE RELIABLE COMMS! Data cannot be re-requested. 55 | */ 56 | void system_comms_write(u8 data); 57 | 58 | #ifdef __cplusplus 59 | } // extern "C" 60 | #endif 61 | 62 | #endif // IO_HEADER 63 | -------------------------------------------------------------------------------- /source/io.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "TLCS900H/TLCS900H.i" 4 | #include "ARMZ80/ARMZ80.i" 5 | #include "K2GE/K2GE.i" 6 | #include "Shared/EmuMenu.i" 7 | 8 | .global joyCfg 9 | .global EMUinput 10 | .global gSubBatteryLevel 11 | .global batteryLevel 12 | .global systemMemory 13 | 14 | .global ioReset 15 | .global convertInput 16 | .global refreshEMUjoypads 17 | .global transferTime 18 | .global Z80In 19 | .global Z80Out 20 | .global ioSaveState 21 | .global ioLoadState 22 | .global ioGetStateSize 23 | 24 | .global updateSlowIO 25 | .global z80LatchR 26 | .global z80LatchW 27 | .global system_comms_read 28 | .global system_comms_write 29 | .global ADStart 30 | 31 | .syntax unified 32 | .arm 33 | 34 | .section .text 35 | .align 2 36 | ;@---------------------------------------------------------------------------- 37 | ioReset: 38 | ;@---------------------------------------------------------------------------- 39 | stmfd sp!,{lr} 40 | 41 | adr r0,SysMemDefault 42 | bl initSysMem 43 | bl transferTime 44 | 45 | ldmfd sp!,{pc} 46 | ;@---------------------------------------------------------------------------- 47 | initSysMem: ;@ In r0=values ptr. 48 | ;@---------------------------------------------------------------------------- 49 | stmfd sp!,{t9Mem,r5,t9cycles,t9ptr,lr} 50 | ldr t9ptr,=tlcs900HState 51 | 52 | mov r5,r0 53 | mov t9Mem,#0xBF 54 | initMemLoop: 55 | ldrb r0,[r5,t9Mem] 56 | bl t9StoreB_Low 57 | subs t9Mem,t9Mem,#1 58 | bpl initMemLoop 59 | 60 | ldmfd sp!,{t9Mem,r5,t9cycles,t9ptr,pc} 61 | ;@---------------------------------------------------------------------------- 62 | ioSaveState: ;@ In r0=destination. Out r0=size. 63 | .type ioSaveState STT_FUNC 64 | ;@---------------------------------------------------------------------------- 65 | mov r2,#0x100 66 | stmfd sp!,{r2,lr} 67 | 68 | ldr r1,=systemMemory 69 | bl memcpy 70 | 71 | ldmfd sp!,{r0,lr} 72 | bx lr 73 | ;@---------------------------------------------------------------------------- 74 | ioLoadState: ;@ In r0=source. Out r0=size. 75 | .type ioLoadState STT_FUNC 76 | ;@---------------------------------------------------------------------------- 77 | stmfd sp!,{lr} 78 | 79 | bl initSysMem 80 | 81 | ldmfd sp!,{lr} 82 | ;@---------------------------------------------------------------------------- 83 | ioGetStateSize: ;@ Out r0=state size. 84 | .type ioGetStateSize STT_FUNC 85 | ;@---------------------------------------------------------------------------- 86 | mov r0,#0x100 87 | bx lr 88 | ;@---------------------------------------------------------------------------- 89 | transferTime: 90 | .type transferTime STT_FUNC 91 | ;@---------------------------------------------------------------------------- 92 | stmfd sp!,{lr} 93 | 94 | bl getTime ;@ r0 = ??ssMMHH, r1 = ??DDMMYY 95 | ldr r2,=systemMemory 96 | strb r1,[r2,#0x91] ;@ Year 97 | mov r1,r1,lsr#8 98 | strb r1,[r2,#0x92] ;@ Month 99 | mov r1,r1,lsr#8 100 | strb r1,[r2,#0x93] ;@ Day 101 | and r1,r0,#0x3F 102 | strb r1,[r2,#0x94] ;@ Hours 103 | mov r0,r0,lsr#8 104 | strb r0,[r2,#0x95] ;@ Minutes 105 | mov r0,r0,lsr#8 106 | strb r0,[r2,#0x96] ;@ Seconds 107 | 108 | ldmfd sp!,{lr} 109 | bx lr 110 | 111 | ;@---------------------------------------------------------------------------- 112 | SysMemDefault: 113 | ;@ 0x00 ;@ 0x08 114 | .byte 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0xFF, 0xFF 115 | ;@ 0x10 ;@ 0x18 116 | .byte 0x34, 0x3C, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x3F, 0xFF, 0x2D, 0x01, 0xFF, 0xFF, 0x03, 0xB2 117 | ;@ 0x20 ;@ 0x28 118 | .byte 0x80, 0x00, 0x01, 0x90, 0x03, 0xCC, 0x90, 0x62, 0x05, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x4C, 0x4C 119 | ;@ 0x30 ;@ 0x38 120 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0xFF, 0x80, 0x7F 121 | ;@ 0x40 ;@ 0x48 122 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 123 | ;@ 0x50 ;@ 0x58 124 | .byte 0x00, 0x20, 0x69, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF 125 | ;@ 0x60 ;@ 0x68 126 | .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x03, 0x03, 0x02, 0x00, 0x10, 0x4E 127 | ;@ 0x70 ;@ 0x78 128 | .byte 0x02, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 129 | ;@ 0x80 ;@ 0x88 130 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 131 | ;@ 0x90 ;@ 0x98 132 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 133 | ;@ 0xA0 ;@ 0xA8 134 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 135 | ;@ 0xB0 ;@ 0xB8 136 | .byte 0x00, 0x00, 0x00, 0x04, 0x0A, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 137 | ;@ 0xC0 ;@ 0xC8 138 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 139 | ;@ 0xD0 ;@ 0xD8 140 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 141 | ;@ 0xE0 ;@ 0xE8 142 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 143 | ;@ 0xF0 ;@ 0xF8 144 | .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 145 | ;@---------------------------------------------------------------------------- 146 | #ifdef GBA 147 | .section .ewram, "ax", %progbits ;@ For the GBA 148 | .align 2 149 | #endif 150 | ;@---------------------------------------------------------------------------- 151 | convertInput: ;@ Convert from device keys to target r0=input/output 152 | .type convertInput STT_FUNC 153 | ;@---------------------------------------------------------------------------- 154 | mvn r1,r0 155 | tst r1,#KEY_L|KEY_R ;@ Keys to open menu 156 | orreq r0,r0,#KEY_OPEN_MENU 157 | bx lr 158 | ;@---------------------------------------------------------------------------- 159 | refreshEMUjoypads: ;@ Call every frame 160 | ;@---------------------------------------------------------------------------- 161 | 162 | ldr r4,=frameTotal 163 | ldr r4,[r4] 164 | movs r0,r4,lsr#2 ;@ C=frame&2 (autofire alternates every other frame) 165 | ldr r4,EMUinput 166 | mov r3,r4 167 | and r0,r4,#0xf0 168 | ldr r2,joyCfg 169 | andcs r3,r3,r2 170 | tstcs r3,r3,lsr#10 ;@ NDS L? 171 | andcs r3,r3,r2,lsr#16 172 | adr r1,rlud2durl 173 | ldrb r0,[r1,r0,lsr#4] 174 | 175 | 176 | ands r1,r3,#3 ;@ A/B buttons 177 | cmpne r1,#3 178 | eorne r1,r1,#3 179 | tst r2,#0x400 ;@ Swap A/B? 180 | andne r1,r3,#3 181 | orr r0,r0,r1,lsl#4 182 | 183 | tst r4,#0x08 ;@ NDS Start 184 | tsteq r4,#0x400 ;@ NDS X 185 | orrne r0,r0,#0x40 ;@ NGP Option 186 | tst r4,#0x200 ;@ NDS L 187 | orrne r0,r0,#0x80 ;@ NGP D 188 | 189 | strb r0,systemMemory+0xB0 ;@ HW joypad 190 | 191 | mov r0,#0xFF 192 | tst r4,#0x04 ;@ NDS Select 193 | tsteq r4,#0x800 ;@ NDS Y 194 | bicne r0,r0,#0x01 ;@ NGP Power 195 | ldr r1,=gSubBatteryLevel 196 | ldr r1,[r1] 197 | tst r1,#0x2000000 ;@ Highest bit of subbattery level 198 | biceq r0,r0,#0x02 199 | strb r0,systemMemory+0xB1 ;@ HW powerbutton + subbattery 200 | 201 | bx lr 202 | 203 | joyCfg: .long 0x00ff01ff ;@ byte0=auto mask, byte1=(saves R), byte2=R auto mask 204 | ;@ bit 31=single/multi, 30,29=1P/2P, 27=(multi) link active, 24=reset signal received 205 | playerCount:.long 0 ;@ Number of players in multilink. 206 | .byte 0 207 | .byte 0 208 | .byte 0 209 | .byte 0 210 | rlud2durl: .byte 0x00,0x08,0x04,0x0C, 0x01,0x09,0x05,0x0D, 0x02,0x0A,0x06,0x0E, 0x03,0x0B,0x07,0x0F 211 | 212 | EMUinput: ;@ This label here for main.c to use 213 | .long 0 ;@ EMUjoypad (this is what Emu sees) 214 | 215 | ;@---------------------------------------------------------------------------- 216 | z80LatchW: ;@ Write communication latch (0x8000) 217 | ;@---------------------------------------------------------------------------- 218 | cmp addy,#0x8000 219 | strbeq r0,systemMemory+0xBC ;@ Z80 communication byte 220 | bxeq lr 221 | b empty_W 222 | ;@---------------------------------------------------------------------------- 223 | z80LatchR: ;@ Read communication latch (0x8000) 224 | ;@---------------------------------------------------------------------------- 225 | cmp addy,#0x8000 226 | bne empty_R 227 | stmfd sp!,{lr} 228 | mov r0,#0 229 | bl Z80SetNMIPinCurrentCpu 230 | ldmfd sp!,{lr} 231 | ldrb r0,systemMemory+0xBC ;@ Z80 communication byte 232 | bx lr 233 | 234 | ;@---------------------------------------------------------------------------- 235 | system_comms_read: ;@ r0 = (u8 *buffer) 236 | .type system_comms_read STT_FUNC 237 | ;@---------------------------------------------------------------------------- 238 | mov r0,#0 239 | bx lr 240 | ;@---------------------------------------------------------------------------- 241 | system_comms_write: ;@ r0 = (u8 data) 242 | .type system_comms_write STT_FUNC 243 | ;@---------------------------------------------------------------------------- 244 | mov r0,#0 245 | bx lr 246 | ;@---------------------------------------------------------------------------- 247 | updateSlowIO: ;@ Call once every frame, updates rtc and battery levels. 248 | ;@---------------------------------------------------------------------------- 249 | ldrb r0,rtcTimer 250 | subs r0,r0,#1 251 | movmi r0,#59 252 | strb r0,rtcTimer 253 | bxpl lr 254 | 255 | stmfd sp!,{r12,lr} 256 | blx getBatteryLevel ;@ Get NDS battery level. 257 | ldmfd sp!,{r12,lr} 258 | ldrb r1,lastBattery 259 | strb r0,lastBattery 260 | ldr r2,batteryLevel 261 | eor r1,r1,r0 262 | tst r1,#0xF 263 | beq notLowBatt 264 | ands r0,r0,#0xC 265 | bne notLowBatt 266 | cmp r2,#0x8400 267 | movcs r2,#0x8400 268 | notLowBatt: 269 | subs r2,r2,#1 270 | movmi r2,#1 271 | str r2,batteryLevel 272 | 273 | ldr r1,=gSubBatteryLevel 274 | ldr r0,[r1] 275 | subs r0,r0,#0x00000100 276 | movmi r0,#0x00001000 277 | str r0,[r1] 278 | 279 | adr r2,systemMemory 280 | ldrb r0,[r2,#0x90] ;@ RTC control 281 | tst r0,#1 ;@ Enabled? 282 | bxeq lr 283 | 284 | ldrb r0,[r2,#0x96] ;@ Seconds 285 | add r0,r0,#0x01 286 | and r1,r0,#0x0F 287 | cmp r1,#0x0A 288 | addpl r0,r0,#0x06 289 | cmp r0,#0x60 290 | movpl r0,#0 291 | strb r0,[r2,#0x96] ;@ Seconds 292 | bmi checkForAlarm 293 | 294 | ldrb r0,[r2,#0x95] ;@ Minutes 295 | add r0,r0,#0x01 296 | and r1,r0,#0x0F 297 | cmp r1,#0x0A 298 | addpl r0,r0,#0x06 299 | cmp r0,#0x60 300 | movpl r0,#0 301 | strb r0,[r2,#0x95] ;@ Minutes 302 | bmi checkForAlarm 303 | 304 | ldrb r0,[r2,#0x94] ;@ Hours 305 | add r0,r0,#0x01 306 | and r1,r0,#0x0F 307 | cmp r1,#0x0A 308 | addpl r0,r0,#0x06 309 | cmp r0,#0x24 310 | movpl r0,#0 311 | strb r0,[r2,#0x94] ;@ Hours 312 | bmi checkForAlarm 313 | 314 | ldrb r0,[r2,#0x93] ;@ Days 315 | add r0,r0,#0x01 316 | and r1,r0,#0x0F 317 | cmp r1,#0x0A 318 | addpl r0,r0,#0x06 319 | cmp r0,#0x32 320 | movpl r0,#0 321 | strb r0,[r2,#0x93] ;@ Days 322 | bmi checkForAlarm 323 | 324 | ldrb r0,[r2,#0x92] ;@ Months 325 | add r0,r0,#0x01 326 | and r1,r0,#0x0F 327 | cmp r1,#0x0A 328 | addpl r0,r0,#0x06 329 | cmp r0,#0x13 330 | movpl r0,#1 331 | strb r0,[r2,#0x92] ;@ Months 332 | 333 | checkForAlarm: 334 | ldrb r0,[r2,#0x96] ;@ Seconds 335 | cmp r0,#0x00 336 | ldrbeq r0,[r2,#0x95] ;@ RTC Minutes 337 | ldrbeq r1,[r2,#0x9A] ;@ ALARM Minutes 338 | cmpeq r0,r1 339 | ldrbeq r0,[r2,#0x94] ;@ RTC Hours 340 | ldrbeq r1,[r2,#0x99] ;@ ALARM Hours 341 | cmpeq r0,r1 342 | ldrbeq r0,[r2,#0x93] ;@ RTC Days 343 | ldrbeq r1,[r2,#0x98] ;@ ALARM Days 344 | cmpeq r0,r1 345 | moveq r0,#0x0A 346 | beq setInterrupt 347 | 348 | bx lr 349 | 350 | ;@---------------------------------------------------------------------------- 351 | ADStart: 352 | ;@---------------------------------------------------------------------------- 353 | tst r0,#0x04 354 | bxeq lr 355 | ldr r0,batteryLevel 356 | orr r0,r0,#0x3F ;@ bit 0=ready, bit 1-5=1. 357 | strh r0,systemMemory+0x60 358 | mov r0,#0x1C 359 | b setInterrupt 360 | 361 | ;@---------------------------------------------------------------------------- 362 | Z80In: 363 | ;@---------------------------------------------------------------------------- 364 | mov r11,r11 ;@ No$GBA breakpoint 365 | mov r0,#0 366 | bx lr 367 | ;@---------------------------------------------------------------------------- 368 | Z80Out: 369 | ;@---------------------------------------------------------------------------- 370 | ;@ mov r11,r11 ;@ No$GBA breakpoint 371 | mov r0,#0 372 | b Z80SetIRQPinCurrentCpu 373 | ;@---------------------------------------------------------------------------- 374 | gSubBatteryLevel: 375 | .long 0x3000000 ;@ subBatteryLevel 376 | batteryLevel: 377 | .long 0xFFFF ;@ Max = 0xFFFF (0x3FF) 378 | ;@ To start > 0x8400 (0x210) 379 | ;@ Low < 0x8000 (0x200) 380 | ;@ Bad < 0x7880 (0x1E2) 381 | ;@ Shutdown <= 0x74C0 (0x1D3) 382 | ;@ Alarm minimum = 0x5B80 (0x16E) 383 | ;@---------------------------------------------------------------------------- 384 | systemMemory: 385 | .space 0x100 386 | 387 | lastBattery: 388 | .byte 0 389 | rtcTimer: 390 | .byte 0 391 | sc0Buf: 392 | .byte 0 393 | commStatus: 394 | .byte 0 395 | 396 | ;@---------------------------------------------------------------------------- 397 | .end 398 | #endif // #ifdef __arm__ 399 | --------------------------------------------------------------------------------