├── LICENSE ├── Makefile ├── Makefile.gc ├── Makefile.wii ├── NeoCDRX ├── NeoCDRX_manual.pdf ├── icon.png └── meta.xml ├── NeoCDRX_manual.pdf ├── README.md ├── build_cpu └── m68kmake.exe └── src ├── cdaudio ├── cdaudio.c └── cdaudio.h ├── cdrom ├── cdrom.c └── cdrom.h ├── cpu ├── cpuintf.c └── cpuintf.h ├── fileio ├── ata.c ├── ata.h ├── dirsel.c ├── dirsel.h ├── dvdfileio.c ├── dvdfileio.h ├── fileio.c ├── fileio.h ├── iso9660.c ├── iso9660.h ├── sdfileio.c ├── sdfileio.h ├── wkf.c └── wkf.h ├── input ├── input.c └── input.h ├── m68000 ├── Makefile ├── doc │ ├── example.zip │ ├── history.txt │ └── readme.txt ├── m68k.h ├── m68k_in.c ├── m68kconf.h ├── m68kcpu.c ├── m68kcpu.h ├── m68kdasm.c ├── m68kmake.c ├── m68kmake.exe ├── m68kmame.c ├── m68kmame.h ├── m68kopac.c ├── m68kopdm.c ├── m68kopnz.c ├── m68kops.c ├── m68kops.h └── neocd68k.c ├── mcard ├── icon.h ├── mcard.c └── mcard.h ├── memory ├── memory.c └── memory.h ├── ncdr_rom.c ├── ncdr_rom.h ├── neocdrx.c ├── neocdrx.h ├── pd4990a ├── pd4990a.c └── pd4990a.h ├── sound ├── 2610intf.c ├── 2610intf.h ├── ay8910.c ├── ay8910.h ├── eq.c ├── eq.h ├── fm.c ├── fm.h ├── gcaudio.c ├── gcaudio.h ├── madfilter.c ├── madfilter.h ├── mixer.c ├── mixer.h ├── sound.c ├── sound.h ├── streams.c ├── streams.h ├── timer.c ├── timer.h ├── ymdeltat.c └── ymdeltat.h ├── video ├── backdrop.h ├── banner.h ├── draw_fix.c ├── gui.c ├── gui.h ├── gxvideo.c ├── gxvideo.h ├── patches.c ├── patches.h ├── scale2x.c ├── video.c └── video.h ├── z80 ├── Makefile ├── z80.c ├── z80.h ├── z80daisy.c ├── z80daisy.h ├── z80dasm.c └── z80dasm.h └── z80i ├── z80intrf.c └── z80intrf.h /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY = all wii gc wii-clean gc-clean wii-run gc-run 2 | 3 | all: wii gc 4 | 5 | clean: wii-clean gc-clean 6 | 7 | clean-all: clean wii-clean-cpus 8 | 9 | wii: 10 | $(MAKE) -f Makefile.wii 11 | 12 | wii-clean: 13 | $(MAKE) -f Makefile.wii clean 14 | 15 | wii-clean-cpus: 16 | $(MAKE) -f Makefile.wii cpus-clean 17 | 18 | wii-run: 19 | $(MAKE) -f Makefile.wii run 20 | 21 | gc: 22 | $(MAKE) -f Makefile.gc 23 | 24 | gc-clean: 25 | $(MAKE) -f Makefile.gc clean 26 | 27 | gc-clean-cpus: 28 | $(MAKE) -f Makefile.gc cpus-clean 29 | 30 | gc-run: 31 | $(MAKE) -f Makefile.gc run -------------------------------------------------------------------------------- /Makefile.gc: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(DEVKITPPC)),) 7 | $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") 8 | endif 9 | 10 | include $(DEVKITPPC)/gamecube_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # INCLUDES is a list of directories containing extra header files 17 | #--------------------------------------------------------------------------------- 18 | TARGET := neocd-rx_cube 19 | TARGETDIR := executables 20 | BUILD := build_cube 21 | SOURCES := src/fileio src src/cdaudio src/cdrom src/z80i \ 22 | src/memory src/pd4990a src/cpu src/input src/video \ 23 | src/mcard src/sound 24 | 25 | INCLUDES := src/z80 src/m68000 $(SOURCES) 26 | 27 | #--------------------------------------------------------------------------------- 28 | # options for code generation 29 | #--------------------------------------------------------------------------------- 30 | 31 | CFLAGS = -O3 -Wall $(MACHDEP) $(INCLUDE) \ 32 | -fstrict-aliasing -fomit-frame-pointer \ 33 | -DTHREADED_AUDIO 34 | CXXFLAGS = $(CFLAGS) 35 | LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map 36 | 37 | #--------------------------------------------------------------------------------- 38 | # any extra libraries we wish to link with the project 39 | #--------------------------------------------------------------------------------- 40 | LIBS := -lfat -logc -lm -lz -lmad -ldb -L ./../build_cpu -lz80 -lmc68000 41 | 42 | #--------------------------------------------------------------------------------- 43 | # list of directories containing libraries, this must be the top level containing 44 | # include and lib 45 | #--------------------------------------------------------------------------------- 46 | LIBDIRS := $(PORTLIBS) 47 | 48 | #--------------------------------------------------------------------------------- 49 | # no real need to edit anything past this point unless you need to add additional 50 | # rules for different file extensions 51 | #--------------------------------------------------------------------------------- 52 | ifneq ($(BUILD),$(notdir $(CURDIR))) 53 | #--------------------------------------------------------------------------------- 54 | 55 | export OUTPUT := $(CURDIR)/$(TARGET) 56 | 57 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 58 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 59 | 60 | export DEPSDIR := $(CURDIR)/$(BUILD) 61 | 62 | #--------------------------------------------------------------------------------- 63 | # automatically build a list of object files for our project 64 | #--------------------------------------------------------------------------------- 65 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 66 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 67 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 68 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 69 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 70 | 71 | #--------------------------------------------------------------------------------- 72 | # use CXX for linking C++ projects, CC for standard C 73 | #--------------------------------------------------------------------------------- 74 | ifeq ($(strip $(CPPFILES)),) 75 | export LD := $(CC) 76 | else 77 | export LD := $(CXX) 78 | endif 79 | 80 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 81 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 82 | $(sFILES:.s=.o) $(SFILES:.S=.o) 83 | 84 | #--------------------------------------------------------------------------------- 85 | # build a list of include paths 86 | #--------------------------------------------------------------------------------- 87 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 88 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 89 | -I$(CURDIR)/$(BUILD) \ 90 | -I$(LIBOGC_INC) 91 | 92 | #--------------------------------------------------------------------------------- 93 | # build a list of library paths 94 | #--------------------------------------------------------------------------------- 95 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 96 | -L$(LIBOGC_LIB) 97 | 98 | export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) 99 | .PHONY: $(BUILD) clean cpus cpus-clean 100 | 101 | #--------------------------------------------------------------------------------- 102 | $(BUILD): 103 | @if test -d build_cpus; then echo ""; else [ -d $@ ] || mkdir -p build_cpu; cd src/m68000 && $(MAKE);cd ..; cd ..; cd src/z80 && $(MAKE); fi 104 | @[ -d $@ ] || mkdir -p $@ 105 | @echo "" 106 | @echo "*** NeoCD RX Gamecube ******************************************************" 107 | @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) 108 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc 109 | @echo "*************************************************************** Yay! \o/ ***" 110 | 111 | #--------------------------------------------------------------------------------- 112 | clean: 113 | @echo clean gc... 114 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol 115 | 116 | cpus: 117 | @[ -d $@ ] || mkdir -p build_cpu 118 | @cd src/m68000 && $(MAKE) 119 | @cd src/z80 && $(MAKE) 120 | 121 | cpus-clean: 122 | @rm -fr build_cpu 123 | 124 | #--------------------------------------------------------------------------------- 125 | all: cpus $(BUILD) 126 | 127 | clean-all: clean cpus-clean 128 | #--------------------------------------------------------------------------------- 129 | run: 130 | dolphin-emu -e $(OUTPUT).elf 131 | 132 | run-dol: 133 | $(DEVKITPRO)/emulators/gcube/gcube $(OUTPUT).dol 134 | 135 | #--------------------------------------------------------------------------------- 136 | else 137 | 138 | DEPENDS := $(OFILES:.o=.d) 139 | 140 | #--------------------------------------------------------------------------------- 141 | # main targets 142 | #--------------------------------------------------------------------------------- 143 | $(OUTPUT).dol: $(OUTPUT).elf 144 | $(OUTPUT).elf: $(OFILES) 145 | 146 | #--------------------------------------------------------------------------------- 147 | endif 148 | #--------------------------------------------------------------------------------- 149 | -------------------------------------------------------------------------------- /Makefile.wii: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(DEVKITPPC)),) 7 | $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") 8 | endif 9 | 10 | include $(DEVKITPPC)/wii_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # INCLUDES is a list of directories containing extra header files 17 | #--------------------------------------------------------------------------------- 18 | TARGET := neocd-rx_wii 19 | TARGETDIR := executables 20 | BUILD := build_wii 21 | SOURCES := src/fileio src src/cdaudio src/cdrom src/z80i \ 22 | src/memory src/pd4990a src/cpu src/input src/video \ 23 | src/mcard src/sound 24 | 25 | INCLUDES := src/z80 src/m68000 $(SOURCES) 26 | 27 | #--------------------------------------------------------------------------------- 28 | # options for code generation 29 | #--------------------------------------------------------------------------------- 30 | 31 | CFLAGS = -O3 -fomit-frame-pointer -mrvl -Wall -Wno-strict-aliasing $(MACHDEP) $(INCLUDE) -DHW_RVL \ 32 | -DTHREADED_AUDIO 33 | CXXFLAGS = $(CFLAGS) 34 | LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map 35 | 36 | #--------------------------------------------------------------------------------- 37 | # any extra libraries we wish to link with the project 38 | #--------------------------------------------------------------------------------- 39 | LIBS := -ldi -lfat -lwiiuse -lbte -logc -lm -lz -lmad -L ./../build_cpu -lz80 -lmc68000 40 | 41 | #--------------------------------------------------------------------------------- 42 | # list of directories containing libraries, this must be the top level containing 43 | # include and lib 44 | #--------------------------------------------------------------------------------- 45 | LIBDIRS := $(PORTLIBS) 46 | 47 | #--------------------------------------------------------------------------------- 48 | # no real need to edit anything past this point unless you need to add additional 49 | # rules for different file extensions 50 | #--------------------------------------------------------------------------------- 51 | ifneq ($(BUILD),$(notdir $(CURDIR))) 52 | #--------------------------------------------------------------------------------- 53 | 54 | export OUTPUT := $(CURDIR)/$(TARGET) 55 | 56 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 57 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 58 | 59 | export DEPSDIR := $(CURDIR)/$(BUILD) 60 | 61 | #--------------------------------------------------------------------------------- 62 | # automatically build a list of object files for our project 63 | #--------------------------------------------------------------------------------- 64 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 65 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 66 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 67 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 68 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 69 | 70 | #--------------------------------------------------------------------------------- 71 | # use CXX for linking C++ projects, CC for standard C 72 | #--------------------------------------------------------------------------------- 73 | ifeq ($(strip $(CPPFILES)),) 74 | export LD := $(CC) 75 | else 76 | export LD := $(CXX) 77 | endif 78 | 79 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 80 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 81 | $(sFILES:.s=.o) $(SFILES:.S=.o) 82 | 83 | #--------------------------------------------------------------------------------- 84 | # build a list of include paths 85 | #--------------------------------------------------------------------------------- 86 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 87 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 88 | -I$(CURDIR)/$(BUILD) \ 89 | -I$(LIBOGC_INC) 90 | 91 | #--------------------------------------------------------------------------------- 92 | # build a list of library paths 93 | #--------------------------------------------------------------------------------- 94 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 95 | -L$(LIBOGC_LIB) 96 | 97 | export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) 98 | .PHONY: $(BUILD) clean cpus cpus-clean 99 | 100 | #--------------------------------------------------------------------------------- 101 | $(BUILD): 102 | @if test -d build_cpus; then echo ""; else [ -d $@ ] || mkdir -p build_cpu; cd src/m68000 && $(MAKE);cd ..; cd ..; cd src/z80 && $(MAKE); fi 103 | @[ -d $@ ] || mkdir -p $@ 104 | @echo "" 105 | @echo "*** NeoCD RX Wii ******************************************************" 106 | @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) 107 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii 108 | @echo "*************************************************************** Yay! \o/ ***" 109 | 110 | #--------------------------------------------------------------------------------- 111 | clean: 112 | @echo clean wii... 113 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol 114 | 115 | cpus: 116 | @[ -d $@ ] || mkdir -p build_cpu 117 | @cd src/m68000 && $(MAKE) 118 | @cd src/z80 && $(MAKE) 119 | 120 | cpus-clean: 121 | @rm -fr build_cpu 122 | 123 | #--------------------------------------------------------------------------------- 124 | all: cpus $(BUILD) 125 | 126 | clean-all: clean cpus-clean 127 | #--------------------------------------------------------------------------------- 128 | run: 129 | dolphin-emu -e $(OUTPUT).elf 130 | 131 | run-dol: 132 | $(DEVKITPRO)/emulators/gcube/gcube $(OUTPUT).dol 133 | 134 | #--------------------------------------------------------------------------------- 135 | else 136 | 137 | DEPENDS := $(OFILES:.o=.d) 138 | 139 | #--------------------------------------------------------------------------------- 140 | # main targets 141 | #--------------------------------------------------------------------------------- 142 | $(OUTPUT).dol: $(OUTPUT).elf 143 | $(OUTPUT).elf: $(OFILES) 144 | 145 | #--------------------------------------------------------------------------------- 146 | endif 147 | #--------------------------------------------------------------------------------- 148 | -------------------------------------------------------------------------------- /NeoCDRX/NeoCDRX_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niuus/NeoCDRX/676eee0a335cccf0a3b86dfc5a17198494922a6a/NeoCDRX/NeoCDRX_manual.pdf -------------------------------------------------------------------------------- /NeoCDRX/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niuus/NeoCDRX/676eee0a335cccf0a3b86dfc5a17198494922a6a/NeoCDRX/icon.png -------------------------------------------------------------------------------- /NeoCDRX/meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NeoCD RX 4 | NiuuS 5 | 1.0.02 6 | 20230403142522 7 | Neo Geo CD Emulator 8 | Features: 9 | - Wiimote, Wiimote Plus, Wiimote+Nunchuk, and GameCube controller support 10 | - Neo Geo CD Virtual Memory Card saving to SD/USB or physical GameCube card for max nostalgia! 11 | - Region select for uncut content and extra languages 12 | - Super fast loading times, unlike the original console! 13 | - UStealth USB devices support 14 | - SD/SDHC, USB, WKF (GameCube), IDE-EXI V1, DVD support 15 | - Sound FX / Music 3-Band equalizer 16 | 17 | NeoCDRX is a Neo-Geo CD/CDZ emulator, running on the GameCube, Wii, and Wii U's Virtual Wii, forked from NEO-CD REDUX. 18 | 19 | Please read the NeoCDRX_manual.pdf included in the zip. 20 | https://github.com/niuus/NeoCDRX 21 | 22 | 23 | -------------------------------------------------------------------------------- /NeoCDRX_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niuus/NeoCDRX/676eee0a335cccf0a3b86dfc5a17198494922a6a/NeoCDRX_manual.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NeoCD RX 2 | https://github.com/niuus/NeoCDRX/ 3 | 4 | **_NeoCD RX_** is a _Neo Geo CD / Neo Geo CDZ_ emulator for the _GameCube_, _Wii_, and _Wii U_'s 5 | Virtual Wii. It owes its existence to various other emulators: 6 | **_NEO-CD REDUX_** (Softdev), **_NeoGeo CD Redux_** (Infact), **_NeoCD-Wii_** (Wiimpathy 7 | / Jacobeian), **_NeoCD Redux Unofficial_** (megalomaniac). **_NEO-CD REDUX_** was itself 8 | based on **_NeoCD/SDL_** 0.3.1 (Foster) and **_NeoGeo CDZ_** (NJ) emulator, 9 | which are source ports of the original **_NeoCD_** emulator (Fabrice Martinez). 10 | 11 | **_NeoCD RX_** is a "homebrew application" which means you will need a way to run 12 | unsigned code on your Nintendo Wii. The best website for getting started with 13 | Wii homebrew is WiiBrew (www.wiibrew.org). 14 | 15 | Based/forked from: 16 | https://github.com/emukidid/neogeo-cd-redux 17 | 18 | (Under GPL License) 19 | 20 | 21 | ## FEATURES 22 | 23 | * Z80 emulator core 3.6 24 | * M68000 emulator core 3.3 25 | * Wii Remote, Wii Remote Plus, Wii Remote+Nunchuk, and GameCube controller support 26 | * SD/SDHC, USB, WKF (GameCube), IDE-EXI V1, DVD support 27 | * UStealth USB devices support 28 | * Region select for uncut content and extra languages (USA / Europe / Japan) 29 | * Neo Geo CD Virtual Memory Card (8KiB battery-backed SRAM chip) support. Save directly to SD/USB or to your physical GameCube card for max nostalgia! 30 | * Sound FX / Music 3-Band equalizer 31 | * Super fast loading times. Original console weakness is no more! 32 | * Available in various skins/colors 33 | * Open Source! 34 | 35 | 36 | ## RECENT CHANGELOG 37 | 38 | [1.0.02 - April 03, 2023] 39 | * First release. 40 | * Fully working SDHC & USB support. You shouldn't see the emulator complaining again about the BIOS not being found, if you already have the proper file in the correct folder, specially on USB devices. 41 | * Virtual Neo Geo Memory Card saving is fixed again. Use SD/USB or the GameCube Memory Card, the latter also works on Wii (backwards compatible unit). 42 | * Fixed GameCube controller analog stick support. It wasn't working on Wii, only when used on a GameCube console. 43 | * Rearranged internal menus for future expansion. 44 | * Some tidying up. 45 | 46 | [older update history in the **NeoCDRX_manual.pdf**] 47 | https://github.com/niuus/NeoCDRX/blob/main/NeoCDRX_manual.pdf 48 | 49 | 50 | ## INSTALLATION AND USE 51 | 52 | To use NeoCD-RX on the Wii / Wii U's Virtual Wii, you will need to extract the 53 | "**_apps_**" and "**_NeoCDRX_**" folders (directories) from the .zip directly to the root 54 | of your SD or USB media. It comes pre-packaged in the Homebrew Channel format, 55 | also compatible with the official forwarders. Then, you need to place your game 56 | files and music tracks into individually named folders inside the "**_\NeoCDRX\games_**" 57 | directory (an in-depth explanation for this in the correspondent section further below). 58 | For the GameCube port, you only need to take care of the "**_NeoCDRX_**" folder included. 59 | 60 | Finally, you need to obtain a proper dump of the _Neo Geo CD/CDZ_ console BIOS. 61 | Copy the file inside the "**_\NeoCDRX\bios_**" directory and name it "**_NeoCD.bin_**". 62 | The emulator only works with the following: 63 | 64 | ``` 65 | Neo Geo CDZ BIOS (NeoCD.bin) 66 | Size: 524.288 bytes 67 | CRC32: DF9DE490 68 | MD5: F39572AF7584CB5B3F70AE8CC848ABA2 69 | SHA-1: 7BB26D1E5D1E930515219CB18BCDE5B7B23E2EDA 70 | ``` 71 | ``` 72 | Neo Geo CDZ BIOS (NeoCD.bin) 73 | Size: 524.288 bytes 74 | CRC32: 33697892 75 | MD5: 11526D58D4C524DAEF7D5D677DC6B004 76 | SHA-1: B0F1C4FA8D4492A04431805F6537138B842B549F 77 | ``` 78 | 79 | Once you are done, you can proceed to run the emulator. Additionally, you can 80 | install the NeoCD-RX Forwarder Channel in your _Wii_ or _vWii_ System Menu, or the 81 | special NeoCD-RX Channel for Wii U, which reads the configuration and necessary 82 | files from your device "**_\NeoCDRX_**" folder, be it SD or USB. 83 | 84 | 85 | ## CONFIGURATION 86 | 87 | To configure NeoCD-RX, press 'A' on the "Settings" box. This will bring up a 88 | screen where you can configure "Region", "Save Device", and "FX / Music Equalizer". 89 | 90 | ``` 91 | • "Region" will allow you to change the emulated console region, to access other 92 | languages and in some cases, change or uncensor game content (fatalities, blood, 93 | difficulty, lives, title screens, etc.). Reload the game (not reset) for the 94 | setting to take effect. 95 | 96 | • "Save Device" offers two options, use "SD/USB" to save the SRAM memory 97 | (sort of a virtual memory card implemented inside the real Neo Geo CD console) 98 | directly to the media drive, or use "MEM Card" to save to a physical GameCube 99 | Memory Card, as you would on a real Neo Geo AES, to take your progress to 100 | another console, or just for the nostalgia factor. 101 | 102 | • "FX / Music Equalizer" allows you to raise the volume on sound FX or MP3 103 | tracks, or raise the gain in Low / Mid / High frequencies to your liking. 104 | ``` 105 | 106 | 107 | ## PREPARING THE GAMES FOR USE WITH THE EMULATOR 108 | 109 | For every game disc, you need to create a subdirectory inside the included 110 | "**_\NeoCDRX\games_**" named whatever you like, and copy all the game data files 111 | there. Inside this folder, create another subdirectory called "**_mp3_**", where 112 | you have to copy your music tracks. **IMPORTANT**: even if you won't use the 113 | music, the folder is needed. 114 | 115 | The music tracks need to be encoded from the original CD's Red Book standard 116 | 44.1 kHz WAV, to MP3 format (128kbps minimum, or better), named exactly 117 | "**_TrackXX.mp3_**" where XX is a number that always starts at 02, as the data 118 | track is always 01. Free CD audio ripping software is readily available. 119 | 120 | Examples and pictures are inside the **NeoCDRX_manual.pdf** 121 | https://github.com/niuus/NeoCDRX/blob/main/NeoCDRX_manual.pdf 122 | 123 | After this, you are more than ready to start playing. Each game folder you 124 | make will be treated by the emulator as a full CD. 125 | 126 | 127 | ## SUPPORTED CONTROLLERS 128 | 129 | NeoCD RX currently supports the following: 130 | 131 | ``` 132 | • Wii Remote (horizontal) 133 | 134 | • Wii Remote Plus (or Wii MotionPlus adapter) 135 | 136 | • Wii Remote+Nunchuk 137 | 138 | • GameCube controller 139 | ``` 140 | 141 | ## DEFAULT MAPPINGS 142 | 143 | ### GameCube Controller 144 | Neo Geo A = B 145 | Neo Geo B = A 146 | Neo Geo C = Y 147 | Neo Geo D = X 148 | Neo Geo Select = Z 149 | Neo Geo Start = START 150 | Neo Geo directions = Dpad or Analog Stick 151 | ### Wii Remote (horizontal) 152 | Neo Geo A = 1 153 | Neo Geo B = 2 154 | Neo Geo C = B 155 | Neo Geo D = A 156 | Neo Geo Select = MINUS (-) 157 | Neo Geo Start = PLUS (+) 158 | Neo Geo directions = Dpad (horizontal) 159 | ### Wii Remote+ Nunchuk 160 | Neo Geo A = A 161 | Neo Geo B = B 162 | Neo Geo C = PLUS (+) 163 | Neo Geo D = 1 164 | Neo Geo Select = MINUS (-) 165 | Neo Geo Start = PLUS (+) 166 | Neo Geo directions = Analog Stick 167 | 168 | 169 | ## EMULATOR MAPPINGS 170 | 171 | _Force saving to Virtual Memory Card (while in-game, for the games that 172 | support it)_ 173 | ``` 174 | "R" button (GameCube controller) 175 | "PLUS (+)" and "MINUS (-)" buttons together (Wii Remote / Wii Remote+Nunchuk) 176 | ``` 177 | _Navigation_ 178 | ``` 179 | Dpad or Left Analog Stick (GameCube controller) 180 | Dpad (Horizontal Wii Remote) 181 | Dpad or Nunchuk Analog Stick (Wii Remote+Nunchuk) 182 | ``` 183 | _Enter directory or Menu option / Change setting_ 184 | ``` 185 | "A" button (GameCube controller) 186 | Button "2" (Wii Remote / Wii Remote+Nunchuk) 187 | ``` 188 | _Go back from any Menu_ 189 | ``` 190 | "B" button (GameCube controller) 191 | Button "1" (Wii Remote / Wii Remote+Nunchuk) 192 | ``` 193 | _Go back from Game List_ 194 | ``` 195 | "Z" button (GameCube controller) 196 | Button "HOME" (Wii Remote / Wii Remote+Nunchuk) 197 | ``` 198 | _Navigate one page forward on the Game List (when you have more than 8 titles)_ 199 | ``` 200 | "R" button (GameCube controller) 201 | "PLUS (+)" button (Wii Remote / Wii Remote+Nunchuk) 202 | ``` 203 | _Navigate one page backwards on the Game List (when you have more than 8 titles)_ 204 | ``` 205 | "L" button (GameCube controller) 206 | "MINUS (-)" button (Wii Remote / Wii Remote+Nunchuk) 207 | ``` 208 | _Mount and run a valid game directory_ 209 | ``` 210 | "A" button (GameCube controller) 211 | Button "2" (Wii Remote / Wii Remote+Nunchuk) 212 | ``` 213 | _Failsafe video mode (Force Menu to 480i with Component / Digital cable)_ 214 | ``` 215 | Hold "L" button right before the emulator is loading to activate 216 | ``` 217 | 218 | 219 | ## CREDITS & THANKS 220 | ``` 221 | • NeoCD-Wii (Wiimpathy / Jacobeian) 222 | • NeoCD Redux Unofficial (megalomaniac) 223 | • NeoGeo CD Redux (Infact) 224 | • NEO-CD REDUX (softdev) 225 | • NeoCD/SDL 0.3.1 (Foster) 226 | • NeoGeo CDZ (NJ) 227 | • NeoCD 0.8 (Fabrice Martinez) 228 | • [M68000 C Core](https://github.com/kstenerud/Musashi) (Karl Stenerud) 229 | • [MAME Z80 C Core](https://github.com/mamedev/mame/tree/master/src/devices/cpu/z80) (Juergen Buchmueller) 230 | • Sound Core (MAMEDev.org) 231 | • The EQ Cookbook (Neil C / Etanza Systems) 232 | • The EQ Cookbook (float only version code - Shagkur) 233 | • WKF & IDE-EXI V1 (code from [Swiss GC](https://github.com/emukidid/swiss-gc) - emu_kidid) 234 | • libMAD (Underbit Technologies) 235 | • libZ (zlib.org) 236 | • TehSkeen forum (2006-2009) 237 | • NeoCDRX emu bg - Style 1 (catar1n0) 238 | • NeoCDRX menu design (NiuuS) 239 | ``` 240 | 241 | 242 | ## RELEVANT LINKS 243 | 244 | * Newest/Latest NeoCDRX release at: 245 | https://github.com/niuus/NeoCDRX/releases 246 | -------------------------------------------------------------------------------- /build_cpu/m68kmake.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niuus/NeoCDRX/676eee0a335cccf0a3b86dfc5a17198494922a6a/build_cpu/m68kmake.exe -------------------------------------------------------------------------------- /src/cdaudio/cdaudio.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #ifndef CDAUDIO_H 8 | #define CDAUDIO_H 9 | 10 | /*** NeoCD/SDL CDaudio - modified for MP3 playback ***/ 11 | 12 | //-- Exported Variables ------------------------------------------------------ 13 | extern int cdda_first_drive; 14 | extern int cdda_nb_of_drives; 15 | extern int cdda_current_drive; 16 | extern int cdda_current_track; 17 | extern int cdda_playing; 18 | extern char drive_list[32]; 19 | extern int nb_of_drives; 20 | extern int cdda_autoloop; 21 | extern char cddapath[1024]; 22 | 23 | //-- Exported Functions ------------------------------------------------------ 24 | int cdda_init(void); 25 | int cdda_play(int); 26 | void cdda_pause(void); 27 | void cdda_stop(void); 28 | void cdda_resume(void); 29 | void cdda_shutdown(void); 30 | void cdda_loop_check(void); 31 | int cdda_get_disk_info(void); 32 | void cdda_build_drive_list(void); 33 | int cdda_get_volume(void); 34 | void cdda_set_volume(int volume); 35 | void audio_setup(void); 36 | 37 | //-- libMP3 ----------------------------------------------------------------- 38 | int mp3_decoder(int len, char *outbuffer); 39 | 40 | #define MP3PLAYING 1 41 | #define MP3NOTPLAYING 2 42 | #define MP3PAUSED 3 43 | 44 | #endif /* CDAUDIO_H */ 45 | -------------------------------------------------------------------------------- /src/cdrom/cdrom.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niuus/NeoCDRX/676eee0a335cccf0a3b86dfc5a17198494922a6a/src/cdrom/cdrom.c -------------------------------------------------------------------------------- /src/cdrom/cdrom.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * CDROM Data interface 9 | * 10 | * Simulate all CDROM reading using standard files. 11 | ****************************************************************************/ 12 | #ifndef __NEOCDROM__ 13 | #define __NEOCDROM__ 14 | 15 | /*** Globals ***/ 16 | extern char cdpath[1024]; 17 | extern int img_display; 18 | extern int ipl_in_progress; 19 | 20 | /*** Prototypes ***/ 21 | int cdrom_process_ipl(void); 22 | int recon_filetype(char *ext); 23 | int cdrom_mount(char *mount); 24 | void cdrom_load_files(void); 25 | void neogeo_upload(void); 26 | void cdrom_load_title(void); 27 | int cdrom_process_ipl(void); 28 | void neogeo_end_upload(void); 29 | void neogeo_start_upload(void); 30 | void neogeo_ipl(void); 31 | 32 | typedef struct 33 | { 34 | char fname[16]; 35 | short bank; 36 | int offset; 37 | int unk1; 38 | short unk2; 39 | short image; 40 | short unk3; 41 | } 42 | __attribute__ ((__packed__)) LOADFILE; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/cpu/cpuintf.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * NeoCD/SDL CPU Timer Interface 9 | * 10 | * Module to schedule CPU, sound timers and interrupts 11 | ****************************************************************************/ 12 | #include 13 | #include 14 | #include 15 | #include "neocdrx.h" 16 | 17 | CPU CPU_Z80; 18 | static CPU CPU_M68K; 19 | 20 | #define TIMESLICE 264 21 | #define M68SEC 12000000 22 | #define Z80SEC 4000000 23 | #define M68FRAME ( M68SEC / 60 ) 24 | #define Z80FRAME ( Z80SEC / 60 ) 25 | #define Z80SCANLINE ( Z80FRAME / TIMESLICE ) 26 | #define M68SCANLINE ( M68FRAME / TIMESLICE ) 27 | 28 | static int inited = 0; 29 | static int raster_interrupt_enabled = 0; 30 | int scanline = 0; 31 | 32 | /**************************************************************************** 33 | * Individual Game Configs 34 | * 35 | * List contains games which do not match the standard configuration 36 | ****************************************************************************/ 37 | static GAMECONFIG gameconfig[] = { 38 | {"THE LAST BLADE 2", 1, 1}, /* 1 */ 39 | {"ART OF FIGHTING2", 0, 1}, /* 2 */ 40 | {"FATAL FURY 3", 0, 1}, /* 3 */ 41 | {"F. HISTORY", 0, 1}, /* 5 */ 42 | {"NEO TURF MASTERS", 0, 1}, /* 6 */ 43 | {"BREAKERS", 0, 1}, /* 7 */ 44 | {"THE LAST BLADE", 0, 1}, /* 8 */ 45 | {"K.O.F.'98", 0, 1}, /* 9 */ 46 | {"DARK KOMBAT", 0, 1}, /* 10 */ 47 | {"OVER TOP", 0, 1}, /* 11 */ 48 | {"NINJA COMBAT", 0, 1}, /* 12 */ 49 | {"RIDING HERO", 0, 2}, /* 13 */ 50 | {"SENGOKU", 0, 1}, /* 14 */ 51 | {"SENGOKU 2", 0, 1}, /* 15 */ 52 | {"Top Hunter", 0, 1}, /* 16 */ 53 | {"TOP PLAYERS GOLF", 0, 1}, /* 17 */ 54 | {"SUPER SIDEKICKS2", 0, 1}, /* 18 */ 55 | {"POWER SPIKES II", 0, 1}, /* 19 */ 56 | {"SUPER SIDEKICKS3", 0, 1}, /* 20 */ 57 | {"SamuraiShodown 3", 0, 1}, /* 21 */ 58 | {"PULSTAR", 0, 1}, /* 22 */ 59 | {"THRASH RALLY CD", 0, 1}, /* 23 */ 60 | {"VIEW-POINT", 0, 1}, /* 27 */ 61 | {"WINDJAMMERS", 0, 1}, /* 28 */ 62 | {"STREET SLAM", 0, 1}, /* 29 */ 63 | {"",0,0} 64 | }; 65 | 66 | /**************************************************************************** 67 | * NeoGeo Configure Game 68 | * Game name is always passed as ENGLISH name 69 | ****************************************************************************/ 70 | void 71 | neogeo_configure_game (char *gamename) 72 | { 73 | int i = 0; 74 | 75 | nowait_irqack = 0; 76 | raster_interrupt_enabled = 0; 77 | 78 | while( strlen(gameconfig[i].gamename) ) 79 | { 80 | if (stricmp (gamename, gameconfig[i].gamename) == 0) 81 | { 82 | nowait_irqack = gameconfig[i].nowait_irqack; 83 | raster_interrupt_enabled = gameconfig[i].raster_interrupt_enabled; 84 | 85 | /*** be verbose ***/ 86 | /* 87 | ActionScreen(gamename); 88 | */ 89 | break; 90 | } 91 | i++; 92 | } 93 | 94 | CPU_Z80.boost = CPU_M68K.boost = 0; 95 | } 96 | 97 | /**************************************************************************** 98 | * neogeo_runframe 99 | * 100 | * This function will run a complete video frame for NeoCD. 101 | * CPU initialization etc is performed in neocd.c as usual. 102 | ****************************************************************************/ 103 | void 104 | neogeo_runframe (void) 105 | { 106 | int cycles; 107 | 108 | if (!inited) 109 | { 110 | memset (&CPU_Z80, 0, sizeof (CPU)); 111 | memset (&CPU_M68K, 0, sizeof (CPU)); 112 | 113 | CPU_Z80.total_cycles = 0.0; 114 | CPU_M68K.total_cycles = 0.0; 115 | 116 | inited = 1; 117 | } 118 | 119 | /*** Set CPU cycles for this frame ***/ 120 | CPU_Z80.cycles_frame = Z80FRAME + CPU_Z80.boost; 121 | CPU_M68K.cycles_frame = M68FRAME + CPU_M68K.boost; 122 | 123 | /*** Set CPU cycles for scanline ***/ 124 | CPU_Z80.cycles_scanline = ((CPU_Z80.cycles_frame) / TIMESLICE); 125 | CPU_M68K.cycles_scanline = (CPU_M68K.cycles_frame) / TIMESLICE; 126 | 127 | /*** Clear done cycles ***/ 128 | CPU_Z80.cycles_done = CPU_M68K.cycles_done = 0; 129 | 130 | for (scanline = TIMESLICE - 1; scanline >= 0; scanline--) 131 | { 132 | /*** Run M68K ***/ 133 | if (CPU_M68K.cycles_done < CPU_M68K.cycles_frame) 134 | { 135 | if (scanline) 136 | cycles = m68k_execute (CPU_M68K.cycles_scanline); 137 | else 138 | cycles = 139 | m68k_execute (CPU_M68K.cycles_frame - CPU_M68K.cycles_done); 140 | 141 | CPU_M68K.cycles_done += cycles; 142 | CPU_M68K.total_cycles += cycles; 143 | } 144 | 145 | /*** Run Z80 ***/ 146 | if ((CPU_Z80.cycles_done < CPU_Z80.cycles_frame) && ( cpu_enabled)) 147 | { 148 | if (scanline) 149 | cycles = mz80exec (CPU_Z80.cycles_scanline); 150 | else 151 | cycles = mz80exec (CPU_Z80.cycles_frame - CPU_Z80.cycles_done); 152 | 153 | CPU_Z80.cycles_done += cycles; 154 | CPU_Z80.total_cycles += cycles; 155 | my_timer (); 156 | } 157 | 158 | switch (raster_interrupt_enabled) 159 | { 160 | case 0: 161 | neogeo_interrupt (); 162 | break; 163 | 164 | case 1: 165 | neogeo_raster_interrupt (); 166 | break; 167 | 168 | case 2: 169 | neogeo_raster_interrupt_busy (); 170 | break; 171 | } 172 | } 173 | 174 | /*** Adjust processors ***/ 175 | CPU_Z80.total_time_us = (CPU_Z80.total_cycles * Z80_USEC); 176 | CPU_M68K.total_time_us = (CPU_M68K.total_cycles * M68K_USEC); 177 | CPU_Z80.boost = CPU_M68K.boost = 0; 178 | 179 | if (CPU_Z80.total_time_us > CPU_M68K.total_time_us) 180 | CPU_M68K.boost = 181 | (int) ((double) M68SEC * 182 | (CPU_Z80.total_time_us - CPU_M68K.total_time_us)); 183 | else 184 | CPU_Z80.boost = 185 | (int) ((double) Z80SEC * 186 | (CPU_M68K.total_time_us - CPU_Z80.total_time_us)); 187 | 188 | } 189 | -------------------------------------------------------------------------------- /src/cpu/cpuintf.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * NeoCD/SDL CPU Timer Interface 9 | * 10 | * Module to schedule CPU, sound timers and interrupts 11 | ****************************************************************************/ 12 | #ifndef __CPUINTF__ 13 | #define __CPUINTF__ 14 | 15 | #define Z80_USEC ((1.0 / 4000000.0)) 16 | #define M68K_USEC ((1.0 / 12000000.0 )) 17 | 18 | typedef struct 19 | { 20 | int cycles_done; 21 | int cycles_frame; 22 | int cycles_scanline; 23 | int cycles_overrun; 24 | int irq_state; 25 | double total_cycles; 26 | double total_time_us; 27 | int boost; 28 | } CPU; 29 | 30 | typedef struct 31 | { 32 | char gamename[20]; 33 | int nowait_irqack; 34 | int raster_interrupt_enabled; 35 | } GAMECONFIG; 36 | 37 | void neogeo_runframe (void); 38 | void neogeo_configure_game (char *gamename); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/fileio/ata.h: -------------------------------------------------------------------------------- 1 | /** 2 | * IDE EXI Driver for Gamecube & Wii 3 | * 4 | * Based loosely on code written by Dampro 5 | * Re-written by emu_kidid 6 | * 7 | * Very helpful ATA document: http://www.t10.org/t13/project/d1410r3a-ATA-ATAPI-6.pdf 8 | **/ 9 | 10 | #ifndef ATA_H 11 | #define ATA_H 12 | 13 | #include 14 | #include 15 | 16 | #include "neocdrx.h" 17 | 18 | #define DEVICE_TYPE_GC_SD (('G'<<24)|('C'<<16)|('S'<<8)|'D') 19 | 20 | // ATA status register bits 21 | #define ATA_SR_BSY 0x80 22 | #define ATA_SR_DRDY 0x40 23 | #define ATA_SR_DF 0x20 24 | #define ATA_SR_DSC 0x10 25 | #define ATA_SR_DRQ 0x08 26 | #define ATA_SR_CORR 0x04 27 | #define ATA_SR_IDX 0x02 28 | #define ATA_SR_ERR 0x01 29 | 30 | // ATA error register bits 31 | #define ATA_ER_UNC 0x40 32 | #define ATA_ER_MC 0x20 33 | #define ATA_ER_IDNF 0x10 34 | #define ATA_ER_MCR 0x08 35 | #define ATA_ER_ABRT 0x04 36 | #define ATA_ER_TK0NF 0x02 37 | #define ATA_ER_AMNF 0x01 38 | 39 | // ATA head register bits 40 | #define ATA_HEAD_USE_LBA 0x40 41 | 42 | // NOTE: cs0 then cs1! 43 | // ATA registers address val - cs0 cs1 a2 a1 a0 44 | #define ATA_REG_DATA 0x10 //1 0000b 45 | #define ATA_REG_COMMAND 0x17 //1 0111b 46 | #define ATA_REG_ALTSTATUS 0x0E //0 1110b 47 | #define ATA_REG_DEVICE 0x16 //1 0110b 48 | #define ATA_REG_DEVICECONTROL 0x0E //0 1110b 49 | #define ATA_REG_ERROR 0x11 //1 0001b 50 | #define ATA_REG_FEATURES 0x11 //1 0001b 51 | #define ATA_REG_LBAHI 0x15 //1 0101b 52 | #define ATA_REG_LBAMID 0x14 //1 0100b 53 | #define ATA_REG_LBALO 0x13 //1 0011b 54 | #define ATA_REG_SECCOUNT 0x12 //1 0010b 55 | #define ATA_REG_STATUS 0x17 //1 0111b 56 | 57 | // ATA commands 58 | #define ATA_CMD_IDENTIFY 0xEC 59 | #define ATA_CMD_READSECT 0x20 60 | #define ATA_CMD_READSECTEXT 0x24 61 | #define ATA_CMD_WRITESECT 0x30 62 | #define ATA_CMD_WRITESECTEXT 0x34 63 | #define ATA_CMD_UNLOCK 0xF2 64 | 65 | // ATA Identity fields 66 | // all offsets refer to word offset (2 byte increments) 67 | #define ATA_IDENT_SERIAL 10 // Drive serial (20 characters) 68 | #define ATA_IDENT_MODEL 27 // Drive model name (40 characters) 69 | #define ATA_IDENT_LBASECTORS 60 // Number of sectors in LBA translation mode 70 | #define ATA_IDENT_COMMANDSET 83 // Command sets supported 71 | #define ATA_IDENT_LBA48SECTORS 100 // Number of sectors in LBA 48-bit mode 72 | #define ATA_IDENT_LBA48MASK 0x04 // Mask for LBA support in the command set top byte 73 | 74 | // typedefs 75 | // drive info structure 76 | typedef struct 77 | { 78 | u64 sizeInSectors; 79 | u32 sizeInGigaBytes; 80 | int lba48Support; 81 | char model[48]; 82 | char serial[24]; 83 | } typeDriveInfo ATTRIBUTE_ALIGN (32); 84 | 85 | typedef struct 86 | { 87 | u16 type; //1 = master pw, 0 = user 88 | char password[32]; 89 | u8 reserved[479]; 90 | } unlockStruct ATTRIBUTE_ALIGN (32); 91 | 92 | extern typeDriveInfo ataDriveInfo; 93 | 94 | // Prototypes 95 | int ataDriveInit(int chn); 96 | int ataUnlock(int chn, int useMaster, char *password); 97 | int ataReadSectors(int chn, u64 sector, unsigned int numSectors, unsigned char *dest); 98 | int ataWriteSectors(int chn, u64 sector,unsigned int numSectors, unsigned char *src); 99 | bool ataIsInserted(int chn); 100 | int ataShutdown(int chn); 101 | extern int _ideexi_version; 102 | 103 | // Swap defines 104 | #define __lhbrx(base,index) \ 105 | ({ register u16 res; \ 106 | __asm__ volatile ("lhbrx %0,%1,%2" : "=r"(res) : "b%"(index), "r"(base) : "memory"); \ 107 | res; }) 108 | 109 | #define __lwbrx(base,index) \ 110 | ({ register u32 res; \ 111 | __asm__ volatile ("lwbrx %0,%1,%2" : "=r"(res) : "b%"(index), "r"(base) : "memory"); \ 112 | res; }) 113 | 114 | #endif 115 | 116 | -------------------------------------------------------------------------------- /src/fileio/dirsel.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoGeo Directory Selector 3 | * 4 | * As there is no 'ROM' to speak of, use the directory as the starting point 5 | ****************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "neocdrx.h" 13 | 14 | #ifdef HW_RVL 15 | #include 16 | #endif 17 | 18 | #define PAGE_SIZE 8 19 | 20 | char basedir[1024]; 21 | char scratchdir[1024]; 22 | char megadir[1024]; 23 | char dirbuffer[0x10000] ATTRIBUTE_ALIGN (32); 24 | 25 | char root_dir[10]; 26 | //int have_ROM; 27 | /**************************************************************************** 28 | * DrawDirSelector 29 | ****************************************************************************/ 30 | static void 31 | DrawDirSelector (int maxfile, int menupos, int currsel) 32 | { 33 | int i; 34 | int j = 158; 35 | int *p = (int *) dirbuffer; 36 | char *m; 37 | char display[40]; 38 | char inverse[40]; 39 | 40 | DrawScreen (); 41 | 42 | for (i = menupos; i < (menupos + PAGE_SIZE) && (i < maxfile); i++) 43 | { 44 | m = (char *) p[i + 1]; 45 | memset (display, 0, 40); 46 | memcpy (display, m, 32); 47 | 48 | if (i == currsel) 49 | { 50 | setfgcolour (BMPANE); 51 | setbgcolour (INVTEXT); 52 | memset (inverse, 32, 40); 53 | inverse[32] = 0; 54 | memcpy (inverse, display, strlen (display)); 55 | gprint (64, j, inverse, TXT_DOUBLE); 56 | } 57 | else 58 | { 59 | setfgcolour (COLOR_WHITE); 60 | setbgcolour (BMPANE); 61 | gprint (64, j, display, TXT_DOUBLE); 62 | } 63 | 64 | j += 32; 65 | } 66 | 67 | ShowScreen (); 68 | } 69 | 70 | /**************************************************************************** 71 | * DirSelector 72 | * 73 | * A == Enter directory 74 | * B == Parent directory 75 | * X == Set directory 76 | ****************************************************************************/ 77 | void 78 | DirSelector (void) 79 | { 80 | int *p = (int *) dirbuffer; 81 | char *m; 82 | int maxfile, i; 83 | int currsel = 0; 84 | int menupos = 0; 85 | int redraw = 1; 86 | short joy; 87 | int quit = 0; 88 | have_ROM = 0; 89 | GENFILE fp; 90 | 91 | maxfile = p[0]; 92 | 93 | while (!quit) 94 | { 95 | if (redraw) 96 | { 97 | DrawDirSelector (maxfile, menupos, currsel); 98 | redraw = 0; 99 | } 100 | 101 | joy = getMenuButtons(); 102 | 103 | // Scroll displayed directories 104 | if (joy & PAD_BUTTON_DOWN) 105 | { 106 | currsel++; 107 | if (currsel == maxfile) 108 | currsel = menupos = 0; 109 | if ((currsel - menupos) >= PAGE_SIZE) 110 | menupos += PAGE_SIZE; 111 | 112 | redraw = 1; 113 | } 114 | 115 | if (joy & PAD_BUTTON_UP) 116 | { 117 | currsel--; 118 | if (currsel < 0) 119 | { 120 | currsel = maxfile - 1; 121 | menupos = currsel - PAGE_SIZE + 1; 122 | } 123 | 124 | if (currsel < menupos) 125 | menupos -= PAGE_SIZE; 126 | 127 | if (menupos < 0) 128 | menupos = 0; 129 | 130 | redraw = 1; 131 | } 132 | 133 | // Previous page of displayed directories 134 | if (joy & PAD_TRIGGER_L) 135 | { 136 | menupos -= PAGE_SIZE; 137 | currsel = menupos; 138 | if (currsel < 0) 139 | { 140 | currsel = maxfile - 1; 141 | menupos = currsel - PAGE_SIZE + 1; 142 | } 143 | 144 | if (menupos < 0) 145 | menupos = 0; 146 | 147 | redraw = 1; 148 | } 149 | 150 | // Next page of displayed directories 151 | if (joy & PAD_TRIGGER_R) 152 | { 153 | menupos += PAGE_SIZE; 154 | currsel = menupos; 155 | if (currsel > maxfile) 156 | currsel = menupos = 0; 157 | 158 | redraw = 1; 159 | } 160 | 161 | // Go to Next Directory 162 | if (joy & PAD_BUTTON_A) 163 | { 164 | strcpy (scratchdir, basedir); 165 | 166 | if (scratchdir[strlen (scratchdir) - 1] != '/') 167 | strcat (scratchdir, "/"); 168 | 169 | m = (char *) p[currsel + 1]; 170 | 171 | strcat (scratchdir, m); 172 | 173 | if (GEN_getdir (scratchdir)) 174 | { 175 | maxfile = p[0]; 176 | currsel = menupos = 0; 177 | strcpy (basedir, scratchdir); 178 | } 179 | else 180 | GEN_getdir (basedir); 181 | 182 | // if IPL.TXT found, automount directory 183 | sprintf(megadir,"%s/IPL.TXT",basedir); 184 | fp = GEN_fopen(megadir, "rb"); 185 | if (fp) 186 | { 187 | have_ROM = 1; 188 | quit = 1; 189 | } 190 | 191 | redraw = 1; 192 | } 193 | 194 | // Go to Previous Directory 195 | if (joy & PAD_BUTTON_B) 196 | { 197 | if (strcmp (basedir, "/")) 198 | { 199 | strcpy (scratchdir, basedir); 200 | for (i = strlen (scratchdir) - 1; i >= 0; i--) 201 | { 202 | if (scratchdir[i] == '/') 203 | { 204 | if (i == 0) strcpy (scratchdir, "/"); 205 | else scratchdir[i] = 0; 206 | 207 | if (strcmp (scratchdir, root_dir) == 0) 208 | sprintf(scratchdir,"%s/",root_dir); 209 | 210 | if (GEN_getdir (scratchdir)) 211 | { 212 | maxfile = p[0]; 213 | currsel = menupos = 0; 214 | strcpy (basedir, scratchdir); 215 | } 216 | break; 217 | } 218 | } 219 | } 220 | redraw = 1; 221 | } 222 | 223 | // Quit browser, return to device menu 224 | if (joy & PAD_TRIGGER_Z) { 225 | have_ROM = 0; 226 | quit = 1; 227 | } 228 | 229 | // LOAD Selected Directory 230 | if (joy & PAD_BUTTON_X) 231 | { 232 | /*** Set basedir to mount point ***/ 233 | if (basedir[strlen (basedir) - 1] != '/') 234 | strcat (basedir, "/"); 235 | 236 | m = (char *) p[currsel + 1]; 237 | strcat (basedir, m); 238 | have_ROM = 1; 239 | quit = 1; 240 | } 241 | } 242 | 243 | /*** Remove any still held buttons ***/ 244 | while (PAD_ButtonsHeld (0)) PAD_ScanPads(); 245 | #ifdef HW_RVL 246 | while (WPAD_ButtonsHeld(0)) WPAD_ScanPads(); 247 | #endif 248 | } 249 | -------------------------------------------------------------------------------- /src/fileio/dirsel.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoGeo Directory Selector 3 | * 4 | * As there is no 'ROM' to speak of, use the directory as the starting point 5 | ****************************************************************************/ 6 | 7 | #ifndef __NEODIRSEL__ 8 | #define __NEODIRSEL__ 9 | 10 | extern char basedir[1024]; 11 | extern char dirbuffer[0x10000]; 12 | extern char scratchdir[1024]; 13 | 14 | extern char root_dir[10]; 15 | extern void DirSelector (void); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/fileio/dvdfileio.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * DVD File I/O 9 | ****************************************************************************/ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "neocdrx.h" 15 | #include "fileio.h" 16 | #include "iso9660.h" 17 | 18 | #ifdef HW_RVL 19 | #include 20 | #endif 21 | 22 | // Generic file system 23 | #define MAXFILES 32 24 | #ifdef HW_RVL 25 | #define BUFFSIZE 0x800 /* LIBDI requires 2048 bytes sectors */ 26 | #else 27 | #define BUFFSIZE 0x8000 28 | #endif 29 | 30 | GENFILEINFO fileinfo[MAXFILES]; 31 | static GENHANDLER dvdhandler; 32 | static u8 dvdfixup[BUFFSIZE] ATTRIBUTE_ALIGN (32); 33 | extern int usleep(); 34 | 35 | /**************************************************************************** 36 | * DVDFindFree 37 | ****************************************************************************/ 38 | static int 39 | DVDFindFree (void) 40 | { 41 | int i = 0; 42 | 43 | while (i < MAXFILES) 44 | { 45 | if (fileinfo[i].handle == -1) 46 | return i; 47 | i++; 48 | } 49 | 50 | return -1; 51 | } 52 | 53 | /**************************************************************************** 54 | * DVD_fopen 55 | * 56 | * Open a file on the DVD. This will only apply to the current DVD directory. 57 | ****************************************************************************/ 58 | static u32 59 | DVDfopen (const char *filename, const char *mode) 60 | { 61 | DIRENTRY *fdir; 62 | int handle; 63 | 64 | // No write mode available 65 | if (strstr (mode, "w")) 66 | return 0; 67 | 68 | handle = DVDFindFree (); 69 | if (handle == -1) 70 | return 0; 71 | 72 | fdir = FindFile ((char *)filename); 73 | 74 | if (fdir == NULL) 75 | { 76 | return 0; 77 | } 78 | 79 | // Make a copy in the file info structure 80 | fileinfo[handle].handle = handle; 81 | fileinfo[handle].mode = GEN_MODE_READ; 82 | fileinfo[handle].length = fdir->lengthbe; 83 | fileinfo[handle].offset_on_media64 = (long long int)fdir->offsetbe * 2048; 84 | fileinfo[handle].currpos = 0; 85 | 86 | return handle | 0x8000; 87 | } 88 | 89 | /**************************************************************************** 90 | * DVD_fclose 91 | * 92 | * Close a previously opened file 93 | ****************************************************************************/ 94 | static int 95 | DVDfclose (u32 fp) 96 | { 97 | if (fileinfo[fp & 0x7fff].handle != -1) 98 | { 99 | fileinfo[fp & 0x7fff].handle = -1; 100 | return 1; 101 | } 102 | return 0; 103 | } 104 | 105 | /**************************************************************************** 106 | * DVDfread 107 | ****************************************************************************/ 108 | static u32 109 | DVDfread (char *buf, int block, int len, u32 fp) 110 | { 111 | int handle = fp & 0x7fff; 112 | int bytesrequested = 0; 113 | int bytesavailable = 0; 114 | int bytestoread = 0; 115 | int bytesdone = 0; 116 | int blocks = 0; 117 | int i, remain; 118 | 119 | // Is this handle valid? 120 | if (fileinfo[handle].handle == -1) 121 | return 0; 122 | 123 | bytesrequested = (block * len); 124 | bytesavailable = fileinfo[handle].length - fileinfo[handle].currpos; 125 | 126 | if (bytesrequested <= bytesavailable) 127 | bytestoread = bytesrequested; 128 | else 129 | bytestoread = bytesavailable; 130 | 131 | if (bytestoread == 0) 132 | return 0; 133 | 134 | memset (dvdfixup, 0, BUFFSIZE); 135 | 136 | // How many blocks 137 | blocks = bytestoread / BUFFSIZE; 138 | 139 | if (blocks) 140 | { 141 | for (i = 0; i < blocks; i++) 142 | { 143 | gcsim64 (dvdfixup, 144 | fileinfo[handle].offset_on_media64 + (long long int)fileinfo[handle].currpos, 145 | BUFFSIZE); 146 | memcpy (buf + bytesdone, dvdfixup, BUFFSIZE); 147 | fileinfo[handle].currpos += BUFFSIZE; 148 | bytesdone += BUFFSIZE; 149 | } 150 | } 151 | 152 | remain = (bytestoread & (BUFFSIZE - 1)); 153 | 154 | // Get remaining bytes 155 | if (remain) 156 | { 157 | gcsim64 (dvdfixup, 158 | fileinfo[handle].offset_on_media64 + (long long int)fileinfo[handle].currpos, 159 | BUFFSIZE); 160 | memcpy (buf + bytesdone, dvdfixup, remain); 161 | fileinfo[handle].currpos += remain; 162 | bytesdone += remain; 163 | } 164 | 165 | return bytesdone; 166 | } 167 | 168 | /**************************************************************************** 169 | * DVD_fseek 170 | * 171 | * Seek to a position in a file 172 | ****************************************************************************/ 173 | static int 174 | DVDfseek (u32 fp, int where, int whence) 175 | { 176 | int handle; 177 | 178 | handle = fp & 0x7fff; 179 | 180 | if (fileinfo[handle].handle == -1) 181 | return -1; 182 | 183 | switch (whence) 184 | { 185 | case SEEK_END: 186 | if (where > 0) 187 | return 0; // Fail 188 | 189 | fileinfo[handle].currpos = fileinfo[handle].length + where; 190 | return 1; 191 | 192 | case SEEK_CUR: 193 | if ((where + fileinfo[handle].currpos) > fileinfo[handle].length) 194 | return 0; 195 | 196 | fileinfo[handle].currpos += where; 197 | return 1; 198 | 199 | case SEEK_SET: 200 | if (where < 0) 201 | return 0; 202 | 203 | fileinfo[handle].currpos = where; 204 | return 1; 205 | } 206 | 207 | return 0; 208 | } 209 | 210 | /**************************************************************************** 211 | * DVD_ftell 212 | * 213 | * Return current position 214 | ****************************************************************************/ 215 | static int 216 | DVDftell (u32 fp) 217 | { 218 | int handle = fp & 0x7fff; 219 | 220 | if (fileinfo[handle].handle != -1) 221 | { 222 | return fileinfo[handle].currpos; 223 | } 224 | 225 | return 0; 226 | } 227 | 228 | /**************************************************************************** 229 | * DVDfcloseall 230 | ****************************************************************************/ 231 | static void 232 | DVDfcloseall (void) 233 | { 234 | memset (&fileinfo, 0xff, sizeof (GENFILEINFO) * MAXFILES); 235 | } 236 | 237 | /**************************************************************************** 238 | * DVDgetdir 239 | ****************************************************************************/ 240 | static int 241 | DVDgetdir(char *dir) 242 | { 243 | int *p = (int *) dirbuffer; 244 | 245 | GetSubDirectories (dir, dirbuffer, 0x10000); 246 | return p[0]; 247 | } 248 | 249 | /**************************************************************************** 250 | * DVDmount 251 | ****************************************************************************/ 252 | static void 253 | DVDmount ( void ) 254 | { 255 | memset (basedir, 0, 1024); 256 | memset (scratchdir, 0, 1024); 257 | // memset (dirbuffer, 0, 0x10000); 258 | 259 | if (!mount_image ()) 260 | { 261 | #ifdef HW_RVL 262 | DI_Init(); 263 | 264 | u32 val; 265 | DI_GetCoverRegister(&val); 266 | while(val & 0x1) 267 | { 268 | InfoScreen((char *) "Please insert disc !"); 269 | DI_GetCoverRegister(&val); 270 | } 271 | DI_Mount(); 272 | while(DI_GetStatus() & DVD_INIT) usleep(10); 273 | if (!(DI_GetStatus() & DVD_READY)) 274 | { 275 | char msg[50]; 276 | sprintf(msg, "DI Status Error: 0x%08X !\n",DI_GetStatus()); 277 | ActionScreen(msg); 278 | } 279 | #else 280 | DVD_Init(); 281 | DVD_Mount(); 282 | #endif 283 | 284 | if (!mount_image()) 285 | { 286 | ActionScreen((char *) "Error reading disc !"); 287 | } 288 | } 289 | 290 | // Always start at the root 291 | strcpy (basedir, "/"); 292 | 293 | // Build sub-directory tree 294 | DVDgetdir (basedir); 295 | 296 | // Do dir selection 297 | DirSelector (); 298 | 299 | bannerscreen(); 300 | } 301 | 302 | 303 | /**************************************************************************** 304 | * DVD_SetHandler 305 | ****************************************************************************/ 306 | void 307 | DVD_SetHandler (void) 308 | { 309 | /*** Clear ***/ 310 | memset (&dvdhandler, 0, sizeof (GENHANDLER)); 311 | memset (&fileinfo, 0xff, sizeof (GENFILEINFO) * MAXFILES); 312 | 313 | /*** Set generic handlers ***/ 314 | dvdhandler.gen_fopen = DVDfopen; 315 | dvdhandler.gen_fclose = DVDfclose; 316 | dvdhandler.gen_fread = DVDfread; 317 | dvdhandler.gen_fseek = DVDfseek; 318 | dvdhandler.gen_ftell = DVDftell; 319 | dvdhandler.gen_fcloseall = DVDfcloseall; 320 | dvdhandler.gen_getdir = DVDgetdir; 321 | dvdhandler.gen_mount = DVDmount; 322 | 323 | GEN_SetHandler (&dvdhandler); 324 | } 325 | 326 | -------------------------------------------------------------------------------- /src/fileio/dvdfileio.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #ifndef __DVDFILEIO__ 8 | #define __DVDFILEIO__ 9 | 10 | extern void DVD_SetHandler (void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/fileio/fileio.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * Generic File I/O 9 | * 10 | * This module attempts to provide a single interface for file I/O. 11 | ****************************************************************************/ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "fileio.h" 17 | 18 | static GENHANDLER genhandler; 19 | 20 | /**************************************************************************** 21 | * GEN_SetHandler 22 | * 23 | * Call BEFORE using any of the other functions 24 | ****************************************************************************/ 25 | void 26 | GEN_SetHandler (GENHANDLER * g) 27 | { 28 | memcpy (&genhandler, g, sizeof (GENHANDLER)); 29 | } 30 | 31 | /**************************************************************************** 32 | * GEN_fopen 33 | * 34 | * Passthrough fopen 35 | ****************************************************************************/ 36 | u32 37 | GEN_fopen (const char *filename, const char *mode) 38 | { 39 | if (genhandler.gen_fopen == NULL) 40 | return 0; /*** NULL - no file or handler ***/ 41 | 42 | return (genhandler.gen_fopen) (filename, mode); 43 | } 44 | 45 | /**************************************************************************** 46 | * GEN_fread 47 | * 48 | * Passthrough fread 49 | ****************************************************************************/ 50 | u32 51 | GEN_fread (char *buffer, int block, int length, u32 fp) 52 | { 53 | if (genhandler.gen_fread == NULL) 54 | return 0; 55 | 56 | return (genhandler.gen_fread) (buffer, block, length, fp); 57 | } 58 | 59 | /**************************************************************************** 60 | * GEN_fwrite 61 | * 62 | * Passthrough fwrite 63 | ****************************************************************************/ 64 | u32 65 | GEN_fwrite (char *buffer, int block, int length, u32 fp) 66 | { 67 | if (genhandler.gen_fwrite == NULL) 68 | return 0; 69 | 70 | return (genhandler.gen_fwrite) (buffer, block, length, fp); 71 | } 72 | 73 | /**************************************************************************** 74 | * GEN_fclose 75 | * 76 | * Passthrough fclose 77 | ****************************************************************************/ 78 | int 79 | GEN_fclose (u32 fp) 80 | { 81 | if (genhandler.gen_fclose == NULL) 82 | return 0; 83 | 84 | return (genhandler.gen_fclose) (fp); 85 | } 86 | 87 | /**************************************************************************** 88 | * GEN_fseek 89 | * 90 | * Passthrough fseek 91 | ****************************************************************************/ 92 | int 93 | GEN_fseek (u32 fp, int where, int whence) 94 | { 95 | if (genhandler.gen_fseek == NULL) 96 | return 0; 97 | 98 | return (genhandler.gen_fseek) (fp, where, whence); 99 | } 100 | 101 | /**************************************************************************** 102 | * GEN_ftell 103 | * 104 | * Passthrough ftell 105 | ****************************************************************************/ 106 | int 107 | GEN_ftell (u32 fp) 108 | { 109 | if (genhandler.gen_ftell == NULL) 110 | return -1; 111 | 112 | return (genhandler.gen_ftell) (fp); 113 | } 114 | 115 | /**************************************************************************** 116 | * GEN_fcloseall 117 | ***************************************************************************/ 118 | void 119 | GEN_fcloseall (void) 120 | { 121 | if (genhandler.gen_fcloseall == NULL) 122 | return; 123 | 124 | (genhandler.gen_fcloseall) (); 125 | } 126 | 127 | 128 | /**************************************************************************** 129 | * GEN_fcloseall 130 | ***************************************************************************/ 131 | int 132 | GEN_getdir (char *dir) 133 | { 134 | if (genhandler.gen_getdir == NULL) 135 | return 0; 136 | 137 | return (genhandler.gen_getdir) (dir); 138 | } 139 | 140 | /**************************************************************************** 141 | * GEN_mount 142 | ***************************************************************************/ 143 | void 144 | GEN_mount (void) 145 | { 146 | if (genhandler.gen_mount == NULL) 147 | return; 148 | 149 | (genhandler.gen_mount) (); 150 | } 151 | 152 | -------------------------------------------------------------------------------- /src/fileio/fileio.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * Generic File I/O 9 | * 10 | * This module attempts to provide a single interface for file I/O. 11 | ****************************************************************************/ 12 | #ifndef __GENFILEIO__ 13 | #define __GENFILEIO__ 14 | 15 | #define GEN_MODE_READ 1 16 | #define GEN_MODE_WRITE 2 17 | 18 | typedef struct 19 | { 20 | u32 handle; 21 | int length; 22 | int currpos; 23 | long long int offset_on_media64; 24 | int mode; 25 | } 26 | GENFILEINFO; 27 | 28 | typedef struct 29 | { 30 | u32 (*gen_fopen) (const char *filename, const char *mode); 31 | u32 (*gen_fread) (char *buffer, int block, int length, u32 fp); 32 | u32 (*gen_fwrite) (char *buffer, int block, int length, u32 fp); 33 | int (*gen_fclose) (u32 fp); 34 | int (*gen_fseek) (u32 fp, int where, int whence); 35 | int (*gen_ftell) (u32 fp); 36 | int (*gen_getdir)(char *dir); 37 | void (*gen_mount) (void); 38 | void (*gen_fcloseall) (void); 39 | } 40 | GENHANDLER; 41 | 42 | typedef u32 GENFILE; 43 | 44 | extern u32 GEN_fopen (const char *filename, const char *mode); 45 | extern u32 GEN_fread (char *buffer, int block, int length, u32 fp); 46 | extern u32 GEN_fwrite (char *buffer, int block, int length, u32 fp); 47 | extern int GEN_fclose (u32 fp); 48 | extern int GEN_fseek (u32 fp, int where, int whence); 49 | extern int GEN_ftell (u32 fp); 50 | extern int GEN_getdir(char *dir); 51 | extern void GEN_mount ( void ); 52 | extern void GEN_fcloseall (void); 53 | 54 | extern void GEN_SetHandler (GENHANDLER * g); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/fileio/iso9660.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * UFS ISO9660 3 | * 4 | * Minimal ISO9660 implementation for Nintendo Gamecube 5 | ****************************************************************************/ 6 | 7 | #ifndef __UFS_ISO9660__ 8 | #define __UFS_ISO9660__ 9 | 10 | /*** Minimal PVD ***/ 11 | #define RECLEN 0 12 | #define EXTENT 6 13 | #define FILE_LENGTH 14 14 | #define FILE_FLAGS 25 15 | #define FILE_NAMELEN 32 16 | #define FILENAME 33 17 | #define PVDROOT 0x9c 18 | #define MAX_LEVELS 256 19 | #define MAX_FILENAME 128 20 | #define SYSID 8 21 | #define VOLID 40 22 | #define VOLSETID 190 23 | #define PUBSETID 318 24 | #define DATASETID 446 25 | #define APPSETID 574 26 | #define PTABLELENGTH 0x88 27 | #define PTABLEOFFSET 0x94 28 | 29 | #define ISDIR 2 30 | #define ISHIDDEN 1 31 | 32 | typedef struct 33 | { 34 | int pvdoffset; 35 | int rootoffset; 36 | int rootlength; 37 | int pathtablelength; 38 | int pathtableoffset; 39 | char system_id[34]; 40 | char volume_id[34]; 41 | char volset_id[130]; 42 | char pubset_id[130]; 43 | char dataset_id[130]; 44 | char appset_id[130]; 45 | } 46 | PVD; 47 | 48 | typedef struct 49 | { 50 | unsigned char nlength; 51 | char extended; 52 | int record; 53 | short parent; 54 | } 55 | __attribute__ ((__packed__)) PATHHDR; 56 | 57 | typedef struct 58 | { 59 | unsigned char nlength; 60 | char extended; 61 | int offsetle; 62 | int offsetbe; 63 | int lengthle; 64 | int lengthbe; 65 | unsigned char years; 66 | unsigned char month; 67 | unsigned char day; 68 | unsigned char hour; 69 | unsigned char minute; 70 | unsigned char second; 71 | unsigned char utcoffset; 72 | unsigned char flags; 73 | unsigned char interleaved; 74 | unsigned char intergap; 75 | short seqnole; 76 | short seqnobe; 77 | unsigned char identifier; 78 | } 79 | __attribute__ ((__packed__)) DIRENTRY; 80 | 81 | typedef struct 82 | { 83 | long long int offset64; 84 | int parent; 85 | char *path; 86 | } 87 | PATHDECODE; 88 | 89 | typedef struct 90 | { 91 | long long int offset64; 92 | char *path; 93 | } 94 | FILEDECODE; 95 | 96 | typedef struct 97 | { 98 | char fname[1024]; 99 | DIRENTRY fdir; 100 | } 101 | CACHEFILE; 102 | 103 | /*** Prototypes ***/ 104 | extern int mount_image (void); 105 | extern void unmount_image (void); 106 | extern void GetSubDirectories (char *dir, char *buf, int len); 107 | extern DIRENTRY *FindFile (char *filename); 108 | extern int gcsim64( void *buffer, long long int offset, int length ); 109 | extern void dvd_motor_off(void); 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /src/fileio/sdfileio.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * SD FileIO 9 | * 10 | ****************************************************************************/ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "neocdrx.h" 19 | #include "fileio.h" 20 | #include 21 | 22 | /* Generic File I/O */ 23 | #define MAXFILES 32 24 | static FILE *sdfsfiles[MAXFILES]; 25 | static GENHANDLER sdhandler; 26 | static u32 sdmutex = 0; 27 | 28 | #define MAXDIRENTRIES 0x4000 29 | static char *direntries[MAXDIRENTRIES]; 30 | 31 | char msg[128]; 32 | 33 | #ifndef HW_RVL 34 | extern const DISC_INTERFACE* WKF_slot; 35 | #endif 36 | extern const DISC_INTERFACE* IDEA_slot; 37 | extern const DISC_INTERFACE* IDEB_slot; 38 | 39 | int have_ROM; 40 | /**************************************************************************** 41 | * SDFindFree 42 | ****************************************************************************/ 43 | int SDFindFree( void ) 44 | { 45 | int i; 46 | 47 | for( i = 0; i < MAXFILES; i++ ) 48 | { 49 | if ( sdfsfiles[i] == NULL ) 50 | return i; 51 | } 52 | 53 | return -1; 54 | } 55 | 56 | /**************************************************************************** 57 | * SDfopen 58 | ****************************************************************************/ 59 | static u32 60 | SDfopen (const char *filename, const char *mode) 61 | { 62 | /* No writing allowed */ 63 | if ( strstr(mode,"w") ) 64 | { 65 | return 0; 66 | } 67 | 68 | /* Open for reading */ 69 | int handle = SDFindFree(); 70 | if ( handle == -1 ) 71 | { 72 | sprintf(msg,"OUT OF HANDLES!"); 73 | ActionScreen(msg); 74 | return 0; 75 | } 76 | 77 | while ( LWP_MutexLock( sdmutex ) ); 78 | 79 | sdfsfiles[handle] = fopen(filename, mode); 80 | if ( sdfsfiles[handle] == NULL ) 81 | { 82 | LWP_MutexUnlock( sdmutex ); 83 | return 0; 84 | } 85 | 86 | LWP_MutexUnlock( sdmutex ); 87 | return handle | 0x8000; 88 | } 89 | 90 | /**************************************************************************** 91 | * SDfclose 92 | ****************************************************************************/ 93 | static int 94 | SDfclose (u32 fp) 95 | { 96 | while ( LWP_MutexLock( sdmutex ) ); 97 | 98 | if( sdfsfiles[fp & 0x7FFF] != NULL ) 99 | { 100 | fclose(sdfsfiles[fp & 0x7FFF]); 101 | sdfsfiles[fp & 0x7FFF] = NULL; 102 | LWP_MutexUnlock( sdmutex ); 103 | return 1; 104 | } 105 | 106 | LWP_MutexUnlock( sdmutex ); 107 | return 0; 108 | } 109 | 110 | /**************************************************************************** 111 | * SDfread 112 | ****************************************************************************/ 113 | static u32 114 | SDfread (char *buf, int block, int len, u32 fp) 115 | { 116 | int handle = ( fp & 0x7FFF ); 117 | 118 | if( sdfsfiles[handle] == NULL ) 119 | return 0; 120 | 121 | while ( LWP_MutexLock ( sdmutex ) ); 122 | 123 | int bytesdone = fread(buf, block, len, sdfsfiles[handle]); 124 | 125 | LWP_MutexUnlock( sdmutex ); 126 | 127 | return bytesdone; 128 | 129 | } 130 | 131 | /**************************************************************************** 132 | * SDSeek 133 | ****************************************************************************/ 134 | static int 135 | SDfseek (u32 fp, int where, int whence) 136 | { 137 | int handle = ( fp & 0x7FFF ); 138 | 139 | if ( sdfsfiles[handle] == NULL ) 140 | { 141 | sprintf(msg,"SEEK : Invalid Handle %d", handle); 142 | ActionScreen(msg); 143 | return -1; 144 | } 145 | 146 | return fseek(sdfsfiles[handle], where, whence ); 147 | 148 | } 149 | 150 | /**************************************************************************** 151 | * SDftell 152 | * 153 | * Return current position 154 | ****************************************************************************/ 155 | static int 156 | SDftell (u32 fp) 157 | { 158 | int handle = ( fp & 0x7FFF ); 159 | 160 | if ( sdfsfiles[handle] == NULL ) 161 | { 162 | sprintf(msg,"FTELL : Invalid Handle %d", handle); 163 | ActionScreen(msg); 164 | return -1; 165 | } 166 | 167 | return ftell(sdfsfiles[handle]); 168 | } 169 | 170 | static void 171 | SDfcloseall (void) 172 | { 173 | int i; 174 | 175 | while ( LWP_MutexLock( sdmutex ) ); 176 | 177 | for( i = 0; i < MAXFILES; i++ ) 178 | { 179 | if ( sdfsfiles[i] != NULL ) 180 | fclose(sdfsfiles[i]); 181 | } 182 | 183 | LWP_MutexUnlock( sdmutex ); 184 | } 185 | 186 | void SortListing( int max ) 187 | { 188 | int top,seek; 189 | char *t; 190 | 191 | for( top = 0; top < max - 1; top++ ) 192 | { 193 | for( seek = top + 1; seek < max; seek++ ) 194 | { 195 | if ( stricmp(direntries[top], direntries[seek]) > 0 ) 196 | { 197 | t = direntries[top]; 198 | direntries[top] = direntries[seek]; 199 | direntries[seek] = t; 200 | } 201 | } 202 | } 203 | } 204 | 205 | /**************************************************************************** 206 | * SDgetdir 207 | ****************************************************************************/ 208 | static int SDgetdir( char *thisdir ) 209 | { 210 | DIR *dirs = NULL; 211 | static int count = 0; 212 | int i; 213 | unsigned int *p; 214 | struct dirent *entry; 215 | 216 | for( i = 0; i < count; i++ ) 217 | free(direntries[i]); 218 | 219 | count = 0; 220 | 221 | dirs = opendir(thisdir); 222 | if ( dirs != NULL ) 223 | { 224 | entry = readdir(dirs); 225 | while ( entry != NULL ) 226 | { 227 | /* Only get subdirectories */ 228 | if (entry->d_type == DT_DIR) 229 | if (strcmp(entry->d_name,".") && 230 | strcmp(entry->d_name,"..")) 231 | { 232 | direntries[count++] = strdup(entry->d_name); 233 | } 234 | 235 | if ( count == MAXDIRENTRIES ) break; 236 | entry = readdir(dirs); 237 | } 238 | } 239 | 240 | if ( count > 1 ) 241 | SortListing(count); 242 | 243 | memcpy(dirbuffer, &count, 4); 244 | p = (unsigned int *)(dirbuffer + 4); 245 | for ( i = 0; i < count; i++ ) 246 | { 247 | memcpy(&p[i], &direntries[i], 4); 248 | } 249 | 250 | return count; 251 | } 252 | 253 | 254 | /**************************************************************************** 255 | * SDmount 256 | ****************************************************************************/ 257 | static void SDmount() 258 | { 259 | memset (basedir, 0, 1024); 260 | memset (scratchdir, 0, 1024); 261 | memset (dirbuffer, 0, 0x10000); 262 | 263 | memset (root_dir, 0, 10); 264 | 265 | // Define DIR search location by Device type 266 | if (use_IDE) { 267 | if ( IDEA_slot->startup() && fatMountSimple("IDEA", IDEA_slot) ) sprintf(root_dir,"IDEA:"); 268 | else if ( IDEB_slot->startup() && fatMountSimple("IDEB", IDEB_slot) ) sprintf(root_dir,"IDEB:"); 269 | else { ActionScreen ("IDE-EXI not initialized"); return; } 270 | } 271 | #ifdef HW_RVL 272 | else if (use_SD) sprintf(root_dir,"sd:"); // search this DIR first 273 | else if (use_USB) sprintf(root_dir,"usb:"); 274 | #else 275 | else if (use_WKF) { 276 | if ( WKF_slot->startup() && fatMountSimple("WKF", WKF_slot) ) sprintf(root_dir,"WKF:"); 277 | else { ActionScreen ("WKF not initialized"); return; } 278 | } 279 | #endif 280 | 281 | // Test if DIR exists, else default to root DIR by Device 282 | sprintf(basedir,"%s/NeoCDRX/games/",root_dir); 283 | DIR *dir = opendir(basedir); 284 | if (!dir) sprintf(basedir,"%s/",root_dir); 285 | else closedir(dir); 286 | 287 | if ( !SDgetdir(basedir) ) 288 | return; 289 | 290 | DirSelector(); 291 | 292 | // Do not show the banner if there is no title selected 293 | if (have_ROM == 1) bannerscreen(); 294 | } 295 | 296 | void 297 | SD_SetHandler () 298 | { 299 | /* Clear */ 300 | memset(&sdhandler, 0, sizeof(GENHANDLER)); 301 | memset(&sdfsfiles, 0, MAXFILES * 4); 302 | memset(&direntries, 0, MAXDIRENTRIES * 4); 303 | 304 | sdhandler.gen_fopen = SDfopen; 305 | sdhandler.gen_fclose = SDfclose; 306 | sdhandler.gen_fread = SDfread; 307 | sdhandler.gen_fseek = SDfseek; 308 | sdhandler.gen_ftell = SDftell; 309 | sdhandler.gen_fcloseall = SDfcloseall; 310 | sdhandler.gen_getdir = SDgetdir; 311 | sdhandler.gen_mount = SDmount; 312 | 313 | GEN_SetHandler (&sdhandler); 314 | 315 | /* Set mutex */ 316 | LWP_MutexInit(&sdmutex, FALSE); 317 | 318 | } 319 | -------------------------------------------------------------------------------- /src/fileio/sdfileio.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #ifndef __SDFSFILEIO__ 8 | #define __SDFSFILEIO__ 9 | 10 | extern void SD_SetHandler (void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/fileio/wkf.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Wiikey Fusion Driver for Gamecube & Wii 3 | * 4 | * Written by emu_kidid 5 | **/ 6 | 7 | #include 8 | #include /*** Wrapper to include common libogc headers ***/ 9 | #include /*** Needed for console support ***/ 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "wkf.h" 26 | 27 | #define WKF_BUF_SIZE 0x8000 28 | u8 wkfBuffer[WKF_BUF_SIZE] ATTRIBUTE_ALIGN (32); // One DVD Sector 29 | 30 | static int wkfInitialized = 0; 31 | static volatile unsigned int* const wkf = (unsigned int*)0xCC006000; 32 | static volatile unsigned int* const pireg = (unsigned int*)0xCC003000; 33 | 34 | extern u8 udelay(); 35 | 36 | 37 | void __wkfReset() { 38 | u32 val; 39 | val = pireg[9]; 40 | pireg[9] = ((val&~4)|1); 41 | usleep(12); 42 | val |= 1 | 4; 43 | pireg[9] = val; 44 | } 45 | 46 | unsigned int __wkfCmdImm(unsigned int cmd, unsigned int p1, unsigned int p2) { 47 | wkf[2] = cmd; 48 | wkf[3] = p1; 49 | wkf[4] = p2; 50 | wkf[6] = 0; 51 | wkf[8] = 0; 52 | wkf[7] = 1; 53 | int retries = 1000000; 54 | while(( wkf[7] & 1) && retries) { 55 | retries --; // Wait for IMM command to finish up 56 | } 57 | return !retries ? -1 : wkf[8]; 58 | } 59 | 60 | // ok 61 | unsigned int __wkfSpiReadId() { 62 | return __wkfCmdImm(0xDF000000, 0xE0009F00, 0x00000000); 63 | } 64 | 65 | unsigned char __wkfSpiReadUC(unsigned int addr) { 66 | u32 ret = __wkfCmdImm(0xDF000000, 0x3C000300 | ((addr>>16)&0xFF), (((addr>>8)&0xFF) << 24) | (((addr)&0xFF)<<16)); 67 | return (u8)(ret&0xFF); 68 | } 69 | 70 | // Reads DVD sectors (returns 0 on success) 71 | void __wkfReadSectors(void* dst, unsigned int len, u64 offset) { 72 | wkf[2] = 0xA8000000; 73 | wkf[3] = (u32)(offset >> 2); 74 | wkf[4] = len; 75 | wkf[5] = (u32)dst; 76 | wkf[6] = len; 77 | wkf[7] = 3; // DMA | START 78 | DCInvalidateRange(dst, len); 79 | while (wkf[7] & 1); 80 | } 81 | 82 | int wkfSpiRead(unsigned char *buf, unsigned int addr, int len) { 83 | int i; 84 | for (i=0; i> 17) & 3); 99 | } 100 | 101 | 102 | // Write to the WKF RAM (0xFFFF is the max offset) 103 | void wkfWriteRam(int offset, int data) { 104 | __wkfCmdImm(0xDD000000, offset, data); 105 | } 106 | 107 | // Write the WKF base offset to base all reads from 108 | void wkfWriteOffset(int offset) { 109 | __wkfCmdImm(0xDE000000, offset, 0x5A000000); 110 | } 111 | 112 | // Returns SD slot status 113 | unsigned int wkfGetSlotStatus() { 114 | return __wkfCmdImm(0xDF000000, 0x00010000, 0x00000000); 115 | } 116 | 117 | void wkfRead(void* dst, int len, u64 offset) 118 | { 119 | u8 *sector_buffer = &wkfBuffer[0]; 120 | while (len) 121 | { 122 | __wkfReadSectors(sector_buffer, WKF_BUF_SIZE, (offset-(offset%WKF_BUF_SIZE))); 123 | u32 off = (u32)((u32)(offset) & (WKF_BUF_SIZE-1)); 124 | 125 | int rl = WKF_BUF_SIZE - off; 126 | if (rl > len) 127 | rl = len; 128 | memcpy(dst, sector_buffer + off, rl); 129 | 130 | offset += rl; 131 | len -= rl; 132 | dst += rl; 133 | } 134 | } 135 | 136 | void wkfInit() { 137 | 138 | // New DVD (aka put it back to WKF mode) 139 | __wkfReset(); 140 | 141 | // one chunk at 0, offset 0 142 | wkfWriteRam(0, 0x0000); 143 | wkfWriteRam(2, 0x0000); 144 | // last chunk sig 145 | wkfWriteRam(4, 0xFFFF); 146 | wkfWriteOffset(0); 147 | 148 | // SD card detect 149 | if ((wkfGetSlotStatus() & 0x000F0000)==0x00070000) { 150 | // no SD card 151 | wkfInitialized = 0; 152 | if (use_WKF == 1) ActionScreen("No WKF SD Card"); 153 | } 154 | else { 155 | // If there's an SD, reset DVD (why?) 156 | __wkfReset(); 157 | udelay(300000); 158 | 159 | // one chunk at 0, offset 0 160 | wkfWriteRam(0, 0x0000); 161 | wkfWriteRam(2, 0x0000); 162 | // last chunk sig 163 | wkfWriteRam(4, 0xFFFF); 164 | wkfWriteOffset(0); 165 | 166 | // Read first sector of SD card 167 | wkfRead(&wkfBuffer[0], 0x200, 0); 168 | if((wkfBuffer[0x1FF] != 0xAA)) { 169 | // No FAT! 170 | wkfInitialized = 0; 171 | if (use_WKF == 1) ActionScreen("No FAT Formatted WKF SD card found!!"); 172 | } 173 | else { 174 | wkfInitialized = 1; 175 | if (use_WKF == 1) InfoScreen("Searching WKF SD Card"); 176 | } 177 | } 178 | } 179 | 180 | void wkfReinit() { 181 | __wkfReset(); 182 | udelay(300000); 183 | 184 | // one chunk at 0, offset 0 185 | wkfWriteRam(0, 0x0000); 186 | wkfWriteRam(2, 0x0000); 187 | // last chunk sig 188 | wkfWriteRam(4, 0xFFFF); 189 | wkfWriteOffset(0); 190 | 191 | // Read first sector of SD card 192 | wkfRead(&wkfBuffer[0], 0x200, 0); 193 | } 194 | 195 | // Wrapper to read a number of sectors 196 | // 0 on Success, -1 on Error 197 | int wkfReadSectors(int chn, u32 sector, unsigned int numSectors, unsigned char *dest) 198 | { 199 | // This is confusing as we're reading 512b sectors from a device that can only address 2048b sectors 200 | wkfRead(dest, numSectors * 512, (u64)((u64)sector * 512)); 201 | return 0; 202 | } 203 | 204 | // Is an SD Card inserted into the Wiikey Fusion? 205 | bool wkfIsInserted(int chn) { 206 | if(!wkfInitialized) { 207 | wkfInit(); 208 | if(!wkfInitialized) { 209 | return false; 210 | } 211 | } 212 | return true; 213 | } 214 | 215 | int wkfShutdown(int chn) { 216 | return 1; 217 | } 218 | 219 | static bool __wkf_startup(void) 220 | { 221 | return wkfIsInserted(0); 222 | } 223 | 224 | static bool __wkf_isInserted(void) 225 | { 226 | return wkfIsInserted(0); 227 | } 228 | 229 | static bool __wkf_readSectors(u32 sector, u32 numSectors, void *buffer) 230 | { 231 | wkfReadSectors(0, sector, numSectors, buffer); 232 | return true; 233 | } 234 | 235 | static bool __wkf_writeSectors(u32 sector, u32 numSectors, void *buffer) 236 | { 237 | return false; 238 | } 239 | 240 | static bool __wkf_clearStatus(void) 241 | { 242 | return true; 243 | } 244 | 245 | static bool __wkf_shutdown(void) 246 | { 247 | return true; 248 | } 249 | 250 | 251 | 252 | const DISC_INTERFACE __io_wkf = { 253 | DEVICE_TYPE_GC_WKF, 254 | FEATURE_MEDIUM_CANREAD | FEATURE_GAMECUBE_DVD, 255 | (FN_MEDIUM_STARTUP)&__wkf_startup, 256 | (FN_MEDIUM_ISINSERTED)&__wkf_isInserted, 257 | (FN_MEDIUM_READSECTORS)&__wkf_readSectors, 258 | (FN_MEDIUM_WRITESECTORS)&__wkf_writeSectors, 259 | (FN_MEDIUM_CLEARSTATUS)&__wkf_clearStatus, 260 | (FN_MEDIUM_SHUTDOWN)&__wkf_shutdown 261 | } ; 262 | 263 | const DISC_INTERFACE* WKF_slot = &__io_wkf; 264 | 265 | 266 | ///////////////////////////////////////////////////////////////////// 267 | -------------------------------------------------------------------------------- /src/fileio/wkf.h: -------------------------------------------------------------------------------- 1 | /* deviceHandler-wiikeyfusion.h 2 | - device implementation for Wiikey Fusion 3 | by emu_kidid 4 | */ 5 | 6 | 7 | #ifndef DEVICE_HANDLER_WKF_H 8 | #define DEVICE_HANDLER_WKF_H 9 | 10 | #include 11 | #include 12 | 13 | #include "neocdrx.h" 14 | 15 | #define DEVICE_TYPE_GC_WKF (('W'<<24)|('K'<<16)|('F'<<8)|'!') 16 | 17 | 18 | void wkfWriteRam(int offset, int data); 19 | void wkfWriteOffset(int offset); 20 | int wkfSpiRead(unsigned char *buf, unsigned int addr, int len); 21 | void wkfRead(void* dst, int len, u64 offset); 22 | unsigned int __wkfSpiReadId(); 23 | void wkfReinit(); 24 | 25 | 26 | void __wkfReset(); 27 | extern bool wkfIsInserted(int chn); 28 | 29 | #endif -------------------------------------------------------------------------------- /src/input/input.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #ifndef __NEOINPUT__ 8 | #define __NEOINPUT__ 9 | void update_input (void); 10 | unsigned char read_player1 (void); 11 | unsigned char read_player2 (void); 12 | unsigned char read_pl12_startsel (void); 13 | extern int accept_input; 14 | extern u16 getMenuButtons(void); 15 | #endif 16 | -------------------------------------------------------------------------------- /src/m68000/Makefile: -------------------------------------------------------------------------------- 1 | ########################## 2 | # Makefile for 68k Core # 3 | ########################## 4 | 5 | CCE = @gcc 6 | BUILDDIR=../../build_cpu 7 | 8 | #setup C Flags 9 | CFLAGS= -I. -I./$(BUILDDIR) -O3 -fomit-frame-pointer -fno-ident -funsigned-char 10 | 11 | # 68k instructions file 12 | INFILE = neocd68k.c 13 | 14 | all: $(BUILDDIR)/libmc68000.a 15 | 16 | clean: rm -f $(BUILDDIR)/libmc68000.a 17 | 18 | $(BUILDDIR)/libmc68000.a: $(BUILDDIR)/m68kcpu.o $(BUILDDIR)/m68kops.o $(BUILDDIR)/m68kopac.o $(BUILDDIR)/m68kopdm.o $(BUILDDIR)/m68kopnz.o 19 | @$(AR) -r $@ $^ 20 | 21 | $(BUILDDIR)/m68kcpu.o: $(BUILDDIR)/m68kops.h m68k.h m68kconf.h 22 | @$(CC) $(CFLAGS) -c m68kcpu.c -o $(BUILDDIR)/m68kcpu.o 23 | 24 | $(BUILDDIR)/m68kops.o: $(BUILDDIR)/m68kmake.exe $(BUILDDIR)/m68kops.h $(BUILDDIR)/m68kops.c m68k.h m68kconf.h 25 | @$(CC) $(CFLAGS) -c $(BUILDDIR)/m68kops.c -o $(BUILDDIR)/m68kops.o 26 | 27 | $(BUILDDIR)/m68kopac.o: $(BUILDDIR)/m68kmake.exe $(BUILDDIR)/m68kops.h $(BUILDDIR)/m68kopac.c m68k.h m68kconf.h 28 | @$(CC) $(CFLAGS) -c $(BUILDDIR)/m68kopac.c -o $(BUILDDIR)/m68kopac.o 29 | 30 | $(BUILDDIR)/m68kopdm.o: $(BUILDDIR)/m68kmake.exe $(BUILDDIR)/m68kops.h $(BUILDDIR)/m68kopdm.c m68k.h m68kconf.h 31 | @$(CC) $(CFLAGS) -c $(BUILDDIR)/m68kopdm.c -o $(BUILDDIR)/m68kopdm.o 32 | 33 | $(BUILDDIR)/m68kopnz.o: $(BUILDDIR)/m68kmake.exe $(BUILDDIR)/m68kops.h $(BUILDDIR)/m68kopnz.c m68k.h m68kconf.h 34 | @$(CC) $(CFLAGS) -c $(BUILDDIR)/m68kopnz.c -o $(BUILDDIR)/m68kopnz.o 35 | 36 | $(BUILDDIR)/m68kops.h: $(BUILDDIR)/m68kmake.exe 37 | @echo "" 38 | @echo "*** Musashi 3.3 ************************************************************" 39 | @$(BUILDDIR)/m68kmake.exe $(BUILDDIR) $(INFILE) 40 | @echo "****************************************************************************" 41 | @echo "" 42 | 43 | $(BUILDDIR)/m68kmake.exe: m68kmake.c $(INFILE) 44 | $(CCE) $(WARNINGS) m68kmake.c -o $(BUILDDIR)/m68kmake.exe 45 | -------------------------------------------------------------------------------- /src/m68000/doc/example.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niuus/NeoCDRX/676eee0a335cccf0a3b86dfc5a17198494922a6a/src/m68000/doc/example.zip -------------------------------------------------------------------------------- /src/m68000/doc/history.txt: -------------------------------------------------------------------------------- 1 | The history of Musashi for anyone who might be interested: 2 | --------------------------------------------------------- 3 | 4 | Musashi was born out of sheer boredom. 5 | I needed something to code, and so having had fun with a few of the emulators 6 | around, I decided to try my hand at CPU emulation. 7 | I had owned an Amiga for many years and had done some assembly coding on it so 8 | I figured it would be the ideal chip to cut my teeth on. 9 | Had I known then how much work was involved in emulating a chip like this, I 10 | may not have even started ;-) 11 | 12 | 13 | 14 | 12-May-1998: First outline 15 | 16 | 11-Jun-1998: Early disassembler 17 | 18 | 20-Nov-1998: First prototype v0.1 19 | 20 | 04-Dec-1998: Final prototype v0.4 21 | 22 | 20-Dec-1998: Beta release of Musashi v0.5 that could run Rastan Saga under MAME 23 | (barely). 24 | 25 | 06-Jan-1999: Musashi 1.0 released 26 | 27 | 17-Mar-1999: Musashi 2.0 released 28 | - Major code overhaul. 29 | - Replaced monolithic codebase with a code generator program. 30 | - Added correct m68000 timing. 31 | - Moved timing into the opcode handlers. 32 | 33 | 25-Mar-1999: Musashi 2.1 released 34 | - Added support for m68010. 35 | - Many bugfixes. 36 | 37 | 13-May-1999: Musashi 2.2 released 38 | - Added support for m68020. 39 | - Lots of bugfixes. 40 | 41 | 05-Apr-2000: Musashi 3.0 released 42 | - Major code overhaul. 43 | - Rewrote code generator program and changed the format of 44 | m68k_in.c. 45 | - Added support for m68ec020. 46 | - Removed timing from the opcode handlers. 47 | - Added correct timing for m68000, m68010, and m68020. 48 | Note: 68020 timing is the cache timing from the manual. 49 | - Removed the m68k_peek_xxx() and m68k_poke_xxx() instructions and 50 | replaced them with m68k_get_reg() and m68k_set_reg(). 51 | - Added support for function codes. 52 | - Revamped m68kconf.h to be easier to configure and more powerful. 53 | - Added option to separate immediate and normal reads. 54 | - Added support for (undocumented) m68000 instruction prefetch. 55 | - Rewrote indexed addressing mode handling. 56 | - Rewrote interrupt handling. 57 | - Fixed a masking bug for m68k_get_reg() when requesting the PC. 58 | - Moved the instruction table sorting routine to m68kmake.c so 59 | that it is invoked at compile time rather than at runtime. 60 | - Rewrote the exception handling routines to support different 61 | stack frames (needed for m68020 emulation). 62 | - Rewrote faster status register and condition code flag handling 63 | functions / macros. 64 | - Fixed function code handling to fetch from program space when 65 | using pc-relative addressing. 66 | - Fixed initial program counter and stack pointer fetching on 67 | reset (loads from program space now). 68 | - A lot of code cleanup. 69 | - LOTS of bugfixes (especially in the m68020 code). 70 | 71 | 28-May-2000: Musashi 3.1 released 72 | - Fixed bug in m68k_get_reg() that retrieved the wrong value for 73 | the status register. 74 | - Fixed register bug in movec. 75 | - Fixed cpu type comparison problem that caused indexed 76 | addressing modes to be incorrectly interpreted when in m68ec020 77 | mode. 78 | - Added code to speed up busy waiting on some branch instructions. 79 | - Fixed some bfxxx opcode bugs. 80 | 81 | 14-Aug-2000: Musashi 3.2 released 82 | - Fixed RTE bug that killed the program counter when in m68020 83 | mode. 84 | - Minor fixes in negx and nbcd. 85 | - renamed d68k.c to m68kdasm.c and merged d68k.h into m68k.h. 86 | d68k_read_xxx() instructions have been renamed to 87 | m68k_read_xxx_disassembler(). 88 | - Rewrote exception processing and fixed 68020 stack frame 89 | problems. 90 | - FINALLY fixed the mull and divl instructions. 91 | - Added 64-bit safe code fixes. 92 | - Added 64-bit optimizations (these will only be ANSI compliant 93 | under c9x, and so to use them you must turn on M68K_USE_64_BIT 94 | in m68kconf.h). 95 | 96 | 27-Jan-2001: Musashi 3.3 released 97 | Note: This is the last release of Musashi before I separate the 98 | 68020 core. 99 | - Fixed problem when displaying negative numbers in disassembler 100 | - Fixed cpu type selector - was allowing 020 instructions to be 101 | disassembled when in 000 mode. 102 | - Fixed opcode jumptable generator (ambiguous operators in the 103 | test for f-line ops) 104 | - Fixed signed/unsigned problem in divl and mull opcodes (not 105 | sure if this was causing an error but best to be sure) 106 | - Cleaned up the naming scheme for the opcode handlers 107 | 108 | 02-Feb-2001: Musashi 3.3.1 released 109 | Note: due to the pc-relative requirement for some new drivers 110 | in MAME, I've released this small update. 111 | - Added pc-relative read modes 112 | - small optimizations to the exception handling that will help 113 | when splitting the cores 114 | - Updated the example (oops!) 115 | -------------------------------------------------------------------------------- /src/m68000/m68kconf.h: -------------------------------------------------------------------------------- 1 | /* ======================================================================== */ 2 | /* ========================= LICENSING & COPYRIGHT ======================== */ 3 | /* ======================================================================== */ 4 | /* 5 | * MUSASHI 6 | * Version 3.3 7 | * 8 | * A portable Motorola M680x0 processor emulation engine. 9 | * Copyright 1998-2001 Karl Stenerud. All rights reserved. 10 | * 11 | * This code may be freely used for non-commercial purposes as long as this 12 | * copyright notice remains unaltered in the source code and any binary files 13 | * containing this code in compiled form. 14 | * 15 | * All other lisencing terms must be negotiated with the author 16 | * (Karl Stenerud). 17 | * 18 | * The latest version of this code can be obtained at: 19 | * http://kstenerud.cjb.net 20 | */ 21 | 22 | 23 | 24 | #ifndef M68KCONF__HEADER 25 | #define M68KCONF__HEADER 26 | 27 | 28 | /* Configuration switches. 29 | * Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks. 30 | * OPT_SPECIFY_HANDLER causes the core to link directly to the function 31 | * or macro you specify, rather than using callback functions whose pointer 32 | * must be passed in using m68k_set_xxx_callback(). 33 | */ 34 | #define OPT_OFF 0 35 | #define OPT_ON 1 36 | #define OPT_SPECIFY_HANDLER 2 37 | 38 | 39 | /* ======================================================================== */ 40 | /* ============================== MAME STUFF ============================== */ 41 | /* ======================================================================== */ 42 | 43 | /* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME 44 | * to OPT_ON and use m68kmame.h to configure the 68k core. 45 | */ 46 | #ifndef M68K_COMPILE_FOR_MAME 47 | #define M68K_COMPILE_FOR_MAME OPT_OFF 48 | #endif /* M68K_COMPILE_FOR_MAME */ 49 | 50 | 51 | #if M68K_COMPILE_FOR_MAME == OPT_OFF 52 | 53 | 54 | /* ======================================================================== */ 55 | /* ============================= CONFIGURATION ============================ */ 56 | /* ======================================================================== */ 57 | 58 | /* Turn ON if you want to use the following M68K variants */ 59 | #define M68K_EMULATE_010 OPT_OFF 60 | #define M68K_EMULATE_EC020 OPT_OFF 61 | #define M68K_EMULATE_020 OPT_OFF 62 | 63 | 64 | /* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing 65 | * and m68k_read_pcrelative_xx() for PC-relative addressing. 66 | * If off, all read requests from the CPU will be redirected to m68k_read_xx() 67 | */ 68 | #define M68K_SEPARATE_READS OPT_OFF 69 | 70 | /* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a 71 | * predecrement destination EA mode instead of m68k_write_32(). 72 | * To simulate real 68k behavior, m68k_write_32_pd() must first write the high 73 | * word to [address+2], and then write the low word to [address]. 74 | */ 75 | #define M68K_SIMULATE_PD_WRITES OPT_OFF 76 | 77 | /* If ON, CPU will call the interrupt acknowledge callback when it services an 78 | * interrupt. 79 | * If off, all interrupts will be autovectored and all interrupt requests will 80 | * auto-clear when the interrupt is serviced. 81 | */ 82 | #define M68K_EMULATE_INT_ACK OPT_OFF 83 | #define M68K_INT_ACK_CALLBACK(A) your_int_ack_handler_function(A) 84 | 85 | 86 | /* If ON, CPU will call the breakpoint acknowledge callback when it encounters 87 | * a breakpoint instruction and it is running a 68010+. 88 | */ 89 | #define M68K_EMULATE_BKPT_ACK OPT_OFF 90 | #define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function() 91 | 92 | 93 | /* If ON, the CPU will monitor the trace flags and take trace exceptions 94 | */ 95 | #define M68K_EMULATE_TRACE OPT_OFF 96 | 97 | 98 | /* If ON, CPU will call the output reset callback when it encounters a reset 99 | * instruction. 100 | */ 101 | #define M68K_EMULATE_RESET OPT_OFF 102 | #define M68K_RESET_CALLBACK() your_reset_handler_function() 103 | 104 | 105 | /* If ON, CPU will call the set fc callback on every memory access to 106 | * differentiate between user/supervisor, program/data access like a real 107 | * 68000 would. This should be enabled and the callback should be set if you 108 | * want to properly emulate the m68010 or higher. (moves uses function codes 109 | * to read/write data from different address spaces) 110 | */ 111 | #define M68K_EMULATE_FC OPT_OFF 112 | #define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A) 113 | 114 | 115 | /* If ON, CPU will call the pc changed callback when it changes the PC by a 116 | * large value. This allows host programs to be nicer when it comes to 117 | * fetching immediate data and instructions on a banked memory system. 118 | */ 119 | #define M68K_MONITOR_PC OPT_OFF 120 | #define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A) 121 | 122 | 123 | /* If ON, CPU will call the instruction hook callback before every 124 | * instruction. 125 | */ 126 | #define M68K_INSTRUCTION_HOOK OPT_OFF 127 | #define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function() 128 | 129 | 130 | /* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */ 131 | #define M68K_EMULATE_PREFETCH OPT_OFF 132 | 133 | 134 | /* If ON, the CPU will generate address error exceptions if it tries to 135 | * access a word or longword at an odd address. 136 | * NOTE: This is only emulated properly for 68000 mode. 137 | */ 138 | #define M68K_EMULATE_ADDRESS_ERROR OPT_OFF 139 | 140 | 141 | /* Turn ON to enable logging of illegal instruction calls. 142 | * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream. 143 | * Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls. 144 | */ 145 | #define M68K_LOG_ENABLE OPT_OFF 146 | #define M68K_LOG_1010_1111 OPT_OFF 147 | #define M68K_LOG_FILEHANDLE some_file_handle 148 | 149 | 150 | /* ----------------------------- COMPATIBILITY ---------------------------- */ 151 | 152 | /* The following options set optimizations that violate the current ANSI 153 | * standard, but will be compliant under the forthcoming C9X standard. 154 | */ 155 | 156 | 157 | /* If ON, the enulation core will use 64-bit integers to speed up some 158 | * operations. 159 | */ 160 | #define M68K_USE_64_BIT OPT_OFF 161 | 162 | 163 | /* Set to your compiler's static inline keyword to enable it, or 164 | * set it to blank to disable it. 165 | * If you define INLINE in the makefile, it will override this value. 166 | * NOTE: not enabling inline functions will SEVERELY slow down emulation. 167 | */ 168 | #ifndef INLINE 169 | #define INLINE static __inline__ 170 | #endif /* INLINE */ 171 | 172 | #endif /* M68K_COMPILE_FOR_MAME */ 173 | 174 | 175 | /* ======================================================================== */ 176 | /* ============================== END OF FILE ============================= */ 177 | /* ======================================================================== */ 178 | 179 | #endif /* M68KCONF__HEADER */ 180 | -------------------------------------------------------------------------------- /src/m68000/m68kmake.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niuus/NeoCDRX/676eee0a335cccf0a3b86dfc5a17198494922a6a/src/m68000/m68kmake.exe -------------------------------------------------------------------------------- /src/m68000/m68kmame.h: -------------------------------------------------------------------------------- 1 | #ifndef M68KMAME__HEADER 2 | #define M68KMAME__HEADER 3 | 4 | /* ======================================================================== */ 5 | /* ============================== MAME STUFF ============================== */ 6 | /* ======================================================================== */ 7 | 8 | #include "driver.h" 9 | #include "cpuintrf.h" 10 | #include "memory.h" 11 | #include "mamedbg.h" 12 | #include "m68000.h" 13 | 14 | /* Configuration switches (see m68kconf.h for explanation) */ 15 | #define M68K_SEPARATE_READS OPT_ON 16 | 17 | #define M68K_SIMULATE_PD_WRITES OPT_ON 18 | 19 | #define M68K_EMULATE_INT_ACK OPT_ON 20 | #define M68K_INT_ACK_CALLBACK(A) 21 | 22 | #define M68K_EMULATE_BKPT_ACK OPT_OFF 23 | #define M68K_BKPT_ACK_CALLBACK() 24 | 25 | #define M68K_EMULATE_TRACE OPT_OFF 26 | 27 | #define M68K_EMULATE_RESET OPT_ON 28 | #define M68K_RESET_CALLBACK() 29 | 30 | #define M68K_EMULATE_FC OPT_OFF 31 | #define M68K_SET_FC_CALLBACK(A) 32 | 33 | #define M68K_MONITOR_PC OPT_SPECIFY_HANDLER 34 | #define M68K_SET_PC_CALLBACK(A) change_pc(A) 35 | 36 | #define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER 37 | #define M68K_INSTRUCTION_CALLBACK() CALL_MAME_DEBUG 38 | 39 | #define M68K_EMULATE_PREFETCH OPT_ON 40 | 41 | #define M68K_LOG_ENABLE OPT_OFF 42 | #define M68K_LOG_1010_1111 OPT_OFF 43 | #define M68K_LOG_FILEHANDLE errorlog 44 | 45 | #define M68K_EMULATE_ADDRESS_ERROR OPT_OFF 46 | 47 | #define M68K_USE_64_BIT OPT_OFF 48 | 49 | 50 | #define m68ki_remaining_cycles m68k_ICount 51 | 52 | 53 | extern struct m68k_memory_interface m68k_memory_intf; 54 | extern offs_t m68k_encrypted_opcode_start[MAX_CPU]; 55 | extern offs_t m68k_encrypted_opcode_end[MAX_CPU]; 56 | 57 | #define m68k_read_memory_8(address) (*m68k_memory_intf.read8)(address) 58 | #define m68k_read_memory_16(address) (*m68k_memory_intf.read16)(address) 59 | #define m68k_read_memory_32(address) (*m68k_memory_intf.read32)(address) 60 | 61 | #define m68k_read_immediate_16(address) m68kx_read_immediate_16(address) 62 | #define m68k_read_immediate_32(address) m68kx_read_immediate_32(address) 63 | #define m68k_read_pcrelative_8(address) m68kx_read_pcrelative_8(address) 64 | #define m68k_read_pcrelative_16(address) m68kx_read_pcrelative_16(address) 65 | #define m68k_read_pcrelative_32(address) m68kx_read_pcrelative_32(address) 66 | 67 | #define m68k_read_disassembler_16(address) m68kx_read_immediate_16(address) 68 | #define m68k_read_disassembler_32(address) m68kx_read_immediate_32(address) 69 | 70 | #define m68k_write_memory_8(address, value) (*m68k_memory_intf.write8)(address, value) 71 | #define m68k_write_memory_16(address, value) (*m68k_memory_intf.write16)(address, value) 72 | #define m68k_write_memory_32(address, value) (*m68k_memory_intf.write32)(address, value) 73 | #define m68k_write_memory_32_pd(address, value) m68kx_write_memory_32_pd(address, value) 74 | 75 | 76 | INLINE unsigned int m68k_read_immediate_16(unsigned int address); 77 | INLINE unsigned int m68k_read_immediate_32(unsigned int address); 78 | INLINE unsigned int m68k_read_pcrelative_8(unsigned int address); 79 | INLINE unsigned int m68k_read_pcrelative_16(unsigned int address); 80 | INLINE unsigned int m68k_read_pcrelative_32(unsigned int address); 81 | INLINE void m68k_write_memory_32_pd(unsigned int address, unsigned int value); 82 | 83 | 84 | INLINE unsigned int m68kx_read_immediate_16(unsigned int address) 85 | { 86 | return cpu_readop16((address) ^ m68k_memory_intf.opcode_xor); 87 | } 88 | 89 | INLINE unsigned int m68kx_read_immediate_32(unsigned int address) 90 | { 91 | return ((m68k_read_immediate_16(address) << 16) | m68k_read_immediate_16((address)+2)); 92 | } 93 | 94 | INLINE unsigned int m68kx_read_pcrelative_8(unsigned int address) 95 | { 96 | if (address >= m68k_encrypted_opcode_start[cpu_getactivecpu()] && 97 | address < m68k_encrypted_opcode_end[cpu_getactivecpu()]) 98 | return ((m68k_read_immediate_16(address&~1)>>(8*(1-(address & 1))))&0xff); 99 | else 100 | return m68k_read_memory_8(address); 101 | } 102 | 103 | INLINE unsigned int m68kx_read_pcrelative_16(unsigned int address) 104 | { 105 | if (address >= m68k_encrypted_opcode_start[cpu_getactivecpu()] && 106 | address < m68k_encrypted_opcode_end[cpu_getactivecpu()]) 107 | return m68k_read_immediate_16(address); 108 | else 109 | return m68k_read_memory_16(address); 110 | } 111 | 112 | INLINE unsigned int m68kx_read_pcrelative_32(unsigned int address) 113 | { 114 | if (address >= m68k_encrypted_opcode_start[cpu_getactivecpu()] && 115 | address < m68k_encrypted_opcode_end[cpu_getactivecpu()]) 116 | return m68k_read_immediate_32(address); 117 | else 118 | return m68k_read_memory_32(address); 119 | } 120 | 121 | 122 | /* Special call to simulate undocumented 68k behavior when move.l with a 123 | * predecrement destination mode is executed. 124 | * A real 68k first writes the high word to [address+2], and then writes the 125 | * low word to [address]. 126 | */ 127 | INLINE void m68kx_write_memory_32_pd(unsigned int address, unsigned int value) 128 | { 129 | (*m68k_memory_intf.write16)(address+2, value>>16); 130 | (*m68k_memory_intf.write16)(address, value&0xffff); 131 | } 132 | 133 | 134 | void m68k_set_encrypted_opcode_range(int cpunum, offs_t start, offs_t end); 135 | 136 | 137 | #ifdef A68K0 138 | #define M68K_EMULATE_010 OPT_OFF 139 | #else 140 | /* M68K Variants */ 141 | #if HAS_M68010 142 | #define M68K_EMULATE_010 OPT_ON 143 | #else 144 | #define M68K_EMULATE_010 OPT_OFF 145 | #endif 146 | 147 | #endif /* A68K0 */ 148 | 149 | #ifdef A68K2 150 | #define M68K_EMULATE_EC020 OPT_OFF 151 | #define M68K_EMULATE_020 OPT_OFF 152 | #else 153 | #undef M68K_EMULATE_010 154 | #define M68K_EMULATE_010 OPT_ON 155 | 156 | #if HAS_M68EC020 157 | #define M68K_EMULATE_EC020 OPT_ON 158 | #else 159 | #define M68K_EMULATE_EC020 OPT_OFF 160 | #endif 161 | 162 | #if HAS_M68020 163 | #define M68K_EMULATE_020 OPT_ON 164 | #else 165 | #define M68K_EMULATE_020 OPT_OFF 166 | #endif 167 | 168 | #endif /* A68K2 */ 169 | 170 | /* ======================================================================== */ 171 | /* ============================== END OF FILE ============================= */ 172 | /* ======================================================================== */ 173 | 174 | #endif /* M68KMAME__HEADER */ 175 | -------------------------------------------------------------------------------- /src/mcard/icon.h: -------------------------------------------------------------------------------- 1 | 2 | unsigned short saveicon[1024] = 3 | { 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 4 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 5 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 6 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 7 | 0x0FFF, 0x0FFF, 0x0FFF, 8 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 9 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 10 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 11 | 0x0FFF, 0x0FFF, 0x0FFF, 12 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 13 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 14 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 15 | 0x0FFF, 0x0FFF, 0x0FFF, 16 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 17 | 0x0FFF, 0x0FFF, 0x0FFF, 18 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 19 | 0x0FFF, 0x0FFF, 0x0FFF, 20 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 21 | 0x0FFF, 0x0FFF, 0x0FFF, 22 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 23 | 0x0FFF, 0x0FFF, 0x0FFF, 24 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 25 | 0x0FFF, 0x0FFF, 0x0FFF, 26 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x2FFF, 0x5FFF, 0x0FFF, 27 | 0x3FFF, 0x7FFF, 0x7EEF, 28 | 0x3FFF, 0x7EFF, 0x7BBC, 0x7AAB, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x1FFF, 29 | 0x0FFF, 0x0FFF, 0x0FFF, 30 | 0x7FFF, 0x2FFF, 0x0FFF, 0x0FFF, 0x7DEE, 0x7FFF, 0x2FFF, 0x0FFF, 0x0FFF, 31 | 0x0FFF, 0x0FFF, 0x0FFF, 32 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x1FFF, 0x0FFF, 33 | 0x0FFF, 0x2FFF, 0x7FFF, 34 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x2FFF, 0x5FFF, 0x6FFF, 0x6FFF, 0x7FFF, 35 | 0x7899, 0x7ABC, 0x7678, 36 | 0x7556, 0x7455, 0x7EFF, 0x7DEE, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x6FFF, 37 | 0x6FFF, 0x6FFF, 0x6FFF, 38 | 0x789A, 0x7CDE, 0x7EEF, 0x7EEE, 0x7CDD, 0x7DEE, 0x7EEE, 0x7CDD, 0x0FFF, 39 | 0x0FFF, 0x0FFF, 0x0FFF, 40 | 0x6FFF, 0x3FFF, 0x0FFF, 0x0FFF, 0x7EFF, 0x7EEF, 0x4FFF, 0x0FFF, 0x7BCC, 41 | 0x7EEE, 0x7EEE, 0x4FFF, 42 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 43 | 0x0FFF, 0x0FFF, 0x0FFF, 44 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x3FFF, 0x0FFF, 45 | 0x0FFF, 0x3FFF, 0x7EEE, 46 | 0x0FFF, 0x3FFF, 0x7EEE, 0x7444, 0x0FFF, 0x6FFF, 0x7789, 0x7CDD, 0x7DEE, 47 | 0x779A, 0x7456, 0x7112, 48 | 0x7344, 0x7345, 0x7123, 0x7000, 0x789A, 0x7345, 0x7000, 0x7000, 0x7789, 49 | 0x7000, 0x7000, 0x7000, 50 | 0x7AAA, 0x7EEF, 0x7FFF, 0x2FFF, 0x7001, 0x7AAB, 0x7CDD, 0x7FFF, 0x7000, 51 | 0x7112, 0x7789, 0x7BCC, 52 | 0x7000, 0x7000, 0x7011, 0x7789, 0x0FFF, 0x2FFF, 0x7FFF, 0x7889, 0x2FFF, 53 | 0x7FFF, 0x7BCD, 0x7789, 54 | 0x7EFF, 0x7ABC, 0x7ABC, 0x7FFF, 0x7789, 0x79AB, 0x7FFF, 0x7FFF, 0x7555, 55 | 0x7FFF, 0x7FFF, 0x7FFF, 56 | 0x7FFF, 0x7FFF, 0x7FFF, 0x7EFF, 0x7FFF, 0x7FFF, 0x7EFF, 0x7EEE, 0x7FFF, 57 | 0x7CCD, 0x789A, 0x7678, 58 | 0x7FFF, 0x7DEE, 0x7BCC, 0x79AB, 0x7EEF, 0x7AAB, 0x7011, 0x7456, 0x7CDE, 59 | 0x7ABB, 0x7556, 0x7345, 60 | 0x78AB, 0x7679, 0x7667, 0x7122, 0x7457, 0x7677, 0x7EEF, 0x7EEE, 0x7234, 61 | 0x7000, 0x7555, 0x7EEE, 62 | 0x7111, 0x7000, 0x7000, 0x7556, 0x7000, 0x7000, 0x7111, 0x7000, 0x4FFF, 63 | 0x0FFF, 0x0FFF, 0x0FFF, 64 | 0x7EEE, 0x4FFF, 0x0FFF, 0x0FFF, 0x7EEE, 0x7EEF, 0x4FFF, 0x0FFF, 0x7556, 65 | 0x7DDE, 0x7CCC, 0x3FFF, 66 | 0x0FFF, 0x7FFF, 0x7445, 0x7889, 0x0FFF, 0x7FFF, 0x7334, 0x7345, 0x0FFF, 67 | 0x7FFF, 0x7455, 0x7556, 68 | 0x0FFF, 0x7FFF, 0x7556, 0x7678, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 69 | 0x7000, 0x7000, 0x7000, 70 | 0x7000, 0x7001, 0x7000, 0x7000, 0x7000, 0x7456, 0x7334, 0x7000, 0x7111, 71 | 0x7456, 0x7111, 0x7011, 72 | 0x7233, 0x7567, 0x7566, 0x7000, 0x7000, 0x7122, 0x7112, 0x7000, 0x7000, 73 | 0x7000, 0x7000, 0x7011, 74 | 0x7789, 0x7FFF, 0x7FFF, 0x7FFF, 0x79AB, 0x7FFF, 0x7FFF, 0x7EEF, 0x79AB, 75 | 0x7FFF, 0x7FFF, 0x7EEF, 76 | 0x789A, 0x7DDD, 0x7BCC, 0x7ABB, 0x7FFF, 0x7BBC, 0x7123, 0x7122, 0x7EEF, 77 | 0x7BCC, 0x7111, 0x7456, 78 | 0x7CDD, 0x7BCD, 0x7AAC, 0x7678, 0x789A, 0x7467, 0x7234, 0x7011, 0x7467, 79 | 0x7223, 0x7001, 0x7000, 80 | 0x7456, 0x7111, 0x7000, 0x7000, 0x7112, 0x7000, 0x7000, 0x7112, 0x7000, 81 | 0x7000, 0x7011, 0x7233, 82 | 0x7000, 0x7111, 0x7111, 0x7111, 0x7111, 0x7112, 0x7111, 0x7001, 0x7112, 83 | 0x7122, 0x7223, 0x7000, 84 | 0x7778, 0x7000, 0x7233, 0x7000, 0x7000, 0x7222, 0x7333, 0x6FFF, 0x7000, 85 | 0x7111, 0x7455, 0x5FFF, 86 | 0x7000, 0x7233, 0x7223, 0x7FFF, 0x7000, 0x7456, 0x7334, 0x7FFF, 0x0FFF, 87 | 0x7FFF, 0x7556, 0x7788, 88 | 0x0FFF, 0x7FFF, 0x7566, 0x7899, 0x0FFF, 0x7FFF, 0x7667, 0x7678, 0x0FFF, 89 | 0x7FFF, 0x7334, 0x7122, 90 | 0x7000, 0x7000, 0x7001, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 91 | 0x7000, 0x7000, 0x7000, 92 | 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7011, 0x7000, 93 | 0x7000, 0x7000, 0x7000, 94 | 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7112, 95 | 0x7122, 0x7112, 0x7011, 96 | 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7011, 0x7000, 0x7000, 0x7000, 97 | 0x7001, 0x7000, 0x7000, 98 | 0x7233, 0x7234, 0x7011, 0x7000, 0x7001, 0x7223, 0x7112, 0x7000, 0x7000, 99 | 0x7000, 0x7122, 0x7112, 100 | 0x7000, 0x7000, 0x7345, 0x7567, 0x7000, 0x7111, 0x7001, 0x7233, 0x7111, 101 | 0x7111, 0x7233, 0x7678, 102 | 0x7111, 0x7001, 0x7556, 0x7778, 0x7122, 0x7000, 0x7233, 0x7CCD, 0x7BCC, 103 | 0x7000, 0x7112, 0x7112, 104 | 0x7334, 0x7111, 0x7345, 0x7345, 0x7000, 0x7446, 0x7567, 0x7011, 0x789A, 105 | 0x7677, 0x7000, 0x7000, 106 | 0x7000, 0x7456, 0x7333, 0x7FFF, 0x7000, 0x7556, 0x7344, 0x7FFF, 0x7000, 107 | 0x7667, 0x7344, 0x7FFF, 108 | 0x7001, 0x7567, 0x7223, 0x7FFF, 0x0FFF, 0x4FFF, 0x7AAA, 0x7111, 0x0FFF, 109 | 0x0FFF, 0x4FFF, 0x799A, 110 | 0x0FFF, 0x0FFF, 0x0FFF, 0x4FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x7122, 111 | 0x7011, 0x7000, 0x7000, 112 | 0x7001, 0x7223, 0x7112, 0x7000, 0x79AA, 0x7001, 0x7234, 0x7122, 0x4FFF, 113 | 0x7999, 0x7011, 0x7345, 114 | 0x7000, 0x7000, 0x7000, 0x7000, 0x7000, 0x7001, 0x7334, 0x7345, 0x7000, 115 | 0x7000, 0x7122, 0x7111, 116 | 0x7678, 0x7456, 0x7122, 0x7345, 0x7011, 0x7000, 0x7000, 0x7000, 0x7112, 117 | 0x7000, 0x7000, 0x7000, 118 | 0x7000, 0x7000, 0x7112, 0x7334, 0x7568, 0x7567, 0x7345, 0x789A, 0x7000, 119 | 0x7333, 0x7ABC, 0x7233, 120 | 0x7333, 0x7CDD, 0x7444, 0x7333, 0x7BCC, 0x7445, 0x7222, 0x7DDD, 0x7444, 121 | 0x7222, 0x7DDD, 0x3FFF, 122 | 0x7112, 0x7112, 0x7000, 0x7233, 0x7BBB, 0x7455, 0x7111, 0x7000, 0x3FFF, 123 | 0x7DDD, 0x7334, 0x7001, 124 | 0x0FFF, 0x3FFF, 0x7DDD, 0x7344, 0x7445, 0x7333, 0x7000, 0x7000, 0x7000, 125 | 0x7000, 0x7111, 0x7568, 126 | 0x7000, 0x7000, 0x7578, 0x7456, 0x7223, 0x7456, 0x7122, 0x7000, 0x7345, 127 | 0x7122, 0x7111, 0x7FFF, 128 | 0x7122, 0x7111, 0x7BBB, 0x4FFF, 0x7111, 0x7BBB, 0x4FFF, 0x0FFF, 0x7BBB, 129 | 0x4FFF, 0x0FFF, 0x0FFF, 130 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 131 | 0x0FFF, 0x0FFF, 0x0FFF, 132 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x4FFF, 0x7999, 0x7456, 0x0FFF, 133 | 0x0FFF, 0x4FFF, 0x7AAA, 134 | 0x0FFF, 0x0FFF, 0x0FFF, 0x3FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x7678, 135 | 0x7456, 0x7456, 0x7567, 136 | 0x7111, 0x7111, 0x7111, 0x7111, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x0FFF, 137 | 0x0FFF, 0x0FFF, 0x0FFF, 138 | 0x7567, 0x7678, 0x7567, 0x7223, 0x7111, 0x7122, 0x7122, 0x7333, 0x7FFF, 139 | 0x7FFF, 0x7FFF, 0x6FFF, 140 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x7222, 0x7DDD, 0x3FFF, 0x0FFF, 0x7DDD, 141 | 0x3FFF, 0x0FFF, 0x0FFF, 142 | 0x2FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 143 | 0x0FFF, 0x3FFF, 0x7DDD, 144 | 0x0FFF, 0x0FFF, 0x0FFF, 0x3FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 145 | 0x0FFF, 0x0FFF, 0x0FFF, 146 | 0x7678, 0x7345, 0x7111, 0x7BBB, 0x7DDE, 0x7333, 0x7AAA, 0x3FFF, 0x2FFF, 147 | 0x6FFF, 0x2FFF, 0x0FFF, 148 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x4FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 149 | 0x0FFF, 0x0FFF, 0x0FFF, 150 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 151 | 0x0FFF, 0x0FFF, 0x0FFF, 152 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 153 | 0x0FFF, 0x0FFF, 0x0FFF, 154 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 155 | 0x0FFF, 0x0FFF, 0x0FFF, 156 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 157 | 0x0FFF, 0x0FFF, 0x0FFF, 158 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 159 | 0x0FFF, 0x0FFF, 0x0FFF, 160 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 161 | 0x0FFF, 0x0FFF, 0x0FFF, 162 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 163 | 0x0FFF, 0x0FFF, 0x0FFF, 164 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 165 | 0x0FFF, 0x0FFF, 0x0FFF, 166 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 167 | 0x0FFF, 0x0FFF, 0x0FFF, 168 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 169 | 0x0FFF, 0x0FFF, 0x0FFF, 170 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 171 | 0x0FFF, 0x0FFF, 0x0FFF, 172 | 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 173 | }; 174 | -------------------------------------------------------------------------------- /src/mcard/mcard.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "neocdrx.h" 12 | #include "icon.h" 13 | 14 | #define MC_SIZE 0x4000 15 | #define MC_MAKER "NCRX" 16 | #define MC_CODE "00" 17 | #define MC_FILENAME "NeoCDRX.sav" 18 | #define MC_COMMENT1 "NeoCD RX 1.5" 19 | #define MC_COMMENT2 "CD Memory Card Save" 20 | 21 | static u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32); 22 | static u8 mcardbuffer[MC_SIZE] ATTRIBUTE_ALIGN (32); 23 | static card_dir CardDir; 24 | static card_file CardFile; 25 | static card_stat CardStatus; 26 | static int cardslot; 27 | 28 | /**************************************************************************** 29 | * MountMemCard 30 | * 31 | * Try to mount a memory card 32 | ****************************************************************************/ 33 | static int 34 | MountMemCard (void) 35 | { 36 | int CardError; 37 | int retries = 0; 38 | 39 | memset (SysArea, 0, CARD_WORKAREA); 40 | 41 | while (retries < 10) 42 | { 43 | CardError = CARD_Mount (CARD_SLOTA, SysArea, NULL); 44 | if (CardError) 45 | { 46 | CardError = CARD_Mount (CARD_SLOTB, SysArea, NULL); 47 | if (!CardError) 48 | cardslot = CARD_SLOTB; 49 | } 50 | else 51 | cardslot = CARD_SLOTA; 52 | 53 | if (CardError) 54 | { 55 | retries++; 56 | } 57 | else 58 | retries = 10; 59 | } 60 | 61 | return (CardError == 0); 62 | } 63 | 64 | /**************************************************************************** 65 | * CardFileExists 66 | * 67 | * Look for an existing memory card save 68 | ****************************************************************************/ 69 | static int 70 | CardFileExists (char *filename) 71 | { 72 | int CardError; 73 | 74 | memset (&CardDir, 0, sizeof (card_dir)); 75 | 76 | CardError = CARD_FindFirst (cardslot, &CardDir, TRUE); 77 | while (CardError != CARD_ERROR_NOFILE) 78 | { 79 | if (strcmp ((char *) CardDir.filename, filename) == 0) 80 | return 1; 81 | 82 | CardError = CARD_FindNext (&CardDir); 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | /**************************************************************************** 89 | * neogeo_get_memorycard 90 | * 91 | * Function to retrieve or create a memory card save 92 | ****************************************************************************/ 93 | int 94 | neogeo_get_memorycard (void) 95 | { 96 | 97 | if (SaveDevice == 0) 98 | { 99 | int carderror; 100 | int blocks; 101 | u32 sectorsize; 102 | int ofs; 103 | char mcfilename[] = MC_FILENAME; 104 | 105 | /*** Initialise the card lib ***/ 106 | CARD_Init (MC_MAKER, MC_CODE); 107 | 108 | if (MountMemCard ()) 109 | { 110 | /*** Get sector size ***/ 111 | carderror = CARD_GetSectorSize (cardslot, §orsize); 112 | blocks = (MC_SIZE / sectorsize) * sectorsize; 113 | if (MC_SIZE % sectorsize) 114 | blocks += sectorsize; 115 | 116 | if (CardFileExists (mcfilename)) 117 | { 118 | carderror = CARD_Open (cardslot, MC_FILENAME, &CardFile); 119 | if (carderror) 120 | { 121 | CARD_Unmount (cardslot); 122 | return 0; 123 | } 124 | 125 | /*** Read in the data ***/ 126 | ofs = 0; 127 | DCInvalidateRange (mcardbuffer, MC_SIZE); 128 | while (ofs < blocks) 129 | { 130 | CARD_Read (&CardFile, mcardbuffer + ofs, sectorsize, ofs); 131 | ofs += sectorsize; 132 | } 133 | 134 | memcpy (neogeo_memorycard, mcardbuffer + 2112, 8192); 135 | CARD_Close (&CardFile); 136 | CARD_Unmount (cardslot); 137 | 138 | return 1; 139 | } 140 | else 141 | { 142 | CARD_Unmount (cardslot); 143 | return neogeo_set_memorycard (); 144 | } 145 | } 146 | } 147 | else //SD Card 148 | { 149 | FILE *fp; 150 | int Readed; 151 | 152 | fp = fopen("/NeoCDRX/NeoCDRXsave.bin", "rb"); 153 | if (!fp) 154 | { 155 | // file does not exist, try to create it 156 | neogeo_set_memorycard(); 157 | 158 | return 0; 159 | } 160 | 161 | Readed = fread(neogeo_memorycard, 1, 8192, fp); 162 | 163 | fclose(fp); 164 | 165 | if (Readed == 8192) 166 | { 167 | return 1; 168 | } 169 | } 170 | 171 | return 0; 172 | } 173 | 174 | /**************************************************************************** 175 | * neogeo_set_memorycard 176 | ****************************************************************************/ 177 | int 178 | neogeo_set_memorycard (void) 179 | { 180 | if (SaveDevice == 0) 181 | { 182 | int carderror; 183 | int blocks; 184 | u32 sectorsize; 185 | int ofs; 186 | char mcfilename[] = MC_FILENAME; 187 | 188 | CARD_Init (MC_MAKER, MC_CODE); 189 | 190 | if (MountMemCard ()) 191 | { 192 | carderror = CARD_GetSectorSize (cardslot, §orsize); 193 | blocks = (MC_SIZE / sectorsize) * sectorsize; 194 | if (blocks % sectorsize) 195 | blocks += sectorsize; 196 | 197 | if (CardFileExists (mcfilename)) 198 | { 199 | carderror = CARD_Open (cardslot, MC_FILENAME, &CardFile); 200 | if (carderror) 201 | { 202 | CARD_Unmount (cardslot); 203 | return 0; 204 | } 205 | } 206 | else 207 | { 208 | carderror = CARD_Create (cardslot, MC_FILENAME, blocks, &CardFile); 209 | if (carderror) 210 | { 211 | CARD_Unmount (cardslot); 212 | return 0; 213 | } 214 | } 215 | 216 | memset (mcardbuffer, 0, MC_SIZE); 217 | 218 | /*** 1. Copy the icon ***/ 219 | memcpy (mcardbuffer, saveicon, 2048); 220 | 221 | /*** 2. Set comments - 32 bytes each***/ 222 | memcpy (mcardbuffer + 2048, MC_COMMENT1, strlen (MC_COMMENT1)); 223 | memcpy (mcardbuffer + 2080, MC_COMMENT2, strlen (MC_COMMENT2)); 224 | 225 | /*** 3. Copy neogeo_memorycard ***/ 226 | memcpy (mcardbuffer + 2112, neogeo_memorycard, 8192); 227 | 228 | /*** Set defaults in card status ***/ 229 | CARD_GetStatus (cardslot, CardFile.filenum, &CardStatus); 230 | CardStatus.icon_addr = 0; 231 | CardStatus.icon_fmt = 2; 232 | CardStatus.icon_speed = 1; 233 | CardStatus.comment_addr = 2048; 234 | CARD_SetStatus (cardslot, CardFile.filenum, &CardStatus); 235 | 236 | /*** Write the file ***/ 237 | ofs = 0; 238 | DCFlushRange (mcardbuffer, MC_SIZE); 239 | while (ofs < blocks) 240 | { 241 | carderror = 242 | CARD_Write (&CardFile, mcardbuffer + ofs, sectorsize, ofs); 243 | ofs += sectorsize; 244 | } 245 | 246 | CARD_Close (&CardFile); 247 | CARD_Unmount (cardslot); 248 | 249 | return 1; 250 | } 251 | } 252 | else //SD Card 253 | { 254 | 255 | FILE *fp; 256 | int Written; 257 | 258 | fp = fopen("/NeoCDRX/NeoCDRXsave.bin", "wb"); 259 | if (!fp) 260 | { 261 | return 0; 262 | } 263 | 264 | Written = fwrite(neogeo_memorycard, 1, 8192, fp); 265 | 266 | fclose(fp); 267 | 268 | if (Written == 8192) 269 | { 270 | return 1; 271 | } 272 | } 273 | return 0; 274 | } 275 | -------------------------------------------------------------------------------- /src/mcard/mcard.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #ifndef __NEOMEMCARD__ 8 | #define __NEOMEMCARD__ 9 | 10 | int neogeo_get_memorycard (void); 11 | int neogeo_set_memorycard (void); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/memory/memory.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * NeoGeo CD Memory Interface 9 | * 10 | * Based on the standard Mame memory interface. 11 | ****************************************************************************/ 12 | #ifndef __MEMINTRF__ 13 | #define __MEMINTRF__ 14 | 15 | #define READ8_HANDLER(name) unsigned char name(unsigned int offset) 16 | #define WRITE8_HANDLER(name) void name(unsigned int offset, unsigned char data) 17 | #define READ16_HANDLER(name) unsigned short name(unsigned int offset, unsigned short mem_mask) 18 | #define WRITE16_HANDLER(name) void name(unsigned int offset, unsigned short data, unsigned short mem_mask) 19 | #define READ32_HANDLER(name) unsigned int name(unsigned int offset) 20 | #define WRITE32_HANDLER(name) void name(unsigned int offset, unsigned int data) 21 | 22 | #define ACCESSING_LSB16 ((mem_mask & 0x00ff) == 0) 23 | #define ACCESSING_MSB16 ((mem_mask & 0xff00) == 0) 24 | #define ACCESSING_LSB ACCESSING_LSB16 25 | #define ACCESSING_MSB ACCESSING_MSB16 26 | 27 | #define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask)) 28 | #define COMBINE_SWABDATA(varptr) (*(varptr) = (*(varptr) & (mem_mask << 8)) | (data & ~(mem_mask >> 8))) 29 | 30 | #define MEM_AMASK 0x00ffffff 31 | 32 | #define MEM_END -1 33 | #define MEM_BAD 0 34 | #define MEM_ROM 1 35 | #define MEM_RAM 2 36 | #define MEM_NOP 3 37 | #define MEM_MAP 4 38 | 39 | #define IRQ1CTRL_AUTOANIM_STOP 0x08 40 | #define IRQ1CTRL_ENABLE 0x10 41 | #define IRQ1CTRL_LOAD_RELATIVE 0x20 42 | #define IRQ1CTRL_AUTOLOAD_VBLANK 0x40 43 | #define IRQ1CTRL_AUTOLOAD_REPEAT 0x80 44 | 45 | #define RASTER_LINES 264 46 | #define RASTER_COUNTER_START 0x1f0 /* value assumed right after vblank */ 47 | #define RASTER_COUNTER_RELOAD 0x0f8 /* value assumed after 0x1ff */ 48 | #define RASTER_LINE_RELOAD (0x200 - RASTER_COUNTER_START) 49 | 50 | #define UPLOAD_IMMEDIATE 0x00 51 | #define UPLOAD_PATTERN 0x01 52 | #define UPLOAD_MEMORY 0x02 53 | #define UPLOAD_FILE 0x03 54 | 55 | #define EXMEM_OBJ 0x00 56 | #define EXMEM_PCMA 0x01 57 | #define EXMEM_Z80 0x04 58 | #define EXMEM_FIX 0x05 59 | #define EXMEM_UNKNOWN 0xff 60 | 61 | #define upload_get_type() m68k_read_memory_8(0x108000 + 0x7eda) 62 | #define upload_get_bank() m68k_read_memory_8(0x108000 + 0x7edb) 63 | #define upload_get_dst() m68k_read_memory_32(0x108000 + 0x7ef4) 64 | #define upload_get_src() m68k_read_memory_32(0x108000 + 0x7ef8) 65 | #define upload_get_length() m68k_read_memory_32(0x108000 + 0x7efc) 66 | 67 | typedef struct 68 | { 69 | int type; 70 | unsigned int start; 71 | unsigned int end; 72 | unsigned short (*func) (unsigned int offset, unsigned short mask); 73 | } READMEM; 74 | 75 | typedef struct 76 | { 77 | int type; 78 | unsigned int start; 79 | unsigned int end; 80 | void (*func) (unsigned int offset, unsigned short data, 81 | unsigned short mask); 82 | } WRITEMEM; 83 | 84 | typedef struct 85 | { 86 | int type; 87 | unsigned int start; 88 | unsigned int end; 89 | unsigned int base; 90 | unsigned short (*func) (unsigned int offset, unsigned short mask); 91 | } READMAP; 92 | 93 | typedef struct 94 | { 95 | int type; 96 | unsigned int start; 97 | unsigned int end; 98 | unsigned int base; 99 | void (*func) (unsigned int offset, unsigned short data, 100 | unsigned short mask); 101 | } WRITEMAP; 102 | 103 | void initialise_memmap (void); 104 | unsigned int m68k_read_memory_8 (unsigned int address); 105 | unsigned int m68k_read_memory_16 (unsigned int address); 106 | unsigned int m68k_read_memory_32 (unsigned int address); 107 | void m68k_write_memory_8 (unsigned int address, unsigned int value); 108 | void m68k_write_memory_16 (unsigned int address, unsigned int value); 109 | void m68k_write_memory_32 (unsigned int address, unsigned int value); 110 | void neogeo_sound_irq (int irq); 111 | void neogeo_interrupt (void); 112 | void neogeo_raster_interrupt (void); 113 | void neogeo_raster_interrupt_busy (void); 114 | void neogeo_decode_spr (unsigned char *mem, unsigned int offset, 115 | unsigned int length); 116 | void neogeo_decode_fix (unsigned char *mem, unsigned int offset, 117 | unsigned int length); 118 | void neogeo_undecode_fix (unsigned char *mem, int offset, 119 | unsigned int length); 120 | void memreset (void); 121 | 122 | extern int watchdog_counter; 123 | extern int scanline; 124 | extern unsigned short *video_paletteram_ng; 125 | extern char neogeo_game_vectors[0x100]; 126 | extern int nowait_irqack; 127 | extern int rastercounter_adjust; 128 | extern int mcard_written; 129 | extern int spr_disable; 130 | extern int fix_disable; 131 | extern int video_enable; 132 | extern int rldivisor; 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /src/ncdr_rom.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "neocdrx.h" 12 | #include "ncdr_rom.h" 13 | 14 | /*** M68K Illegal Op Exceptions ***/ 15 | #define NEOGEO_END_UPLOAD 0xFABF 16 | #define CDROM_LOAD_FILES 0xFAC0 17 | #define NEOGEO_EXIT_CDPLAYER 0xFAC4 18 | #define NEOGEO_PROGRESS_SHOW 0xFAC5 19 | #define NEOGEO_START_UPLOAD 0xFAC6 20 | #define NEOGEO_IPL 0xFAC7 21 | #define NEOGEO_IPL_END 0xFAC8 22 | #define NEOGEO_TRACE 0xFACE 23 | 24 | typedef struct { 25 | unsigned short offset; 26 | unsigned short patch; 27 | } ROMPATCH; 28 | 29 | static ROMPATCH rompatch[] = { 30 | /*** Patch BIOS load files with/without image to use the BIOS routines to decode 31 | the actual filenames needed. This makes more sense to me and safeguards against 32 | unknown filetypes. ***/ 33 | {0xDBFC, 0x4E71}, 34 | {0xDBFE, 0x4E71}, 35 | {0xDC24, 0x4E71}, 36 | {0xDC26, 0x4E71}, 37 | {0xDD42, CDROM_LOAD_FILES}, 38 | {0xDD44, 0x4E71}, 39 | {0xDD46, 0x4E71}, 40 | 41 | /*** Hook for loading animations ***/ 42 | {0xDE48, NEOGEO_PROGRESS_SHOW}, 43 | {0xDE4A, 0x4E71}, 44 | {0xDE4C, 0x4E71}, 45 | {0xDE4E, 0x4E71}, 46 | {0xDE72, 0x4E71}, 47 | {0xDE74, 0x4E71}, 48 | 49 | /*** Reuse FABF for end of file loading cleanups ***/ 50 | {0xDC54, NEOGEO_END_UPLOAD}, 51 | 52 | /*** Patch start of loading with image ***/ 53 | {0xDB80, NEOGEO_START_UPLOAD}, 54 | 55 | /*** Patch BIOS CDROM Check ***/ 56 | {0xB040, 0x4E71}, 57 | {0xB042, 0x4E71}, 58 | 59 | /*** Patch BIOS upload command ***/ 60 | {0x546, 0xFAC1}, 61 | {0x548, 0x4E75}, 62 | 63 | /*** Patch BIOS CDDA check ***/ 64 | {0x56A, 0xFAC3}, 65 | {0x56C, 0x4E75}, 66 | 67 | /*** Patch CD Player Exit ***/ 68 | {0x55E, NEOGEO_EXIT_CDPLAYER}, 69 | {0x560, 0x4E75}, 70 | 71 | /*** Full reset, please ***/ 72 | {0xA87A, 0x4239}, 73 | {0xA87C, 0x0010}, 74 | {0xA87E, 0xFDAE}, 75 | 76 | /*** Patch CD Player ***/ 77 | {0x120, 0x55E}, 78 | 79 | /*** IPL.TXT Processing patches ***/ 80 | {0xD85A, NEOGEO_IPL}, 81 | {0xD85C, 0x4E71}, 82 | {0xD864, 0x4E71}, 83 | {0xD866, 0x4E71}, 84 | {0xD868, 0x4E71}, 85 | {0xD86A, 0x4E71}, 86 | {0xD700, 0x4E71}, 87 | {0xD702, 0x4E71}, 88 | {0xD736, 0x4E71}, 89 | {0xD738, 0x4E71}, 90 | {0xD766, NEOGEO_IPL_END}, 91 | 92 | /*** Removed - BIOS needs to perform this task! ***/ 93 | //{0xD77E, 0x4E71}, 94 | 95 | //{0xD9DA, NEOGEO_TRACE}, 96 | 97 | /*** Terminator ***/ 98 | {0xFFFF, 0xFFFF}, 99 | 100 | /*** System checks ***/ 101 | {0xAD36, 5} 102 | }; 103 | 104 | /**************************************************************************** 105 | * neogeo_patch_rom 106 | ****************************************************************************/ 107 | void neogeo_patch_rom(void) 108 | { 109 | int i = 0; 110 | 111 | while (rompatch[i].offset != 0xFFFF) { 112 | *(unsigned short *) (neogeo_rom_memory + rompatch[i].offset) = 113 | rompatch[i].patch; 114 | i++; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/ncdr_rom.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #ifndef __NCDRROM__ 8 | #define __NCDRROM__ 9 | 10 | void neogeo_patch_rom(void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/neocdrx.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | * 6 | * Acknowledgements 7 | * 8 | * NGCD 0.8 "The Kick Ass NeoGeo CD Emulator" - Martinez Fabrice 9 | * NeoCD/SDL 0.3.1 - Fosters 10 | * NeogeoCDZ - NJ 11 | * Musashi M68000 C Core - Karl Stenerud 12 | * Mame Z80 C Core - Juergen Buchmueller 13 | * Sound core and miscellaneous - Mame Team 14 | * 15 | ****************************************************************************/ 16 | 17 | #ifndef __NEOGEOREDUX__ 18 | #define __NEOGEOREDUX__ 19 | 20 | #define APPTITLE "NeoCD-RX" 21 | #define VERSION "0.1.55" 22 | #define SAMPLE_RATE 48000 23 | 24 | /*** SDL Replacement Types ***/ 25 | typedef signed char Sint8; 26 | typedef unsigned char Uint8; 27 | typedef signed short Sint16; 28 | typedef unsigned short Uint16; 29 | typedef signed int Sint32; 30 | typedef unsigned int Uint32; 31 | 32 | /*** Header files ***/ 33 | #include 34 | #include "m68k.h" 35 | #include "z80intrf.h" 36 | #include "fileio.h" 37 | #include "memory.h" 38 | #include "cpuintf.h" 39 | #include "cdrom.h" 40 | #include "cdaudio.h" 41 | #include "patches.h" 42 | #include "video.h" 43 | #include "gxvideo.h" 44 | #include "pd4990a.h" 45 | #include "input.h" 46 | #include "timer.h" 47 | #include "streams.h" 48 | #include "ay8910.h" 49 | #include "2610intf.h" 50 | #include "sound.h" 51 | #include "gcaudio.h" 52 | #include "mcard.h" 53 | #include "gui.h" 54 | #include "iso9660.h" 55 | #include "dirsel.h" 56 | #include "dvdfileio.h" 57 | #include "sdfileio.h" 58 | #include "wkf.h" 59 | #include "ata.h" 60 | 61 | /*** Functions ***/ 62 | void neogeo_swab(const void *src1, const void *src2, int isize); 63 | int neogeo_redux(void); 64 | void neogeo_decode_spr(unsigned char *mem, unsigned int offset, 65 | unsigned int length); 66 | void neogeo_decode_fix(unsigned char *mem, unsigned int offset, 67 | unsigned int length); 68 | void neogeo_cdda_control(void); 69 | void neogeo_prio_switch(void); 70 | void neogeo_exit(void); 71 | void neogeo_exit_cdplayer(void); 72 | void neogeo_new_game(void); 73 | void neogeo_trace(void); 74 | void neogeo_reset(void); 75 | 76 | /*** Globals ***/ 77 | extern unsigned char *neogeo_rom_memory; 78 | extern unsigned char *neogeo_prg_memory; 79 | extern unsigned char *neogeo_fix_memory; 80 | extern unsigned char *neogeo_ipl_memory; 81 | extern unsigned char *neogeo_spr_memory; 82 | extern unsigned char *neogeo_pcm_memory; 83 | extern unsigned char neogeo_memorycard[8192]; 84 | extern unsigned short SaveDevice; 85 | extern int use_SD; 86 | extern int use_USB; 87 | extern int use_IDE; 88 | extern int use_WKF; 89 | extern int use_DVD; 90 | 91 | extern int have_ROM; 92 | 93 | extern char neogeo_game_vectors[0x100]; 94 | extern char neogeo_region; 95 | extern int patch_ssrpg; 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /src/pd4990a/pd4990a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Emulation for the NEC PD4990A. 3 | * 4 | * The PD4990A is a serial I/O Calendar & Clock IC used in the 5 | * NEO GEO and probably a couple of other machines. 6 | */ 7 | 8 | #include 9 | #include "neocdrx.h" 10 | 11 | /* Set the data in the chip to Monday 09/09/73 00:00:00 */ 12 | /* If you ever read this Leejanne, you know what I mean :-) */ 13 | struct pd4990a_s pd4990a = 14 | { 15 | 0x00, /* seconds BCD */ 16 | 0x00, /* minutes BCD */ 17 | 0x00, /* hours BCD */ 18 | 0x09, /* days BCD */ 19 | 9, /* month Hexadecimal form */ 20 | 0x73, /* year BCD */ 21 | 1 /* weekday BCD */ 22 | }; 23 | 24 | 25 | static int retraces = 0; /* Assumes 60 retraces a second */ 26 | 27 | static int coinflip = 0; /* Pulses a bit in order to simulate */ 28 | 29 | /* test output */ 30 | static int outputbit = 0; 31 | 32 | static int bitno = 0; 33 | 34 | 35 | void 36 | pd4990a_addretrace (void) 37 | { 38 | 39 | coinflip ^= 1; 40 | 41 | retraces++; 42 | 43 | if (retraces < 60) 44 | 45 | return; 46 | 47 | retraces = 0; 48 | 49 | pd4990a.seconds++; 50 | 51 | if ((pd4990a.seconds & 0x0f) < 10) 52 | 53 | return; 54 | 55 | pd4990a.seconds &= 0xf0; 56 | 57 | pd4990a.seconds += 0x10; 58 | 59 | if (pd4990a.seconds < 0x60) 60 | 61 | return; 62 | 63 | pd4990a.seconds = 0; 64 | 65 | pd4990a.minutes++; 66 | 67 | if ((pd4990a.minutes & 0x0f) < 10) 68 | 69 | return; 70 | 71 | pd4990a.minutes &= 0xf0; 72 | 73 | pd4990a.minutes += 0x10; 74 | 75 | if (pd4990a.minutes < 0x60) 76 | 77 | return; 78 | 79 | pd4990a.minutes = 0; 80 | 81 | pd4990a.hours++; 82 | 83 | if ((pd4990a.hours & 0x0f) < 10) 84 | 85 | return; 86 | 87 | pd4990a.hours &= 0xf0; 88 | 89 | pd4990a.hours += 0x10; 90 | 91 | if (pd4990a.hours < 0x24) 92 | 93 | return; 94 | 95 | pd4990a.hours = 0; 96 | 97 | pd4990a_increment_day (); 98 | 99 | } 100 | 101 | 102 | void 103 | pd4990a_increment_day (void) 104 | { 105 | 106 | int real_year; 107 | 108 | 109 | pd4990a.days++; 110 | 111 | if ((pd4990a.days & 0x0f) >= 10) 112 | 113 | { 114 | 115 | pd4990a.days &= 0xf0; 116 | 117 | pd4990a.days += 0x10; 118 | 119 | } 120 | 121 | 122 | pd4990a.weekday++; 123 | 124 | if (pd4990a.weekday == 7) 125 | 126 | pd4990a.weekday = 0; 127 | 128 | 129 | switch (pd4990a.month) 130 | 131 | { 132 | 133 | case 1: 134 | case 3: 135 | case 5: 136 | case 7: 137 | case 8: 138 | case 10: 139 | case 12: 140 | 141 | if (pd4990a.days == 0x32) 142 | 143 | { 144 | 145 | pd4990a.days = 1; 146 | 147 | pd4990a_increment_month (); 148 | 149 | } 150 | 151 | break; 152 | 153 | case 2: 154 | 155 | real_year = (pd4990a.year >> 4) * 10 + (pd4990a.year & 0xf); 156 | 157 | if ((real_year % 4) && (!(real_year % 100) || (real_year % 400))) 158 | 159 | { 160 | 161 | if (pd4990a.days == 0x29) 162 | 163 | { 164 | 165 | pd4990a.days = 1; 166 | 167 | pd4990a_increment_month (); 168 | 169 | } 170 | 171 | } 172 | 173 | else 174 | 175 | { 176 | 177 | if (pd4990a.days == 0x30) 178 | 179 | { 180 | 181 | pd4990a.days = 1; 182 | 183 | pd4990a_increment_month (); 184 | 185 | } 186 | 187 | } 188 | 189 | break; 190 | 191 | case 4: 192 | case 6: 193 | case 9: 194 | case 11: 195 | 196 | if (pd4990a.days == 0x31) 197 | 198 | { 199 | 200 | pd4990a.days = 1; 201 | 202 | pd4990a_increment_month (); 203 | 204 | } 205 | 206 | break; 207 | 208 | } 209 | 210 | } 211 | 212 | 213 | void 214 | pd4990a_increment_month (void) 215 | { 216 | 217 | pd4990a.month++; 218 | 219 | if (pd4990a.month == 13) 220 | 221 | { 222 | 223 | pd4990a.month = 1; 224 | 225 | pd4990a.year++; 226 | 227 | if ((pd4990a.year & 0x0f) >= 10) 228 | 229 | { 230 | 231 | pd4990a.year &= 0xf0; 232 | 233 | pd4990a.year += 0x10; 234 | 235 | } 236 | 237 | if (pd4990a.year == 0xA0) 238 | 239 | pd4990a.year = 0; 240 | 241 | } 242 | 243 | } 244 | 245 | 246 | 247 | READ8_HANDLER (pd4990a_testbit_r) 248 | { 249 | 250 | return (coinflip); 251 | 252 | } 253 | 254 | 255 | 256 | READ8_HANDLER (pd4990a_databit_r) 257 | { 258 | 259 | return (outputbit); 260 | 261 | } 262 | 263 | 264 | 265 | WRITE8_HANDLER (pd4990a_control_w) 266 | { 267 | 268 | switch (data) 269 | 270 | { 271 | 272 | case 0x00: /* Load Register */ 273 | 274 | switch (bitno) 275 | 276 | { 277 | 278 | case 0x00: 279 | case 0x01: 280 | case 0x02: 281 | case 0x03: 282 | 283 | case 0x04: 284 | case 0x05: 285 | case 0x06: 286 | case 0x07: 287 | 288 | outputbit = (pd4990a.seconds >> bitno) & 0x01; 289 | 290 | break; 291 | 292 | case 0x08: 293 | case 0x09: 294 | case 0x0a: 295 | case 0x0b: 296 | 297 | case 0x0c: 298 | case 0x0d: 299 | case 0x0e: 300 | case 0x0f: 301 | 302 | outputbit = (pd4990a.minutes >> (bitno - 0x08)) & 0x01; 303 | 304 | break; 305 | 306 | case 0x10: 307 | case 0x11: 308 | case 0x12: 309 | case 0x13: 310 | 311 | case 0x14: 312 | case 0x15: 313 | case 0x16: 314 | case 0x17: 315 | 316 | outputbit = (pd4990a.hours >> (bitno - 0x10)) & 0x01; 317 | 318 | break; 319 | 320 | case 0x18: 321 | case 0x19: 322 | case 0x1a: 323 | case 0x1b: 324 | 325 | case 0x1c: 326 | case 0x1d: 327 | case 0x1e: 328 | case 0x1f: 329 | 330 | outputbit = (pd4990a.days >> (bitno - 0x18)) & 0x01; 331 | 332 | break; 333 | 334 | case 0x20: 335 | case 0x21: 336 | case 0x22: 337 | case 0x23: 338 | 339 | outputbit = (pd4990a.weekday >> (bitno - 0x20)) & 0x01; 340 | 341 | break; 342 | 343 | case 0x24: 344 | case 0x25: 345 | case 0x26: 346 | case 0x27: 347 | 348 | outputbit = (pd4990a.month >> (bitno - 0x24)) & 0x01; 349 | 350 | break; 351 | 352 | case 0x28: 353 | case 0x29: 354 | case 0x2a: 355 | case 0x2b: 356 | 357 | case 0x2c: 358 | case 0x2d: 359 | case 0x2e: 360 | case 0x2f: 361 | 362 | outputbit = (pd4990a.year >> (bitno - 0x28)) & 0x01; 363 | 364 | break; 365 | 366 | } 367 | 368 | break; 369 | 370 | 371 | case 0x02: /* shift one position */ 372 | 373 | bitno++; 374 | 375 | break; 376 | 377 | 378 | case 0x04: /* Start afresh with shifting */ 379 | 380 | bitno = 0; 381 | 382 | break; 383 | 384 | 385 | default: /* Unhandled value */ 386 | 387 | break; 388 | 389 | } 390 | 391 | } 392 | 393 | 394 | 395 | WRITE16_HANDLER (pd4990a_control_16_w) 396 | { 397 | 398 | pd4990a_control_w (offset, data & 0xff); 399 | 400 | } 401 | 402 | 403 | -------------------------------------------------------------------------------- /src/pd4990a/pd4990a.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for the PD4990A Serial I/O calendar & clock. 3 | */ 4 | 5 | struct pd4990a_s 6 | { 7 | int seconds; 8 | int minutes; 9 | int hours; 10 | int days; 11 | int month; 12 | int year; 13 | int weekday; 14 | }; 15 | 16 | extern struct pd4990a_s pd4990a; 17 | 18 | #define READ8_HANDLER(name) unsigned char name(unsigned int offset) 19 | #define WRITE8_HANDLER(name) void name(unsigned int offset, unsigned char data) 20 | #define WRITE16_HANDLER(name) void name(unsigned int offset, unsigned short data, unsigned short mem_mask) 21 | 22 | void pd4990a_addretrace (void); 23 | READ8_HANDLER (pd4990a_testbit_r); 24 | READ8_HANDLER (pd4990a_databit_r); 25 | WRITE8_HANDLER (pd4990a_control_w); 26 | WRITE16_HANDLER (pd4990a_control_16_w); 27 | void pd4990a_increment_day (void); 28 | void pd4990a_increment_month (void); 29 | -------------------------------------------------------------------------------- /src/sound/2610intf.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * 2610intf.c 4 | * 5 | * The YM2610 emulator supports up to 2 chips. 6 | * Each chip has the following connections: 7 | * - Status Read / Control Write A 8 | * - Port Read / Data Write A 9 | * - Control Write B 10 | * - Data Write B 11 | * 12 | ****************************************************************************/ 13 | 14 | #include 15 | #include "neocdrx.h" 16 | #include "ay8910.h" 17 | #include "fm.h" 18 | #include "2610intf.h" 19 | #include "timer.h" 20 | #include "streams.h" 21 | 22 | /* use FM.C with stream system */ 23 | 24 | static int stream; 25 | static timer_struct *Timer[2]; 26 | 27 | /*------------------------- TM2610 -------------------------------*/ 28 | /* IRQ Handler */ 29 | static void IRQHandler(int n, int irq) 30 | { 31 | //printf("IRQ!!!\n"); 32 | neogeo_sound_irq(irq); 33 | } 34 | 35 | /* Timer overflow callback from timer.c */ 36 | void timer_callback_2610(int param) 37 | { 38 | int c = param; 39 | 40 | Timer[c] = 0; 41 | YM2610TimerOver(c); 42 | } 43 | 44 | /* TimerHandler from fm.c */ 45 | static void TimerHandler(int c, int count, double stepTime) 46 | { 47 | 48 | if (count == 0) { /* Reset FM Timer */ 49 | if (Timer[c]) { 50 | del_timer(Timer[c]); 51 | Timer[c] = 0; 52 | } 53 | } else { /* Start FM Timer */ 54 | double timeSec = (double) count * stepTime; 55 | 56 | if (Timer[c] == 0) { 57 | Timer[c] = 58 | (timer_struct *) insert_timer(timeSec, c, 59 | timer_callback_2610); 60 | } 61 | } 62 | } 63 | 64 | void FMTimerInit(void) 65 | { 66 | Timer[0] = Timer[1] = 0; 67 | free_all_timer(); 68 | } 69 | 70 | /* update request from fm.c */ 71 | void YM2610UpdateRequest(void) 72 | { 73 | static double old_tc; 74 | double tc = timer_count - old_tc; 75 | int len = (int) (SAMPLE_RATE * tc) << 2; 76 | if (len > 4) { 77 | old_tc = timer_count; 78 | streamupdate(len); 79 | } 80 | } 81 | 82 | int YM2610_sh_start(void) 83 | { 84 | int j; 85 | int rate = SAMPLE_RATE; 86 | char buf[YM2610_NUMBUF][40]; 87 | void *pcmbufa, *pcmbufb; 88 | int pcmsizea, pcmsizeb; 89 | 90 | if (AY8910_sh_start()) 91 | return 1; 92 | 93 | /* Timer Handler set */ 94 | FMTimerInit(); 95 | for (j = 0; j < YM2610_NUMBUF; j++) { 96 | buf[j][0] = 0; 97 | } 98 | if (buf == NULL) { } 99 | 100 | stream = stream_init_multi(YM2610_NUMBUF, 0, YM2610UpdateOne); 101 | pcmbufa = (void *) neogeo_pcm_memory; 102 | pcmsizea = 0x100000; //1048576; 103 | pcmbufb = NULL; /*(void *) memory.sound2; */ 104 | pcmsizeb = 0; /*memory.sound2_size; */ 105 | 106 | //} 107 | 108 | /**** initialize YM2610 ****/ 109 | /* 110 | * if (YM2610Init(8000000,rate, 111 | * pcmbufa,pcmsizea,pcmbufb,pcmsizeb, 112 | * TimerHandler,IRQHandler) == 0) 113 | */ 114 | if (YM2610Init(8000000, rate, 115 | pcmbufa, pcmsizea, pcmbufb, pcmsizeb, 116 | TimerHandler, IRQHandler) == 0) 117 | return 0; 118 | 119 | /* error */ 120 | return 1; 121 | } 122 | 123 | /************************************************/ 124 | /* Sound Hardware Stop */ 125 | /************************************************/ 126 | void YM2610_sh_stop(void) 127 | { 128 | YM2610Shutdown(); 129 | } 130 | 131 | /* reset */ 132 | void YM2610_sh_reset(void) 133 | { 134 | YM2610ResetChip(); 135 | } 136 | 137 | /************************************************/ 138 | /* Status Read for YM2610 - Chip 0 */ 139 | /************************************************/ 140 | Uint32 YM2610_status_port_0_A_r(Uint32 offset) 141 | { 142 | return YM2610Read(0); 143 | } 144 | 145 | Uint32 YM2610_status_port_0_B_r(Uint32 offset) 146 | { 147 | return YM2610Read(2); 148 | } 149 | 150 | /************************************************/ 151 | /* Port Read for YM2610 - Chip 0 */ 152 | /************************************************/ 153 | Uint32 YM2610_read_port_0_r(Uint32 offset) 154 | { 155 | return YM2610Read(1); 156 | } 157 | 158 | 159 | /************************************************/ 160 | /* Control Write for YM2610 - Chip 0 */ 161 | /* Consists of 2 addresses */ 162 | /************************************************/ 163 | void YM2610_control_port_0_A_w(Uint32 offset, Uint32 data) 164 | { 165 | YM2610Write(0, data); 166 | } 167 | 168 | void YM2610_control_port_0_B_w(Uint32 offset, Uint32 data) 169 | { 170 | YM2610Write(2, data); 171 | } 172 | 173 | /************************************************/ 174 | /* Data Write for YM2610 - Chip 0 */ 175 | /* Consists of 2 addresses */ 176 | /************************************************/ 177 | void YM2610_data_port_0_A_w(Uint32 offset, Uint32 data) 178 | { 179 | YM2610Write(1, data); 180 | } 181 | 182 | void YM2610_data_port_0_B_w(Uint32 offset, Uint32 data) 183 | { 184 | YM2610Write(3, data); 185 | } 186 | -------------------------------------------------------------------------------- /src/sound/2610intf.h: -------------------------------------------------------------------------------- 1 | #ifndef __2610INTF_H__ 2 | #define __2610INTF_H__ 3 | 4 | #include "neocdrx.h" 5 | #include "fm.h" 6 | #include "ay8910.h" 7 | 8 | #ifdef BUILD_YM2610 9 | void YM2610UpdateRequest(void /*int chip */ ); 10 | #endif 11 | 12 | #define MAX_2610 (2) 13 | 14 | #ifndef VOL_YM3012 15 | /* #define YM3014_VOL(Vol,Pan) VOL_YM3012((Vol)/2,Pan,(Vol)/2,Pan) */ 16 | #define YM3012_VOL(LVol,LPan,RVol,RPan) (MIXER(LVol,LPan)|(MIXER(RVol,RPan) << 16)) 17 | #endif 18 | 19 | struct YM2610interface { 20 | int num; /* total number of 8910 in the machine */ 21 | int baseclock; 22 | int volumeSSG[MAX_8910]; /* for SSG sound */ 23 | mem_read_handler portAread[MAX_8910]; 24 | mem_read_handler portBread[MAX_8910]; 25 | mem_write_handler portAwrite[MAX_8910]; 26 | mem_write_handler portBwrite[MAX_8910]; 27 | void (*handler[MAX_8910]) (int irq); /* IRQ handler for the YM2610 */ 28 | int pcmromb[MAX_2610]; /* Delta-T rom region */ 29 | int pcmroma[MAX_2610]; /* ADPCM rom region */ 30 | int volumeFM[MAX_2610]; /* use YM3012_VOL macro */ 31 | }; 32 | 33 | /************************************************/ 34 | /* Sound Hardware Start */ 35 | /************************************************/ 36 | int YM2610_sh_start( /*const struct MachineSound *msound */ void); 37 | //int YM2610B_sh_start(const struct MachineSound *msound); 38 | 39 | /************************************************/ 40 | /* Sound Hardware Stop */ 41 | /************************************************/ 42 | void YM2610_sh_stop(void); 43 | 44 | void YM2610_sh_reset(void); 45 | 46 | /************************************************/ 47 | /* Chip 0 functions */ 48 | /************************************************/ 49 | Uint32 YM2610_status_port_0_A_r(Uint32 offset); 50 | Uint32 YM2610_status_port_0_B_r(Uint32 offset); 51 | Uint32 YM2610_read_port_0_r(Uint32 offset); 52 | void YM2610_control_port_0_A_w(Uint32 offset, Uint32 data); 53 | void YM2610_control_port_0_B_w(Uint32 offset, Uint32 data); 54 | void YM2610_data_port_0_A_w(Uint32 offset, Uint32 data); 55 | void YM2610_data_port_0_B_w(Uint32 offset, Uint32 data); 56 | 57 | void FMTimerInit(void); 58 | 59 | /************************************************/ 60 | /* Chip 1 functions */ 61 | /************************************************/ 62 | //Uint32 YM2610_status_port_1_A_r (Uint32 offset); 63 | //Uint32 YM2610_status_port_1_B_r (Uint32 offset); 64 | //Uint32 YM2610_read_port_1_r (Uint32 offset); 65 | //void YM2610_control_port_1_A_w (Uint32 offset,Uint32 data); 66 | //void YM2610_control_port_1_B_w (Uint32 offset,Uint32 data); 67 | //void YM2610_data_port_1_A_w (Uint32 offset,Uint32 data); 68 | //void YM2610_data_port_1_B_w (Uint32 offset,Uint32 data); 69 | 70 | #endif 71 | /**************** end of file ****************/ 72 | -------------------------------------------------------------------------------- /src/sound/ay8910.h: -------------------------------------------------------------------------------- 1 | #ifndef AY8910_H 2 | #define AY8910_H 3 | 4 | #define MAX_8910 5 5 | #define ALL_8910_CHANNELS -1 6 | 7 | #include "neocdrx.h" 8 | 9 | typedef Uint32(*mem_read_handler) (Uint32 offset); 10 | typedef void (*mem_write_handler) (Uint32 offset, Uint32 data); 11 | 12 | struct AY8910interface { 13 | int num; /* total number of 8910 in the machine */ 14 | int baseclock; 15 | int mixing_level[MAX_8910]; 16 | mem_read_handler portAread[MAX_8910]; 17 | mem_read_handler portBread[MAX_8910]; 18 | mem_write_handler portAwrite[MAX_8910]; 19 | mem_write_handler portBwrite[MAX_8910]; 20 | void (*handler[MAX_8910]) (int irq); /* IRQ handler for the YM2203 */ 21 | }; 22 | 23 | void AY8910_reset( /*int chip */ void); 24 | 25 | void AY8910_set_clock( /*int chip, */ int _clock); 26 | void AY8910_set_volume( /*int chip, */ int channel, int volume); 27 | 28 | 29 | void AY8910Write( /*int chip, */ int a, int data); 30 | int AY8910Read( /*int chip */ void); 31 | 32 | 33 | Uint32 AY8910_read_port_0_r(Uint32 offset); 34 | Uint32 AY8910_read_port_1_r(Uint32 offset); 35 | Uint32 AY8910_read_port_2_r(Uint32 offset); 36 | Uint32 AY8910_read_port_3_r(Uint32 offset); 37 | Uint32 AY8910_read_port_4_r(Uint32 offset); 38 | 39 | void AY8910_control_port_0_w(Uint32 offset, Uint32 data); 40 | void AY8910_control_port_1_w(Uint32 offset, Uint32 data); 41 | void AY8910_control_port_2_w(Uint32 offset, Uint32 data); 42 | void AY8910_control_port_3_w(Uint32 offset, Uint32 data); 43 | void AY8910_control_port_4_w(Uint32 offset, Uint32 data); 44 | 45 | void AY8910_write_port_0_w(Uint32 offset, Uint32 data); 46 | void AY8910_write_port_1_w(Uint32 offset, Uint32 data); 47 | void AY8910_write_port_2_w(Uint32 offset, Uint32 data); 48 | void AY8910_write_port_3_w(Uint32 offset, Uint32 data); 49 | void AY8910_write_port_4_w(Uint32 offset, Uint32 data); 50 | 51 | int AY8910_sh_start( /*const struct MachineSound *msound */ void); 52 | void AY8910Update(int param, Sint16 ** buffer, int length); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/sound/eq.c: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------- 2 | // 3 | // 3 Band EQ :) 4 | // 5 | // EQ.C - Main Source file for 3 band EQ 6 | // 7 | // (c) Neil C / Etanza Systems / 2K6 8 | // 9 | // Shouts / Loves / Moans = etanza at lycos dot co dot uk 10 | // 11 | // This work is hereby placed in the public domain for all purposes, including 12 | // use in commercial applications. 13 | // 14 | // The author assumes NO RESPONSIBILITY for any problems caused by the use of 15 | // this software. 16 | // 17 | //---------------------------------------------------------------------------- 18 | 19 | // NOTES : 20 | // 21 | // - Original filter code by Paul Kellet (musicdsp.pdf) 22 | // 23 | // - Uses 4 first order filters in series, should give 24dB per octave 24 | // 25 | // - Now with P4 Denormal fix :) 26 | 27 | //---------------------------------------------------------------------------- 28 | 29 | // ---------- 30 | //| Includes | 31 | // ---------- 32 | #include 33 | #include 34 | #include 35 | #include "eq.h" 36 | 37 | // ----------- 38 | //| Constants | 39 | // ----------- 40 | 41 | static double vsa = (1.0 / 4294967295.0); // Very small amount (Denormal Fix) 42 | 43 | // --------------- 44 | //| Initialise EQ | 45 | // --------------- 46 | 47 | // Recommended frequencies are ... 48 | // 49 | // lowfreq = 880 Hz 50 | // highfreq = 5000 Hz 51 | // 52 | // Set mixfreq to whatever rate your system is using (eg 48Khz) 53 | 54 | void init_3band_state(EQSTATE * es, int lowfreq, int highfreq, int mixfreq) 55 | { 56 | // Clear state 57 | 58 | memset(es, 0, sizeof(EQSTATE)); 59 | 60 | // Set Low/Mid/High gains to unity 61 | 62 | es->lg = 1.0; 63 | es->mg = 1.0; 64 | es->hg = 1.0; 65 | 66 | // Calculate filter cutoff frequencies 67 | 68 | es->lf = 2 * sin(M_PI * ((double) lowfreq / (double) mixfreq)); 69 | es->hf = 2 * sin(M_PI * ((double) highfreq / (double) mixfreq)); 70 | } 71 | 72 | // --------------- 73 | //| EQ one sample | 74 | // --------------- 75 | 76 | // - sample can be any range you like :) 77 | // 78 | // Note that the output will depend on the gain settings for each band 79 | // (especially the bass) so may require clipping before output, but you 80 | // knew that anyway :) 81 | 82 | double do_3band(EQSTATE * es, int sample) 83 | { 84 | // Locals 85 | 86 | double l, m, h; // Low / Mid / High - Sample Values 87 | 88 | // Filter #1 (lowpass) 89 | 90 | es->f1p0 += (es->lf * ((double) sample - es->f1p0)) + vsa; 91 | es->f1p1 += (es->lf * (es->f1p0 - es->f1p1)); 92 | es->f1p2 += (es->lf * (es->f1p1 - es->f1p2)); 93 | es->f1p3 += (es->lf * (es->f1p2 - es->f1p3)); 94 | 95 | l = es->f1p3; 96 | 97 | // Filter #2 (highpass) 98 | 99 | es->f2p0 += (es->hf * ((double) sample - es->f2p0)) + vsa; 100 | es->f2p1 += (es->hf * (es->f2p0 - es->f2p1)); 101 | es->f2p2 += (es->hf * (es->f2p1 - es->f2p2)); 102 | es->f2p3 += (es->hf * (es->f2p2 - es->f2p3)); 103 | 104 | h = es->sdm3 - es->f2p3; 105 | 106 | // Calculate midrange (signal - (low + high)) 107 | 108 | m = es->sdm3 - (h + l); 109 | 110 | //Suggestion by philip[ AT ]blastbay[ DOT ]com: 111 | // m = sample - (h + l); 112 | 113 | // Scale, Combine and store 114 | 115 | l *= es->lg; 116 | m *= es->mg; 117 | h *= es->hg; 118 | 119 | // Shuffle history buffer 120 | 121 | es->sdm3 = es->sdm2; 122 | es->sdm2 = es->sdm1; 123 | es->sdm1 = sample; 124 | 125 | // Return result 126 | 127 | return (int) (l + m + h); 128 | } 129 | -------------------------------------------------------------------------------- /src/sound/eq.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // 3 | // 3 Band EQ :) 4 | // 5 | // EQ.H - Header file for 3 band EQ 6 | // 7 | // (c) Neil C / Etanza Systems / 2K6 8 | // 9 | // Shouts / Loves / Moans = etanza at lycos dot co dot uk 10 | // 11 | // This work is hereby placed in the public domain for all purposes, including 12 | // use in commercial applications. 13 | // 14 | // The author assumes NO RESPONSIBILITY for any problems caused by the use of 15 | // this software. 16 | // 17 | //---------------------------------------------------------------------------- 18 | 19 | #ifndef __EQ3BAND__ 20 | #define __EQ3BAND__ 21 | 22 | // ------------ 23 | //| Structures | 24 | // ------------ 25 | 26 | typedef struct { 27 | // Filter #1 (Low band) 28 | 29 | double lf; // Frequency 30 | double f1p0; // Poles ... 31 | double f1p1; 32 | double f1p2; 33 | double f1p3; 34 | 35 | // Filter #2 (High band) 36 | 37 | double hf; // Frequency 38 | double f2p0; // Poles ... 39 | double f2p1; 40 | double f2p2; 41 | double f2p3; 42 | 43 | // Sample history buffer 44 | 45 | double sdm1; // Sample data minus 1 46 | double sdm2; // 2 47 | double sdm3; // 3 48 | 49 | // Gain Controls 50 | 51 | double lg; // low gain 52 | double mg; // mid gain 53 | double hg; // high gain 54 | 55 | } EQSTATE; 56 | 57 | 58 | // --------- 59 | //| Exports | 60 | // --------- 61 | 62 | extern void init_3band_state(EQSTATE * es, int lowfreq, int highfreq, 63 | int mixfreq); 64 | extern double do_3band(EQSTATE * es, int sample); 65 | 66 | 67 | #endif // __EQ3BAND__ 68 | -------------------------------------------------------------------------------- /src/sound/fm.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: fm.h -- header file for software emuration for FM sound genelator 3 | 4 | */ 5 | #ifndef _H_FM_FM_ 6 | #define _H_FM_FM_ 7 | 8 | #include "ymdeltat.h" 9 | /* --- select emulation chips --- */ 10 | 11 | #define BUILD_YM2610 1 //(HAS_YM2610) /* build YM2610(OPNB) emulator */ 12 | #define BUILD_YM2608 0 13 | 14 | /* --- system optimize --- */ 15 | /* select stereo output buffer : 1=mixing / 0=separate */ 16 | #define FM_STEREO_MIX 0 17 | /* select bit size of output : 8 or 16 */ 18 | #define FM_OUTPUT_BIT 16 19 | /* select timer system internal or external */ 20 | #define FM_INTERNAL_TIMER 1 21 | 22 | /* --- speedup optimize --- */ 23 | /* support LFO unit */ 24 | #define FM_LFO_SUPPORT 1 25 | /* support OPN SSG type envelope mode */ 26 | #define FM_SEG_SUPPORT 1 27 | 28 | /* --- external SSG(YM2149/AY-3-8910)emulator interface port */ 29 | /* used by YM2203,YM2608,and YM2610 */ 30 | 31 | /* SSGClk : Set SSG Clock */ 32 | /* int n = chip number */ 33 | /* int clk = MasterClock(Hz) */ 34 | /* int rate = sample rate(Hz) */ 35 | #define SSGClk(/*chip,*/clock) AY8910_set_clock(/*chip,*/clock) 36 | 37 | /* SSGWrite : Write SSG port */ 38 | /* int n = chip number */ 39 | /* int a = address */ 40 | /* int v = data */ 41 | #define SSGWrite(/*n,*/a,v) AY8910Write(/*n,*/a,v) 42 | 43 | /* SSGRead : Read SSG port */ 44 | /* int n = chip number */ 45 | /* return = Read data */ 46 | #define SSGRead(/*n*/) AY8910Read(/*n*/) 47 | 48 | /* SSGReset : Reset SSG chip */ 49 | /* int n = chip number */ 50 | #define SSGReset(/*chip*/) AY8910_reset(/*chip*/) 51 | 52 | /* --- external callback funstions for realtime update --- */ 53 | #if BUILD_YM2610 54 | /* in 2610intf.c */ 55 | //#define YM2610UpdateReq(/*chip*/) YM2610UpdateRequest(/*chip*/); 56 | #define YM2610UpdateReq() 57 | #endif 58 | 59 | #if FM_STEREO_MIX 60 | #define YM2151_NUMBUF 1 61 | #define YM2608_NUMBUF 1 62 | #define YM2612_NUMBUF 1 63 | #define YM2610_NUMBUF 1 64 | #else 65 | #define YM2151_NUMBUF 2 /* FM L+R */ 66 | #define YM2608_NUMBUF 2 /* FM L+R+ADPCM+RYTHM */ 67 | #define YM2610_NUMBUF 2 /* FM L+R+ADPCMA+ADPCMB */ 68 | #define YM2612_NUMBUF 2 /* FM L+R */ 69 | #endif 70 | 71 | #if (FM_OUTPUT_BIT==16) 72 | typedef short FMSAMPLE; 73 | typedef unsigned long FMSAMPLE_MIX; 74 | #endif 75 | #if (FM_OUTPUT_BIT==8) 76 | typedef unsigned char FMSAMPLE; 77 | typedef unsigned short FMSAMPLE_MIX; 78 | #endif 79 | 80 | typedef void (*FM_TIMERHANDLER) (int c, int cnt, double stepTime); 81 | typedef void (*FM_IRQHANDLER) (int n, int irq); 82 | /* FM_TIMERHANDLER : Stop or Start timer */ 83 | /* int n = chip number */ 84 | /* int c = Channel 0=TimerA,1=TimerB */ 85 | /* int count = timer count (0=stop) */ 86 | /* doube stepTime = step time of one count (sec.)*/ 87 | 88 | /* FM_IRQHHANDLER : IRQ level changing sense */ 89 | /* int n = chip number */ 90 | /* int irq = IRQ level 0=OFF,1=ON */ 91 | 92 | /* ---------- OPN / OPM one channel ---------- */ 93 | typedef struct fm_slot { 94 | Sint32 *DT; /* detune :DT_TABLE[DT] */ 95 | int DT2; /* multiple,Detune2:(DT2<<4)|ML for OPM */ 96 | int TL; /* total level :TL << 8 */ 97 | Uint8 KSR; /* key scale rate :3-KSR */ 98 | const Sint32 *AR; /* attack rate :&AR_TABLE[AR<<1] */ 99 | const Sint32 *DR; /* decay rate :&DR_TABLE[DR<<1] */ 100 | const Sint32 *SR; /* sustin rate :&DR_TABLE[SR<<1] */ 101 | int SL; /* sustin level :SL_TABLE[SL] */ 102 | const Sint32 *RR; /* release rate :&DR_TABLE[RR<<2+2] */ 103 | Uint8 SEG; /* SSG EG type :SSGEG */ 104 | Uint8 ksr; /* key scale rate :kcode>>(3-KSR) */ 105 | Uint32 mul; /* multiple :ML_TABLE[ML] */ 106 | /* Phase Generator */ 107 | Uint32 Cnt; /* frequency count : */ 108 | Uint32 Incr; /* frequency step : */ 109 | /* Envelope Generator */ 110 | Uint8 state; 111 | void (*eg_next) (struct fm_slot * SLOT); /* pointer of phase handler */ 112 | Sint32 evc; /* envelope counter */ 113 | Sint32 eve; /* envelope counter end point */ 114 | Sint32 evs; /* envelope counter step */ 115 | Sint32 evsa; /* envelope step for Attack */ 116 | Sint32 evsd; /* envelope step for Decay */ 117 | Sint32 evss; /* envelope step for Sustain */ 118 | Sint32 evsr; /* envelope step for Release */ 119 | Sint32 TLL; /* adjusted TotalLevel */ 120 | /* LFO */ 121 | Uint8 amon; /* AMS enable flag */ 122 | Uint32 ams; /* AMS depth level of this SLOT */ 123 | } FM_SLOT; 124 | 125 | typedef struct fm_chan { 126 | FM_SLOT SLOT[4]; 127 | Uint8 PAN; /* PAN :NONE,LEFT,RIGHT or CENTER */ 128 | Uint8 ALGO; /* Algorythm */ 129 | Uint8 FB; /* shift count of self feed back */ 130 | Sint32 op1_out[2]; /* op1 output for beedback */ 131 | /* Algorythm (connection) */ 132 | Sint32 *connect1; /* pointer of SLOT1 output */ 133 | Sint32 *connect2; /* pointer of SLOT2 output */ 134 | Sint32 *connect3; /* pointer of SLOT3 output */ 135 | Sint32 *connect4; /* pointer of SLOT4 output */ 136 | /* LFO */ 137 | Sint32 pms; /* PMS depth level of channel */ 138 | Uint32 ams; /* AMS depth level of channel */ 139 | /* Phase Generator */ 140 | Uint32 fc; /* fnum,blk :adjusted to sampling rate */ 141 | Uint8 fn_h; /* freq latch : */ 142 | Uint8 kcode; /* key code : */ 143 | } FM_CH; 144 | 145 | /* OPN/OPM common state */ 146 | typedef struct fm_state { 147 | Uint8 index; /* chip index (number of chip) */ 148 | int clock; /* master clock (Hz) */ 149 | int rate; /* sampling rate (Hz) */ 150 | double freqbase; /* frequency base */ 151 | double TimerBase; /* Timer base time */ 152 | Uint8 address; /* address register */ 153 | Uint8 irq; /* interrupt level */ 154 | Uint8 irqmask; /* irq mask */ 155 | Uint8 status; /* status flag */ 156 | Uint32 mode; /* mode CSM / 3SLOT */ 157 | Uint8 prescaler_sel; /* prescaler selector */ 158 | Uint8 fn_h; /* freq latch */ 159 | int TA; /* timer a */ 160 | int TAC; /* timer a counter */ 161 | Uint8 TB; /* timer b */ 162 | int TBC; /* timer b counter */ 163 | /* speedup customize */ 164 | /* local time tables */ 165 | Sint32 DT_TABLE[8][32]; /* DeTune tables */ 166 | Sint32 AR_TABLE[94]; /* Atttack rate tables */ 167 | Sint32 DR_TABLE[94]; /* Decay rate tables */ 168 | /* Extention Timer and IRQ handler */ 169 | FM_TIMERHANDLER Timer_Handler; 170 | FM_IRQHANDLER IRQ_Handler; 171 | /* timer model single / interval */ 172 | Uint8 timermodel; 173 | } FM_ST; 174 | 175 | /***********************************************************/ 176 | /* OPN unit */ 177 | /***********************************************************/ 178 | 179 | /* OPN 3slot struct */ 180 | typedef struct opn_3slot { 181 | Uint32 fc[3]; /* fnum3,blk3 :calcrated */ 182 | Uint8 fn_h[3]; /* freq3 latch */ 183 | Uint8 kcode[3]; /* key code : */ 184 | } FM_3SLOT; 185 | 186 | /* OPN/A/B common state */ 187 | typedef struct opn_f { 188 | Uint8 type; /* chip type */ 189 | FM_ST ST; /* general state */ 190 | FM_3SLOT SL3; /* 3 slot mode state */ 191 | FM_CH *P_CH; /* pointer of CH */ 192 | Uint32 FN_TABLE[2048]; /* fnumber -> increment counter */ 193 | #if FM_LFO_SUPPORT 194 | /* LFO */ 195 | Uint32 LFOCnt; 196 | Uint32 LFOIncr; 197 | Uint32 LFO_FREQ[8]; /* LFO FREQ table */ 198 | #endif 199 | } FM_OPN; 200 | 201 | 202 | /* adpcm type A struct */ 203 | typedef struct adpcm_state { 204 | Uint8 flag; /* port state */ 205 | Uint8 flagMask; /* arrived flag mask */ 206 | Uint8 now_data; 207 | Uint32 now_addr; 208 | Uint32 now_step; 209 | Uint32 step; 210 | Uint32 start; 211 | Uint32 end; 212 | int IL; 213 | int volume; /* calcrated mixing level */ 214 | Sint32 *pan; /* &out_ch[OPN_xxxx] */ 215 | int /*adpcmm, */ adpcmx, adpcmd; 216 | int adpcml; /* hiro-shi!! */ 217 | } ADPCM_CH; 218 | 219 | /* here's the virtual YM2610 */ 220 | typedef struct ym2610_f { 221 | Uint8 REGS[512]; /* registers */ 222 | FM_OPN OPN; /* OPN state */ 223 | FM_CH CH[6]; /* channel state */ 224 | int address1; /* address register1 */ 225 | /* ADPCM-A unit */ 226 | Uint8 *pcmbuf; /* pcm rom buffer */ 227 | Uint32 pcm_size; /* size of pcm rom */ 228 | Sint32 *adpcmTL; /* adpcmA total level */ 229 | ADPCM_CH adpcm[6]; /* adpcm channels */ 230 | Uint32 adpcmreg[0x30]; /* registers */ 231 | Uint8 adpcm_arrivedEndAddress; 232 | /* Delta-T ADPCM unit */ 233 | YM_DELTAT deltaT; 234 | } YM2610; 235 | 236 | extern YM2610 FM2610; 237 | 238 | #if (BUILD_YM2610||BUILD_YM2610B) 239 | /* -------------------- YM2610(OPNB) Interface -------------------- */ 240 | int YM2610Init(int baseclock, int rate, 241 | void *pcmroma, int pcmasize, void *pcmromb, int pcmbsize, 242 | FM_TIMERHANDLER TimerHandler, FM_IRQHANDLER IRQHandler); 243 | void YM2610Shutdown(void); 244 | void YM2610ResetChip(void); 245 | void YM2610UpdateOne(int num, Sint16 ** buffer, int length); 246 | 247 | int YM2610Write(int a, unsigned char v); 248 | unsigned char YM2610Read(int a); 249 | int YM2610TimerOver(int c); 250 | 251 | #endif /* BUILD_YM2610 */ 252 | 253 | 254 | 255 | #endif /* _H_FM_FM_ */ 256 | -------------------------------------------------------------------------------- /src/sound/gcaudio.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #include "neocdrx.h" 8 | #include "streams.h" 9 | #include "eq.h" 10 | 11 | /** 12 | * Nintendo Gamecube Audio Interface 13 | */ 14 | 15 | u8 soundbuffer[2][8192] ATTRIBUTE_ALIGN(32); 16 | u32 mixbuffer; 17 | u32 audioStarted; 18 | static int whichab = 0; 19 | static int IsPlaying = 0; 20 | /**************************************************************************** 21 | * AudioSwitchBuffers 22 | * 23 | * Genesis Plus only provides sound data on completion of each frame. 24 | * To try to make the audio less choppy, this function is called from both the 25 | * DMA completion and update_audio. 26 | * 27 | * Testing for data in the buffer ensures that there are no clashes. 28 | ****************************************************************************/ 29 | static void AudioSwitchBuffers(void) 30 | { 31 | static int len[2] = { 8192, 8192 }; 32 | 33 | whichab ^= 1; 34 | len[whichab] = mixer_getaudio(soundbuffer[whichab], 8192); 35 | 36 | IsPlaying = 1; 37 | AUDIO_InitDMA((u32) soundbuffer[whichab], len[whichab]); 38 | DCFlushRange(soundbuffer[whichab], len[whichab]); 39 | AUDIO_StartDMA(); 40 | } 41 | 42 | /**************************************************************************** 43 | * InitGCAudio 44 | * 45 | * Stock code to set the DSP at 48Khz 46 | ****************************************************************************/ 47 | void InitGCAudio(void) 48 | { 49 | AUDIO_Init(NULL); 50 | AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ); 51 | AUDIO_RegisterDMACallback(AudioSwitchBuffers); 52 | memset(soundbuffer, 0, 8192); 53 | mixer_init(); 54 | } 55 | 56 | /**************************************************************************** 57 | * NeoCD Audio Update 58 | * 59 | * This is called on each VBL to get the next frame of audio. 60 | *****************************************************************************/ 61 | void update_audio(void) 62 | { 63 | mixer_update_audio(); 64 | 65 | if (IsPlaying == 0) { 66 | AUDIO_StopDMA(); 67 | AudioSwitchBuffers(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/sound/gcaudio.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | #ifndef __GCAUDIO__ 7 | #define __GCAUDIO__ 8 | 9 | #include "mixer.h" 10 | 11 | void InitGCAudio (void); 12 | void update_audio(void); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/sound/madfilter.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /*** Dither algorithm adapted from Madplay 0.15.2b ***/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "madfilter.h" 14 | 15 | enum { 16 | MADMIN = -MAD_F_ONE, 17 | MADMAX = MAD_F_ONE -1 18 | }; 19 | 20 | s32 audio_linear_dither( mad_fixed_t sample, struct audio_dither *dither ) 21 | { 22 | u32 scalebits; 23 | mad_fixed_t output, mask, random; 24 | 25 | /* noise shape */ 26 | sample += dither->error[0] - dither->error[1] + dither->error[2]; 27 | dither->error[2] = dither->error[1]; 28 | dither->error[1] = dither->error[0] / 2; 29 | 30 | /* bias */ 31 | output = sample + (1L << (MAD_F_FRACBITS + 1 - 16 - 1)); 32 | 33 | scalebits = MAD_F_FRACBITS + 1 - 16; 34 | mask = (1L << scalebits) - 1; 35 | 36 | /* dither */ 37 | random = (dither->random * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;; 38 | output += (random & mask) - (dither->random & mask); 39 | dither->random = random; 40 | 41 | /* clip */ 42 | if (output >= dither->peak_sample) { 43 | if (output > MADMAX) { 44 | ++dither->clipped_samples; 45 | if (output - MADMAX > dither->peak_clipping) 46 | dither->peak_clipping = output - MADMAX; 47 | 48 | output = MADMAX; 49 | 50 | if (sample > MADMAX) 51 | sample = MADMAX; 52 | } 53 | dither->peak_sample = output; 54 | } 55 | else if (output < -dither->peak_sample) { 56 | if (output < MADMIN) { 57 | ++dither->clipped_samples; 58 | if (MADMIN - output > dither->peak_clipping) 59 | dither->peak_clipping = MADMIN - output; 60 | 61 | output = MADMIN; 62 | 63 | if (sample < MADMIN) 64 | sample = MADMIN; 65 | } 66 | dither->peak_sample = -output; 67 | } 68 | 69 | /* quantize */ 70 | output &= ~mask; 71 | 72 | /* error feedback */ 73 | dither->error[0] = sample - output; 74 | 75 | /* scale */ 76 | return (output >> scalebits); 77 | } 78 | -------------------------------------------------------------------------------- /src/sound/madfilter.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | #ifndef __MADPLAYFILTER__ 8 | #define __MADPLAYFILTER__ 9 | 10 | struct audio_dither { 11 | mad_fixed_t error[3]; 12 | mad_fixed_t random; 13 | unsigned long clipped_samples; 14 | mad_fixed_t peak_clipping; 15 | mad_fixed_t peak_sample; 16 | }; 17 | 18 | s32 audio_linear_dither( mad_fixed_t sample, struct audio_dither *dither ); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/sound/mixer.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "neocdrx.h" 11 | #include "streams.h" 12 | #include "eq.h" 13 | 14 | #define MIXBUFFER 16384 15 | #define MIXMASK ((MIXBUFFER >> 2) -1) 16 | 17 | static u8 mixbuffer[MIXBUFFER]; /*** 16k mixing buffer ***/ 18 | char mp3buffer[8192]; /*** Filled on each call by streamupdate ***/ 19 | 20 | static double mp3volume = 1.0f; 21 | static double fxvolume = 1.0f; 22 | static EQSTATE eqs; 23 | static MIXER mixer; 24 | 25 | /**************************************************************************** 26 | * Nintendo GameCube SDL_MixAudio replacement function. 27 | * 28 | * This is adapted from the source of libsdl-1.2.9 29 | * As such it only contains the mixing function for 16BITMSB samples. 30 | ****************************************************************************/ 31 | void 32 | ngcMixAudio (u8 * dst, u8 * src, int len, int volume) 33 | //ngcMixAudio (Uint8 * dst, Uint8 * src, int len, int volume) 34 | { 35 | 36 | s16 src1, src2; 37 | s16 *dsts = (s16 *) dst; 38 | s16 *srcs = (s16 *) src; 39 | 40 | int dst_sample; 41 | const int max_audioval = 32767; 42 | const int min_audioval = -32768; 43 | 44 | //len >>= 1; 45 | 46 | while (len--) 47 | { 48 | src1 = srcs[0]; 49 | src2 = dsts[0]; 50 | srcs++; 51 | 52 | dst_sample = (src1 + src2); 53 | 54 | if (dst_sample > max_audioval) 55 | { 56 | dst_sample = max_audioval; 57 | } 58 | else if (dst_sample < min_audioval) 59 | { 60 | dst_sample = min_audioval; 61 | } 62 | 63 | *dsts++ = (s16) dst_sample; 64 | } 65 | } 66 | 67 | static void 68 | MP3MixAudio (char * dst, u8 * src, int len) 69 | { 70 | s16 *s, *d; 71 | int i; 72 | double lsample; 73 | double rsample; 74 | 75 | s = (s16 *) src; 76 | d = (s16 *) dst; 77 | 78 | for (i = 0; i < len >> 1; i += 2) 79 | { 80 | lsample = ((int) ((double) d[i] * mp3volume) + (int)((double) s[i] * fxvolume)); 81 | rsample = ((int) ((double) d[i + 1] * mp3volume) + (int)((double) s[i + 1] * fxvolume)); 82 | 83 | // lsample = (int)((double) s[i] * fxvolume); 84 | // rsample = (int)((double) s[i + 1] * fxvolume); 85 | 86 | lsample = do_3band (&eqs, lsample); 87 | rsample = do_3band (&eqs, rsample); 88 | 89 | if (lsample < -32768) 90 | lsample = -32768; 91 | else 92 | { 93 | if (lsample > 32767) 94 | lsample = 32767; 95 | } 96 | 97 | if (rsample < -32768) 98 | rsample = -32768; 99 | else 100 | { 101 | if (rsample > 32767) 102 | rsample = 32767; 103 | } 104 | 105 | d[i] = (s16) lsample; 106 | d[i + 1] = (s16) rsample; 107 | 108 | } 109 | } 110 | 111 | /**************************************************************************** 112 | * audio_update 113 | * 114 | * Called from NeoCD every frame. 115 | ****************************************************************************/ 116 | void 117 | mixer_update_audio (void) 118 | { 119 | int i; 120 | int *src = (int *) mp3buffer; 121 | int *dst = (int *) mixbuffer; 122 | 123 | /*** Update from sound core ***/ 124 | streamupdate (3200); 125 | MP3MixAudio (mp3buffer, (u8 *) play_buffer, 3200); 126 | 127 | /*** Update the mixbuffer ***/ 128 | for (i = 0; i < 800; i++) 129 | { 130 | dst[mixer.head] = *src++; 131 | mixer.head++; 132 | mixer.head &= MIXMASK; 133 | } 134 | } 135 | 136 | /**************************************************************************** 137 | * mixer_init 138 | ****************************************************************************/ 139 | void 140 | mixer_init (void) 141 | { 142 | memset (&mixer, 0, sizeof (MIXER)); 143 | memset (mp3buffer, 0, 8192); 144 | memset (mixbuffer, 0, MIXBUFFER); 145 | init_3band_state (&eqs, 880, 5000, 48000); 146 | } 147 | 148 | /**************************************************************************** 149 | * mixer_getaudio 150 | ****************************************************************************/ 151 | int 152 | mixer_getaudio (u8 * outbuffer, int length) 153 | { 154 | int *dst = (int *) outbuffer; 155 | int *src = (int *) mixbuffer; 156 | int donebytes = 0; 157 | 158 | /*** Always clear the buffer ***/ 159 | memset (outbuffer, 0, length); 160 | 161 | while ((mixer.tail != mixer.head) && (donebytes < length)) 162 | { 163 | *dst++ = src[mixer.tail]; 164 | mixer.tail++; 165 | mixer.tail &= MIXMASK; 166 | donebytes += 4; 167 | } 168 | 169 | donebytes &= ~0x1f; 170 | 171 | if (donebytes == 0) 172 | return length >> 1; 173 | 174 | return donebytes; 175 | } 176 | 177 | /**************************************************************************** 178 | * mixer_set 179 | ****************************************************************************/ 180 | void mixer_set( float fx, float mp3, float l, float m, float h ) 181 | { 182 | mp3volume = (double)mp3; 183 | fxvolume = (double)fx; 184 | eqs.lg = (double)l; 185 | eqs.mg = (double)m; 186 | eqs.hg = (double)h; 187 | } 188 | -------------------------------------------------------------------------------- /src/sound/mixer.h: -------------------------------------------------------------------------------- 1 | #ifndef __NGCMIXER__ 2 | #define __NGCMIXER__ 3 | 4 | typedef struct 5 | { 6 | int head; 7 | int tail; 8 | } MIXER; 9 | 10 | void mixer_update_audio (void); 11 | void mixer_init (void); 12 | //void ngcMixAudio (Uint8 * dst, Uint8 * src, int len, int volume); 13 | void ngcMixAudio (u8 * dst, u8 * src, int len, int volume); 14 | int mixer_getaudio (u8 * outbuffer, int length); 15 | void mixer_set( float fx, float mp3, float l, float m, float h ); 16 | 17 | extern char mp3buffer[8192]; 18 | #endif 19 | -------------------------------------------------------------------------------- /src/sound/sound.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "neocdrx.h" 6 | #include "streams.h" 7 | extern int YM2610_sh_start (void); 8 | extern void YM2610_sh_stop (void); 9 | int sound = 1; 10 | #include "sound.h" 11 | 12 | #define MIXER_MAX_CHANNELS 16 13 | #define BUFFER_LEN 16384 14 | 15 | extern Uint16 play_buffer[BUFFER_LEN]; 16 | 17 | void 18 | update_sdl_stream (void *userdata, Uint8 * stream, int len) 19 | { 20 | streamupdate (len); 21 | memcpy (stream, (Uint8 *) play_buffer, len); 22 | } 23 | 24 | int 25 | init_sdl_audio (void) 26 | { 27 | streams_sh_start (); 28 | YM2610_sh_start (); 29 | 30 | return 1; 31 | } 32 | 33 | void 34 | sound_toggle (void) 35 | { 36 | sound ^= 1; 37 | } 38 | 39 | void 40 | sound_shutdown (void) 41 | { 42 | streams_sh_stop (); 43 | YM2610_sh_stop (); 44 | } 45 | -------------------------------------------------------------------------------- /src/sound/sound.h: -------------------------------------------------------------------------------- 1 | #ifndef SOUND_H 2 | #define SOUND_H 3 | 4 | #include "neocdrx.h" 5 | #define NB_SEGMENT 20 6 | 7 | int init_sdl_audio (void); 8 | void sound_shutdown (void); 9 | void sound_toggle (void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/sound/streams.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | 3 | streams.c 4 | 5 | Handle general purpose audio streams 6 | 7 | ***************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "neocdrx.h" 13 | 14 | #define MIXER_MAX_CHANNELS 16 15 | #define BUFFER_LEN 16384 16 | 17 | #define CPU_FPS 60 18 | 19 | extern int frame; 20 | 21 | Uint16 left_buffer[BUFFER_LEN]; 22 | Uint16 right_buffer[BUFFER_LEN]; 23 | Uint16 play_buffer[BUFFER_LEN]; 24 | 25 | int SamplePan[] = { 0, 255, 128, 0, 255 }; 26 | 27 | static int stream_joined_channels[MIXER_MAX_CHANNELS]; 28 | 29 | static int stream_vol[MIXER_MAX_CHANNELS]; 30 | struct 31 | { 32 | Sint16 *buffer; 33 | int param; 34 | void (*callback) (int param, Sint16 ** buffer, int length); 35 | } stream[MIXER_MAX_CHANNELS]; 36 | 37 | void 38 | mixer_set_volume (int channel, int volume) 39 | { 40 | stream_vol[channel] = volume; 41 | } 42 | 43 | int 44 | streams_sh_start (void) 45 | { 46 | int i; 47 | 48 | for (i = 0; i < MIXER_MAX_CHANNELS; i++) 49 | { 50 | stream_joined_channels[i] = 1; 51 | stream[i].buffer = 0; 52 | } 53 | return 0; 54 | } 55 | 56 | void 57 | streams_sh_stop (void) 58 | { 59 | int i; 60 | 61 | for (i = 0; i < MIXER_MAX_CHANNELS; i++) 62 | { 63 | free (stream[i].buffer); 64 | stream[i].buffer = 0; 65 | } 66 | } 67 | 68 | void 69 | streamupdate (int len) 70 | { 71 | /*static int current_pos; */ 72 | int channel, i; 73 | Uint16 *bl, *br; 74 | Uint16 *pl; 75 | 76 | /* 77 | if (len+current_pos >= (desired->samples<<2)) 78 | len = (desired->samples<<2) - current_pos; 79 | */ 80 | /* update all the output buffers */ 81 | memset (left_buffer, 0, len); 82 | memset (right_buffer, 0, len); 83 | 84 | for (channel = 0; channel < MIXER_MAX_CHANNELS; 85 | channel += stream_joined_channels[channel]) 86 | { 87 | if (stream[channel].buffer) 88 | { 89 | int buflen; 90 | 91 | 92 | buflen = len >> 2; // BUFFER_LEN; // newpos - stream_buffer_pos[channel]; 93 | 94 | if (stream_joined_channels[channel] > 1) 95 | { 96 | Sint16 *buf[MIXER_MAX_CHANNELS]; 97 | 98 | // on update le YM2610 99 | if (buflen > 0) 100 | { 101 | for (i = 0; i < stream_joined_channels[channel]; i++) 102 | buf[i] = stream[channel + i].buffer; // + stream[channel+i].buffer_pos; 103 | 104 | 105 | (*stream[channel].callback) (stream[channel].param, 106 | buf, buflen); 107 | } 108 | 109 | } 110 | } 111 | } 112 | 113 | bl = left_buffer; 114 | br = right_buffer; 115 | 116 | for (channel = 0; channel < MIXER_MAX_CHANNELS; 117 | channel += stream_joined_channels[channel]) 118 | { 119 | 120 | if (stream[channel].buffer) 121 | { 122 | 123 | for (i = 0; i < stream_joined_channels[channel]; i++) 124 | { 125 | 126 | if (SamplePan[channel + i] <= 128) 127 | ngcMixAudio ((Uint8 *) bl, 128 | (Uint8 *) stream[channel + i].buffer, 129 | len >> 1, 128); 130 | if (SamplePan[channel + i] >= 128) 131 | ngcMixAudio ((Uint8 *) br, 132 | (Uint8 *) stream[channel + i].buffer, 133 | len >> 1, 128); 134 | 135 | } 136 | } 137 | } 138 | 139 | pl = play_buffer; 140 | for (i = 0; i < len >> 2; ++i) 141 | { 142 | *pl++ = left_buffer[i]; 143 | *pl++ = right_buffer[i]; 144 | } 145 | /* 146 | current_pos+=len; 147 | if (current_pos >= (desired->samples<<2)) 148 | current_pos=0; 149 | */ 150 | } 151 | 152 | int 153 | stream_init_multi (int channels, int param, 154 | void (*callback) (int param, Sint16 ** buffer, int length)) 155 | { 156 | static int channel, i; 157 | 158 | stream_joined_channels[channel] = channels; 159 | 160 | for (i = 0; i < channels; i++) 161 | { 162 | 163 | if ((stream[channel + i].buffer = 164 | malloc (sizeof (Sint16) * BUFFER_LEN)) == 0) 165 | return -1; 166 | else 167 | memset(stream[channel+i].buffer, 0, BUFFER_LEN * 2); 168 | } 169 | 170 | stream[channel].param = param; 171 | stream[channel].callback = callback; 172 | channel += channels; 173 | return channel - channels; 174 | } 175 | -------------------------------------------------------------------------------- /src/sound/streams.h: -------------------------------------------------------------------------------- 1 | #ifndef STREAMS_H 2 | #define STREAMS_H 3 | 4 | #include "neocdrx.h" 5 | 6 | //void set_RC_filter(int channel,int R1,int R2,int R3,int C); 7 | 8 | int streams_sh_start (void); 9 | void streams_sh_stop (void); 10 | //void streams_sh_update(void); 11 | 12 | /*int stream_init(const char *name,int default_mixing_level, 13 | int sample_rate, 14 | int param,void (*callback)(int param,INT16 *buffer,int length)); 15 | */ 16 | int stream_init_multi (int channels, int param, 17 | void (*callback) (int param, Sint16 ** buffer, 18 | int length)); 19 | //void stream_update(int channel,int min_interval); /* min_interval is in usec */ 20 | 21 | void streamupdate (int len); 22 | void mixer_set_volume (int channel, int volume); 23 | 24 | extern u16 play_buffer[16384]; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/sound/timer.c: -------------------------------------------------------------------------------- 1 | /* gngeo a neogeo emulator 2 | * Copyright (C) 2001 Peponas Mathieu 3 | */ 4 | 5 | #include 6 | #include 7 | #include "neocdrx.h" 8 | 9 | extern CPU CPU_Z80; 10 | 11 | double timer_count; 12 | timer_struct *timer_list; 13 | #define MAX_TIMER 3 14 | timer_struct timers[MAX_TIMER]; 15 | int nb_interlace = 264 * 4; 16 | //int nb_timer=0; 17 | 18 | double 19 | timer_get_time (void) 20 | { 21 | return timer_count; 22 | } 23 | 24 | timer_struct * 25 | insert_timer (double duration, int param, void (*func) (int)) 26 | { 27 | int i; 28 | for (i = 0; i < MAX_TIMER; i++) 29 | { 30 | if (timers[i].del_it) 31 | { 32 | timers[i].time = timer_count + duration; 33 | timers[i].param = param; 34 | timers[i].func = func; 35 | //printf("Insert_timer %d duration=%f param=%d\n",i,timers[i].time,timers[i].param); 36 | timers[i].del_it = 0; 37 | return &timers[i]; 38 | } 39 | } 40 | printf ("YM2610: No timer free!\n"); 41 | return NULL; /* No timer free */ 42 | } 43 | 44 | void 45 | free_all_timer (void) 46 | { 47 | int i; 48 | for (i = 0; i < MAX_TIMER; i++) 49 | { 50 | timers[i].del_it = 1; 51 | } 52 | } 53 | 54 | void 55 | del_timer (timer_struct * ts) 56 | { 57 | ts->del_it = 1; 58 | } 59 | 60 | static double inc; 61 | 62 | void 63 | my_timer (void) 64 | { 65 | 66 | static int init = 1; 67 | int i; 68 | 69 | if (init) 70 | { 71 | //timer_init_save_state(); 72 | init = 0; 73 | if (0) 74 | { 75 | inc = (double) (0.02) / nb_interlace; 76 | //(conf.sound ? (double) nb_interlace : 1.0); 77 | } 78 | else 79 | { 80 | inc = (double) (0.01666) / nb_interlace; 81 | //(conf.sound ? (double) nb_interlace : 1.0); 82 | } 83 | for (i = 0; i < MAX_TIMER; i++) 84 | timers[i].del_it = 1; 85 | 86 | } 87 | 88 | //timer_count += inc; /* 16ms par frame */ 89 | 90 | /*** This keeps the YM2610 in sync with the Z80 ***/ 91 | timer_count = (CPU_Z80.total_cycles * Z80_USEC); 92 | 93 | for (i = 0; i < MAX_TIMER; i++) 94 | { 95 | if (timer_count >= timers[i].time && timers[i].del_it == 0) 96 | { 97 | //printf("Timer_expire %d duration=%f param=%d\n",i,timers[i].time,timers[i].param); 98 | if (timers[i].func) 99 | timers[i].func (timers[i].param); 100 | timers[i].del_it = 1; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/sound/timer.h: -------------------------------------------------------------------------------- 1 | /* gngeo a neogeo emulator 2 | * Copyright (C) 2001 Peponas Mathieu 3 | */ 4 | 5 | #ifndef _TIMER_H_ 6 | #define _TIMER_H_ 7 | 8 | 9 | typedef struct timer_struct 10 | { 11 | double time; 12 | unsigned int odo_debut; 13 | unsigned int nb_cycle; 14 | int param; 15 | unsigned int del_it; 16 | void (*func) (int param); 17 | struct timer_struct *next; 18 | } timer_struct; 19 | 20 | extern double timer_count; 21 | 22 | timer_struct *insert_timer (double duration, int param, void (*func) (int)); 23 | void del_timer (timer_struct * ts); 24 | void my_timer (void); 25 | double timer_get_time (void); 26 | void free_all_timer (void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/sound/ymdeltat.h: -------------------------------------------------------------------------------- 1 | #ifndef __YMDELTAT_H_ 2 | #define __YMDELTAT_H_ 3 | 4 | #include "neocdrx.h" 5 | 6 | #define YM_DELTAT_SHIFT (16) 7 | 8 | /* adpcm type A and type B struct */ 9 | typedef struct deltat_adpcm_state 10 | { 11 | Uint8 *memory; 12 | int memory_size; 13 | double freqbase; 14 | Sint32 *output_pointer; /* pointer of output pointers */ 15 | int output_range; 16 | 17 | Uint8 reg[16]; 18 | Uint8 portstate, portcontrol; 19 | int portshift; 20 | 21 | Uint8 flag; /* port state */ 22 | Uint8 flagMask; /* arrived flag mask */ 23 | Uint8 now_data; 24 | Uint32 now_addr; 25 | Uint32 now_step; 26 | Uint32 step; 27 | Uint32 start; 28 | Uint32 end; 29 | Uint32 delta; 30 | Sint32 volume; 31 | Sint32 *pan; /* &output_pointer[pan] */ 32 | Sint32 /*adpcmm, */ adpcmx, adpcmd; 33 | Sint32 adpcml; /* hiro-shi!! */ 34 | 35 | /* leveling and re-sampling state for DELTA-T */ 36 | Sint32 volume_w_step; /* volume with step rate */ 37 | Sint32 next_leveling; /* leveling value */ 38 | Sint32 sample_step; /* step of re-sampling */ 39 | 40 | Uint8 arrivedFlag; /* flag of arrived end address */ 41 | } YM_DELTAT; 42 | 43 | /* static state */ 44 | extern Uint8 *ym_deltat_memory; /* memory pointer */ 45 | 46 | /* before YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT); */ 47 | #define YM_DELTAT_DECODE_PRESET(DELTAT) {ym_deltat_memory = DELTAT->memory;} 48 | 49 | void YM_DELTAT_ADPCM_Write (YM_DELTAT * DELTAT, int r, int v); 50 | void YM_DELTAT_ADPCM_Reset (YM_DELTAT * DELTAT, int pan); 51 | 52 | 53 | /* ---------- inline block ---------- */ 54 | 55 | /* DELTA-T particle adjuster */ 56 | #define YM_DELTAT_DELTA_MAX (24576) 57 | #define YM_DELTAT_DELTA_MIN (127) 58 | #define YM_DELTAT_DELTA_DEF (127) 59 | 60 | #define YM_DELTAT_DECODE_RANGE 32768 61 | #define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE)) 62 | #define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1) 63 | 64 | extern const Sint32 ym_deltat_decode_tableB1[]; 65 | extern const Sint32 ym_deltat_decode_tableB2[]; 66 | 67 | #define YM_DELTAT_Limit(val,max,min) \ 68 | { \ 69 | if ( val > max ) val = max; \ 70 | else if ( val < min ) val = min;\ 71 | } 72 | 73 | /**** ADPCM B (Delta-T control type) ****/ 74 | inline void YM_DELTAT_ADPCM_CALC (YM_DELTAT * DELTAT); 75 | 76 | /* INLINE void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT); */ 77 | //#define YM_INLINE_BLOCK 78 | //#include "ymdeltat.c" /* include inline function section */ 79 | //#undef YM_INLINE_BLOCK 80 | 81 | void YM_DELTAT_postload (YM_DELTAT * DELTAT, Uint8 * regs); 82 | void YM_DELTAT_savestate (YM_DELTAT * DELTAT); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/video/draw_fix.c: -------------------------------------------------------------------------------- 1 | /****************************************** 2 | **** Fixed Text Layer Drawing Routines **** 3 | ******************************************/ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "neocdrx.h" 9 | 10 | /* Draw Single FIX character */ 11 | INLINE void 12 | draw_fix (u16 code, u16 colour, u16 sx, u16 sy, u16 * palette, 13 | unsigned char *fix_memory, int opaque) 14 | { 15 | u8 y; 16 | u32 mydword; 17 | u32 *fix = (u32 *) & (fix_memory[code << 5]); 18 | u16 *dest; 19 | u16 *paldata = (unsigned short *) &palette[colour]; 20 | u16 col; 21 | 22 | for (y = 0; y < 8; y++) 23 | { 24 | dest = video_line_ptr[sy + y] + sx; 25 | mydword = *fix++; 26 | 27 | if (!opaque) 28 | { 29 | col = (mydword >> 0) & 0x0f; 30 | if (col) 31 | dest[0] = paldata[col]; 32 | col = (mydword >> 4) & 0x0f; 33 | if (col) 34 | dest[1] = paldata[col]; 35 | col = (mydword >> 8) & 0x0f; 36 | if (col) 37 | dest[2] = paldata[col]; 38 | col = (mydword >> 12) & 0x0f; 39 | if (col) 40 | dest[3] = paldata[col]; 41 | col = (mydword >> 16) & 0x0f; 42 | if (col) 43 | dest[4] = paldata[col]; 44 | col = (mydword >> 20) & 0x0f; 45 | if (col) 46 | dest[5] = paldata[col]; 47 | col = (mydword >> 24) & 0x0f; 48 | if (col) 49 | dest[6] = paldata[col]; 50 | col = (mydword >> 28) & 0x0f; 51 | if (col) 52 | dest[7] = paldata[col]; 53 | } 54 | else 55 | { 56 | col = (mydword >> 0) & 0x0f; 57 | dest[0] = paldata[col]; 58 | col = (mydword >> 4) & 0x0f; 59 | dest[1] = paldata[col]; 60 | col = (mydword >> 8) & 0x0f; 61 | dest[2] = paldata[col]; 62 | col = (mydword >> 12) & 0x0f; 63 | dest[3] = paldata[col]; 64 | col = (mydword >> 16) & 0x0f; 65 | dest[4] = paldata[col]; 66 | col = (mydword >> 20) & 0x0f; 67 | dest[5] = paldata[col]; 68 | col = (mydword >> 24) & 0x0f; 69 | dest[6] = paldata[col]; 70 | col = (mydword >> 28) & 0x0f; 71 | dest[7] = paldata[col]; 72 | } 73 | } 74 | } 75 | 76 | 77 | /* Draw entire Character Foreground */ 78 | void 79 | video_draw_fix (void) 80 | { 81 | u16 x, y; 82 | u16 code, colour; 83 | u16 *fixarea = (u16 *)(video_vidram + 0xE004); 84 | 85 | for (y = 0; y < 28; y++) 86 | { 87 | for (x = 0; x < 40; x++) 88 | { 89 | code = fixarea[x << 5]; 90 | 91 | colour = (code & 0xf000) >> 8; 92 | code &= 0xfff; 93 | 94 | if (video_fix_usage[code]) 95 | draw_fix (code, colour, (x << 3), (y << 3), video_paletteram_pc, 96 | neogeo_fix_memory, video_fix_usage[code] & 1); 97 | } 98 | fixarea++; 99 | } 100 | } 101 | 102 | /* FIX palette for fixputs*/ 103 | u16 palette[16] = { 0x0000, 0xffff, 0x0000, 0x0000, 104 | 0x0000, 0x0000, 0x0000, 0x0000, 105 | 0xffff, 0x0000, 0x0000, 0x0000, 106 | 0x0000, 0x0000, 0x0000, 0xffff 107 | }; 108 | 109 | void 110 | fixputs (u16 x, u16 y, const char *string) 111 | { 112 | u8 i; 113 | int length = strlen (string); 114 | 115 | if (y > 27) 116 | return; 117 | 118 | if (x + length > 40) 119 | { 120 | length = 40 - x; 121 | } 122 | 123 | if (length < 0) 124 | return; 125 | 126 | y <<= 3; 127 | 128 | for (i = 0; i < length; i++) 129 | { 130 | draw_fix (toupper ((u8)(string[i])) + 0x300, 0, (x + i) << 3, y, palette, 131 | neogeo_rom_memory + 0x7C000, 0); 132 | } 133 | 134 | return; 135 | } 136 | -------------------------------------------------------------------------------- /src/video/gui.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * 4 | * GUI File Selector 5 | ****************************************************************************/ 6 | 7 | #ifndef __NEOGUI__ 8 | #define __NEOGUI__ 9 | 10 | #define TXT_NORMAL 0 11 | #define TXT_INVERSE 1 12 | #define TXT_DOUBLE 2 13 | 14 | #define BGCOLOUR 0x74b3745a 15 | #define BGBANNER 0x962a96ca 16 | #define BGPANE 0x63b3635b 17 | #define BMPANE 0xa685a67b 18 | #define INVTEXT 0x628a6277 19 | 20 | void gprint (int x, int y, char *text, int mode); 21 | void ShowScreen (void); 22 | void DrawScreen (void); 23 | void setbgcolour (u32 colour); 24 | void setfgcolour (u32 colour); 25 | void WaitButtonA (void); 26 | void ActionScreen (char *msg); 27 | void InfoScreen (char *msg); 28 | void LoadingScreen (char *msg); 29 | void bannerscreen (void); 30 | int load_mainmenu (void); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/video/gxvideo.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * NeoCDRX 9 | * 10 | * GX Video 11 | ****************************************************************************/ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "neocdrx.h" 17 | 18 | /*** External 2D Video ***/ 19 | extern u32 whichfb; 20 | extern u32 *xfb[2]; 21 | extern GXRModeObj *vmode; 22 | 23 | /*** 3D GX ***/ 24 | #define DEFAULT_FIFO_SIZE ( 256 * 1024 ) 25 | #define TEXSIZE ( (NEOSCR_WIDTH * NEOSCR_HEIGHT) * 2 ) 26 | 27 | static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32); 28 | static u8 texturemem[TEXSIZE] ATTRIBUTE_ALIGN (32); 29 | 30 | GXTexObj texobj; 31 | static Mtx view; 32 | int vwidth, vheight, oldvwidth, oldvheight; 33 | 34 | #define HASPECT 80 35 | #define VASPECT 50 36 | 37 | /* New texture based scaler */ 38 | typedef struct tagcamera 39 | { 40 | guVector pos; 41 | guVector up; 42 | guVector view; 43 | } 44 | camera; 45 | 46 | /*** Square Matrix 47 | This structure controls the size of the image on the screen. 48 | Think of the output as a -80 x 80 by -60 x 60 graph. 49 | ***/ 50 | s16 square[] ATTRIBUTE_ALIGN (32) = 51 | { 52 | /* 53 | * X, Y, Z 54 | * Values set are for roughly 4:3 aspect 55 | */ 56 | -HASPECT, VASPECT, 0, // 0 57 | HASPECT, VASPECT, 0, // 1 58 | HASPECT, -VASPECT, 0, // 2 59 | -HASPECT, -VASPECT, 0, // 3 60 | }; 61 | 62 | static camera cam = { {0.0F, 0.0F, 0.0F}, 63 | {0.0F, 0.5F, 0.0F}, 64 | {0.0F, 0.0F, -0.5F} 65 | }; 66 | 67 | /**************************************************************************** 68 | * Scaler Support Functions 69 | ****************************************************************************/ 70 | static void 71 | draw_init (void) 72 | { 73 | GX_ClearVtxDesc (); 74 | GX_SetVtxDesc (GX_VA_POS, GX_INDEX8); 75 | GX_SetVtxDesc (GX_VA_CLR0, GX_INDEX8); 76 | GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); 77 | 78 | GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); 79 | GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); 80 | GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); 81 | 82 | GX_SetArray (GX_VA_POS, square, 3 * sizeof (s16)); 83 | 84 | GX_SetNumTexGens (1); 85 | GX_SetTexCoordGen (GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); 86 | 87 | GX_InvalidateTexAll (); 88 | 89 | GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, 90 | GX_CLAMP, GX_CLAMP, GX_FALSE); 91 | } 92 | 93 | static void 94 | draw_vert (u8 pos, u8 c, f32 s, f32 t) 95 | { 96 | GX_Position1x8 (pos); 97 | GX_Color1x8 (c); 98 | GX_TexCoord2f32 (s, t); 99 | } 100 | 101 | static void 102 | draw_square (Mtx v) 103 | { 104 | Mtx m; // model matrix. 105 | Mtx mv; // modelview matrix. 106 | 107 | guMtxIdentity (m); 108 | guMtxTransApply (m, m, 0, 0, -100); 109 | guMtxConcat (v, m, mv); 110 | 111 | GX_LoadPosMtxImm (mv, GX_PNMTX0); 112 | GX_Begin (GX_QUADS, GX_VTXFMT0, 4); 113 | draw_vert (0, 0, 0.0, 0.0); 114 | draw_vert (1, 0, 1.0, 0.0); 115 | draw_vert (2, 0, 1.0, 1.0); 116 | draw_vert (3, 0, 0.0, 1.0); 117 | GX_End (); 118 | } 119 | 120 | /**************************************************************************** 121 | * StartGX 122 | ****************************************************************************/ 123 | void 124 | StartGX (void) 125 | { 126 | Mtx p; 127 | 128 | GXColor gxbackground = { 0, 0, 0, 0xff }; 129 | 130 | /*** Clear out FIFO area ***/ 131 | memset (&gp_fifo, 0, DEFAULT_FIFO_SIZE); 132 | 133 | /*** Initialise GX ***/ 134 | GX_Init (&gp_fifo, DEFAULT_FIFO_SIZE); 135 | GX_SetCopyClear (gxbackground, 0x00ffffff); 136 | 137 | GX_SetViewport (0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1); 138 | GX_SetDispCopyYScale ((f32) vmode->xfbHeight / (f32) vmode->efbHeight); 139 | GX_SetScissor (0, 0, vmode->fbWidth, vmode->efbHeight); 140 | GX_SetDispCopySrc (0, 0, vmode->fbWidth, vmode->efbHeight); 141 | GX_SetDispCopyDst (vmode->fbWidth, vmode->xfbHeight); 142 | GX_SetCopyFilter (vmode->aa, vmode->sample_pattern, GX_TRUE, vmode->vfilter); 143 | GX_SetFieldMode (vmode->field_rendering, ((vmode->viHeight == 2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); 144 | 145 | GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR); 146 | GX_SetCullMode (GX_CULL_NONE); 147 | GX_CopyDisp (xfb[whichfb ^ 1], GX_TRUE); 148 | GX_SetDispCopyGamma (GX_GM_1_0); 149 | 150 | guPerspective (p, 60, 1.33F, 10.0F, 1000.0F); 151 | GX_LoadProjectionMtx (p, GX_PERSPECTIVE); 152 | memset (texturemem, 0, TEXSIZE); 153 | vwidth = 100; 154 | vheight = 100; 155 | } 156 | 157 | /**************************************************************************** 158 | * Update Video 159 | ****************************************************************************/ 160 | void 161 | update_video (int width, int height, char *vbuffer) 162 | { 163 | 164 | int h, w; 165 | long long int *dst = (long long int *) texturemem; 166 | long long int *src1 = (long long int *) vbuffer; 167 | long long int *src2 = (long long int *) (vbuffer + 640); 168 | long long int *src3 = (long long int *) (vbuffer + 1280); 169 | long long int *src4 = (long long int *) (vbuffer + 1920); 170 | 171 | vwidth = 320; 172 | vheight = 224; 173 | 174 | whichfb ^= 1; 175 | 176 | if ((oldvheight != vheight) || (oldvwidth != vwidth)) 177 | { 178 | /** Update scaling **/ 179 | oldvwidth = vwidth; 180 | oldvheight = vheight; 181 | draw_init (); 182 | 183 | memset (&view, 0, sizeof (Mtx)); 184 | 185 | /*** Calling guLookAt seems to reboot to IPL! 186 | I've moved the equivalent code below, 187 | and only call the C GU functions. ***/ 188 | guLookAt (view, &cam.pos, &cam.up, &cam.view); 189 | GX_SetViewport (0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1); 190 | 191 | } 192 | 193 | GX_InvVtxCache (); 194 | GX_InvalidateTexAll (); 195 | GX_SetTevOp (GX_TEVSTAGE0, GX_DECAL); 196 | GX_SetTevOrder (GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); 197 | 198 | for (h = 0; h < vheight; h += 4) 199 | { 200 | for (w = 0; w < 80; w++) 201 | { 202 | *dst++ = *src1++; 203 | *dst++ = *src2++; 204 | *dst++ = *src3++; 205 | *dst++ = *src4++; 206 | } 207 | 208 | src1 += 240; 209 | src2 += 240; 210 | src3 += 240; 211 | src4 += 240; 212 | } 213 | 214 | DCFlushRange (texturemem, TEXSIZE); 215 | 216 | GX_SetNumChans (1); 217 | GX_LoadTexObj (&texobj, GX_TEXMAP0); 218 | 219 | draw_square (view); 220 | 221 | GX_DrawDone (); 222 | 223 | GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE); 224 | GX_SetColorUpdate (GX_TRUE); 225 | GX_CopyDisp (xfb[whichfb], GX_TRUE); 226 | GX_Flush (); 227 | 228 | VIDEO_SetNextFramebuffer (xfb[whichfb]); 229 | VIDEO_Flush (); 230 | 231 | VIDEO_WaitVSync (); 232 | 233 | } 234 | -------------------------------------------------------------------------------- /src/video/gxvideo.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * NeoCD-Redux 9 | * 10 | * GX Video 11 | ****************************************************************************/ 12 | #ifndef __GXVIDEO__ 13 | #define __GXVIDEO__ 14 | 15 | void StartGX (void); 16 | void update_video (int width, int height, char *vbuffer); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/video/patches.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * NeoGeo CD 9 | * 10 | * VRAM patches from NeoGeoCDZ 11 | ****************************************************************************/ 12 | #include 13 | #include 14 | #include 15 | #include "neocdrx.h" 16 | 17 | /**************************************************************************** 18 | * Patch Fatal Fury 2 19 | ****************************************************************************/ 20 | void 21 | patch_vram_rbff2 (void) 22 | { 23 | UINT16 offs; 24 | UINT16 *neogeo_vidram16 = (UINT16 *) video_vidram; 25 | 26 | for (offs = 0; offs < ((0x300 >> 1) << 6); offs += 2) 27 | { 28 | UINT16 tileno = neogeo_vidram16[offs]; 29 | UINT16 tileatr = neogeo_vidram16[offs + 1]; 30 | 31 | if (tileno == 0x7a00 && (tileatr == 0x4b00 || tileatr == 0x1400)) 32 | { 33 | neogeo_vidram16[offs] = 0x7ae9; 34 | return; 35 | } 36 | } 37 | } 38 | 39 | /**************************************************************************** 40 | * Patch ADK world 41 | ****************************************************************************/ 42 | void 43 | patch_vram_adkworld (void) 44 | { 45 | UINT16 offs; 46 | UINT16 *neogeo_vidram16 = (UINT16 *) video_vidram; 47 | 48 | for (offs = 0; offs < ((0x300 >> 1) << 6); offs += 2) 49 | { 50 | UINT16 tileno = neogeo_vidram16[offs]; 51 | UINT16 tileatr = neogeo_vidram16[offs + 1]; 52 | 53 | if ((tileno == 0x14c0 || tileno == 0x1520) && tileatr == 0x0000) 54 | neogeo_vidram16[offs] = 0x0000; 55 | } 56 | } 57 | 58 | /**************************************************************************** 59 | * Patch CrossSwords 2 60 | ****************************************************************************/ 61 | void 62 | patch_vram_crsword2 (void) 63 | { 64 | UINT16 offs; 65 | UINT16 *neogeo_vidram16 = (UINT16 *) video_vidram; 66 | 67 | for (offs = 0; offs < ((0x300 >> 1) << 6); offs += 2) 68 | { 69 | UINT16 tileno = neogeo_vidram16[offs]; 70 | UINT16 tileatr = neogeo_vidram16[offs + 1]; 71 | 72 | if (tileno == 0x52a0 && tileatr == 0x0000) 73 | neogeo_vidram16[offs] = 0x0000; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/video/patches.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /**************************************************************************** 8 | * NeoGeo CD 9 | * 10 | * VRAM patches from NeoGeoCDZ 11 | ****************************************************************************/ 12 | #ifndef __NEOVIDPATCH__ 13 | #define __NEOVIDPATCH__ 14 | 15 | void patch_vram_rbff2 (void); 16 | void patch_vram_adkworld (void); 17 | void patch_vram_crsword2 (void); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/video/scale2x.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Scale2X GC Implementation 3 | * 4 | * Only works with RGB565!!! 5 | * 6 | * Check http://scale2x.sourceforge.net for algorithm info and complete 7 | * Scale2X package 8 | *****************************************************************************/ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /**************************************************************************** 15 | * Init_Scale2X 16 | * 17 | * Build a colour LUT for RGB565 18 | ****************************************************************************/ 19 | void Init_Scale2X(void) 20 | { 21 | } 22 | 23 | /**************************************************************************** 24 | * Scale2X 25 | * 26 | * This is the actual algorithm implemented for the GC 27 | ****************************************************************************/ 28 | void Scale2X(char *srcpix, int srcpitch, char *dstpix, int dstpitch, 29 | int width, int height) 30 | { 31 | u16 E0, E1, E2, E3, B, D, E, F, H; 32 | int looph, loopw; 33 | int t; 34 | 35 | for (looph = 0; looph < height; ++looph) { 36 | for (loopw = 0; loopw < width; ++loopw) { 37 | 38 | t = looph * srcpitch; 39 | B = *(u16 *) (srcpix + (MAX(0, looph - 1) * srcpitch) + 40 | (loopw << 1)); 41 | D = *(u16 *) (srcpix + t + 42 | (MAX(0, loopw - 1)<<1)); 43 | E = *(u16 *) (srcpix + t + (loopw << 1)); 44 | F = *(u16 *) (srcpix + t + 45 | (2 * MIN(width - 1, loopw + 1))); 46 | H = *(u16 *) (srcpix + (MIN(height - 1, looph + 1) * srcpitch) + 47 | (loopw << 1)); 48 | 49 | E0 = D == B && B != F && D != H ? D : E; 50 | E1 = B == F && B != D && F != H ? F : E; 51 | E2 = D == H && D != B && H != F ? D : E; 52 | E3 = H == F && D != H && B != F ? F : E; 53 | 54 | t = looph * dstpitch * 2; 55 | *(u16 *) (dstpix + t + loopw * 2 * 2) = E0; 56 | *(u16 *) (dstpix + t + (loopw * 2 + 1) * 2) = 57 | E1; 58 | *(u16 *) (dstpix + (looph * 2 + 1) * dstpitch + loopw * 2 * 2) = 59 | E2; 60 | *(u16 *) (dstpix + (looph * 2 + 1) * dstpitch + 61 | (loopw * 2 + 1) * 2) = E3; 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/video/video.h: -------------------------------------------------------------------------------- 1 | /******************************************* 2 | **** VIDEO.H - Video Hardware Emulation **** 3 | **** Header File **** 4 | *******************************************/ 5 | 6 | #ifndef VIDEO_H 7 | #define VIDEO_H 8 | 9 | /*-- Defines ---------------------------------------------------------------*/ 10 | #define VIDEO_TEXT 0 11 | #define VIDEO_NORMAL 1 12 | #define VIDEO_SCANLINES 2 13 | #define NEOSCR_WIDTH 320 14 | #define NEOSCR_HEIGHT 224 15 | 16 | /*-- Global Variables ------------------------------------------------------*/ 17 | extern char video_vidram[0x20000]; 18 | extern unsigned short *video_paletteram_ng; 19 | extern unsigned short video_palette_bank0_ng[4096]; 20 | extern unsigned short video_palette_bank1_ng[4096]; 21 | extern unsigned short *video_paletteram_pc; 22 | extern unsigned short video_palette_bank0_pc[4096]; 23 | extern unsigned short video_palette_bank1_pc[4096]; 24 | extern int video_modulo; 25 | extern int video_pointer; 26 | extern unsigned short *video_paletteram; 27 | extern unsigned short *video_paletteram_pc; 28 | extern unsigned short video_palette_bank0[4096]; 29 | extern unsigned short video_palette_bank1[4096]; 30 | extern unsigned short *video_line_ptr[224]; 31 | extern unsigned char video_fix_usage[4096]; 32 | extern unsigned char video_spr_usage[0x10000]; 33 | extern unsigned int video_hide_fps; 34 | extern unsigned short video_color_lut[32768]; 35 | extern int spr_disable; 36 | extern int fix_disable; 37 | extern int video_mode; 38 | extern double gamma_correction; 39 | extern int frameskip; 40 | 41 | extern unsigned int neogeo_frame_counter; 42 | extern unsigned int neogeo_frame_counter_speed; 43 | 44 | /*-- video.c functions ----------------------------------------------------*/ 45 | int video_init (void); 46 | void video_shutdown (void); 47 | int video_set_mode (int); 48 | void video_draw_screen1 (void); 49 | void video_save_snapshot (void); 50 | void video_draw_spr (unsigned int code, unsigned int color, int flipx, 51 | int flipy, int sx, int sy, int zx, int zy); 52 | void video_setup (void); 53 | void video_fullscreen_toggle (void); 54 | void video_mode_toggle (void); 55 | void video_clear (void); 56 | void blitter (void); 57 | void savescreen (char *buffer); 58 | 59 | /*-- draw_fix.c functions -------------------------------------------------*/ 60 | void video_draw_fix (void); 61 | void fixputs (u16 x, u16 y, const char *string); 62 | 63 | #endif /* VIDEO_H */ 64 | -------------------------------------------------------------------------------- /src/z80/Makefile: -------------------------------------------------------------------------------- 1 | ########################## 2 | # Makefile for Z80 Core # 3 | ########################## 4 | 5 | BUILDDIR=../../build_cpu 6 | 7 | #setup C Flags 8 | CFLAGS= -I. -I./$(BUILDDIR) -Wall -O3 -fomit-frame-pointer -fno-ident -DINLINE="static inline" -DCLEANBUILD=1 \ 9 | -fstrict-aliasing -D__ASMPREFIX__ 10 | 11 | all: $(BUILDDIR)/libz80.a 12 | 13 | clean: 14 | rm -f $(BUILDDIR)/libz80.a 15 | 16 | $(BUILDDIR)/libz80.a: $(BUILDDIR)/z80.o $(BUILDDIR)/z80daisy.o 17 | @$(AR) -r $@ $^ 18 | 19 | $(BUILDDIR)/z80.o: z80.c z80.h 20 | @echo "" 21 | @echo "*** Mame Z80 Core 3.6 ******************************************************" 22 | @echo " Copyright (C) 1998,1999,2000 Juergen Buchmueller, all rights reserved." 23 | @echo "****************************************************************************" 24 | @echo "" 25 | @$(CC) $(CFLAGS) -c z80.c -o $(BUILDDIR)/z80.o 26 | 27 | $(BUILDDIR)/z80daisy.o: z80daisy.c z80daisy.h 28 | @$(CC) $(CFLAGS) -c z80daisy.c -o $(BUILDDIR)/z80daisy.o 29 | -------------------------------------------------------------------------------- /src/z80/z80.h: -------------------------------------------------------------------------------- 1 | #ifndef _Z80_H_ 2 | #define _Z80_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define CPUINFO_PTR_CPU_SPECIFIC 0x8000 9 | #define CALL_MAME_DEBUG // 10 | 11 | typedef unsigned int UINT32; 12 | typedef signed int INT32; 13 | typedef unsigned short UINT16; 14 | typedef signed short INT16; 15 | typedef unsigned char UINT8; 16 | typedef signed char INT8; 17 | 18 | /************************************* 19 | * 20 | * Interrupt line constants 21 | * 22 | *************************************/ 23 | 24 | enum 25 | { 26 | /* line states */ 27 | CLEAR_LINE = 0, /* clear (a fired, held or pulsed) line */ 28 | ASSERT_LINE, /* assert an interrupt immediately */ 29 | HOLD_LINE, /* hold interrupt line until acknowledged */ 30 | PULSE_LINE, /* pulse interrupt line for one instruction */ 31 | 32 | /* internal flags (not for use by drivers!) */ 33 | INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE, 34 | INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE, 35 | 36 | /* input lines */ 37 | MAX_INPUT_LINES = 32+3, 38 | INPUT_LINE_IRQ0 = 0, 39 | INPUT_LINE_IRQ1 = 1, 40 | INPUT_LINE_IRQ2 = 2, 41 | INPUT_LINE_IRQ3 = 3, 42 | INPUT_LINE_IRQ4 = 4, 43 | INPUT_LINE_IRQ5 = 5, 44 | INPUT_LINE_IRQ6 = 6, 45 | INPUT_LINE_IRQ7 = 7, 46 | INPUT_LINE_IRQ8 = 8, 47 | INPUT_LINE_IRQ9 = 9, 48 | INPUT_LINE_NMI = MAX_INPUT_LINES - 3, 49 | 50 | /* special input lines that are implemented in the core */ 51 | INPUT_LINE_RESET = MAX_INPUT_LINES - 2, 52 | INPUT_LINE_HALT = MAX_INPUT_LINES - 1, 53 | 54 | /* output lines */ 55 | MAX_OUTPUT_LINES = 32 56 | }; 57 | 58 | /*************************************************************************** 59 | * Union of UINT8, UINT16 and UINT32 in native endianess of the target 60 | * This is used to access bytes and words in a machine independent manner. 61 | * The upper bytes h2 and h3 normally contain zero (16 bit CPU cores) 62 | * thus PAIR.d can be used to pass arguments to the memory system 63 | * which expects 'int' really. 64 | ***************************************************************************/ 65 | typedef union 66 | { 67 | #ifdef LSB_FIRST 68 | struct { UINT8 l,h,h2,h3; } b; 69 | struct { UINT16 l,h; } w; 70 | #else 71 | struct { UINT8 h3,h2,h,l; } b; 72 | struct { UINT16 h,l; } w; 73 | #endif 74 | UINT32 d; 75 | } PAIR; 76 | 77 | enum { 78 | Z80_PC=1, Z80_SP, 79 | Z80_A, Z80_B, Z80_C, Z80_D, Z80_E, Z80_H, Z80_L, 80 | Z80_AF, Z80_BC, Z80_DE, Z80_HL, 81 | Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2, 82 | Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT, 83 | Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3 84 | }; 85 | 86 | enum { 87 | Z80_TABLE_op, 88 | Z80_TABLE_cb, 89 | Z80_TABLE_ed, 90 | Z80_TABLE_xy, 91 | Z80_TABLE_xycb, 92 | Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */ 93 | }; 94 | 95 | enum 96 | { 97 | CPUINFO_PTR_Z80_CYCLE_TABLE = CPUINFO_PTR_CPU_SPECIFIC, 98 | CPUINFO_PTR_Z80_CYCLE_TABLE_LAST = CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_ex 99 | }; 100 | 101 | /**************************************************************************** 102 | * mz80 wrappers 103 | ****************************************************************************/ 104 | void mz80_init(void); 105 | INT32 mz80exec( INT32 cycles ); 106 | void mz80nmi( void ); 107 | void mz80int( INT32 irq ); 108 | void mz80ClearPendingInterrupt( INT32 irq ); 109 | void mz80_reset( void ); 110 | extern int cpu_enabled; 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/z80/z80daisy.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | 3 | z80daisy.c 4 | 5 | Z80/180 daisy chaining support functions. 6 | 7 | ***************************************************************************/ 8 | 9 | #include "z80.h" 10 | #include "z80daisy.h" 11 | 12 | void z80daisy_reset(const struct z80_irq_daisy_chain *daisy) 13 | { 14 | /* loop over all devices and call their reset function */ 15 | for ( ; daisy->param != -1; daisy++) 16 | if (daisy->reset) 17 | (*daisy->reset)(daisy->param); 18 | } 19 | 20 | int z80daisy_update_irq_state(const struct z80_irq_daisy_chain *daisy) 21 | { 22 | /* loop over all devices; dev[0] is highest priority */ 23 | for ( ; daisy->param != -1; daisy++) 24 | { 25 | int state = (*daisy->irq_state)(daisy->param); 26 | 27 | /* if this device is asserting the INT line, that's the one we want */ 28 | if (state & Z80_DAISY_INT) 29 | return ASSERT_LINE; 30 | 31 | /* if this device is asserting the IEO line, it blocks everyone else */ 32 | if (state & Z80_DAISY_IEO) 33 | return CLEAR_LINE; 34 | } 35 | 36 | return CLEAR_LINE; 37 | } 38 | 39 | int z80daisy_call_ack_device(const struct z80_irq_daisy_chain *daisy) 40 | { 41 | /* loop over all devices; dev[0] is the highest priority */ 42 | for ( ; daisy->param != -1; daisy++) 43 | { 44 | int state = (*daisy->irq_state)(daisy->param); 45 | 46 | /* if this device is asserting the INT line, that's the one we want */ 47 | if (state & Z80_DAISY_INT) 48 | return (*daisy->irq_ack)(daisy->param); 49 | } 50 | 51 | //logerror("z80daisy_call_ack_device: failed to find an device to ack!\n"); 52 | return 0; 53 | } 54 | 55 | void z80daisy_call_reti_device(const struct z80_irq_daisy_chain *daisy) 56 | { 57 | /* loop over all devices; dev[0] is the highest priority */ 58 | for ( ; daisy->param != -1; daisy++) 59 | { 60 | int state = (*daisy->irq_state)(daisy->param); 61 | 62 | /* if this device is asserting the IEO line, that's the one we want */ 63 | if (state & Z80_DAISY_IEO) 64 | { 65 | (*daisy->irq_reti)(daisy->param); 66 | return; 67 | } 68 | } 69 | 70 | //logerror("z80daisy_call_reti_device: failed to find an device to reti!\n"); 71 | } 72 | -------------------------------------------------------------------------------- /src/z80/z80daisy.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | 3 | z80daisy.h 4 | 5 | Z80/180 daisy chaining support functions. 6 | 7 | ***************************************************************************/ 8 | 9 | #ifndef Z80DAISY_H 10 | #define Z80DAISY_H 11 | 12 | /* daisy-chain link */ 13 | struct z80_irq_daisy_chain 14 | { 15 | void (*reset)(int); /* reset callback */ 16 | int (*irq_state)(int); /* get interrupt state */ 17 | int (*irq_ack)(int); /* interrupt acknowledge callback */ 18 | void (*irq_reti)(int); /* reti callback */ 19 | int param; /* callback parameter (-1 ends list) */ 20 | }; 21 | 22 | /* these constants are returned from the irq_state function */ 23 | #define Z80_DAISY_INT 0x01 /* interrupt request mask */ 24 | #define Z80_DAISY_IEO 0x02 /* interrupt disable mask (IEO) */ 25 | 26 | /* prototypes */ 27 | void z80daisy_reset(const struct z80_irq_daisy_chain *daisy); 28 | int z80daisy_update_irq_state(const struct z80_irq_daisy_chain *chain); 29 | int z80daisy_call_ack_device(const struct z80_irq_daisy_chain *chain); 30 | void z80daisy_call_reti_device(const struct z80_irq_daisy_chain *chain); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/z80/z80dasm.h: -------------------------------------------------------------------------------- 1 | extern int DasmZ80(char *buffer, int PC); 2 | 3 | -------------------------------------------------------------------------------- /src/z80i/z80intrf.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /************************ 8 | *** Z80 CPU Interface *** 9 | ************************/ 10 | 11 | //-- Include Files ---------------------------------------------------------- 12 | #include 13 | #include "neocdrx.h" 14 | #include 15 | #include 16 | 17 | //-- Exported Functions ----------------------------------------------------- 18 | unsigned char subcpu_memspace[65536]; 19 | int sound_code = 0; 20 | int pending_command = 0; 21 | int result_code = 0; 22 | int nmi_over = 0; 23 | 24 | //--------------------------------------------------------------------------- 25 | /*** 26 | * Whilst tracing the Z80, it appears that PORT0/8/C are always written 27 | * with the same value after NMI. 28 | * 29 | * At this point, the M68K reads from address 0x32000 to determine the 30 | * success or failure of the previous NMI. 31 | * 32 | * On NMI, sound_code == 3 is total reset. 33 | * sound_code == 1 is a partial reset. 34 | * 35 | * So really, it should not be called sound_code, as it does this 36 | * very important task too. 37 | ***/ 38 | 39 | void 40 | PortWrite (UINT16 PortNo, UINT8 data) 41 | { 42 | 43 | switch (PortNo & 0xff) 44 | { 45 | 46 | case 0x4: 47 | YM2610_control_port_0_A_w (0, data); 48 | break; 49 | 50 | case 0x5: 51 | YM2610_data_port_0_A_w (0, data); 52 | break; 53 | 54 | case 0x6: 55 | YM2610_control_port_0_B_w (0, data); 56 | break; 57 | 58 | case 0x7: 59 | YM2610_data_port_0_B_w (0, data); 60 | break; 61 | 62 | case 0x8: 63 | /* NMI enable / acknowledge? (the data written doesn't matter) */ 64 | break; 65 | 66 | case 0xc: 67 | result_code = data; 68 | break; 69 | 70 | case 0x18: 71 | /* NMI disable? (the data written doesn't matter) */ 72 | break; 73 | 74 | case 0x80: 75 | cdda_stop (); 76 | break; 77 | 78 | default: 79 | //printf("Unimplemented Z80 Write Port: %x data: %x\n",PortNo&0xff,data); 80 | break; 81 | } 82 | } 83 | 84 | //--------------------------------------------------------------------------- 85 | UINT8 86 | PortRead (UINT16 PortNo) 87 | { 88 | switch (PortNo & 0xff) 89 | { 90 | case 0x0: 91 | pending_command = 0; 92 | return sound_code; 93 | break; 94 | 95 | case 0x4: 96 | return YM2610_status_port_0_A_r (0); 97 | break; 98 | 99 | case 0x5: 100 | return YM2610_read_port_0_r (0); 101 | break; 102 | 103 | case 0x6: 104 | return YM2610_status_port_0_B_r (0); 105 | break; 106 | 107 | default: 108 | //printf("Unimplemented Z80 Read Port: %d\n",PortNo&0xff); 109 | break; 110 | }; 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /src/z80i/z80intrf.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * NeoCDRX 3 | * NeoGeo CD Emulator 4 | * NeoCD Redux - Copyright (C) 2007 softdev 5 | ****************************************************************************/ 6 | 7 | /************************ 8 | *** Z80 CPU Interface *** 9 | *** Header File *** 10 | ************************/ 11 | 12 | #ifndef Z80INTRF_H 13 | #define Z80INRTF_H 14 | 15 | #include "z80.h" 16 | 17 | void z80_init (void); 18 | int mz80exec (int cycles); 19 | void mz80nmi (void); 20 | void mz80int (int irq); 21 | void z80_exit (void); 22 | 23 | extern UINT8 subcpu_memspace[65536]; 24 | extern int sound_code; 25 | extern int pending_command; 26 | extern int result_code; 27 | extern int z80_cycles; 28 | 29 | #endif /* Z80INTRF_H */ 30 | --------------------------------------------------------------------------------