├── .gitignore ├── .gitmodules ├── .vscode ├── c_cpp_properties.json ├── launch.json └── tasks.json ├── Docs ├── CXD1095Q.txt ├── GGIO.txt ├── Mark3tech.txt ├── S8-differences.txt ├── Sord M5.txt ├── System-E tech.txt ├── YM2413 Application Manual.mht ├── megaplay.c ├── megatech-schem.pdf ├── megatech.c ├── portar.txt ├── sc3000h.txt ├── segae.c ├── sg1000a.c ├── sms-vdp.txt ├── smstech.txt ├── system1.c └── tms9918a.txt ├── History.txt ├── Makefile ├── README.md ├── S8DS.code-workspace ├── S8DS.pnproj ├── S8DS.pnws ├── S8DS.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ └── S8DS.xcscheme ├── S8DS_todo.txt ├── Sms.bmp ├── copytodsx.bat ├── graphics ├── ColecoNumpad.grit ├── ColecoNumpad.png ├── GG.grit ├── GG.png ├── MD.grit ├── MD.png ├── MSX.grit ├── MSX.png ├── Mark3.grit ├── Mark3.png ├── OmvBgr.grit ├── OmvBgr.png ├── SC3000.grit ├── SC3000.png ├── SG1000-II.grit ├── SG1000-II.png ├── SG1000.grit ├── SG1000.png ├── SMS1.grit ├── SMS1.png ├── SMS2.grit ├── SMS2.png ├── SordM5Kb.grit └── SordM5Kb.png ├── include └── MiniBios.sms ├── s8ds.pnps └── source ├── Cart.h ├── Cart.s ├── Emubase.h ├── Equates.h ├── FileHandling.c ├── FileHandling.h ├── Gfx.h ├── Gfx.s ├── Gui.c ├── Gui.h ├── MSXIO.s ├── Main.c ├── Main.h ├── MasterSystem.c ├── MasterSystem.h ├── MegaTech.s ├── Memory.s ├── RomLoading.c ├── RomLoading.h ├── SordM5.s ├── Sound.h ├── Sound.s ├── SystemE.s ├── cpu.h ├── cpu.s ├── io.h ├── io.s ├── ym2413.c └── ym2413.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.gg 2 | *.rom 3 | *.sms 4 | *.ic21 5 | *.sg 6 | S8DS.xcodeproj/project.xcworkspace/xcuserdata 7 | build 8 | *.elf 9 | *.nds 10 | *.zip 11 | include/ac 12 | include/col 13 | include/mt 14 | include/PV-2000 15 | include/sc 16 | include/saves 17 | *.sav 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "source/ARMZ80"] 2 | path = source/ARMZ80 3 | url = https://github.com/FluBBaOfWard/ARMZ80.git 4 | [submodule "source/ARMZ80CTC"] 5 | path = source/ARMZ80CTC 6 | url = https://github.com/FluBBaOfWard/ARMZ80CTC.git 7 | [submodule "source/SegaVDP"] 8 | path = source/SegaVDP 9 | url = https://github.com/FluBBaOfWard/SegaVDP.git 10 | [submodule "source/SN76496"] 11 | path = source/SN76496 12 | url = https://github.com/FluBBaOfWard/SN76496.git 13 | [submodule "source/Shared"] 14 | path = source/Shared 15 | url = https://github.com/FluBBaOfWard/NDS_Shared.git 16 | [submodule "source/AY38910"] 17 | path = source/AY38910 18 | url = https://github.com/FluBBaOfWard/AY38910.git 19 | [submodule "source/YM2413"] 20 | path = source/YM2413 21 | url = https://github.com/FluBBaOfWard/YM2413.git 22 | [submodule "source/PPI8255"] 23 | path = source/PPI8255 24 | url = https://github.com/FluBBaOfWard/PPI8255.git 25 | [submodule "source/SCC"] 26 | path = source/SCC 27 | url = https://github.com/FluBBaOfWard/SCC.git 28 | [submodule "source/CXD1095Q"] 29 | path = source/CXD1095Q 30 | url = https://github.com/FluBBaOfWard/CXD1095Q.git 31 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "/usr/local/include", 7 | "${workspaceFolder}", 8 | "${workspaceFolder}/include", 9 | "${workspaceFolder}/build", 10 | "/opt/devkitPro/libnds/include", 11 | "/opt/devkitPro/devkitARM/arm-none-eabi/include", 12 | "/opt/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 13 | ], 14 | "defines": [], 15 | "intelliSenseMode": "clang-x64", 16 | "browse": { 17 | "path": [ 18 | "/usr/local/include", 19 | "${workspaceFolder}", 20 | "${workspaceFolder}/include", 21 | "/opt/devkitPro/libnds/include", 22 | "/opt/devkitPro/devkitARM/arm-none-eabi/include", 23 | "/opt/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 24 | ], 25 | "limitSymbolsToIncludedHeaders": true, 26 | "databaseFilename": "" 27 | }, 28 | "macFrameworkPath": [ 29 | "/System/Library/Frameworks", 30 | "/Library/Frameworks" 31 | ], 32 | "compilerPath": "/opt/devkitpro/devkitARM/bin/arm-none-eabi-gcc" 33 | }, 34 | { 35 | "name": "Linux", 36 | "includePath": [ 37 | "/usr/include", 38 | "/usr/local/include", 39 | "${workspaceFolder}/include" 40 | ], 41 | "defines": [], 42 | "intelliSenseMode": "clang-x64", 43 | "browse": { 44 | "path": [ 45 | "/usr/include", 46 | "/usr/local/include", 47 | "${workspaceFolder}/include" 48 | ], 49 | "limitSymbolsToIncludedHeaders": true, 50 | "databaseFilename": "" 51 | } 52 | }, 53 | { 54 | "name": "Win32", 55 | "includePath": [ 56 | "${workspaceFolder}", 57 | "${workspaceFolder}/include", 58 | "C:/devkitPro/devkitARM/arm-none-eabi/include", 59 | "C:/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 60 | ], 61 | "defines": [ 62 | "_DEBUG", 63 | "UNICODE", 64 | "_UNICODE", 65 | "ARM7", 66 | "WIN32" 67 | ], 68 | "intelliSenseMode": "msvc-x64", 69 | "browse": { 70 | "path": [ 71 | "${workspaceFolder}", 72 | "${workspaceFolder}/include", 73 | "C:/devkitPro/devkitARM/arm-none-eabi/include", 74 | "C:/devkitPro/devkitARM/lib/gcc/arm-none-eabi/10.2.0/include" 75 | ], 76 | "limitSymbolsToIncludedHeaders": true, 77 | "databaseFilename": "" 78 | }, 79 | "cStandard": "c11", 80 | "cppStandard": "c++17" 81 | } 82 | ], 83 | "version": 4 84 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "2.0.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "preLaunchTask": "gdb-debug", 12 | "postDebugTask": "stop emulation", 13 | "serverLaunchTimeout": 10000, 14 | "stopAtEntry": true, 15 | "program": "${workspaceFolder}/${workspaceFolderBasename}.elf", 16 | "MIMode": "gdb", 17 | "externalConsole": true, 18 | "cwd": "${workspaceFolder}", 19 | "targetArchitecture": "arm", 20 | "miDebuggerServerAddress": "localhost:2345", 21 | "windows": { 22 | "miDebuggerPath": "C:/devkitPro/devkitARM/bin/arm-none-eabi-gdb.exe", 23 | "setupCommands": [ 24 | { 25 | "description": "Enable pretty-printing for gdb", 26 | "ignoreFailures": true, 27 | "text": "file ${workspaceFolder}/${workspaceFolderBasename}.elf -enable-pretty-printing" 28 | }] 29 | }, 30 | "osx":{ 31 | "miDebuggerPath": "/opt/devkitPro/devkitARM/bin/arm-none-eabi-gdb", 32 | "setupCommands": [ 33 | { 34 | "description": "Enable pretty-printing for gdb", 35 | "ignoreFailures": true, 36 | "text": "file ${workspaceFolder}/${workspaceFolderBasename}.elf -enable-pretty-printing" 37 | }] 38 | }, 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "stop emulation", 8 | "type": "shell", 9 | "windows": { 10 | "command": "taskkill /im mGBA.exe /F" 11 | }, 12 | "osx": { 13 | "command": "killall mGBA" 14 | } 15 | }, 16 | { 17 | "label": "make debug", 18 | "type": "process", 19 | "command": "make", 20 | "args": [ 21 | "DEBUG=1" 22 | ], 23 | "problemMatcher": [] 24 | }, 25 | { 26 | "label": "make release", 27 | "type": "process", 28 | "command": "make", 29 | "args": [ 30 | "DEBUG=0" 31 | ], 32 | "problemMatcher": [], 33 | "group": { 34 | "kind": "build", 35 | "isDefault": true 36 | } 37 | }, 38 | { 39 | "label": "clean", 40 | "type": "shell", 41 | "command": "make clean" 42 | }, 43 | { 44 | "label": "gdb-debug", 45 | "type": "shell", 46 | "dependsOn": [ 47 | "make debug" 48 | ], 49 | "isBackground": false, 50 | "windows": { 51 | "command": "C:/mGBA/mGBA.exe -g ${workspaceFolder}/${workspaceFolderBasename}.nds;sleep 5;echo debuggerReady" 52 | }, 53 | "osx": { 54 | "command": "/Applications/desmume.app/Contents/MacOS/desmume", 55 | "args": [ 56 | "-g", 57 | "${workspaceFolder}/${workspaceFolderBasename}.nds" 58 | ] 59 | }, 60 | "presentation": { 61 | "clear": true, 62 | "reveal": "always", 63 | "panel": "new" 64 | }, 65 | "command": "debuggerReady", 66 | "problemMatcher": { 67 | "background": { 68 | "activeOnStart": true, 69 | "beginsPattern": "^.*debuggerReady.*$", 70 | "endsPattern": "^.*debuggerReady.*$" 71 | } 72 | } 73 | }, 74 | { 75 | "label": "run", 76 | "type": "shell", 77 | "isBackground": true, 78 | "command": "C:/NO$GBADebugger/NO$GBA.exe ${workspaceFolder}/${workspaceFolderBasename}.elf", 79 | "problemMatcher": [] 80 | } 81 | ] 82 | } -------------------------------------------------------------------------------- /Docs/CXD1095Q.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | I/O hardware 3 | ---------------------------------------------------------------------------- 4 | 5 | Two Sony CXD1095Q I/O chips are used. Each has the following capabilities: 6 | 7 | - Five I/O ports; A through D are 8 bits and E is 4 bits. 8 | - Pin direction can be set for bit groups 7-4 or 3-0 for ports A through D. 9 | - Pin direction can be set for bits 3-0 individually for port E. 10 | - Output-disable pin to force input mode for ports A through D. 11 | 12 | Each port consists of an output latch which is loaded when the port 13 | is written to, and an input buffer. When in output mode, reading a port 14 | returns the latch contents. When in input mode, the latch does nothing 15 | (though it can still be written to) and reading a port returns the input 16 | buffer data. 17 | 18 | Commonly used addresses are: 19 | 20 | $140000-$14000F : I/O chip #1 21 | $150000-$15000F : I/O chip #2 22 | $160000 : I/O chip output control 23 | 24 | Each chip has eight internal registers: 25 | 26 | $0001 - Port A data (r/w) 27 | $0003 - Port B data (r/w) 28 | $0005 - Port C data (r/w) 29 | $0007 - Port D data (r/w) 30 | $0009 - Port E data (r/w) 31 | $000B - Unused 32 | $000D - REG1 (w/o) 33 | $000F - REG2 (w/o) 34 | 35 | The upper 4 bits of port E, the unused register, and REG1, REG2 return zero 36 | when read. 37 | 38 | REG1 has the following layout: 39 | 40 | Bit 7 : Port D bits 7-4 pin direction (0= output, 1= input) 41 | Bit 6 : Port D bits 3-0 pin direction (0= output, 1= input) 42 | Bit 5 : Port C bits 7-4 pin direction (0= output, 1= input) 43 | Bit 4 : Port C bits 3-0 pin direction (0= output, 1= input) 44 | Bit 3 : Port B bits 7-4 pin direction (0= output, 1= input) 45 | Bit 2 : Port B bits 3-0 pin direction (0= output, 1= input) 46 | Bit 1 : Port A bits 7-4 pin direction (0= output, 1= input) 47 | Bit 0 : Port A bits 3-0 pin direction (0= output, 1= input) 48 | 49 | REG2 has the following layout: 50 | 51 | Bit 7 : Unused 52 | Bit 6 : Unused 53 | Bit 5 : Unused 54 | Bit 4 : Unused 55 | Bit 3 : Bit 3 pin direction (0= output, 1= input) 56 | Bit 2 : Bit 2 pin direction (0= output, 1= input) 57 | Bit 1 : Bit 1 pin direction (0= output, 1= input) 58 | Bit 0 : Bit 0 pin direction (0= output, 1= input) 59 | 60 | For the X-Board hardware these should be initialized to $03 and $FF, 61 | respectively. 62 | 63 | Default states 64 | 65 | When the ports are inputs (by /ODEN==L or REG1=$FF), their values 66 | (as read by the CPU) are: 67 | 68 | $140001 = $00 69 | $140003 = $00 70 | $140005 = $00 71 | $140007 = $00 72 | $140009 = $00 73 | 74 | $150001 = $FF 75 | $150003 = $FF 76 | $150005 = $FF 77 | $150007 = $FF 78 | $150009 = $00 79 | 80 | Output disable control 81 | 82 | Each I/O chip has an input called /ODEN. When pulled low, ports A through D 83 | become inputs in all eight bits. 84 | 85 | Writing to ports A-D will update the internal latch, but the pin state 86 | is unchanged. Reading ports A-D will return their input data, just as 87 | if REG1 = $FF (though REG1 hasn't changed). 88 | 89 | Accessing any location within $160000-$16FFFF latches bit 0 of the data 90 | bus and outputs it to the /ODEN pin of both I/O chips. When /ODEN is low, 91 | all pins of ports A through D become inputs. When /ODEN is high, the ports 92 | are programmable through REG2. 93 | 94 | Port E is unaffected by /ODEN, and none of the internal registers are 95 | modified while /ODEN is low; furthermore changes to registers are 96 | accepted though direction changes are not noticable until /ODEN is high. 97 | -------------------------------------------------------------------------------- /Docs/GGIO.txt: -------------------------------------------------------------------------------- 1 | GG I/O information and mapper question 2 | 3 | Here's some information on the Game Gear I/O registers when the console is in 4 | native GG mode, and nothing is connected to the EXT connector. 5 | 6 | The EXT connector has seven pins: TH, TR, DL, D3, D2, D1, D0. Each one is an 7 | active-low input. There are dedicated registers for controlling the EXT 8 | connector pins; incidentally each of these map to the same like-named pins of 9 | I/O port #2. For the same reason, the I/O port #2 TR and TH pin controls 10 | (direction and output level) in port $3F do not affect TR and TH at all. 11 | 12 | Port $05 is the serial control and status register. 13 | Bits 7-3 can be read and written. 14 | Bits 2-0 return status information and are read-only. Reset value is $00. 15 | 16 | If bit 5 is set, TR is unaffected by the settings of ports $01 and $02, and becomes an input. 17 | If bit 4 is set, TL is unaffected by the settings of ports $01 and $02, and becomes an output. 18 | Writing to port $03 causes data to be shifted out serially through TL, at the 19 | baud rate specified by bit 7,6 of this register. 20 | 21 | Amusing side note: if you read TL through port $DD, you can capture the data 22 | being shifted out if the baud rate is slow enough (I tried 300bps). 23 | 24 | Port $04 is the serial data receive buffer. Always returns $FF. 25 | 26 | Port $03 is the serial data transmit buffer. 27 | Can be read and written, reset value is $00. 28 | Writing a value starts the serial transmit process. 29 | 30 | Port $02 is the EXT connector pin direction register. 31 | Can be read and written, reset value is $FF. 32 | 33 | D7 : 0= Generate NMI on falling edge of TH. (ONLY when TH is an input), 1= No NMI generation. 34 | D6 : TH is a 0=output, 1=input 35 | D5 : TR is a 0=output, 1=input 36 | D4 : TL is a 0=output, 1=input 37 | D3 : D3 is a 0=output, 1=input 38 | D2 : D2 is a 0=output, 1=input 39 | D1 : D1 is a 0=output, 1=input 40 | D0 : D0 is a 0=output, 1=input 41 | 42 | As far as I can tell enabling NMI's and toggling bit 6 (through any 43 | combination of the data output and data direction registers) will not force 44 | NMI's to occur. You need something plugged into the EXT connector to pull TH 45 | low to do this. The Genesis and Saturn are the same way. 46 | 47 | Port $01 returns the state of the EXT connector pins in D6-D0 when read; 48 | and sets their output level (to be used when/if any of the pins are configured 49 | as outputs) when written to. Bit 7 can be read and written and does not 50 | correspond to any pin or any other part of the I/O hardware, at reset it 51 | is set on VA0 and clear on VA1 HW. 52 | 53 | Write: 54 | D6 : TH output level is 0=low, 1=high 55 | D5 : TR output level is 0=low, 1=high 56 | D4 : TL output level is 0=low, 1=high 57 | D3 : D3 output level is 0=low, 1=high 58 | D2 : D2 output level is 0=low, 1=high 59 | D1 : D1 output level is 0=low, 1=high 60 | D0 : D0 output level is 0=low, 1=high 61 | 62 | Read: 63 | D6 : TH pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to bit 6) 64 | D5 : TR pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to bit 5) 65 | D4 : TL pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to bit 4) 66 | D3 : D3 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to bit 3) 67 | D2 : D2 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to bit 2) 68 | D1 : D1 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to bit 1) 69 | D0 : D0 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to bit 0) 70 | 71 | Likewise, reading I/O ports $DC/$DD returns the same information above: 72 | 73 | Port $DD bit 7: TH pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to I/O port $01 bit 6) 74 | Port $DD bit 3: TR pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to I/O port $01 bit 5) 75 | Port $DD bit 2: TL pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to I/O port $01 bit 4) 76 | Port $DD bit 1: D3 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to I/O port $01 bit 3) 77 | Port $DD bit 0: D2 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to I/O port $01 bit 2) 78 | Port $DC bit 7: D1 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to I/O port $01 bit 1) 79 | Port $DC bit 6: D0 pin state (if an input, '1' if the pin is unconnected; if an output, whatever value was written to I/O port $01 bit 0) 80 | 81 | Setting bit 2 of port $3E to stop the I/O chip from returning data when 82 | reading ports $C0-$FF does nothing; this feature seems to have been removed. 83 | 84 | I think the correlation between I/O port #2 and the EXT connector are the same 85 | in SMS mode; I remember reading in GamePro many years ago that an adapter 86 | existed to connect a Master System pad to the EXT connector for 2-player games 87 | through the MasterGear adapter. How two people would look at the same tiny LCD 88 | screen for extended bouts of gameplay is a mystery to me. 89 | 90 | Here are the test programs I wrote: 91 | 92 | http://cgfm2.emuviews.com/zip/ggiotest.zip 93 | http://cgfm2.emuviews.com/zip/msiotest.zip 94 | 95 | Source included. I found these useful to test my emulator, maybe somebody 96 | could put these in the S8-DEV software section? 97 | 98 | And now for my question: 99 | 100 | What pin, if any, on the 315-5235 mapper is SRAM address bit 14? 101 | I have a spare 32K SRAM and would like to try replacing the 8K one in my 102 | Phantasy Star cart, but right now only 16K would be usable. 103 | I'm guessing pin 28 but have no way to verify. 104 | -------------------------------------------------------------------------------- /Docs/Mark3tech.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | Sega Mark-III Hardware Notes 3 | (C) 2008 Charles MacDonald 4 | ---------------------------------------------------------------------------- 5 | 6 | [11/14/08] 7 | - Initial release 8 | 9 | ---------------------------------------------------------------------------- 10 | Overview 11 | ---------------------------------------------------------------------------- 12 | 13 | Primary differences from other Sega 8-bit consoles: 14 | 15 | - Has an expansion port for the "FM Sound Unit" or keyboard. 16 | But not pin compatible with the SMS/SMSJ expansion port. 17 | - No RESET button. 18 | - No support for SC-3000H BASIC cartridges with extra RAM. 19 | - No support for lightguns in the controller port. 20 | - No TH pin on the controller port. 21 | - No output pins available on the controller port. 22 | 23 | ---------------------------------------------------------------------------- 24 | Parts list 25 | ---------------------------------------------------------------------------- 26 | 27 | Part Description Package Comments 28 | 29 | IC1 : NEC uPD780C-1 40-pin DIP Z80-A CPU. 4.00 MHz speed rating. 30 | IC2 : NEC uPD4168C-15 28-pin DIP 8Kx8 PSRAM. 150 ns speed rating. 31 | IC3 : Sega 315-5124 64-pin SDIP Custom component. 32 | IC4 : NEC uPD4168C-15 28-pin DIP 8Kx8 PSRAM. 150 ns speed rating. 33 | IC5 : NEC uPD4168C-15 28-pin DIP 8Kx8 PSRAM. 150 ns speed rating. 34 | IC6 : ROHM BA7230LS 24-pin SZIP Color TV signal encoder. 35 | IC7 : NEC 7805 TO-220 Voltage regulator. 36 | IC8 : Fujitsu MB74LS257 16-pin DIP Quad 2-to-1 multiplexer w/ output enable. 37 | IC9 : Fujitsu MB74LS257 16-pin DIP Quad 2-to-1 multiplexer w/ output enable. 38 | IC10 : Fujitsu MB74LS32 14-pin DIP Quad positive OR gate. 39 | 40 | ---------------------------------------------------------------------------- 41 | Miscellaneous 42 | ---------------------------------------------------------------------------- 43 | 44 | Timing 45 | 46 | The VDP is connected to a 10.7386 MHz crystal. It divides this by three 47 | to generate the 3.579545 MHz clock signal used for: 48 | 49 | - The Z80 CPU clock 50 | - The PSG clock (internal to the VDP) 51 | - The color burst clock input (Vc) of the BA7230LS 52 | 53 | Sega PCB numbers 54 | 55 | 171-5304 : Main PCB 56 | 171-5305 : Card slot PCB 57 | 58 | System configuration 59 | 60 | The VDP PAL//NTSC pin is tied to ground via J2 to select NTSC mode. 61 | J2 can be moved up to the empty position above it to connect the pin to 62 | +5V for PAL mode, or these points could be wired to a switch. 63 | 64 | System compatibility 65 | 66 | SMS/SMSJ software 67 | 68 | The unused inputs would appear as follows to the software: 69 | 70 | Port 1 TH pin (D7): HIGH 71 | Port 2 TH pin (D6): HIGH 72 | Unused input (D5): HIGH ('1' on SMS/SMSJ/GG/MK3, '0' on PBC) 73 | Reset input (D4): HIGH (Reset button not pressed) 74 | 75 | As D7,D6 are always '1', the territory detection routine would interpret 76 | the machine as being a Mark-III or Japanese SMS console. 77 | 78 | ---------------------------------------------------------------------------- 79 | Connectors 80 | ---------------------------------------------------------------------------- 81 | CN1 : Gamepad connector for 1P (Male DB-9) 82 | CN2 : Gamepad connector for 2P (Male DB-9) 83 | 84 | 1 : Up 85 | 2 : Down 86 | 3 : Left 87 | 4 : Right 88 | 5 : +5V 89 | 6 : Button 1 90 | 7 : Ground 91 | 8 : Ground 92 | 9 : Button 2 93 | 94 | CN3 : Cartridge connector (card edge socket) 95 | 96 | Solder side 97 | 98 | A01 : Z80 A0 99 | A02 : Z80 A1 100 | A03 : Z80 A2 101 | A04 : Z80 A3 102 | A05 : Z80 A4 103 | A06 : Z80 A5 104 | A07 : Z80 A6 105 | A08 : Z80 A7 106 | A09 : Z80 A8 107 | A10 : Z80 A9 108 | A11 : Z80 A10 109 | A12 : Z80 A11 110 | A13 : Z80 A12 111 | A14 : Z80 A13 112 | A15 : Z80 D0 113 | A16 : Z80 D1 114 | A17 : Z80 D2 115 | A18 : Z80 D3 116 | A19 : Z80 D4 117 | A20 : Z80 D5 118 | A21 : Z80 D6 119 | A22 : Z80 D7 120 | 121 | Component side 122 | 123 | B01 : +5V 124 | B02 : Card slot enable (*1) 125 | B03 : Work RAM enable (*2) 126 | B04 : VDP /EXM1 127 | B05 : Z80 /RD (SC-3000H: /MREQ+/RD, strobe for reads from memory) 128 | B06 : Z80 /WR (SC-3000H: /MREQ+/WR, strobe for writes to memory) 129 | B07 : (N.C.) (SC-3000H: /IORQ+/RD, strobe for reads from I/O ports) 130 | B08 : (N.C.) (SC-3000H: /IORQ+/WR, strobe for writes to I/O ports) 131 | B09 : (N.C.) 132 | B10 : Z80 /MREQ 133 | B11 : /CONT input 134 | B12 : (N.C.) (SC-3000H: /RAS0) 135 | B13 : (N.C.) (SC-3000H: /CAS0) 136 | B14 : (N.C.) (SC-3000H: CA7) 137 | B15 : (N.C.) (SC-3000H: /RAS1) 138 | B16 : (N.C.) (SC-3000H: /CAS1) 139 | B17 : (N.C.) (SC-3000H: /RCSEL) 140 | B18 : Z80 A14 141 | B19 : VDP /EXM2 (SC-3000H: Z80 A15) 142 | B20 : (N.C.) (SMS/SMSJ: Z80 /M1) 143 | B21 : GND 144 | B22 : GND 145 | 146 | Note that many pins are unused or simplified versions of their counterparts 147 | in the SC-3000H. BASIC cartridges with DRAM cannot be used on the Mark-III 148 | as all the necessary refresh signals are missing. 149 | 150 | 1.) Card slot enable 151 | 152 | Cartridges should have pin 2 tied high to disable the /CS output to the 153 | card slot. Otherwise pin 2 has a pull-down resistor, and when tied low 154 | or left unconnected the card slot will be enabled. 155 | 156 | 2.) Work RAM enable 157 | 158 | Cartridges with extra RAM in the $C000-$FFFF range should have pin 3 tied 159 | high to disable the /CS output to the work RAM in the Mark-III. Otherwise 160 | pin 3 has a pull-down resistor, and when tied low or left unconnected the 161 | work RAM will be enabled. 162 | 163 | If the mapper in a cartridge supports mapping battery backed RAM to 164 | the $C000-$FFFF area, it will have a connection to this pin. 165 | 166 | CN4 : Card slot PCB connectors (two 18-pin ribbon cables) 167 | 168 | No information. 169 | 170 | CN5 : External keyboard connector (single sided card edge) 171 | 172 | 1 : +5V 173 | 2 : +5V 174 | 3 : Input ports enable (*1) 175 | 4 : Z80 A0 176 | 5 : Z80 A1 177 | 6 : Z80 D0 178 | 7 : Z80 D1 179 | 8 : Z80 D2 180 | 9 : Z80 D3 181 | 10 : Z80 D4 182 | 11 : Z80 D5 183 | 12 : Z80 D6 184 | 13 : Z80 D7 185 | 14 : VDP /KBSEL 186 | 15 : Z80 /RD 187 | 16 : Z80 /WR 188 | 17 : (KEY) 189 | 18 : /CONT (same signal as cartridge pin B11) 190 | 19 : Z80 /IORQ 191 | 20 : (N.C.) To test point on reverse side. 192 | 21 : Z80 A2 193 | 22 : GND 194 | 23 : GND 195 | 24 : GND 196 | 25 : GND 197 | 198 | 1.) Input ports enable 199 | 200 | When pin 3 is tied high the input port circuit in the Mark-III is disabled, 201 | freeing up I/O port range $C0-$FF for use by a device on the keyboard 202 | connector. Otherwise pin 3 has a pull-down resistor, and when tied low 203 | or left unconnected the input ports will be enabled. 204 | 205 | CN6 : Audio and video connector (8-pin DIN) 206 | 207 | Pin connections from the solder side. 208 | 209 | 1 2 3 210 | 4 5 211 | 6 7 8 212 | 213 | 1 : Composite video 214 | 2 : Ground 215 | 3 : Monoaural audio 216 | 4 : Green video output 217 | 5 : +5V 218 | 6 : Composite sync output 219 | 7 : Blue video output 220 | 8 : Red video output 221 | 222 | The RGB and composite sync outputs come directly from the VDP and are 223 | not amplified or buffered. They may not be sufficient to drive a RGB 224 | monitor. 225 | 226 | CN7 : DC power jack 227 | 228 | Tip = Ground 229 | Ring = +9V DC @ 850mA 230 | 231 | ---------------------------------------------------------------------------- 232 | I/O hardware 233 | ---------------------------------------------------------------------------- 234 | 235 | There is no I/O chip such as the 8255 used in the SC-3000H or the custom 236 | I/O chip found in the SMS/SMSJ. Several TTL components (74LS32, 74LS257) 237 | are used to implement the input ports. 238 | 239 | When the I/O ports are enabled, there are two read-only addresses 240 | selected by Z80 A0. Commonly accessed offsets are $C0,$C1 or $DC,$DD. 241 | 242 | Offset 0 ($C0/$DC) 243 | 244 | D7 : 2P down 245 | D6 : 2P up 246 | D5 : 1P button 2 247 | D4 : 1P button 1 248 | D3 : 1P right 249 | D2 : 1P left 250 | D1 : 1P down 251 | D0 : 1P up 252 | 253 | Offset 1 ($C1/$DD) 254 | 255 | D7 : Unconnected 256 | D6 : Unconnected 257 | D5 : Unconnected 258 | D4 : /CONT pin state 259 | D3 : 2P button 2 260 | D2 : 2P button 1 261 | D1 : 2P right 262 | D0 : 2P left 263 | 264 | The gamepad inputs read '1' when a button or direction is not pressed, 265 | or when a gamepad is not connected. 266 | 267 | Unconnected inputs of 74LS-series chips tend to float high. For this 268 | reason D7, D6, D5 all return '1' when read, but have no pull-up resistors. 269 | 270 | If the /CONT pin is not connected to anything (either at cartridge pin B11 271 | or keyboard connector pin 18) it will return '1' as well. 272 | 273 | ---------------------------------------------------------------------------- 274 | Color TV signal encoder 275 | ---------------------------------------------------------------------------- 276 | 277 | The Mark-III uses a Rohm BA7230LS NTSC color TV signal encoder chip. 278 | It has several capabilities: 279 | 280 | - Conversion of analog RGB video to component (R-Y,B-Y,Y) video. 281 | 282 | - Conversion of component video to composite video. 283 | 284 | - Dynamic selection between component video input and a composite 285 | video input for purposes of superimposition. The composite video 286 | source can also be darkened to bring attention to the component video. 287 | 288 | In the Mark-III, the RGB output of the VDP is converted to component 289 | video, then the component video is fed back into the chip and converted 290 | to composite video. The superimpose function is not used. 291 | 292 | The VDP seems to be developed for this particular chip in mind, as it 293 | provides the color burst pulses (/CBT) and pedestal clamping pulses (/PCP) 294 | specific to the BA7230LS. 295 | 296 | ---------------------------------------------------------------------------- 297 | 315-5124 298 | ---------------------------------------------------------------------------- 299 | 300 | Pin assignments 301 | 302 | +----v----+ 303 | Z80 D0 |01 b o 64| Z80 /INT 304 | Z80 D1 |02 b i 63| Z80 A7 305 | Z80 D2 |03 b i 62| Z80 A6 306 | Z80 D3 |04 b i 61| Z80 A0 307 | Z80 D4 |05 b i 60| Z80 /IORQ 308 | Z80 D5 |06 b i 59| Z80 /WR 309 | Z80 D6 |07 b i 58| Z80 /RD 310 | Z80 D7 |08 b i 57| PAL//NTSC 311 | GND |09 s b 56| VRAM AD15 312 | AUDIO |10 o b 55| VRAM AD14 313 | +5V |11 s b 54| VRAM AD13 314 | T0 |12 o b 53| VRAM AD12 315 | T1 |13 o b 52| VRAM AD11 316 | /KBSEL |14 o b 51| VRAM AD10 317 | /CSRAM |15 o b 50| VRAM AD9 318 | /EXM1 |16 o b 49| VRAM AD8 319 | /EXM2 |17 o b 48| VRAM AD7 320 | Z80 A14 |18 i b 47| VRAM AD6 321 | Z80 A15 |19 i b 46| VRAM AD5 322 | Z80 /MREQ |20 i b 45| VRAM AD4 323 | Z80 /NMI |21 o b 44| VRAM AD3 324 | /NMI-IN |22 i b 43| VRAM AD2 325 | Z80 /RST |23 i b 42| VRAM AD1 326 | /CBT |24 o b 41| VRAM AD0 327 | /PCP |25 o s 40| +5V 328 | R-VIDEO |26 o o 39| VRAM /CE 329 | G-VIDEO |27 o o 38| VRAM /WE1 330 | B-VIDEO |28 o o 37| VRAM /WE0 331 | /C-SYNC |29 o o 36| VRAM /OE 332 | XTAL1 |30 i i 35| /H-L 333 | XTAL2 |31 o o 34| Z80 /CLK output 334 | GND |32 s o 33| Y1 335 | +---------+ 336 | 337 | Legend 338 | 339 | s = Power supply 340 | b = Bidirectional 341 | i = Input 342 | o = Output 343 | 344 | Unused pins 345 | 346 | /H-L is not used and is connected to a test point. 347 | Y1 is not used and is connected to a test point. 348 | 349 | Pin description 350 | 351 | T0 352 | /T1 353 | 354 | Related to /CSYNC. Has 1 mclk wide pulses on each scanline except for 355 | the the ones occupied by the /VSYNC pulse. 356 | 357 | T0 has positive pulses and has a range of about 0-1.90V 358 | /T1 has negative pulses and has a range of about 0-.45V 359 | 360 | /KBSEL 361 | 362 | Strobe for read/write access to I/O ports $C0-$FF. 363 | Asserted when A7, A6 are high, IORQ low. 364 | 365 | /CSRAM 366 | 367 | Strobe for read/write access to memory range $C000-$FFFF. 368 | Asserted when A15, A14 high, MREQ low. 369 | 370 | /EXM1 371 | 372 | Strobe for read/write access to memory range $8000-$BFFF. 373 | Asserted when A15 high, A14 and MREQ low. 374 | 375 | /EXM2 376 | 377 | Strobe for read/write access to memory range $0000-$7FFF. 378 | Asserted when A15 and MREQ low. 379 | 380 | /NMI-IN 381 | 382 | Input to the VDP's debouncing logic for the pause button. 383 | 384 | Z80 /NMI 385 | 386 | At the start of scanline 261, /NMI will be asserted if the pause button 387 | had been pressed, or negated if the pause button has been released. 388 | 389 | /CBT (Color burst pulse) 390 | 391 | Asserted to indicate the position on a scanline where the color burst 392 | signal should be inserted into the composite video output. This connects 393 | to the /BFP (burst flag pulse) pin on the BA7230LS. 394 | 395 | Asserted 615 mclks into the scanline relative from pixel 0. 396 | Pulse width is 28 mclks. Not asserted on scanlines 215 through 235. 397 | 398 | /PCP (Pedestal clamp pulse) 399 | 400 | Asserted 623 mclks into the scanline relative from pixel 0. 401 | Pulse width is 28 mclks. Not asserted on scanlines 215 through 235. 402 | 403 | R-VIDEO 404 | G-VIDEO 405 | B-VIDEO 406 | 407 | Analog red, green, and blue video outputs. 408 | 409 | XTAL1 410 | XTAL2 411 | 412 | Input and output for a connection to a 10.7368 MHz oscillator. 413 | 414 | Y1 415 | 416 | Goes low when outputting transparent pixels in the active display period, 417 | and high for everything else: scanline border area, blanked lines, 418 | blanked lines due to the screen being turned off, and the left 8 pixels 419 | when left column blanking is enabled. 420 | 421 | Not used in the Mark-III. 422 | 423 | /H-L 424 | 425 | The Z80 samples the horizontal counter through a transparent latch. This 426 | signal latches the counter when held low, and passes the counter value 427 | through when held high. 428 | 429 | Not used in the Mark-III. 430 | 431 | Z80 /CLK 432 | 433 | Used by the Z80 and BA7230LS. 434 | 435 | ---------------------------------------------------------------------------- 436 | End 437 | ---------------------------------------------------------------------------- 438 | -------------------------------------------------------------------------------- /Docs/S8-differences.txt: -------------------------------------------------------------------------------- 1 | S8 differences 2 | -------------- 3 | 4 | This document is meant to describe all the differences of the different 5 | Sega 8-bit consoles (From the SG-1000 to the MegaDrive with a PBC). 6 | 7 | Chips: 8 | ------------------------------------------------------------------------------- 9 | SG-1000 M2: 10 | TMM2009P-B (8255PPI?) 11 | 12 | CPU: 13 | ------------------------------------------------------------------------------- 14 | SMS1, SMS2 & MD. 15 | The Z80 in the SMS has some registers initialized to 0xFF, supposedly NMOS. 16 | The opcode "OUT (c),0" (0xED71) outputs 0x00 to the IO port pointed to by the c reg. 17 | 18 | Mark III. 19 | NEC 20 | �PD780-1 21 | 22 | SMS. 23 | Zilog 24 | Z0840004PSC 25 | Z80 CPU 26 | 8829 SL0965 27 | (Tested by me) 28 | Register startup values. 29 | SP: $ 30 | IR: $ 31 | AF: $ 32 | BC: $ 33 | DE: $ 34 | HL: $ 35 | IX: $FFFF - $FFFF - $FFFF 36 | IY: $FFFF - $FFFF - $FFFF 37 | AF': $FFFF - $FFFF - $FFFF 38 | BC': $ 39 | DE': $ 40 | HL': $ 41 | 42 | SMS2. 43 | Zilog 44 | Z0840004PSC 45 | SL0965 46 | Z80 CPU 47 | 9228 2A 48 | (Tested by jpx072) 49 | Register startup values. 50 | SP: $FFFF - $FFFF - $FFFF 51 | IR: $0019 - $0019 - $0019 52 | AF: $FFFF - $FFFF - $FFFF 53 | BC: $BDBF - $BDBF - $BDBD 54 | DE: $FFFF - $FFED - $FFFF 55 | HL: $FFFF - $FFFF - $FFFF 56 | IX: $BDFF - $BDBF - $BDFF 57 | IY: $FFBD - $FFBD - $FFBD 58 | AF': $FFFF - $FFFF - $FFBF 59 | BC': $BFBD - $BFBD - $BDBF 60 | DE': $FFFF - $FFEF - $FFFF 61 | HL': $FFFF - $BFBF - $FFFD 62 | Actual R value would be 2 (0 before ld a,r). 63 | 64 | MD. 65 | Zilog 66 | Z0840004PSC 67 | SL0965 68 | Z80 CPU 69 | 9210 7Z 70 | (Tested by me on my MD1 PAL-G with PBC) 71 | Register startup values. 72 | SP: $DFFF - $DFFF - $DFFF 73 | IR: $001D - $001D - $001D 74 | AF: $FFA3 - $FFA3 - $FFA3 75 | BC: $FFFF - $FFFF - $FFFF 76 | DE: $FFFF - $FFFF - $FFFF 77 | HL: $E001 - $E001 - $E001 78 | IX: $FFFF - $FFFF - $FFFF 79 | IY: $FFFF - $FFFF - $FFFF 80 | AF': $FFFF - $FFFF - $FFFF 81 | BC': $FFFF - $FFFF - $FFFF 82 | DE': $FFFF - $FFFF - $FFFF 83 | HL': $FFFF - $FDFF - $FFFD 84 | Actual R value is 6 (4 before ld a,r). 85 | 86 | GG. 87 | The Z80 in the GG has all (most?) registers initialized to 0x00, supposedly CMOS. 88 | The opcode "OUT (c),0" (0xED71) outputs 0xFF to the IO port pointed to by the c reg. 89 | (Tested by Charles McDonald) 90 | Register startup values. 91 | SP: $0000 - $0000 - $0000 92 | IR: $0000 - $0000 - $0000 93 | AF: $0000 - $0000 - $0000 94 | BC: $0000 - $0000 - $0000 95 | DE: $0000 - $0000 - $0000 96 | HL: $0000 - $0000 - $0000 97 | IX: $0000 - $0000 - $0000 98 | IY: $0000 - $0000 - $0000 99 | AF': $0000 - $0000 - $0000 100 | BC': $0000 - $0000 - $0000 101 | DE': $0000 - $0000 - $0000 102 | HL': $0000 - $0000 - $0000 103 | 104 | 105 | Video: 106 | ------------------------------------------------------------------------------- 107 | SG-1000, SC-3000, OMV. 108 | - Mode0, Mode1, Mode2, Mode3. 109 | - 4 sprites per scanline. 110 | - Sprites can be zoomed using bit 0 of register #1 111 | - Doesn't have linecounter/irq. 112 | - Both code values of 2 & 3 makes a register write. 113 | - All accesses after a VDP_CTRL write go to the VRAM as it doesn't have CRAM. 114 | - Data written to the data port is also copied to the VRAM read buffer. 115 | - Address lines are swaped with bit 7 of reg1. 116 | 8/16k 4k 117 | A0 A0 118 | A1 A1 119 | A2 A2 120 | A3 A3 121 | A4 A4 122 | A5 A5 123 | A6 A12 124 | A7 A6 125 | A8 A7 126 | A9 A8 127 | A10 A9 128 | A11 A10 129 | A12 A11 130 | A13 A13 131 | 132 | Mark III, SMS1. 133 | - Mode0, Mode1, Mode2, Mode3, Mode4. 134 | - 8 sprites per scanline. 135 | - Only the first 4 sprites can be fully zoomed using bit 0 of register #1, 136 | the rest are only zoomed vertically. 137 | - Bit 0 of register #2 acts as a mask for the tilemap adress. 138 | - VDP Address is updated on first 8bit write. 139 | - Sprite collision flag is set on the pixel it happens. 140 | 141 | SMS2. 142 | - Mode0, Mode1, Mode2, Mode3, Mode4, Mode4 V224, Mode4 V240. 143 | - 8 sprites per scanline. 144 | 145 | GG. 146 | - Mode0, Mode1, Mode2, Mode3, Mode4, Mode4 V224, Mode4 V240. 147 | - 8 sprites per scanline. 148 | - The GG has the TMS9918 modes but doesn't switch to a hardcoded palette 149 | instead uses the normal palette that is usercontrolled. 150 | 151 | MD. 152 | - Mode4, Mode5. 153 | - 8 sprites per scanline in mode 4. 154 | - Bit 2 of register #1 enables mode 5 when set and mode 4 when clear. 155 | - None of the TMS9918 modes are available, nor are the extended resolutions of 156 | the SMS 2 and GG VDP. 157 | - When the TMS9918 modes are selected, the display is always blanked and 158 | is colored black. The M1, M2 and M3 bits have no effect. 159 | - When the first byte of the command word is written, it is latched and the 160 | LSB of the address register is not updated until the second byte is written. 161 | - When the data port is written to, the read buffer is not updated. 162 | It is only updated when the data port is read. 163 | - When writing to the data port, data will go to CRAM if bit 1 of the code 164 | register is set. For the other VDP types the code register must be set to 165 | $03 to access CRAM. 166 | - Sprites cannot be zoomed using bit 0 of register #1, this bit does nothing. 167 | - The tilemap adress mask bit is not available from the SMS1. 168 | - Sprite collision flag is set in the border? 169 | - VCount start value is 0x14... 170 | - HCount start value is 0x47... (0x5f-(0x21*3/4))=0x47, (382 - 99 = 283). 171 | - HCount latch is 0x00 before any value is latched. 172 | 173 | 174 | Mode5 specifics: 175 | - In mode5 there are 2 flags for vdp writes as it now uses 32bit command words. 176 | 177 | - Reg $0F handles VRAM access autoincrement, when first switching from mode4 178 | to mode5 it's set to 0 (representing 1 for mode4), if set to 1 and switched 179 | back mode4 it now increases 2 for every VRAM access. 180 | 181 | - After setting address in mode5 you can not set a new address until you have 182 | read from or written to the VRAM, new writes set vdp regs? 183 | 184 | - In mode 4 VRAM is filled with 0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00 repeated. 185 | - In mode 5 VRAM is filled with 186 | 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00 repeated. 187 | - Address lines are swaped between mode4 & mode5. 188 | Mode4 Mode5 189 | A0 A0 190 | A1 A2 191 | A2 A3 192 | A3 A4 193 | A4 A5 194 | A5 A6 195 | A6 A7 196 | A7 A8 197 | A8 A9 198 | A9 A1 199 | A10 A10 200 | A11 A11 201 | A12 A12 202 | A13 A13 203 | - A14 204 | - A15 205 | 206 | 207 | - Writing to the palette in mode 4, bits 0-2 affect the Red bits of the MD palette 208 | & bits 3-5 affect the the Green bits of the MD palette, bit 6 & 7 has no effect. 209 | mode4-$01 -> mode5-$0002 210 | mode4-$02 -> mode5-$0004 211 | mode4-$04 -> mode5-$0008 212 | mode4-$08 -> mode5-$0020 213 | mode4-$10 -> mode5-$0040 214 | mode4-$20 -> mode5-$0080 215 | 216 | IO Ports: 217 | ------------------------------------------------------------------------------- 218 | SG-1000. 219 | 220 | SC-3000. 221 | 222 | Mark III. 223 | - IO port $3F (IO control) doesn't exist. 224 | 225 | SMS1. 226 | - IO ports $00-$3F return the last byte of the instruction that read the port. 227 | - On cold boot WRAM is ????. 228 | - Disabling RAM makes it return the last byte of the instruction that read the port. 229 | 230 | SMS2. 231 | - IO ports $00-$3F return 0xFF? 232 | - On cold boot WRAM is (allmost entirely) filled with 256*0xFF, 256*0x00 repeated. 233 | Also a repeating pattern is at 0xCA00, 0xCE00, 0xDA00, 0xDE00 and is 0x200 long. 234 | 0xEA 0x16 0xB1 0x08 0x9F 0x0C 0x0D 0xFF. Bios writes this? 235 | - Disabling RAM makes it return 0x7E for all addresses. 236 | 237 | GG in SMS mode. 238 | - The GG can't disable the IO ports? 239 | - IO ports $07-$3F return 0xFF? 240 | - On cold boot WRAM is ????. 241 | 242 | GG. 243 | - The GG can't disable the IO ports? 244 | - IO ports $07-$3F return 0xFF? 245 | - On cold boot WRAM is ????. 246 | 247 | MD. 248 | - Can not (de)select cart/card/exp/bios/IO, only ram? 249 | - IO ports $00-$3F return 0xFF? 250 | - Bit 5 of Port B ($DD) is 0 instead of 1. 251 | - On cold boot WRAM is (allmost entirely) filled with 32*0x00, 32*0xFF repeated. 252 | Addresses 0xXXFD isn't 0xFF but some random number, except 0xCFFD which is 0x00. 253 | Also address 0xDFFC is 0x08 and address 0xDFFF is 0x06. 254 | - Disabling RAM makes it return 0xFF for all addresses? 255 | 256 | 257 | 258 | 259 | 260 | 261 | How to check which HW we're running on: 262 | ------------------------------------------------------------------------------- 263 | 264 | SG-1000. 265 | Try to write to the palette and see if we can read back the same values 266 | from VRAM. 267 | 268 | SG-1000/SC-3000. 269 | Check RAM size, 1k for SG-1000 and 2k for SC-3000/Othello Multivision. 270 | 271 | SMS1/SMS2. 272 | Read a port in the range $00-$3F. 273 | Returns the last byte of the instruction which read the port on SMS1. 274 | Returns $FF on SMS2. 275 | 276 | GG. 277 | Use OUT (C),0 to write to VRAM and see if it writes $00 or $FF. 278 | 279 | MD. 280 | Check bit 5 of IO reg $DD. 281 | 282 | 283 | 284 | 285 | ------------------------------------------------------------------------------- 286 | 287 | static ADDRESS_MAP_START( megatech_bios_map, AS_PROGRAM, 8, mtech_state ) 288 | AM_RANGE(0x0000, 0x2fff) AM_ROM // from bios rom (0x0000-0x2fff populated in ROM) 289 | AM_RANGE(0x3000, 0x3fff) AM_READWRITE(banked_ram_r, banked_ram_w) // copies instruction data here at startup, must be banked 290 | AM_RANGE(0x4000, 0x5fff) AM_RAM // plain ram? 291 | AM_RANGE(0x6000, 0x6000) AM_WRITE(mt_z80_bank_w ) 292 | AM_RANGE(0x6400, 0x6400) AM_READ_PORT("BIOS_DSW0") 293 | AM_RANGE(0x6401, 0x6401) AM_READ_PORT("BIOS_DSW1") 294 | AM_RANGE(0x6404, 0x6404) AM_READWRITE(cart_select_r, cart_select_w) // cart select & ram bank 295 | AM_RANGE(0x6800, 0x6800) AM_READ_PORT("BIOS_IN0") 296 | AM_RANGE(0x6801, 0x6801) AM_READ_PORT("BIOS_IN1") 297 | AM_RANGE(0x6802, 0x6807) AM_READWRITE(bios_ctrl_r, bios_ctrl_w) 298 | // AM_RANGE(0x6805, 0x6805) AM_READ_PORT("???") 299 | AM_RANGE(0x7000, 0x77ff) AM_ROM // from bios rom (0x7000-0x77ff populated in ROM) 300 | //AM_RANGE(0x7800, 0x7fff) AM_RAM // ? 301 | AM_RANGE(0x8000, 0x9fff) AM_READWRITE(read_68k_banked_data, write_68k_banked_data) // window into 68k address space, reads instr rom and writes to reset banks on z80 carts? 302 | ADDRESS_MAP_END 303 | 304 | 305 | 306 | static ADDRESS_MAP_START( megatech_bios_portmap, AS_IO, 8, mtech_state ) 307 | ADDRESS_MAP_GLOBAL_MASK(0xff) 308 | AM_RANGE(0x3f, 0x3f) AM_WRITE(bios_port_ctrl_w) 309 | AM_RANGE(0x7f, 0x7f) AM_WRITE(bios_port_7f_w) 310 | 311 | AM_RANGE(0x40, 0x41) AM_MIRROR(0x3e) AM_READ(vdp1_count_r) 312 | AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("vdp1", sega315_5124_device, vram_read, vram_write) 313 | AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("vdp1", sega315_5124_device, register_read, register_write) 314 | 315 | AM_RANGE(0xdc, 0xdd) AM_READ(bios_joypad_r) // player inputs 316 | ADDRESS_MAP_END 317 | 318 | ------------------------------------------------------------------------------- 319 | 320 | static ADDRESS_MAP_START( megaplay_bios_map, AS_PROGRAM, 8, mplay_state ) 321 | AM_RANGE(0x0000, 0x3fff) AM_ROM 322 | AM_RANGE(0x4000, 0x4fff) AM_RAM 323 | AM_RANGE(0x5000, 0x5fff) AM_RAM 324 | AM_RANGE(0x6000, 0x6000) AM_WRITE(game_w) 325 | AM_RANGE(0x6200, 0x6200) AM_READ_PORT("DSW0") 326 | AM_RANGE(0x6201, 0x6201) AM_READ_PORT("DSW1") 327 | AM_RANGE(0x6203, 0x6203) AM_READWRITE(bios_banksel_r, bios_banksel_w) 328 | AM_RANGE(0x6204, 0x6204) AM_READWRITE(bios_6204_r, bios_width_w) 329 | AM_RANGE(0x6400, 0x6400) AM_READ_PORT("TEST") 330 | AM_RANGE(0x6401, 0x6401) AM_READ_PORT("COIN") 331 | AM_RANGE(0x6402, 0x6402) AM_READWRITE(bios_6402_r, bios_6402_w) 332 | AM_RANGE(0x6403, 0x6403) AM_READWRITE(bios_gamesel_r, bios_gamesel_w) 333 | AM_RANGE(0x6404, 0x6404) AM_READWRITE(bios_6404_r, bios_6404_w) 334 | AM_RANGE(0x6600, 0x6600) AM_READWRITE(bios_6600_r, bios_6600_w) 335 | AM_RANGE(0x6001, 0x67ff) AM_WRITEONLY 336 | AM_RANGE(0x6800, 0x77ff) AM_RAM AM_SHARE("ic3_ram") 337 | AM_RANGE(0x8000, 0xffff) AM_READWRITE(bank_r, bank_w) 338 | ADDRESS_MAP_END 339 | 340 | 341 | 342 | static ADDRESS_MAP_START( megaplay_bios_io_map, AS_IO, 8, mplay_state ) 343 | ADDRESS_MAP_GLOBAL_MASK(0xff) 344 | AM_RANGE(0x7f, 0x7f) AM_DEVWRITE("sn2", sn76496_device, write) 345 | AM_RANGE(0x40, 0x41) AM_MIRROR(0x3e) AM_READ(vdp1_count_r) 346 | AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("vdp1", sega315_5124_device, vram_read, vram_write) 347 | AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("vdp1", sega315_5124_device, register_read, register_write) 348 | ADDRESS_MAP_END 349 | 350 | -------------------------------------------------------------------------------- /Docs/Sord M5.txt: -------------------------------------------------------------------------------- 1 | Memory Manage : 2 | 3 | *Memory bank 4 | 5 | 0000h-5FFFh (ROM Area) 6 | 6000h-6FFFh (Reserved) 7 | 7000h-FFFFh (RAM Area) 8 | 9 | *Detailed Memory map 10 | 11 | 0000h - 1FFFh : M5 MONITOR (Internal ROM 8KB) 12 | 2000h - 5FFFh : External ROM Cartride (MAX 16KB) 13 | 6000h - 6FFFh : Reserved Area 14 | 7000h - 7FFFh : Internal RAM (4KB) 15 | 8000h - FFFFh : External RAM Cartride (MAX 8KB) or 32K Expand Box (MAX 32KB) 16 | 17 | 18 | 2) I/O Ports 19 | 20 | *Z80CTC 21 | 00h : Channel #0: SIO Int. 22 | 01h : Channel #1: Peripheral Timer 23 | 02h : Channel #2: SIO Clock Generator 24 | 03h : Channel #3: VDP Blanking(Frame) Interrupt 25 | 26 | *VDP TMS9918A 27 | 10h : Data port 28 | 11h : Control port 29 | 30 | *Sound Generator SN76489AN 31 | 20h : Data write 32 | 33 | *Keyboard 34 | 30h : row#0 35 | 31h : row#1 + Joypad buttons 36 | 32h : row#2 37 | 33h : row#3 38 | 34h : row#4 39 | 35h : row#5 40 | 36h : row#6 41 | 37h : Joypad Direction Input 42 | 43 | *Parallel Out 44 | 40h : DATA 45 | 50h : STROBE(Bit 0) 46 | 50h : BUSY(Bit 1) 47 | 48 | *Cassette tape recorder 49 | 50h : Output port(Bit 0) 50 | 50h : Input port(Bit 0) 51 | 50h : Remote port(Bit 1) (motor?) 52 | *RESET/HALT Key 53 | 50h : Reset/Halt Key data port(Bit 7) 54 | 55 | 60h : EXIOA 56 | 57 | 70h : EXIOB 58 | 59 | -------------------------------------------------------------------------------- /Docs/sg1000a.c: -------------------------------------------------------------------------------- 1 | // license:LGPL-2.1+ 2 | // copyright-holders:Tomasz Slanina 3 | /********************************************************* 4 | Sega hardware based on their SG-1000 console 5 | Driver by Tomasz Slanina analog [at] op.pl 6 | 7 | 8 | Supported games : 9 | - Champion Boxing 10 | - Champion Pro Wrestling 11 | - Doki Doki Penguin Land 12 | 13 | Memory map : 14 | 0x0000 - 0xBFFF ROM 15 | 0xC000 - 0xC3FF RAM 16 | 17 | CPU: 18 | Z80 A 3.57954 MHz (Champion Boxing) 19 | 315-5114 (encrypted Z80) 3.57954 MHz (Champion Pro Wrestling) 20 | 21 | 8255 for I/O port work 22 | 3 Eproms for program and graphics 23 | TMM2064 for program RAM 24 | TMS9928 for graphics ( 3.57954 MHz? ) 25 | 8 8118 dynamic RAMs for the graphics 26 | 74LS139 and 74LS32 for logic gating 27 | ULN2003 for coin counter output 28 | 76489 for music 29 | 7808 voltage regulator to a transistorized circuit for TV output 30 | secondary crystal, numbers unknown for the TMS9928 31 | 32 | -- 33 | 34 | Doki Doki Penguin Land 35 | Sega, 1985 36 | 37 | PCB Layout 38 | ---------- 39 | 40 | 834-5492 41 | |---------------------------------------------| 42 | | CN3 CN2 CN4 | 43 | | DSW(4) | 44 | |3.579545MHz TD62003 | 45 | | 74HC04 8255 SN76489 | 46 | | CN5 | 47 | | VR5 | 48 | | 6116 Z80A | 49 | | LA4460 | 50 | | 74LS32 74LS139 | 51 | |EPR-7358.IC3 | 52 | | TMS9928 CN1 | 53 | | | 54 | | 10.7386MHz | 55 | | MB8118 MB8118 | 56 | |EPR-7357.IC2 | 57 | | MB8118 MB8118 | 58 | | 7808 | 59 | | MB8118 MB8118 VR4 | 60 | |EPR7356.IC1 | 61 | | 7805 MB8118 MB8118 VR3 VR2 VR1| 62 | |---------------------------------------------| 63 | Notes: 64 | All IC's shown 65 | CN1/2/3/4/5 - Connectors for power/video/sound/controls 66 | VR1/2/3 - Potentiometers for RGB adjustment 67 | VR4 - Potentiometer for Horizontal Sync adjustment 68 | VR5 - Potentiometer for volume 69 | TMS9928 clock - 2.68465 [10.7386/4] 70 | Z80 clock - 3.579545MHz 71 | VSync - 60Hz 72 | HSync - 15.58kHz 73 | 74 | Doki Doki Penguinland Dip Switches (DIP4) and Pinout 75 | 76 | Option 1 2 3 4 77 | ------------------------------------------ 78 | 1coin 1credit off off 79 | 1c 2cr on off 80 | 1c 3cr off on 81 | 2c 1cr on on 82 | attract sound yes on 83 | no off 84 | not used off 85 | 86 | Hold Service + 1P start = test mode 87 | 88 | 89 | CN1 CN2 CN3 90 | 1 Red 1 Player 1 UP 1 Player 2 UP 91 | 2 Green 2 Player 1 DOWN 2 Player 2 DOWN 92 | 3 Blue 3 Player 1 LEFT 3 Player 2 LEFT 93 | 4 Gnd 4 Player 1 RIGHT 4 Player 2 RIGHT 94 | 5 Sync 5 Player 1 Button B 5 Player 2 Button B 95 | 6 Key 6 Player 1 Button A 6 Player 2 Button A 96 | 7 7 Key 7 Service 97 | 8 Speaker + 8 Player 1 START 8 Coin 98 | 9 Speaker - 9 Player 2 START 9 Key 99 | 10 10 Gnd 10 Gnd 100 | 101 | 102 | CN4 CN5 103 | 1 1 +5V 104 | 2 2 +5V 105 | 3 3 +5V 106 | 4 4 Gnd 107 | 5 Key 5 Gnd 108 | 6 Coin Meter 6 Gnd 109 | 7 7 +12V 110 | 8 8 Key 111 | 9 +5V 9 +12V 112 | 10 Gnd 10 Gnd 113 | 114 | ******************************************************/ 115 | 116 | #include "emu.h" 117 | #include "cpu/z80/z80.h" 118 | #include "sound/sn76496.h" 119 | #include "video/tms9928a.h" 120 | #include "machine/i8255.h" 121 | #include "machine/segacrpt.h" 122 | 123 | 124 | class sg1000a_state : public driver_device 125 | { 126 | public: 127 | sg1000a_state(const machine_config &mconfig, device_type type, const char *tag) 128 | : driver_device(mconfig, type, tag), 129 | m_maincpu(*this, "maincpu") { } 130 | 131 | DECLARE_WRITE_LINE_MEMBER(vdp_interrupt); 132 | DECLARE_WRITE8_MEMBER(sg1000a_coin_counter_w); 133 | DECLARE_DRIVER_INIT(sg1000a); 134 | DECLARE_DRIVER_INIT(chwrestl); 135 | required_device m_maincpu; 136 | }; 137 | 138 | 139 | /************************************* 140 | * 141 | * CPU memory handlers 142 | * 143 | *************************************/ 144 | 145 | static ADDRESS_MAP_START( program_map, AS_PROGRAM, 8, sg1000a_state ) 146 | AM_RANGE(0x0000, 0x7fff) AM_ROM // separate region needed for decrypting 147 | AM_RANGE(0x8000, 0xbfff) AM_ROM 148 | AM_RANGE(0xc000, 0xc3ff) AM_RAM AM_MIRROR(0x400) 149 | ADDRESS_MAP_END 150 | 151 | static ADDRESS_MAP_START( io_map, AS_IO, 8, sg1000a_state ) 152 | ADDRESS_MAP_GLOBAL_MASK(0xff) 153 | AM_RANGE(0x7f, 0x7f) AM_DEVWRITE("snsnd", sn76489_device, write) 154 | AM_RANGE(0xbe, 0xbe) AM_DEVREADWRITE("tms9928a", tms9928a_device, vram_read, vram_write) 155 | AM_RANGE(0xbf, 0xbf) AM_DEVREADWRITE("tms9928a", tms9928a_device, register_read, register_write) 156 | AM_RANGE(0xdc, 0xdf) AM_DEVREADWRITE("ppi8255", i8255_device, read, write) 157 | ADDRESS_MAP_END 158 | 159 | /************************************* 160 | * 161 | * Generic Port definitions 162 | * 163 | *************************************/ 164 | 165 | static INPUT_PORTS_START( sg1000 ) 166 | PORT_START("P1") 167 | PORT_BIT ( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) 168 | PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) 169 | PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) 170 | PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) 171 | PORT_BIT ( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) 172 | PORT_BIT ( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) 173 | PORT_BIT ( 0x40, IP_ACTIVE_LOW, IPT_START1 ) 174 | PORT_BIT ( 0x80, IP_ACTIVE_LOW, IPT_START2 ) 175 | 176 | PORT_START("P2") 177 | PORT_BIT ( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) 178 | PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) 179 | PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) 180 | PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) 181 | PORT_BIT ( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) 182 | PORT_BIT ( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) 183 | PORT_BIT ( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) 184 | PORT_BIT ( 0x80, IP_ACTIVE_LOW, IPT_COIN1 ) 185 | 186 | PORT_START("DSW") 187 | PORT_BIT ( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) 188 | PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coinage ) ) PORT_DIPLOCATION("DSW:1,2") 189 | PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) ) 190 | PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) ) 191 | PORT_DIPSETTING( 0x20, DEF_STR( 1C_2C ) ) 192 | PORT_DIPSETTING( 0x10, DEF_STR( 1C_3C ) ) 193 | PORT_DIPNAME( 0x40, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("DSW:3") 194 | PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) 195 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) 196 | PORT_DIPNAME( 0x80, 0x80, DEF_STR( Language ) ) PORT_DIPLOCATION("DSW:4") 197 | PORT_DIPSETTING( 0x00, DEF_STR( Japanese ) ) 198 | PORT_DIPSETTING( 0x80, DEF_STR( English ) ) 199 | INPUT_PORTS_END 200 | 201 | /************************************* 202 | * 203 | * Port definitions 204 | * 205 | *************************************/ 206 | 207 | static INPUT_PORTS_START( chwrestl ) 208 | PORT_INCLUDE( sg1000 ) 209 | 210 | PORT_MODIFY("P1") 211 | PORT_BIT ( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) 212 | PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) 213 | PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) 214 | PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) 215 | PORT_BIT ( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) 216 | PORT_BIT ( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) 217 | 218 | PORT_MODIFY("P2") 219 | PORT_BIT ( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) 220 | PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) 221 | PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) 222 | PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) 223 | PORT_BIT ( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) 224 | PORT_BIT ( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) 225 | INPUT_PORTS_END 226 | 227 | static INPUT_PORTS_START( chboxing ) 228 | PORT_INCLUDE( sg1000 ) 229 | 230 | PORT_MODIFY("DSW") 231 | PORT_DIPNAME( 0x80, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("DSW:4") 232 | PORT_DIPSETTING( 0x00, DEF_STR( English ) ) 233 | PORT_DIPSETTING( 0x80, DEF_STR( Japanese ) ) 234 | INPUT_PORTS_END 235 | 236 | static INPUT_PORTS_START( dokidoki ) 237 | PORT_INCLUDE( sg1000 ) 238 | 239 | PORT_MODIFY("DSW") 240 | PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unused ) ) PORT_DIPLOCATION("DSW:4") 241 | PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) 242 | PORT_DIPSETTING( 0x00, DEF_STR( On ) ) 243 | INPUT_PORTS_END 244 | 245 | WRITE_LINE_MEMBER(sg1000a_state::vdp_interrupt) 246 | { 247 | m_maincpu->set_input_line(INPUT_LINE_IRQ0, state); 248 | } 249 | 250 | WRITE8_MEMBER(sg1000a_state::sg1000a_coin_counter_w) 251 | { 252 | coin_counter_w(machine(), 0, data & 0x01); 253 | } 254 | 255 | /************************************* 256 | * 257 | * Machine drivers 258 | * 259 | *************************************/ 260 | 261 | static MACHINE_CONFIG_START( sg1000a, sg1000a_state ) 262 | /* basic machine hardware */ 263 | MCFG_CPU_ADD("maincpu", Z80, XTAL_3_579545MHz) 264 | MCFG_CPU_PROGRAM_MAP(program_map) 265 | MCFG_CPU_IO_MAP(io_map) 266 | 267 | MCFG_DEVICE_ADD("ppi8255", I8255, 0) 268 | MCFG_I8255_IN_PORTA_CB(IOPORT("P1")) 269 | MCFG_I8255_IN_PORTB_CB(IOPORT("P2")) 270 | MCFG_I8255_IN_PORTC_CB(IOPORT("DSW")) 271 | MCFG_I8255_OUT_PORTC_CB(WRITE8(sg1000a_state, sg1000a_coin_counter_w)) 272 | 273 | /* video hardware */ 274 | MCFG_DEVICE_ADD( "tms9928a", TMS9928A, XTAL_10_738635MHz / 2 ) 275 | MCFG_TMS9928A_VRAM_SIZE(0x4000) 276 | MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(sg1000a_state, vdp_interrupt)) 277 | 278 | MCFG_TMS9928A_SCREEN_ADD_NTSC( "screen" ) 279 | MCFG_SCREEN_UPDATE_DEVICE( "tms9928a", tms9928a_device, screen_update ) 280 | 281 | /* sound hardware */ 282 | MCFG_SPEAKER_STANDARD_MONO("mono") 283 | 284 | MCFG_SOUND_ADD("snsnd", SN76489, XTAL_3_579545MHz) 285 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) 286 | MACHINE_CONFIG_END 287 | 288 | /************************************* 289 | * 290 | * ROM definitions 291 | * 292 | *************************************/ 293 | 294 | ROM_START( chwrestl ) 295 | ROM_REGION( 2*0x10000, "maincpu", 0 ) 296 | ROM_LOAD( "5732", 0x0000, 0x4000, CRC(a4e44370) SHA1(a9dbf60e77327dd2bec6816f3142b42ad9ca4d09) ) /* encrypted */ 297 | ROM_LOAD( "5733", 0x4000, 0x4000, CRC(4f493538) SHA1(467862fe9337497e3cdebb29bf28f6cfe3066ccd) ) /* encrypted */ 298 | ROM_LOAD( "5734", 0x8000, 0x4000, CRC(d99b6301) SHA1(5e762ed45cde08d5223828c6b1d3569b2240462c) ) 299 | ROM_END 300 | 301 | ROM_START( chboxing ) 302 | ROM_REGION( 0x10000, "maincpu", 0 ) 303 | ROM_LOAD( "cb6105.bin", 0x0000, 0x4000, CRC(43516f2e) SHA1(e3a9bbe914b5bfdcd1f85ca5fae922c4cae3c106) ) 304 | ROM_LOAD( "cb6106.bin", 0x4000, 0x4000, CRC(65e2c750) SHA1(843466b8d6baebb4d5e434fbdafe3ae8fed03475) ) 305 | ROM_LOAD( "cb6107.bin", 0x8000, 0x2000, CRC(c2f8e522) SHA1(932276e7ad33aa9efbb4cd10bc3071d88cb082cb) ) 306 | ROM_END 307 | 308 | ROM_START( dokidoki ) 309 | ROM_REGION( 0x10000, "maincpu", 0 ) 310 | ROM_LOAD( "epr-7356.ic1", 0x0000, 0x4000, CRC(95658c31) SHA1(f7b5638ab1b8b244b189317d954eb37b51923791) ) 311 | ROM_LOAD( "epr-7357.ic2", 0x4000, 0x4000, CRC(e8dbad85) SHA1(9f13dafacee370d6e4720d8e27cf889053e79eb3) ) 312 | ROM_LOAD( "epr-7358.ic3", 0x8000, 0x4000, CRC(c6f26b0b) SHA1(3753e05b6e77159832dbe88562ba7a818120d1a3) ) 313 | ROM_END 314 | 315 | /************************************* 316 | * 317 | * Driver initialization 318 | * 319 | *************************************/ 320 | 321 | DRIVER_INIT_MEMBER(sg1000a_state,sg1000a) 322 | { 323 | } 324 | 325 | DRIVER_INIT_MEMBER(sg1000a_state,chwrestl) 326 | { 327 | DRIVER_INIT_CALL(sg1000a); 328 | regulus_decode(machine(), "maincpu"); 329 | } 330 | 331 | /************************************* 332 | * 333 | * Game drivers 334 | * 335 | *************************************/ 336 | 337 | GAME( 1984, chboxing, 0, sg1000a, chboxing, sg1000a_state, sg1000a, ROT0, "Sega", "Champion Boxing", 0 ) 338 | GAME( 1985, chwrestl, 0, sg1000a, chwrestl, sg1000a_state, chwrestl, ROT0, "Sega", "Champion Pro Wrestling", 0 ) 339 | GAME( 1985, dokidoki, 0, sg1000a, dokidoki, sg1000a_state, sg1000a, ROT0, "Sega", "Doki Doki Penguin Land", 0 ) 340 | -------------------------------------------------------------------------------- /Docs/smstech.txt: -------------------------------------------------------------------------------- 1 | 2 | SMS/GG hardware notes 3 | by Charles MacDonald 4 | WWW: http://cgfm2.emuviews.com 5 | 6 | Unpublished work Copyright 2000, 2001, 2002 Charles MacDonald 7 | 8 | This document describes the hardware of several Sega systems that are SMS 9 | compatible, including the SMS, SMS 2, GameGear, and Genesis. 10 | 11 | Table of Contents 12 | 13 | 1.) Overview 14 | 2.) Z80 memory map 15 | 3.) Z80 I/O ports 16 | 4.) I/O port registers 17 | 5.) Interrupts 18 | 6.) BIOS information 19 | 7.) Sound hardware 20 | 8.) Credits and Acknowledgements 21 | 9.) Disclaimer 22 | 23 | What's new: 24 | 25 | (11/12/02) 26 | - Added description of SMS interrupt behavior. 27 | - Added description of bit 5 of port $DD for the SMS. 28 | - Added description of SMS Z80 port map. 29 | - Fixed reset button entries in the features table. (Thanks Bock) 30 | - Added mirrored addresses for the 3D glasses. (Thanks Bock) 31 | - Added description of SMS to memory control register. 32 | - Fixed description of ports $DE/$DF. (Thanks Richard) 33 | 34 | ---------------------------------------------------------------------------- 35 | 1.) Overview 36 | ---------------------------------------------------------------------------- 37 | 38 | The main differences between various Sega consoles are what slots are 39 | available (cartridge, card, expansion, BIOS), if there is a YM2413 sound 40 | chip, and if there is a reset or pause button. 41 | 42 | Console Cart Card Exp. BIOS YM2413 Reset Pause 43 | 44 | SG-1000 y ? ? n n ? y 45 | SG-1000 II y ? ? n n ? y 46 | SC-3000 y ? ? n n ? y 47 | Mark III y y y n? *1 n y 48 | Japanese SMS y y y y y n y 49 | SMS y y y y n y y 50 | SMS 2 y n n y n n y 51 | Genesis y n n n n n n 52 | Genesis+PBC y y n y n n y 53 | GameGear y n n *2 n n y 54 | 55 | 1.) The YM2413 is an optional add-on for the Mark III which uses the 56 | expansion port. 57 | 58 | 2.) Some Sega Game Gears do not have a BIOS, others are reported to. 59 | All Majesco Game Gears have a BIOS. 60 | 61 | The Genesis is mostly compatible with the Sega 8-bit systems, but some 62 | additional hardware is needed to interface the cartridge connector with 63 | a standard SMS cartridge or card game. 64 | 65 | Also, while the Genesis has a expansion port, reset button, and some models 66 | have a BIOS ROM, they are used for different purposes and are not related 67 | to the expansion port, reset button, and BIOS of other Sega 8-bit systems. 68 | 69 | ---------------------------------------------------------------------------- 70 | 2.) Z80 memory map 71 | ---------------------------------------------------------------------------- 72 | 73 | The Z80's address space is shared by several components. 74 | It has the following layout: 75 | 76 | $0000-$BFFF : Slot area 77 | $C000-$FFFF : Work RAM (8K, mirrored at $E000-$FFFF) 78 | 79 | The slot area can be assigned to the expansion connector, cartridge, card, 80 | or BIOS ROM. Any of these slots may have extra hardware such as a memory 81 | mapping chip to provide bank switching. 82 | 83 | 3D glasses 84 | 85 | The 3D glasses adapter plugs into the card slot of a SMS or Genesis+PBC. 86 | It has a single register at address $FFF8 with mirrors at $FFF9,$FFFA, and 87 | $FFFB (Jap SMS only have $FFFB?). Bit 0 toggles which shutter on the LCD 88 | glasses is closed, leaving the other one open. 89 | 90 | Register mirroring 91 | 92 | The work RAM is only 8K, and is mirrored at $E000-$FFFF. The Sega memory 93 | mapping hardware and 3D glasses have write-only registers at $FFF8 and 94 | $FFFC-$FFFF, which cause data written to be sent to RAM as well. 95 | Consequently, RAM addresses $1FF8 and $1FFC-1FFF hold the values written, 96 | and this data can be read back from both the regular and mirrored addresses 97 | at $DFF8/$FFF8 and $DFFC-$DFFF/$FFFC-$FFFF. 98 | 99 | Codemasters mapper 100 | 101 | All SMS and GG games by Codemasters have a fixed 32K ROM area at $0000-$7FFF 102 | and a 16K bank at $8000-$BFFF. The bank can be selected by writing a byte 103 | to address $8000. 104 | 105 | I'll also point out that the Codemasters SMS games are only compatible 106 | for the most part with PAL SMS 2 machines, as they use or rely on features 107 | specific to the video hardware of those consoles. 108 | 109 | ---------------------------------------------------------------------------- 110 | 3.) Z80 I/O ports 111 | ---------------------------------------------------------------------------- 112 | 113 | The Z80 has a 16-bit address bus that can be used to access 64K 8-bit 114 | ports. In the SMS, only the lower 8 bits of the address bus are used and 115 | the upper 8 bits are ignored. 116 | 117 | While this doesn't cover all of the exceptions, a general way of looking 118 | at the port layout is that A7, A6, and A0 are used to decode the addresses. 119 | This makes for eight unique addresses out of the entire 256 port range. 120 | 121 | The following addresses are most often used in commercial software: 122 | 123 | $3E : Memory control 124 | $3F : I/O port control 125 | $7E : V counter / PSG 126 | $7F : H counter / PSG 127 | $BE : VDP data 128 | $BF : VDP control 129 | $DC : I/O port A/B 130 | $DD : I/O port B/misc. 131 | 132 | And some mirrors are used too: 133 | 134 | $BD : VDP control 135 | $C0 : I/O port A/B 136 | $C1 : I/O port B/misc. 137 | 138 | Some software will write data to ports $DE and $DF. The SG-1000 and SC-3000 139 | had an 8255 PPI which used these ports to control a keyboard, but later 140 | consoles got rid of it. There is a keyboard peripheral for the Mark III, 141 | which perhaps some games try to detect and use. 142 | 143 | The Japanese SMS has a YM2413 mapped to port $F0-F1, and sound control on port $F2... 144 | 145 | Arcade machines based on the SG1000 use port $DE for dipswitches( and $DF for control?). 146 | bit 6 & 7 of port $DC are Start buttons, bit 6 of port $DD is service switch, 147 | bit 7 of port $DD is coin switch. 148 | System-E use ports $E0 & $E1 for controls and $F2 & $F3 for dipswitches. 149 | Port $F7 is used for bankswitching. 150 | Port $FA is used for controlling input from port $F8. 151 | ?for start button and coin(s). 152 | 153 | SG-1000/SC-3000 port map: 154 | 155 | Range PPI VDP PSG Data returned 156 | ------ --- --- --- --------------------------- 157 | $00-1F Y Y Y PPI+VDP 158 | $20-3F N Y Y VDP 159 | $40-5F Y N Y PPI 160 | $60-7F N N Y Instruction referenced by R 161 | $80-9F Y Y N PPI+VDP 162 | $A0-BF N Y N VDP 163 | $C0-DF Y N N PPI 164 | $E0-FF N N N Instruction referenced by R 165 | 166 | For each location, data written goes to all devices that are enabled. 167 | 168 | 169 | Mark3 port map: 170 | 171 | $00-$3F : Writes to even addresses go to memory control register? 172 | Writes to odd addresses have no effect. 173 | Reads return the last byte of the instruction which read the port. 174 | $40-$7F : Writes to any address go to the SN76489 PSG. 175 | Reads from even addresses return the V counter. 176 | Reads from odd address return the H counter. 177 | $80-$BF : Writes to even addresses go to the VDP data port. 178 | Writes to odd addresses go to the VDP control port. 179 | Reads from even addresses return the VDP data port contents. 180 | Reads from odd address return the VDP status flags. 181 | $C0-$FF : Writes have no effect. 182 | Reads from even addresses return the I/O port A/B register. 183 | Reads from odd address return the I/O port B/misc. register. 184 | 185 | SMS J port map: 186 | 187 | $00-$3F : Writes to even addresses go to memory control register. 188 | Writes to odd addresses go to I/O control register? 189 | Reads return the last byte of the instruction which read the port. 190 | $40-$7F : Writes to any address go to the SN76489 PSG. 191 | Reads from even addresses return the V counter. 192 | Reads from odd address return the H counter. 193 | $80-$BF : Writes to even addresses go to the VDP data port. 194 | Writes to odd addresses go to the VDP control port. 195 | Reads from even addresses return the VDP data port contents. 196 | Reads from odd address return the VDP status flags. 197 | $C0-$FF : Writes have no effect, except 0xF2 which goes to the YM2413. 198 | Reads from even addresses return the I/O port A/B register. 199 | Reads from odd address return the I/O port B/misc. register. 200 | 201 | 202 | 203 | SMS port map: 204 | 205 | $00-$3F : Writes to even addresses go to memory control register. 206 | Writes to odd addresses go to I/O control register. 207 | Reads return the last byte of the instruction which read the port. 208 | $40-$7F : Writes to any address go to the SN76489 PSG. 209 | Reads from even addresses return the V counter. 210 | Reads from odd address return the H counter. 211 | $80-$BF : Writes to even addresses go to the VDP data port. 212 | Writes to odd addresses go to the VDP control port. 213 | Reads from even addresses return the VDP data port contents. 214 | Reads from odd address return the VDP status flags. 215 | $C0-$FF : Writes have no effect. 216 | Reads from even addresses return the I/O port A/B register. 217 | Reads from odd address return the I/O port B/misc. register. 218 | 219 | SMS 2 port map: 220 | 221 | $00-$3F : Writes to even addresses go to memory control register. 222 | Writes to odd addresses go to I/O control register. 223 | Reads return $FF. 224 | $40-$7F : Writes to any address go to the SN76489 PSG. 225 | Reads from even addresses return the V counter. 226 | Reads from odd address return the H counter. 227 | $80-$BF : Writes to even addresses go to the VDP data port. 228 | Writes to odd addresses go to the VDP control port. 229 | Reads from even addresses return the VDP data port contents. 230 | Reads from odd address return the VDP status flags. 231 | $C0-$FF : Writes have no effect. 232 | Reads from even addresses return the I/O port A/B register. 233 | Reads from odd address return the I/O port B/misc. register. 234 | 235 | Game Gear port map: (GG mode) 236 | 237 | $00-$06 : GG specific registers. Initial state is 'C0 7F FF 00 FF 00 FF'. 238 | $07-$3F : Writes to even addresses go to memory control register. 239 | Writes to odd addresses go to I/O control register. 240 | Reads return $FF. 241 | $40-$7F : Writes to any address go to the SN76489 PSG. 242 | Reads from even addresses return the V counter. 243 | Reads from odd address return the H counter. 244 | $80-$BF : Writes to even addresses go to the VDP data port. 245 | Writes to odd addresses go to the VDP control port. 246 | Reads from even addresses return the VDP data port contents. 247 | Reads from odd address return the VDP status flags. 248 | $C0-$FF : Writes have no effect. 249 | Reads from $C0 and $DC return the I/O port A/B register. 250 | Reads from $C1 and $DD return the I/O port B/misc. register. 251 | The remaining locations return $FF. 252 | 253 | Game Gear port map: (MS mode) 254 | 255 | $00-$3F : Writes to even addresses go to memory control register. 256 | Writes to odd addresses go to I/O control register. 257 | Reads return $FF. 258 | $40-$7F : Writes to any address go to the SN76489 PSG. 259 | Reads from even addresses return the V counter. 260 | Reads from odd address return the H counter. 261 | $80-$BF : Writes to even addresses go to the VDP data port. 262 | Writes to odd addresses go to the VDP control port. 263 | Reads from even addresses return the VDP data port contents. 264 | Reads from odd address return the VDP status flags. 265 | $C0-$FF : Writes have no effect. 266 | Reads from $C0 and $DC return the I/O port A/B register. 267 | Reads from $C1 and $DD return the I/O port B/misc. register. 268 | The remaining locations return $FF. 269 | 270 | Genesis port map: 271 | 272 | $00-$3F : Writes to even addresses go to memory control register. 273 | Writes to odd addresses go to I/O control register. 274 | Reads return $00 or random data. 275 | $40-$7F : Writes to any address go to the SN76489 PSG. 276 | Reads from even addresses return the V counter. 277 | Reads from odd address return the H counter. 278 | $80-$BF : Writes to even addresses go to the VDP data port. 279 | Writes to odd addresses go to the VDP control port. 280 | Reads from even addresses return the VDP data port contents. 281 | Reads from odd address return the VDP status flags. 282 | $C0-$FF : Writes have no effect. 283 | Reads from $C0 and $DC return the I/O port A/B register. 284 | Reads from $C1 and $DD return the I/O port B/misc. register. 285 | The remaining locations return $00 or random data. 286 | 287 | Genesis port map: (with PBC) 288 | 289 | $00-$3F : Writes to even addresses go to memory control register. 290 | Writes to odd addresses go to I/O control register. 291 | Reads return $FF. 292 | $40-$7F : Writes to any address go to the SN76489 PSG. 293 | Reads from even addresses return the V counter. 294 | Reads from odd address return the H counter. 295 | $80-$BF : Writes to even addresses go to the VDP data port. 296 | Writes to odd addresses go to the VDP control port. 297 | Reads from even addresses return the VDP data port contents. 298 | Reads from odd address return the VDP status flags. 299 | $C0-$FF : Writes have no effect. 300 | Reads from $C0 and $DC return the I/O port A/B register. 301 | Reads from $C1 and $DD return the I/O port B/misc. register. 302 | The remaining locations return $FF. 303 | 304 | Remember that ports $C0-$FF for some consoles will return different data 305 | when the I/O ports are disabled. See the following section for details. 306 | 307 | ---------------------------------------------------------------------------- 308 | 4.) I/O port registers 309 | ---------------------------------------------------------------------------- 310 | 311 | Port $3E : Memory control 312 | 313 | D7 : Expansion slot enable (1= disabled, 0= enabled) 314 | D6 : Cartridge slot enable (1= disabled, 0= enabled) 315 | D5 : Card slot disabled (1= disabled, 0= enabled) 316 | D4 : Work RAM disabled (1= disabled, 0= enabled) 317 | D3 : BIOS ROM disabled (1= disabled, 0= enabled) 318 | D2 : I/O chip disabled (1= disabled, 0= enabled) 319 | D1 : Unknown 320 | D0 : Unknown 321 | 322 | A SMS with the snail maze BIOS sets this to $AB when running a cartridge. 323 | A SMS 2 with Alex Kidd sets this to $AB when running a cartridge. 324 | A Majesco Game Gear sets this to $A8 when running a cartridge. 325 | The Genesis does not initialize Z80 RAM prior to a game starting. 326 | 327 | For an SMS system with a cartridge inserted but no card, neither the 328 | card or expansion slots do anything when enabled. Reading these locations 329 | will return the last byte of the instruction which read memory. If the 330 | BIOS and cartridge are enabled at the same time, the cartridge has 331 | precedence and has it's data returned instead. No data bytes are corrupted 332 | in this case. I haven't checked to see what values are returned when work 333 | RAM is disabled. 334 | 335 | Bits 7 and 5 have no effect on a SMS 2. If the BIOS is enabled at the 336 | same time the cartridge slot is, the data from both sources are logically 337 | ANDed together when read. The BIOS only enables the cartridge slot after 338 | relocating itself to work RAM and disabling the BIOS beforehand. 339 | 340 | When bit 2 is set, all ports at $C0 through $FF return $FF on a SMS 2, 341 | Game Gear, and Genesis. For a SMS, these ports return the last byte of 342 | the instruction which read the port. 343 | 344 | Bits 7, 6, 5, 3, and 2 have no effect on a Genesis, or a Genesis with a PBC. 345 | My MegaDrive with PBC returns $FF when work RAM is disabled. 346 | 347 | Even though a PBC includes a card slot, there is no BIOS to handle 348 | slot selection, so most likely PBC hardware enables the card slot or 349 | the cartridge slot, instead of it being software controlled. I couldn't 350 | get bit 5 to do anything, though I didn't have a card game to test with 351 | at the time. 352 | 353 | Bits 7, 6, 5, and 2 have no effect on a GameGear. I haven't checked to see 354 | what values are returned when work RAM is disabled. Bit 3 will enable a 355 | 1K BIOS ROM at $0000-$03FF when clear, and map the cartridge slot to 356 | the same space when set. When the BIOS is enabled, the rest of the 357 | address space ($0400-$BFFF) is mapped to the cartridge slot as well, so 358 | the BIOS can write to the cartridge mapper registers (if any) and read 359 | the header data as well. 360 | 361 | Bits 1 and 0 have no effect on a SMS, SMS 2, Game Gear, and Genesis. They 362 | may be unused. 363 | 364 | Port $3F : I/O port control 365 | 366 | D7 : Port B TH pin output level (1=high, 0=low) 367 | D6 : Port B TR pin output level (1=high, 0=low) 368 | D5 : Port A TH pin output level (1=high, 0=low) 369 | D4 : Port A TR pin output level (1=high, 0=low) 370 | D3 : Port B TH pin direction (1=input, 0=output) 371 | D2 : Port B TR pin direction (1=input, 0=output) 372 | D1 : Port A TH pin direction (1=input, 0=output) 373 | D0 : Port A TR pin direction (1=input, 0=output) 374 | 375 | This port is used to detect if the machine is domestic (Japanese model) 376 | or export (US, European, Brazil, etc.) While the exact details of the 377 | detection scheme are unknown, it seems to be as follows: 378 | 379 | Set the TH pins for ports A and B as outputs. Set their output level 380 | to any value desired by writing to bits 7 and 5. Read the state of both 381 | TH pins back through bits 7 and 6 of port $DD. If the data returned is 382 | the same as the data written, it's an export machine, otherwise it's 383 | a domestic one. 384 | 385 | I ran a test on my Genesis which has an export/domestic mode switch. When 386 | in export mode reading the TH and TR pins for either port returns their 387 | current output level when they are set as outputs, like normal. When in 388 | domestic mode they always return zero, no matter what. 389 | 390 | A standard 2-button controller uses TR as an input and does not use TH. 391 | The light gun uses TH as an input to signal the VDP to latch the H counter, 392 | and Genesis style 3 and 6 button controllers can be used by setting TH as 393 | an output. 394 | 395 | Port $DC : I/O port A and B 396 | 397 | D7 : Port B DOWN pin input 398 | D6 : Port B UP pin input 399 | D5 : Port A TR pin input 400 | D4 : Port A TL pin input 401 | D3 : Port A RIGHT pin input 402 | D2 : Port A LEFT pin input 403 | D1 : Port A DOWN pin input 404 | D0 : Port A UP pin input 405 | 406 | In the case of a controller, a pressed button returns 0, otherwise 1. 407 | 408 | Port $DD : I/O port B and miscellaneous 409 | 410 | D7 : Port B TH pin in-/output, PC6 on GG. 411 | D6 : Port A TH pin in-/output 412 | D5 : Unused 413 | D4 : RESET button (1= not pressed, 0= pressed) 414 | D3 : Port B TR pin input 415 | D2 : Port B TL pin input 416 | D1 : Port B RIGHT pin input 417 | D0 : Port B LEFT pin input 418 | 419 | Bit 5 returns 0 on a Genesis and 1 on an Mark3, SMS, SMS 2, GG and SC3000 (printer FAULT). 420 | Bit 4 always returns 1 on a Genesis and GG which have no RESET button. 421 | 422 | In the case of a controller, a pressed button returns 0, otherwise 1. 423 | 424 | ---------------------------------------------------------------------------- 425 | 5.) Interrupts 426 | ---------------------------------------------------------------------------- 427 | 428 | Interrupts: 429 | 430 | The Z80's NMI pin is connected to the PAUSE button. When this button is 431 | pressed an NMI is generated on the last scanline (-1), causing the PC to 432 | change to $0066. Releasing the button does nothing. 433 | 434 | Interrupt mode 0 435 | 436 | The interrupting device can place a single or multi-byte opcode on the 437 | data bus for the Z80 to fetch and execute when an interrupt occurs. 438 | 439 | For the SMS 2, Game Gear, and Genesis, the value $FF is always read from 440 | the data bus, which corresponds to the instruction 'RST 38H'. 441 | 442 | For the SMS, a random value is returned which could correspond to any 443 | possible instruction. 444 | 445 | Interrupt mode 1 446 | 447 | When an interrupt occurs the Z80's PC register is set to $0038. 448 | 449 | Interrupt mode 2 450 | 451 | The interrupting device can place a single byte on the data bus which is 452 | used as the LSB of a 16-bit address, of which the MSB comes from the Z80's 453 | I register. The Z80 manual says the address must be even, but odd addresses 454 | work fine. The Z80 then jumps to that address. 455 | 456 | The SMS 2, Game Gear, and Genesis will return $FF. If the I register was 457 | set to $C0, this means the interrupt vector would be read from addresses 458 | $C0FF and $C100. For example: 459 | 460 | di 461 | ld a, $C0 462 | ld i, a 463 | ld hl, $xxxx ; Address of your interrupt handler 464 | ld ($C0FF), hl 465 | im 2 466 | ei 467 | wait: jr wait 468 | 469 | The SMS returns a random value. The only way to use mode 2 in this case is 470 | to fill a 257-byte table with the same value, which corresponds to an 471 | address. No matter which set of bytes the Z80 ends up reading, it will 472 | always pick the same value: 473 | 474 | di 475 | ld a, $C0 476 | ld i, a 477 | ld b, $00 478 | ld hl, $C000 ; Fill $C000-$C0FF with $70 479 | ld a, $70 480 | fill: ld (hl), a 481 | inc hl 482 | djnz fill 483 | ld (hl), a ; Fill 257th byte ($C100) 484 | im 2 485 | ei 486 | wait: jr wait 487 | 488 | .org $7070 489 | ; Your interrupt handler goes here 490 | 491 | ---------------------------------------------------------------------------- 492 | 6.) BIOS information 493 | ---------------------------------------------------------------------------- 494 | 495 | The SMS and SMS 2 consoles have a BIOS which is enabled on power-up. 496 | The BIOS copies a portion of code to RAM, and executes from there. 497 | It then checks the cartridge, card, and expansion slots to see if 498 | there is any valid software to run. 499 | 500 | This is done by examining the header, which is a 16-byte region that 501 | can start at addresses $1FF0, $3FF0, and $7FF0. I won't go into the 502 | details of the header, as this is documented elsewhere. 503 | 504 | Some SMS games rely on the BIOS to initialize certain parts of the 505 | system, such as memory or Z80 registers. They will not work in an emulator 506 | that doesn't support the BIOS or at least set up the system as how the 507 | BIOS would last leave it. 508 | 509 | The BIOS keeps a copy of the last value written to port $3E and stores this 510 | at memory address $C000. Game software uses this value when manipulating 511 | port $3E. One possible advantage of this method instead of using hard-coded 512 | values is that a game could also be run from a card or the expansion port 513 | as well as the cartridge slot. (Such as games like Hang-On, Transbot 514 | which were released on card and cartridge formats) 515 | 516 | ---------------------------------------------------------------------------- 517 | 7.) Sound hardware 518 | ---------------------------------------------------------------------------- 519 | 520 | Game Gear: 521 | 522 | Port $06 is used to control the stereo output of the GG's PSG. Each channel 523 | can be sent to the left or right speaker, as follows: 524 | 525 | D7 : Channel #4 output from left speaker. (1= disabled, 0= enabled) 526 | D6 : Channel #3 output from left speaker. (1= disabled, 0= enabled) 527 | D5 : Channel #2 output from left speaker. (1= disabled, 0= enabled) 528 | D4 : Channel #1 output from left speaker. (1= disabled, 0= enabled) 529 | D3 : Channel #4 output from right speaker. (1= disabled, 0= enabled) 530 | D2 : Channel #3 output from right speaker. (1= disabled, 0= enabled) 531 | D1 : Channel #2 output from right speaker. (1= disabled, 0= enabled) 532 | D0 : Channel #1 output from right speaker. (1= disabled, 0= enabled) 533 | 534 | Writing $FF enables all channels through both speakers. 535 | Writing $00 disables all channels, and effectively mutes the sound. 536 | 537 | YM2413 sound: 538 | 539 | Mark III consoles had a FM sound unit which primarily consisted 540 | of a Yamaha YM2413 sound chip. The Japanese SMS had the YM2413 built in. 541 | Some games try to detect the YM2413 hardware as to be compatible with 542 | Mark III systems that do not have FM sound unit. 543 | 544 | The following ports are used by the FM add-on: 545 | 546 | Port $F0 : Output to YM2413 data port (with A0=0, select register latch) 547 | Port $F1 : Output to YM2413 data port (with A0=1, select register data) 548 | Port $F2 : Bit 0 can be read and written to detect if YM2413 is available. 549 | 550 | The SMS normally assigns reads from $C0-$FF to the I/O chip. You must 551 | disable the I/O chip by setting bit 2 of port $3E if you want to read 552 | port $F2 to perform YM2413 detection. 553 | 554 | The YM2413 has no readable registers. It isn't known exactly what data 555 | is returned from ports $C0-$FF if the YM2413 is present. 556 | 557 | ---------------------------------------------------------------------------- 558 | 8.) Credits and Acknowledgements 559 | ---------------------------------------------------------------------------- 560 | 561 | In particular I'd like to thank Asynchronous and Mike G. for their many 562 | contributions to the S8-DEV forum. Quite a few things mentioned here are 563 | based on their posts. 564 | 565 | And I would like to thank everyone else: 566 | 567 | - Charles Doty 568 | - Chris MacDonald 569 | - Flavio Morsoletto 570 | - Jon 571 | - Marat Fayzullin 572 | - Maxim 573 | - Omar Cornut 574 | - Pascal Bosquet 575 | - Richard Atkinson 576 | - Richard Talbot-Watkins 577 | - Sean Young 578 | - Steve Snake 579 | - Everyone on the S8-DEV forum 580 | 581 | If I've missed anyone, please let me know. 582 | 583 | ---------------------------------------------------------------------------- 584 | 9.) Disclaimer 585 | ---------------------------------------------------------------------------- 586 | 587 | If you use any information from this document, please credit me 588 | (Charles MacDonald) and optionally provide a link to my webpage 589 | (http://cgfm2.emuviews.com/) so interested parties can access it. 590 | 591 | The credit text should be present in the accompanying documentation of 592 | whatever project which used the information, or even in the program 593 | itself (e.g. an about box) 594 | 595 | Regarding distribution, you cannot put this document on another 596 | website, nor link directly to it. 597 | 598 | ---------------------------------------------------------------------------- 599 | 600 | Unpublished work Copyright 2002 Charles MacDonald 601 | 602 | -------------------------------------------------------------------------------- /History.txt: -------------------------------------------------------------------------------- 1 | S8DS revision history 2 | -=-=-=-=-=-=-=-=-=-=-=- 3 | 4 | 5 | V1.1.8 - 2024-09-11 (FluBBa) 6 | 7 | V1.1.7 - 2023-11-07 (FluBBa) 8 | Added support for "Megumi Rescue" on System-E. 9 | Added support for "Opa Opa unencrypted" on System-E. 10 | Added support for "Slap Shooter" on System-E. 11 | Added support for "Super Derby (satellite board)" on SG-AC (not working). 12 | Added support for "Super Derby II (satellite board)" on SG-AC (not working). 13 | Added new debug menu. 14 | Fixed vertical scrolling for BG2 on System-E. 15 | Fixed envelope handling on the AY38910. 16 | Fixed pause on older Sega machines (again). 17 | Better menu traversing. 18 | 19 | V1.1.6 - 2021-10-18 (FluBBa) 20 | Fixed load/save state for Coleco. 21 | 22 | V1.1.5 - 2021-10-17 (FluBBa) 23 | Fixed load/save state. 24 | 25 | V1.1.4 - 2021-10-16 (FluBBa) 26 | Reverted a GG_IO optimization. 27 | Fixed TV noise graphics after Power off. 28 | Fixed file extension checking. 29 | Fixed menu glitch if loading game directly. 30 | Fixed pause on older Sega machines. 31 | Better selection of machines. 32 | 33 | V1.1.3 - 2021-10-12 (FluBBa) 34 | Fixed crash at startup. 35 | Added ui to enable/disable YM2413. 36 | 37 | V1.1.2 - 2021-10-11 (FluBBa) 38 | Fixed TV noise. 39 | 40 | V1.1.1 - 2021-09-05 (FluBBa) 41 | Code cleanup. 42 | 43 | V1.1.0 - 2018-07-28 (FluBBa) 44 | Added Sord M5 support. 45 | 46 | V1.0.0 - 2016-03-12 (FluBBa) 47 | Fixed Pause on SG-1000. 48 | 49 | V0.9.0 - 2015-07-25 (FluBBa) 50 | Added SRAM support. 51 | Fixed folder browsing a bit. 52 | Fixed some nasty bugs which affected saving of settings and more. 53 | 54 | V0.8.0 - 2015-07-08 (FluBBa) 55 | Added basic MSX 1 support. 56 | Added SG-1000 Arcade support. 57 | Added System-E support. 58 | Added MegaTech files support. 59 | Added support for 3 button MegaDrive pad. 60 | Added mini Bios from Power Base Converter for MegaDrive. 61 | Added background images for all Systems. 62 | Added support for arguments from flashcard menus. 63 | Added SDSC debugging support and forwarder to DS emulators. 64 | Support for longer filenames and more files per folder. 65 | Fixed sprite palette bug for TMS9918. 66 | Turned of sprites for Mode 1. 67 | 68 | V0.7.0 - 2010-01-16 (FluBBa) 69 | Fixed Super Tetris & Frogger proto when machine is set to "Auto". 70 | Fixed PGA Tour Golf (low bits of VDP Stat not zero). 71 | Changed palette buffering to middle of screen. 72 | Changed default scale mode to "Scale To Fit". 73 | 74 | V0.6.0 - 2010-01-07 (FluBBa) 75 | Added option to turn off 3D display. 76 | Fixed color/saturation setting for SG/Coleco games. 77 | Fixed some bogus handling of the 3D display mode. 78 | Fixed "Perfect Sprites" mode, should now be used as default. 79 | Changed startup values for VDP regs 0,1 & 10, might break something. 80 | Changed sound renderer to be more correct. 81 | Removed PAL timing for GG. 82 | 83 | V0.5.0 - 2009-12-02 (FluBBa) 84 | Added support for Coleco Vision. 85 | Added keyboard support for SC-3000/SG-1000. 86 | Added support for mode 3 graphics. 87 | Added support for red/cyan glasses in SMS 3D games. 88 | Added color/saturation setting to display. 89 | Fixed issues with mode 0,1 & 2 graphics. 90 | Fixed cut off of long filenames in the browser. 91 | Fixed timing of VInt. 92 | Changed colors for the filebrowser. 93 | 94 | V0.4.0 - 2009-11-01 (FluBBa) 95 | Added R as FastForward. 96 | Fixed Bios handling on MD (Frogger proto GG2SMS works). 97 | Fixed "Border Off" for GG. 98 | Sprite collision is now "On" by default. 99 | Changed R as GG start to X as GG Start. 100 | 101 | V0.3.0 - 2009-10-20 (FluBBa) 102 | Fixed Bios handling a bit (GG games works again). 103 | 104 | V0.2.0 - 2009-10-19 (FluBBa) 105 | After loading game GUI is automatically closed. 106 | Added internal Bios (for Ace of Aces & Shadow Dancer). 107 | 108 | V0.1.0 - 2009-10-13 (FluBBa) 109 | Initial release, allmost everything from SMSAdvance seems to work. 110 | 111 | V0.0.0 - 2009-07-25 (FluBBa) 112 | Started Coding. 113 | 114 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | GAME_TITLE := S8DS 10 | GAME_SUBTITLE1 := Sega 8-bit Emulator 11 | GAME_SUBTITLE2 := www.ndsretro.com 12 | GAME_ICON := $(CURDIR)/../Sms.bmp 13 | 14 | include $(DEVKITARM)/ds_rules 15 | 16 | #--------------------------------------------------------------------------------- 17 | # TARGET is the name of the output 18 | # BUILD is the directory where object files & intermediate files will be placed 19 | # SOURCES is a list of directories containing source code 20 | # INCLUDES is a list of directories containing extra header files 21 | # DATA is a list of directories containing binary files 22 | # GRAPHICS is a list of directories containing files to be processed by grit 23 | # All directories are relative to this makefile 24 | #--------------------------------------------------------------------------------- 25 | TARGET := $(shell basename $(CURDIR)) 26 | BUILD := build 27 | SOURCES := source \ 28 | source/Shared \ 29 | source/Shared/Unzip \ 30 | source/ARMZ80 \ 31 | source/SegaVDP \ 32 | source/SN76496 \ 33 | source/YM2413 \ 34 | source/PPI8255 \ 35 | source/AY38910 \ 36 | source/SCC \ 37 | source/CXD1095Q \ 38 | source/ARMZ80CTC 39 | DATA := data 40 | INCLUDES := include 41 | GRAPHICS := graphics \ 42 | source/Shared/graphics 43 | 44 | #--------------------------------------------------------------------------------- 45 | # options for code generation 46 | #--------------------------------------------------------------------------------- 47 | ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork 48 | FLAGS := -DARM9 -DNDS -DZ80_LARGE_MAP -DZ80_USE_FAST_MEM -DAY_UPSHIFT=2 -DSCC_UPSHIFT=2 49 | 50 | ifeq ($(DEBUG),1) 51 | CFLAGS := -gdwarf-2 -Wall -ffast-math $(ARCH) 52 | else 53 | CFLAGS := -g -Wall -O3 -fomit-frame-pointer -ffast-math $(ARCH) 54 | endif 55 | 56 | CFLAGS += $(INCLUDE) $(FLAGS) 57 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions 58 | 59 | ASFLAGS := -g $(ARCH) $(INCLUDE) $(FLAGS) 60 | LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 61 | 62 | #--------------------------------------------------------------------------------- 63 | # any extra libraries we wish to link with the project 64 | #--------------------------------------------------------------------------------- 65 | LIBS := -lfat -lmm9 -lnds9 -lm 66 | 67 | 68 | #--------------------------------------------------------------------------------- 69 | # list of directories containing libraries, this must be the top level containing 70 | # include and lib 71 | #--------------------------------------------------------------------------------- 72 | LIBDIRS := $(LIBNDS) 73 | 74 | #--------------------------------------------------------------------------------- 75 | # no real need to edit anything past this point unless you need to add additional 76 | # rules for different file extensions 77 | #--------------------------------------------------------------------------------- 78 | ifneq ($(BUILD),$(notdir $(CURDIR))) 79 | #--------------------------------------------------------------------------------- 80 | 81 | export OUTPUT := $(CURDIR)/$(TARGET) 82 | 83 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 84 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ 85 | $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) 86 | 87 | export DEPSDIR := $(CURDIR)/$(BUILD) 88 | 89 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 90 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 91 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 92 | PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) 93 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 94 | 95 | #--------------------------------------------------------------------------------- 96 | # use CXX for linking C++ projects, CC for standard C 97 | #--------------------------------------------------------------------------------- 98 | ifeq ($(strip $(CPPFILES)),) 99 | #--------------------------------------------------------------------------------- 100 | export LD := $(CC) 101 | #--------------------------------------------------------------------------------- 102 | else 103 | #--------------------------------------------------------------------------------- 104 | export LD := $(CXX) 105 | #--------------------------------------------------------------------------------- 106 | endif 107 | #--------------------------------------------------------------------------------- 108 | 109 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 110 | $(PNGFILES:.png=.o) \ 111 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 112 | 113 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 114 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 115 | -I$(CURDIR)/$(BUILD) 116 | 117 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 118 | 119 | .PHONY: $(BUILD) clean 120 | 121 | #--------------------------------------------------------------------------------- 122 | $(BUILD): 123 | @[ -d $@ ] || mkdir -p $@ 124 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 125 | 126 | #--------------------------------------------------------------------------------- 127 | clean: 128 | @echo clean ... 129 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).arm9 $(TARGET).ds.gba 130 | 131 | 132 | #--------------------------------------------------------------------------------- 133 | else 134 | 135 | DEPENDS := $(OFILES:.o=.d) 136 | 137 | #--------------------------------------------------------------------------------- 138 | # main targets 139 | #--------------------------------------------------------------------------------- 140 | $(OUTPUT).nds : $(OUTPUT).elf 141 | $(OUTPUT).elf : $(OFILES) 142 | 143 | #--------------------------------------------------------------------------------- 144 | %.pcx.o : %.pcx 145 | #--------------------------------------------------------------------------------- 146 | @echo $(notdir $<) 147 | @$(bin2o) 148 | 149 | #--------------------------------------------------------------------------------- 150 | %.s %.h : %.png %.grit 151 | #--------------------------------------------------------------------------------- 152 | grit $< -fts -o$* 153 | 154 | 155 | -include $(DEPENDS) 156 | 157 | #--------------------------------------------------------------------------------------- 158 | endif 159 | #--------------------------------------------------------------------------------------- 160 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # S8DS V1.1.8 2 | 3 | This is a SEGA 8Bit emulator for the Nintendo DS(i)/3DS, it support the following systems: 4 | 5 | SEGA SG-1000 / SG-1000 II 6 | SEGA SC-3000 7 | SEGA Mark III 8 | SEGA Master System J, 1 & 2 9 | SEGA Game Gear 10 | SEGA System-E 11 | Othello Multivision 12 | Coleco 13 | MSX 1 14 | Sord M5 15 | 16 | Some systems require you to add their Bios'es to function correctly. 17 | 18 | Features: 19 | 20 | Most things you'd expect from an SMS emulator. 21 | Except these... 22 | 23 | Missing: 24 | 25 | Correct sprite collision. 26 | Speech samples. 27 | Good YM2413 emulation. 28 | EEPROM save for the few GG games that use it. 29 | 30 | Check your roms! 31 | https://www.smspower.org/maxim/Software/SMSChecker 32 | 33 | ## How to use 34 | 35 | 1. Create a "S8DS" directory either in the root of your card or in the data 36 | directory (eg h:\data\S8DS). This is where settings and save files end up. 37 | 2. Now put game/bios files into a folder where you have (SEGA 8-bit) roms, max 38 | 768 games per folder, filenames must not be longer than 127 chars. You can use 39 | zipped files (as long as they use the deflate compression). 40 | 3. Depending on your flashcart you might have to DLDI patch the emulator. 41 | 42 | Put your games on your flash card, max 768 games per folder (though shouldn't 43 | be a problem if you separate SMS, GG, SG & Coleco games into different 44 | folders). Filenames must not be longer than 127 chars. You can use zipped 45 | files (as long as they use the deflate compression). The emulator should also 46 | recognise SMS games for SEGAs MegaTech arcade machine, the SG-1000 arcade 47 | games and System-E (using MAME zip files). 48 | 49 | The GUI is accessed by pressing L+R (shoulder buttons) or by touching the 50 | screen, tabs are changed by pressing the L or R button, going to the left most 51 | tab exits the GUI. Closing your DS puts the emulator in sleep mode, just open 52 | it to resume. 53 | 54 | When you first run the emulator I suggest you take a peak through the options 55 | and change the settings to your liking and then save them. 56 | Now load up a game and you should be good to go. 57 | 58 | When playing SMS 3D games you might want to turn down the color a bit for 59 | better 3D effect, I have only tested with red/cyan glasses. 60 | 61 | ## Menu 62 | 63 | ### File 64 | 65 | * Load Game: 66 | * Load State: Select which state you want to load. 67 | * Save State: Select if you want to overwrite an old state or create a new. 68 | * Save SRAM: 69 | * Save Settings: 70 | * Eject Game: 71 | * Power On/Off: 72 | * Reset Game: 73 | * Quit Emulator: (If your card supports it.) 74 | 75 | ### Options 76 | 77 | * Controller: 78 | * Autofire: Select if you want autofire. 79 | * Controller: 2P control player 2. 80 | * Swap A-B: Swap which NDS button is mapped to which SMS/GG button. 81 | * Joypad Type: You can select 3 button Megadrive/Genesis pad. 82 | * Use Select as Reset: Map the NDS SELECT button to the SMS Reset button. 83 | * Use R as FastForward: Select turbo speed as long as R button is held. 84 | * Display: 85 | * Display: Here you can select if you want scaled or unscaled screenmode. 86 | * Scaling: Here you can select if you want flicker or barebones lineskip. 87 | * Gamma: Lets you change the gamma ("brightness"). 88 | * Color: Lets you change the color. 89 | * GG Border: Lets you change between black, bordercolor and none. 90 | * Perfect Sprites: Uses a bit more cpu but is worth it. 91 | * 3D Display: Terminator vs Robocop needs this off. 92 | * Machine: 93 | * Region: Change the region of the SMS and video standard. 94 | * Machine: Here you can select the hardware, Auto should work for most games. 95 | * Bios Settings: 96 | * Use Bios: Here you can select if you want to use the selected BIOSes. 97 | * Select Export Bios: Browse for export bios. 98 | * Select Japanese Bios: Browse for japanese bios. 99 | * Select GameGear Bios: Browse for GameGear bios. 100 | * Select Coleco Bios: Browse for Coleco bios. 101 | * Select MSX Bios: Browse for MSX bios. 102 | * YM2413: Enable YM2413 emulation for SMS1 & Mark 3. 103 | * Settings: 104 | * Speed: Switch between speed modes, can also be toggled with L+START. 105 | * Normal: Standard, 100% speed. 106 | * Fast: Double, 200% speed. 107 | * Max: Fastest, 400% speed. 108 | * Slowmo: Slow, 50% speed. 109 | * Autoload State: Toggle Savestate autoloading. Automagicaly load the 110 | savestate associated with the selected game. 111 | * Autosave Settings: This will save settings when leaving menu if any 112 | changes are made. 113 | * Autopause Game: Toggle if the game should pause when opening the menu. 114 | * Powersave 2nd Screen: If graphics/light should be turned off for the GUI 115 | screen when menu is not active. 116 | * Emulator on Bottom: Select if top or bottom screen should be used for 117 | emulator, when menu is active emulator screen is allways on top. 118 | * Autosleep: Change the autosleep time, also see Sleep. !!!DoesntWork!!! 119 | * Debug: 120 | * Debug Output: Toggle fps meter & more. 121 | * Disable Background: Turn on/off background rendering. 122 | * Disable Sprites: Turn on/off sprite rendering. 123 | * Step Frame: Emulate one frame. 124 | * Dipswitches: For arcade games 125 | 126 | ### About 127 | 128 | Some dumb info... 129 | 130 | ## Arcade roms 131 | 132 | ### MegaTech 133 | 134 | * After Burner MT - mt_aftrb.zip 135 | * Alien Syndrom MT - mt_asyn.zip 136 | * Astro Warrior MT - mt_astro.zip 137 | * Fantasy Zone MT - mt_fz.zip 138 | * Great Football MT - mt_gfoot.zip 139 | * Great Golf MT - mt_ggolf.zip 140 | * Great Soccer MT - mt_gsocr.zip (bad dump) 141 | * Out Run MT - mt_orun.zip 142 | * Parlour Games MT - mt_parlg.zip 143 | * Shinobi MT - mt_shnbi.zip 144 | 145 | ### SG AC 146 | 147 | * Champion Boxing SG-AC - chboxing.zip 148 | * Champion Wrestling SG-AC - chwrestl.zip (encrypted) 149 | * Doki Doki Penguin SG-AC - dokidoki.zip 150 | * Super Derby (satellite board) SG-AC - sderbys (not working) 151 | * Super Derby II (satellite board) SG-AC - sderby2s (not working) 152 | 153 | ### System-E 154 | 155 | * Astro Flash System-E - astrofl.zip (encrypted) 156 | * Fantasy Zone 2 System-E - fantzn2.zip (encrypted) 157 | * Hang On Jr System-E - hangonjr.zip 158 | * Megumi Rescue System-E - megrescu.zip 159 | * Opa Opa System-E - opaopa.zip (encrypted) 160 | * Opa Opa System-E - opaopan.zip 161 | * Riddle Of Pythagoras System-E - ridleofp.zip 162 | * Slap Shooter System-E - slapshtr.zip 163 | * Tetris System-E - tetrisse.zip 164 | * Transformer System-E - transfrm.zip 165 | 166 | ## Credits 167 | 168 | ```text 169 | Thanks to: 170 | Reesy for help with the Z80 emu core. 171 | Some MAME people + Maxim for the SN76496 info. 172 | Charles MacDonald (http://cgfm2.emuviews.com/) for VDP info. 173 | Omar Cornut (http://www.smspower.org/) for help with various SMS stuff. 174 | The crew at PocketHeaven for their support. 175 | ``` 176 | 177 | Fredrik Ahlström 178 | 179 | X/Twitter @TheRealFluBBa 180 | 181 | 182 | -------------------------------------------------------------------------------- /S8DS.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /S8DS.pnproj: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /S8DS.pnws: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /S8DS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /S8DS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /S8DS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /S8DS.xcodeproj/xcshareddata/xcschemes/S8DS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 47 | 48 | 49 | 55 | 56 | 57 | 58 | 61 | 62 | 63 | 64 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /S8DS_todo.txt: -------------------------------------------------------------------------------- 1 | S8DS To do 2 | ------------ 3 | 4 | Games that crash the emulator when machine is set to 'auto' : 5 | Master of darkness 6 | Vampire 7 | Dragon's trap 8 | Ninja gaiden 9 | AK miracle world (jap) 10 | AK shinobi world 11 | Makai retsuden 12 | 13 | Update sound more often? See NitroSwan. 14 | 15 | Add Casio PV-2000? http://www43.tok2.com/home/cmpslv/Pv2000/EnrPV.htm 16 | Add TOMY PuyTa? Tomy Tutor? 17 | VDP Test crashes in MegaDrive test? 18 | Check size of used SRAM 8kB, 16kB, 24kB & 32kB. 19 | Try to save SRAM if it exists? 20 | Add more mappers for Korean SMS games. games database? 21 | Add mapper chooser for MSX. 22 | Fix real IO-map for SC-3000. 23 | Map SMS palette to GG palette in GGSMS mode. 24 | 25 | Sprite glitch in Tetris? 26 | 27 | 28 | Misc: 29 | Add loadCard for SMS1/MD. 30 | Terebi Oekaki/Graphic Board support? 31 | Light Phaser support? 32 | Add SMS(J) as options in machine? 33 | ActionReplay/GameGenie support? 34 | Add MSX second slot FFFF? 35 | Save region & machine? 36 | EEPROM support for some GG titles. 37 | VGM logging? 38 | Add Arcade System-1 & System-2? 39 | SG-1000 has 1kB RAM. Done. 40 | SC-3000 (and OMV?) has 2kB RAM. Done. 41 | Add MegaDrive joypad emulation. Done? 42 | 50Hz fps display wrong? Done. 43 | System-E, decryption? 44 | Check 2player in F-16 Fightin Falcon (J). 45 | Fix Arcade Mega-Tech. 46 | 47 | GUI: 48 | Show cart inserted/ejected. 49 | Pad left and right to switch Tabs in GUI? 50 | 51 | Sound: 52 | Pitch is wrong? 53 | Add YM2413? 54 | 55 | Games: 56 | PitFighter, scroll glitch. 57 | BattleToads GG, check old revisions. VDP loop hang? 58 | Terminator 2 Judgement Day.gg, test! Glitches on CrabEmu. 59 | Moldorian(JP).gg - Sensitive to startup timing, HIrq timing? 60 | Super Tetris - doesn't work on export SMS? 61 | Excellent Dizzy Collection - Changes screen resolution before it hangs? 62 | 63 | CPU: 64 | 65 | Arcade: 66 | SG1kAC: 67 | chboxing 68 | chwrestl 69 | dokidoki 70 | 71 | System-E: 72 | astrofl 73 | fantzn2 74 | hangonjr 75 | megrescu 76 | opaopa 77 | ridleofp 78 | tetrisse 79 | transfrm 80 | 81 | MegaTech: 82 | mt_aftrb 83 | mt_astro 84 | mt_asyn 85 | mt_ggolf 86 | mt_gsocr 87 | mt_orun 88 | mt_parlg 89 | mt_shnbi 90 | 91 | 92 | 93 | 94 | Code: 95 | 96 | 97 | DAA table: 98 | -------------------------------------------- 99 | |H in| val |N|H out| out | 100 | | 0 | 0-9 |0| 0 | 0-9 | 101 | | 0 | A-F |0| 1 | 0-5 | 102 | | 1 | 0-9 |0| 0 | 6-F | 103 | | 1 | A-F |0| 1 | 0-5 | 104 | 105 | | 0 | 0-9 |1| 0 | 0-9 | 106 | | 0 | A-F |1| 0 | 4-9 | 107 | | 1 | 0-5 |1| 1 | A-F | 108 | | 1 | 6-F |1| 0 | 0-9 | 109 | | | | | | 110 | 111 | 112 | 113 | 114 | mov r0,z80a,lsl#4 115 | cmn r0,#0x60000000 ;@ check low nybble and save top nybble for H check 116 | tstcc z80f,z80f,lsr#5 ;@ PSR_H to carry. 117 | orrcs r0,r0,#0x06 118 | 119 | cmn z80a,#0x66000000 120 | tstcc z80f,z80f,lsr#2 ;@ PSR_C to carry. 121 | orrcs r0,r0,#0x60 122 | 123 | ands z80f,z80f,#PSR_n ;@ check if last instruction was add or sub. 124 | orrcs z80f,z80f,#PSR_C ;@ the ands doesn't change carry as long as it doesn't have to shift the imidiate value. 125 | 126 | rsbne r0,r0,#0x100 127 | add z80a,z80a,r0,lsl#24 128 | get_pzs_tbl r2 129 | ldrb r2,[r2,z80a,lsr#24] ;@ get PZS 130 | orr z80f,z80f,r2 131 | adds r0,r0,r0,lsl#28 132 | orrcs z80f,z80f,#PSR_H 133 | 134 | -------------------------------------------------------------------------------- /Sms.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/Sms.bmp -------------------------------------------------------------------------------- /copytodsx.bat: -------------------------------------------------------------------------------- 1 | copy S8DS.nds h:\apps -------------------------------------------------------------------------------- /graphics/ColecoNumpad.grit: -------------------------------------------------------------------------------- 1 | 2 | -gB 4 3 | 4 | # use lz77 compression 5 | -gzl 6 | 7 | # map output, lz77 compression 8 | -mzl 9 | 10 | # standard 4bpp tilereduction 11 | -mR4 -------------------------------------------------------------------------------- /graphics/ColecoNumpad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/ColecoNumpad.png -------------------------------------------------------------------------------- /graphics/GG.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 13 | 14 | #palette options 15 | -pn32 -------------------------------------------------------------------------------- /graphics/GG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/GG.png -------------------------------------------------------------------------------- /graphics/MD.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 13 | 14 | # palette options 15 | -pn32 -------------------------------------------------------------------------------- /graphics/MD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/MD.png -------------------------------------------------------------------------------- /graphics/MSX.grit: -------------------------------------------------------------------------------- 1 | 2 | -gB 4 3 | 4 | # use lz77 compression 5 | -gzl 6 | 7 | # map output, lz77 compression 8 | -mzl 9 | 10 | # standard 4bpp tilereduction 11 | -mR4 12 | 13 | # palette options 14 | -pn32 -------------------------------------------------------------------------------- /graphics/MSX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/MSX.png -------------------------------------------------------------------------------- /graphics/Mark3.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 -------------------------------------------------------------------------------- /graphics/Mark3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/Mark3.png -------------------------------------------------------------------------------- /graphics/OmvBgr.grit: -------------------------------------------------------------------------------- 1 | 2 | -gB 4 3 | 4 | # use lz77 compression 5 | -gzl 6 | 7 | # map output, lz77 compression 8 | -mzl 9 | 10 | # standard 4bpp tilereduction 11 | -mR4 12 | 13 | # palette options 14 | -pn32 -------------------------------------------------------------------------------- /graphics/OmvBgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/OmvBgr.png -------------------------------------------------------------------------------- /graphics/SC3000.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 13 | 14 | # palette options 15 | -pn32 -------------------------------------------------------------------------------- /graphics/SC3000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/SC3000.png -------------------------------------------------------------------------------- /graphics/SG1000-II.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 -------------------------------------------------------------------------------- /graphics/SG1000-II.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/SG1000-II.png -------------------------------------------------------------------------------- /graphics/SG1000.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 -------------------------------------------------------------------------------- /graphics/SG1000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/SG1000.png -------------------------------------------------------------------------------- /graphics/SMS1.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # graphics output, lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 -------------------------------------------------------------------------------- /graphics/SMS1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/SMS1.png -------------------------------------------------------------------------------- /graphics/SMS2.grit: -------------------------------------------------------------------------------- 1 | 2 | # output 4bit tiles 3 | -gB 4 4 | 5 | # use lz77 compression 6 | -gzl 7 | 8 | # map output, lz77 compression 9 | -mzl 10 | 11 | # standard 4bpp tilereduction 12 | -mR4 -------------------------------------------------------------------------------- /graphics/SMS2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/SMS2.png -------------------------------------------------------------------------------- /graphics/SordM5Kb.grit: -------------------------------------------------------------------------------- 1 | 2 | -gB 4 3 | 4 | # use lz77 compression 5 | -gzl 6 | 7 | # map output, lz77 compression 8 | -mzl 9 | 10 | # standard 4bpp tilereduction 11 | -mR4 12 | 13 | # palette options 14 | -pn32 -------------------------------------------------------------------------------- /graphics/SordM5Kb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/graphics/SordM5Kb.png -------------------------------------------------------------------------------- /include/MiniBios.sms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FluBBaOfWard/S8DS/b7e65d1c2238616e4934b2b9b8ffaab3868cdefa/include/MiniBios.sms -------------------------------------------------------------------------------- /s8ds.pnps: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source/Cart.h: -------------------------------------------------------------------------------- 1 | #ifndef CART_HEADER 2 | #define CART_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern u32 g_ROM_Size; 9 | extern u32 gEmuFlags; 10 | extern u8 gCartFlags; 11 | extern u8 gConfigSet; 12 | extern u8 gScalingSet; 13 | extern u8 gMachineSet; 14 | extern u8 gMachine; 15 | extern u8 gRegion; 16 | extern u8 gArcadeGameSet; 17 | 18 | extern u8 EMU_SRAM[0x8000]; 19 | extern u8 ROM_Space[0x100000]; 20 | extern u8 BIOS_US_Space[0x40000]; 21 | extern u8 BIOS_JP_Space[0x2000]; 22 | extern u8 BIOS_GG_Space[0x400]; 23 | extern u8 BIOS_COLECO_Space[0x2000]; 24 | extern u8 BIOS_MSX_Space[0x8000]; 25 | extern u8 BIOS_SORDM5_Space[0x2000]; 26 | extern void *g_BIOSBASE_US; 27 | extern void *g_BIOSBASE_JP; 28 | extern void *g_BIOSBASE_GG; 29 | extern void *g_BIOSBASE_COLECO; 30 | extern void *g_BIOSBASE_MSX; 31 | extern void *g_BIOSBASE_SORDM5; 32 | 33 | void loadCart(int); 34 | void ejectCart(void); 35 | 36 | /** 37 | * Saves the state of cart to the destination. 38 | * @param *destination: Where to save the state. 39 | * @return The size of the state. 40 | */ 41 | int cartSaveState(void *destination); 42 | 43 | /** 44 | * Loads the state of cart from the source. 45 | * @param *source: Where to load the state from. 46 | * @return The size of the state. 47 | */ 48 | int cartLoadState(const void *source); 49 | 50 | /** 51 | * Gets the state size of cart state. 52 | * @return The size of the state. 53 | */ 54 | int cartGetStateSize(void); 55 | 56 | #ifdef __cplusplus 57 | } // extern "C" 58 | #endif 59 | 60 | #endif // CART_HEADER 61 | -------------------------------------------------------------------------------- /source/Emubase.h: -------------------------------------------------------------------------------- 1 | #ifndef EMUBASE 2 | #define EMUBASE 3 | 4 | typedef struct { //(config struct) 5 | char magic[4]; //="CFG",0 6 | int emuSettings; 7 | int sleepTime; // autoSleepTime 8 | u8 scaling; // from gfx.s 9 | u8 flicker; // from gfx.s 10 | u8 gammaValue; // from gfx.s 11 | u8 sprites; // from gfx.s 12 | u8 glasses; // from gfx.s 13 | u8 config; // from cart.s 14 | u8 controller; // from io.s 15 | u8 dipSwitch0; // from io.s 16 | char currentPath[256]; 17 | char biosUS[256]; 18 | char biosJP[256]; 19 | char biosGG[256]; 20 | char biosCOLECO[256]; 21 | char biosMSX[256]; 22 | char biosSORDM5[256]; 23 | } ConfigData; 24 | 25 | #endif // EMUBASE 26 | -------------------------------------------------------------------------------- /source/Equates.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | //-----------------------------------------------------------machine 4 | #define HW_AUTO (0x00) 5 | #define HW_SG1000 (0x01) 6 | #define HW_SC3000 (0x02) 7 | #define HW_OMV (0x03) 8 | #define HW_SG1000II (0x04) 9 | #define HW_MARK3 (0x05) 10 | #define HW_SMS1 (0x06) 11 | #define HW_SMS2 (0x07) 12 | #define HW_GG (0x08) 13 | #define HW_MEGADRIVE (0x09) 14 | #define HW_COLECO (0x0A) 15 | #define HW_MSX (0x0B) 16 | #define HW_SORDM5 (0x0C) 17 | #define HW_SYSE (0x0D) 18 | #define HW_SGAC (0x0E) 19 | #define HW_MEGATECH (0x0F) 20 | 21 | #define HW_SELECT_END (0x0D) 22 | //-----------------------------------------------------------region 23 | #define REGION_AUTO 0 24 | #define REGION_US 1 25 | #define REGION_PAL 2 26 | #define REGION_JAPAN 3 27 | //-----------------------------------------------------------cartflags 28 | #define SRAMFLAG (0x02) // Save SRAM 29 | //-----------------------------------------------------------emuflags 30 | #define PALTIMING (0x0001) // 0=NTSC 1=PAL timing 31 | #define COUNTRY (0x0002) // 0=Export 1=JAP 32 | #define GG_MODE (0x0004) // 0=SMS mode, 1=GG mode 33 | #define SG_MODE (0x0008) // 0=SMS mode, 1=SG mode 34 | #define SC_MODE (0x0010) // 0=SMS mode, 1=SC mode 35 | #define OMV_MODE (0x0020) // 0=SMS mode, 1=OMV mode 36 | #define MD_MODE (0x0040) // 0=SMS mode, 1=MegaDrive mode 37 | #define SGAC_MODE (0x0080) // 0=SMS mode, 1=SG-Arcade mode 38 | #define COL_MODE (0x0100) // 0=SMS mode, 1=Coleco mode 39 | #define MSX_MODE (0x0200) // 0=SMS mode, 1=MSX mode 40 | #define SORDM5_MODE (0x0400) // 0=SMS mode, 1=SordM5 mode 41 | #define SYSE_MODE (0x0800) // 0=SMS mode, 1=System E mode 42 | #define MT_MODE (0x1000) // 0=SMS mode, 1=MegaTech mode 43 | 44 | 45 | #define SCALED_1_1 0 // Display types 46 | #define SCALED_FIT 1 47 | #define SCALED_ASPECT 2 48 | 49 | //------------------------------------------------------- Arcade games 50 | #define AC_NONE (0x00) 51 | #define AC_CHAMPION_BOXING (0x01) 52 | #define AC_CHAMPION_WRESTLING (0x02) 53 | #define AC_DOKI_DOKI_PENGUIN (0x03) 54 | #define AC_SUPER_DERBY (0x04) 55 | #define AC_SUPER_DERBY_II (0x05) 56 | #define AC_HANG_ON_JR (0x10) 57 | #define AC_SLAP_SHOOTER (0x11) 58 | #define AC_TRANSFORMER (0x12) 59 | #define AC_ASTRO_FLASH (0x13) 60 | #define AC_RIDDLE_OF_PYTHAGORAS (0x14) 61 | #define AC_OPA_OPA (0x15) 62 | #define AC_OPA_OPA_N (0x16) 63 | #define AC_FANTASY_ZONE_2 (0x17) 64 | #define AC_TETRIS (0x18) 65 | #define AC_MEGUMI_RESCUE (0x19) 66 | #define AC_MT_GREAT_GOLF (0x20) 67 | #define AC_MT_GREAT_SOCCER (0x21) 68 | #define AC_MT_OUT_RUN (0x22) 69 | #define AC_MT_ALIEN_SYNDROME (0x23) 70 | #define AC_MT_SHINOBI (0x24) 71 | #define AC_MT_FANTASY_ZONE (0x25) 72 | #define AC_MT_AFTER_BURNER (0x26) 73 | #define AC_MT_ASTRO_WARRIOR (0x27) 74 | #define AC_MT_KUNG_FU_KID (0x28) 75 | #define AC_MT_GREAT_FOOTBALL (0x29) 76 | #define AC_MT_PARLOUR_GAMES (0x2A) 77 | -------------------------------------------------------------------------------- /source/FileHandling.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "FileHandling.h" 6 | #include "Emubase.h" 7 | #include "Main.h" 8 | #include "Shared/EmuMenu.h" 9 | #include "Shared/EmuSettings.h" 10 | #include "Shared/FileHelper.h" 11 | #include "Gui.h" 12 | #include "RomLoading.h" 13 | #include "Equates.h" 14 | #include "SegaVDP/SegaVDP.h" 15 | #include "Cart.h" 16 | #include "Gfx.h" 17 | #include "io.h" 18 | 19 | static const char *const folderName = "s8ds"; 20 | static const char *const settingName = "settings.cfg"; 21 | 22 | 23 | static ConfigData cfg; 24 | 25 | //static char tempState[STATESIZE]; 26 | 27 | //--------------------------------------------------------------------------------- 28 | int loadSettings() { 29 | FILE *file; 30 | 31 | cfg.currentPath[0] = 0; 32 | cfg.biosUS[0] = 0; 33 | cfg.biosJP[0] = 0; 34 | cfg.biosGG[0] = 0; 35 | cfg.biosCOLECO[0] = 0; 36 | cfg.biosMSX[0] = 0; 37 | cfg.biosSORDM5[0] = 0; 38 | if (findFolder(folderName)) { 39 | return 1; 40 | } 41 | if ( (file = fopen(settingName, "r")) ) { 42 | fread(&cfg, 1, sizeof(ConfigData), file); 43 | fclose(file); 44 | if (!strstr(cfg.magic, "cfg")) { 45 | infoOutput("Error in settings file."); 46 | return 1; 47 | } 48 | } else { 49 | infoOutput("Couldn't open file:"); 50 | infoOutput(settingName); 51 | return 1; 52 | } 53 | 54 | // gDipSwitch0 = cfg.dipSwitch0; 55 | // gDipSwitch1 = cfg.dipSwitch1; 56 | SPRS = cfg.sprites; 57 | g3DEnable = cfg.glasses; 58 | gConfigSet = cfg.config; 59 | gScalingSet = cfg.scaling & 3; 60 | gFlicker = cfg.flicker & 1; 61 | gGammaValue = cfg.gammaValue & 0x7; 62 | gColorValue = (cfg.gammaValue>>4) & 0x7; 63 | emuSettings = cfg.emuSettings & ~EMUSPEED_MASK; // Clear speed setting. 64 | sleepTime = cfg.sleepTime; 65 | joyCfg = (joyCfg & ~0x400) | ((cfg.controller & 1)<<10); 66 | strlcpy(currentDir, cfg.currentPath, sizeof(currentDir)); 67 | 68 | infoOutput("Settings loaded."); 69 | return 0; 70 | } 71 | 72 | void saveSettings() { 73 | FILE *file; 74 | 75 | strcpy(cfg.magic, "cfg"); 76 | // cfg.dipSwitch0 = gDipSwitch0; 77 | cfg.sprites = SPRS; 78 | cfg.glasses = g3DEnable; 79 | cfg.config = gConfigSet; 80 | cfg.scaling = gScalingSet & 3; 81 | cfg.flicker = gFlicker & 1; 82 | cfg.gammaValue = (gGammaValue & 0x7)|((gColorValue & 0x7)<<4); 83 | cfg.emuSettings = emuSettings & ~EMUSPEED_MASK; // Clear speed setting. 84 | cfg.sleepTime = sleepTime; 85 | cfg.controller = (joyCfg>>10) & 1; 86 | strlcpy(cfg.currentPath, currentDir, sizeof(cfg.currentPath)); 87 | 88 | if ( findFolder(folderName) ) { 89 | return; 90 | } 91 | if ( (file = fopen(settingName, "w")) ) { 92 | fwrite(&cfg, 1, sizeof(ConfigData), file); 93 | fclose(file); 94 | infoOutput("Settings saved."); 95 | } else { 96 | infoOutput("Couldn't open file:"); 97 | infoOutput(settingName); 98 | } 99 | } 100 | 101 | int loadNVRAM() { 102 | return loadSRAM(); 103 | } 104 | int loadSRAM() { 105 | FILE *file; 106 | char sramName[FILENAME_MAX_LENGTH]; 107 | 108 | if (findFolder(folderName)) { 109 | return 1; 110 | } 111 | setFileExtension(sramName, currentFilename, ".sav", sizeof(sramName)); 112 | if ( (file = fopen(sramName, "r")) ) { 113 | fread(EMU_SRAM, 1, 0x2000, file); 114 | fclose(file); 115 | infoOutput("Loaded SRAM."); 116 | } else { 117 | return 1; 118 | } 119 | return 0; 120 | } 121 | void saveNVRAM() { 122 | saveSRAM(); 123 | } 124 | void saveSRAM() { 125 | FILE *file; 126 | char sramName[FILENAME_MAX_LENGTH]; 127 | 128 | if (findFolder(folderName)) { 129 | return; 130 | } 131 | setFileExtension(sramName, currentFilename, ".sav", sizeof(sramName)); 132 | if ( (file = fopen(sramName, "w")) ) { 133 | fwrite(EMU_SRAM, 1, 0x2000, file); 134 | fclose(file); 135 | infoOutput("Saved SRAM."); 136 | } 137 | } 138 | 139 | void loadState() { 140 | loadDeviceState(folderName); 141 | } 142 | 143 | void saveState() { 144 | saveDeviceState(folderName); 145 | } 146 | 147 | bool loadGame(const char *gameName) { 148 | char fileExt[8]; 149 | if (gameName) { 150 | cls(0); 151 | drawText(" Please wait, loading.", 11, 0); 152 | gEmuFlags &= ~(MD_MODE|GG_MODE|SG_MODE|SC_MODE|COL_MODE|MSX_MODE|SORDM5_MODE|SGAC_MODE|SYSE_MODE|MT_MODE); 153 | g_ROM_Size = loadROM(ROM_Space, gameName, 0x100000); 154 | if (!g_ROM_Size) { 155 | g_ROM_Size = loadArcadeROM(ROM_Space, gameName); 156 | } 157 | if (g_ROM_Size) { 158 | getFileExtension(fileExt, currentFilename); 159 | if (strstr(fileExt, ".gg")) { 160 | gEmuFlags |= GG_MODE; 161 | } 162 | else if (strstr(fileExt, ".sg")) { 163 | gEmuFlags |= SG_MODE; 164 | } 165 | else if (strstr(fileExt, ".sc")) { 166 | gEmuFlags |= SC_MODE; 167 | } 168 | else if ((strstr(fileExt, ".mx1") || strstr(fileExt, ".mx2") || strstr(fileExt, ".rom")) 169 | && ((ROM_Space[0] == 0x41 && ROM_Space[1] == 0x42) || (ROM_Space[0x4000] == 0x41 && ROM_Space[0x4001] == 0x42))) { 170 | gEmuFlags |= MSX_MODE; 171 | } 172 | else if ((strstr(fileExt, ".col") || strstr(fileExt, ".rom")) 173 | && ((ROM_Space[0] == 0xAA && ROM_Space[1] == 0x55) || (ROM_Space[0] == 0x55 && ROM_Space[1] == 0xAA))) { 174 | gEmuFlags |= COL_MODE; 175 | } 176 | else if (strstr(fileExt, ".rom") 177 | && (ROM_Space[0] == 0x00 || ROM_Space[0] == 0x02)) { 178 | gEmuFlags |= SORDM5_MODE; 179 | } 180 | setEmuSpeed(0); 181 | loadCart(gEmuFlags); 182 | loadSRAM(); 183 | if (emuSettings & AUTOLOAD_STATE) { 184 | loadState(); 185 | } 186 | gameInserted = true; 187 | powerButton = true; 188 | closeMenu(); 189 | return false; 190 | } 191 | } 192 | return true; 193 | } 194 | 195 | void selectGame() { 196 | pauseEmulation = true; 197 | ui10(); 198 | const char *gameName = browseForFileType(FILEEXTENSIONS".zip"); 199 | if (loadGame(gameName)) { 200 | backOutOfMenu(); 201 | } 202 | } 203 | 204 | static bool selectBios(const char *fileTypes, char *dest) { 205 | const char *biosName = browseForFileType(fileTypes); 206 | cls(0); 207 | 208 | if (biosName) { 209 | strlcpy(dest, currentDir, FILEPATH_MAX_LENGTH); 210 | strlcat(dest, "/", FILEPATH_MAX_LENGTH); 211 | strlcat(dest, biosName, FILEPATH_MAX_LENGTH); 212 | return true; 213 | } 214 | return false; 215 | } 216 | 217 | void selectUSBios() { 218 | if (selectBios(".sms.zip", cfg.biosUS)) { 219 | loadUSBIOS(); 220 | } 221 | } 222 | 223 | void selectJPBios() { 224 | if (selectBios(".sms.zip", cfg.biosJP)) { 225 | loadJPBIOS(); 226 | } 227 | } 228 | 229 | void selectGGBios() { 230 | if (selectBios(".gg.zip", cfg.biosGG)) { 231 | loadGGBIOS(); 232 | } 233 | } 234 | 235 | void selectCOLECOBios() { 236 | if (selectBios(".rom.col.zip", cfg.biosCOLECO)) { 237 | loadCOLECOBIOS(); 238 | } 239 | } 240 | 241 | void selectMSXBios() { 242 | if (selectBios(".mx1.mx2.rom.zip", cfg.biosMSX)) { 243 | loadMSXBIOS(); 244 | } 245 | } 246 | 247 | void selectSORDM5Bios() { 248 | if (selectBios(".ic21.rom.zip", cfg.biosSORDM5)) { 249 | loadSORDM5BIOS(); 250 | } 251 | } 252 | 253 | static int loadBIOS(void *dest, const char *fPath, const int maxSize) { 254 | char tempString[FILEPATH_MAX_LENGTH]; 255 | char *sPtr; 256 | 257 | strlcpy(tempString, fPath, sizeof(tempString)); 258 | if ((sPtr = strrchr(tempString, '/'))) { 259 | sPtr[0] = 0; 260 | sPtr += 1; 261 | chdir("/"); 262 | chdir(tempString); 263 | return loadROM(dest, sPtr, maxSize); 264 | } 265 | return 0; 266 | } 267 | 268 | int loadUSBIOS(void) { 269 | if (loadBIOS(BIOS_US_Space, cfg.biosUS, sizeof(BIOS_US_Space))) { 270 | g_BIOSBASE_US = BIOS_US_Space; 271 | return 1; 272 | } 273 | g_BIOSBASE_US = NULL; 274 | return 0; 275 | } 276 | 277 | int loadJPBIOS(void) { 278 | if (loadBIOS(BIOS_JP_Space, cfg.biosJP, sizeof(BIOS_JP_Space))) { 279 | g_BIOSBASE_JP = BIOS_JP_Space; 280 | return 1; 281 | } 282 | g_BIOSBASE_JP = NULL; 283 | return 0; 284 | } 285 | 286 | int loadGGBIOS(void) { 287 | if (loadBIOS(BIOS_GG_Space, cfg.biosGG, sizeof(BIOS_GG_Space))) { 288 | g_BIOSBASE_GG = BIOS_GG_Space; 289 | return 1; 290 | } 291 | g_BIOSBASE_GG = NULL; 292 | return 0; 293 | } 294 | 295 | int loadCOLECOBIOS(void) { 296 | if (loadBIOS(BIOS_COLECO_Space, cfg.biosCOLECO, sizeof(BIOS_COLECO_Space))) { 297 | g_BIOSBASE_COLECO = BIOS_COLECO_Space; 298 | return 1; 299 | } 300 | g_BIOSBASE_COLECO = NULL; 301 | return 0; 302 | } 303 | 304 | int loadMSXBIOS(void) { 305 | if (loadBIOS(BIOS_MSX_Space, cfg.biosMSX, sizeof(BIOS_MSX_Space))) { 306 | g_BIOSBASE_MSX = BIOS_MSX_Space; 307 | return 1; 308 | } 309 | g_BIOSBASE_MSX = NULL; 310 | return 0; 311 | } 312 | 313 | int loadSORDM5BIOS(void) { 314 | if (loadBIOS(BIOS_SORDM5_Space, cfg.biosSORDM5, sizeof(BIOS_SORDM5_Space))) { 315 | g_BIOSBASE_SORDM5 = BIOS_SORDM5_Space; 316 | return 1; 317 | } 318 | g_BIOSBASE_SORDM5 = NULL; 319 | return 0; 320 | } 321 | -------------------------------------------------------------------------------- /source/FileHandling.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEHANDLING_HEADER 2 | #define FILEHANDLING_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "MasterSystem.h" 9 | 10 | #define FILEEXTENSIONS ".sms.gg.sg.sc.col.rom.mx1.mx2" 11 | 12 | int loadSettings(void); 13 | void saveSettings(void); 14 | bool loadGame(const char *gameName); 15 | void loadState(void); 16 | void saveState(void); 17 | int loadNVRAM(void); 18 | int loadSRAM(void); 19 | void saveNVRAM(void); 20 | void saveSRAM(void); 21 | void selectGame(void); 22 | void selectUSBios(void); 23 | void selectJPBios(void); 24 | void selectGGBios(void); 25 | void selectCOLECOBios(void); 26 | void selectMSXBios(void); 27 | void selectSORDM5Bios(void); 28 | int loadUSBIOS(void); 29 | int loadJPBIOS(void); 30 | int loadGGBIOS(void); 31 | int loadCOLECOBIOS(void); 32 | int loadMSXBIOS(void); 33 | int loadSORDM5BIOS(void); 34 | 35 | #ifdef __cplusplus 36 | } // extern "C" 37 | #endif 38 | 39 | #endif // FILEHANDLING_HEADER 40 | -------------------------------------------------------------------------------- /source/Gfx.h: -------------------------------------------------------------------------------- 1 | #ifndef GFX_HEADER 2 | #define GFX_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "SegaVDP/SegaVDP.h" 9 | 10 | extern u8 gFlicker; 11 | extern u8 gTwitch; 12 | extern u8 gGfxMask; 13 | extern u8 gColorValue; 14 | extern u8 g3DEnable; 15 | extern u8 bColor; 16 | extern u8 SPRS; 17 | 18 | extern SegaVDP VDP0; 19 | extern u16 EMUPALBUFF[200]; 20 | 21 | void gfxInit(void); 22 | void vblIrqHandler(void); 23 | void antWars(void); 24 | void paletteInit(u8 gammaVal); 25 | void mapSGPalette(u8 gammaVal); 26 | void paletteTxAll(void); 27 | void refreshGfx(void); 28 | void makeBorder(void); 29 | void setupScaling(void); 30 | 31 | void VDP0ApplyScaling(void); 32 | void VDP0SetMode(void); 33 | void VDP0ScanlineBPReset(void); 34 | 35 | #ifdef __cplusplus 36 | } // extern "C" 37 | #endif 38 | 39 | #endif // GFX_HEADER 40 | -------------------------------------------------------------------------------- /source/Gui.h: -------------------------------------------------------------------------------- 1 | #ifndef GUI_HEADER 2 | #define GUI_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern u8 gGammaValue; 9 | 10 | void setupGUI(void); 11 | void enterGUI(void); 12 | void exitGUI(void); 13 | void nullUINormal(int key); 14 | void nullUIDebug(int key); 15 | 16 | void uiNullNormal(void); 17 | 18 | void ejectGame(void); 19 | void sdscHandler(const unsigned char sdscChar); 20 | void debugIOUnimplR(u16 port); 21 | void debugIOUnimplW(u8 val, u16 port); 22 | 23 | #ifdef __cplusplus 24 | } // extern "C" 25 | #endif 26 | 27 | #endif // GUI_HEADER 28 | -------------------------------------------------------------------------------- /source/MSXIO.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "AY38910/AY38910.i" 4 | #include "PPI8255/PPI8255.i" 5 | 6 | .global IO_Params_MSX_R 7 | .global IO_Params_MSX_W 8 | 9 | .global msxReset 10 | .global MSXJoyReadCallBack 11 | 12 | .syntax unified 13 | .arm 14 | 15 | .section .text 16 | .align 2 17 | ;@---------------------------------------------------------------------------- 18 | ;@ MSX 19 | IO_Params_MSX_R: 20 | .long 0x009800FF, VDP0DataR ;@ 0x98 VDP Data 21 | .long 0x009900FF, VDP0StatR ;@ 0x99 VDP Ctrl 22 | .long 0x00A200FF, AY38910Data_0_R ;@ 0xA2 AY38910DataR 23 | .long 0x00A800FF, PPI1PortAR ;@ 0xA8 PPI Port A, PSLOT_R 24 | .long 0x00A900FF, PPI1PortBR ;@ 0xA9 PPI Port B, Keyboard_R 25 | .long 0x00AA00FF, PPI1PortCR ;@ 0xAA PPI Port C, Keyb_Row_W 26 | .long 0x00AB00FF, PPI1PortDR ;@ 0xAB PPI Ctrl_R 27 | // .long 0x00FC00FF, empty_R ;@ 0xFC RAM slot for $0000 28 | // .long 0x00FD00FF, empty_R ;@ 0xFD RAM slot for $4000 29 | // .long 0x00FE00FF, empty_R ;@ 0xFE RAM slot for $8000 30 | // .long 0x00FF00FF, empty_R ;@ 0xFF RAM slot for $C000 31 | .long 0x00000000, empty_R ;@ everything else 32 | IO_Params_MSX_W: 33 | // .long 0x009000FF, empty_W ;@ 0x90 Cent_W 34 | .long 0x009800FF, VDP0DataTMSW ;@ 0x98 VDP Data 35 | .long 0x009900FF, VDP0CtrlW ;@ 0x99 VDP Ctrl 36 | // .long 0x009A00FF, VDP0DataTMSW ;@ 0x9A MVDP MSX2 37 | // .long 0x009B00FF, VDP0CtrlW ;@ 0x9B MVDP MSX2 38 | .long 0x00A000FF, AY38910Index_0_W ;@ 0xA0 AY38910IndexW 39 | .long 0x00A100FF, AY38910Data_0_W ;@ 0xA1 AY38910DataW 40 | .long 0x00A800FF, PPI1PortAW ;@ 0xA8 PPI Port A, PSlot_W 41 | .long 0x00A900FF, PPI1PortBW ;@ 0xA9 PPI Port B 42 | .long 0x00AA00FF, PPI1PortCW ;@ 0xAA PPI Port C, Keyb_Row_W 43 | .long 0x00AB00FF, PPI1PortDW ;@ 0xAB PPI Ctrl_W 44 | .long 0x00FC00FF, MSXMapRAM0W ;@ 0xFC RAM slot for $0000 45 | .long 0x00FD00FF, MSXMapRAM1W ;@ 0xFD RAM slot for $4000 46 | .long 0x00FE00FF, MSXMapRAM2W ;@ 0xFE RAM slot for $8000 47 | .long 0x00FF00FF, MSXMapRAM3W ;@ 0xFF RAM slot for $C000 48 | .long 0x00000000, empty_W ;@ everything else 49 | 50 | ;@---------------------------------------------------------------------------- 51 | msxReset: 52 | ;@---------------------------------------------------------------------------- 53 | stmfd sp!,{r4,lr} 54 | 55 | bl PPI1Reset 56 | ldr r0,=PSlot_W 57 | str r0,[ppiptr,#ppiPortAOutFptr] 58 | ldr r0,=IOPortB_MSX_R 59 | str r0,[ppiptr,#ppiPortBInFptr] 60 | 61 | ldmfd sp!,{r4,lr} 62 | bx lr 63 | 64 | ;@---------------------------------------------------------------------------- 65 | IOPortB_MSX_R: ;@ KB/Printer/Cassette input, PPI_PortB 66 | ;@---------------------------------------------------------------------------- 67 | mov r0,#0xFF ;@ Default output 68 | ldrb r1,[ppiptr,#ppiPortCOut] 69 | and r1,r1,#0xF 70 | ldr r2,=sc3Keyboard 71 | ldrb r2,[r2] 72 | cmp r1,r2,lsr#4 ;@ check row 73 | bxne lr 74 | and r2,r2,#0x07 75 | mov r1,#1 76 | bic r0,r0,r1,lsl r2 77 | bx lr 78 | ;@---------------------------------------------------------------------------- 79 | PSlot_W: ;@ MSX PSLOT, PPI_PortA 80 | ;@---------------------------------------------------------------------------- 81 | stmfd sp!,{r3,lr} 82 | ldr r1,=BankMap0 83 | ldrb r3,[r1] 84 | strb r0,[r1] 85 | eor r3,r3,r0 ;@ Which Banks are changed? 86 | tst r3,#0x03 87 | blne BankMSX0_W 88 | tst r3,#0x0C 89 | blne BankMSX1_W 90 | tst r3,#0x30 91 | blne BankMSX2_W 92 | tst r3,#0xC0 93 | blne BankMSX3_W 94 | ldmfd sp!,{r3,lr} 95 | bx lr 96 | ;@---------------------------------------------------------------------------- 97 | MSXJoyReadCallBack: ;@ r0=ayptr 98 | ;@---------------------------------------------------------------------------- 99 | ldrb r1,[r0,#ayPortBOut] 100 | tst r1,#0x40 101 | ldreq r0,=joy0State 102 | ldrne r0,=joy1State 103 | ldrb r0,[r0] 104 | bx lr 105 | 106 | ;@---------------------------------------------------------------------------- 107 | .end 108 | #endif // #ifdef __arm__ 109 | -------------------------------------------------------------------------------- /source/Main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "Main.h" 6 | #include "Shared/EmuMenu.h" 7 | #include "Shared/FileHelper.h" 8 | #include "Shared/AsmExtra.h" 9 | #include "Gui.h" 10 | #include "ym2413.h" 11 | #include "FileHandling.h" 12 | #include "EmuFont.h" 13 | #include "Cart.h" 14 | #include "cpu.h" 15 | #include "Gfx.h" 16 | #include "io.h" 17 | #include "Sound.h" 18 | 19 | static void checkTimeOut(void); 20 | static void setupGraphics(void); 21 | static void setupStream(void); 22 | 23 | bool powerButton = false; 24 | bool gameInserted = false; 25 | static int sleepTimer = 0x7FFFFFFF; // 5 min 26 | static bool vBlankOverflow = false; 27 | 28 | static mm_ds_system sys; 29 | static mm_stream myStream; 30 | 31 | uint16 *map0sub; 32 | uint16 *map1sub; 33 | 34 | static const u8 guiPalette[] = { 35 | 0x00,0x00,0xC0, 0x00,0x00,0x00, 0x81,0x81,0x81, 0x93,0x93,0x93, 0xA5,0xA5,0xA5, 0xB7,0xB7,0xB7, 0xC9,0xC9,0xC9, 0xDB,0xDB,0xDB, 36 | 0xED,0xED,0xED, 0xFF,0xFF,0xFF, 0x00,0x00,0xC0, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 37 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x50,0x78,0x78, 0x60,0x90,0x90, 0x78,0xB0,0xB0, 0x88,0xC8,0xC8, 0x90,0xE0,0xE0, 0xA0,0xF0,0xF0, 38 | 0xB8,0xF8,0xF8, 0xEF,0xFF,0xFF, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 39 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x21,0x21,0x21, 0x33,0x33,0x33, 0x45,0x45,0x45, 0x47,0x47,0x47, 0x59,0x59,0x59, 0x6B,0x6B,0x6B, 40 | 0x7D,0x7D,0x7D, 0x8F,0x8F,0x8F, 0x20,0x20,0xE0, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 41 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x81,0x81,0x81, 0x93,0x93,0x93, 0xA5,0xA5,0xA5, 0xB7,0xB7,0xB7, 0xC9,0xC9,0xC9, 0xDB,0xDB,0xDB, 42 | 0xED,0xED,0xED, 0xFF,0xFF,0xFF, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 43 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x70,0x70,0x20, 0x88,0x88,0x40, 0xA0,0xA0,0x60, 0xB8,0xB8,0x80, 0xD0,0xD0,0x90, 0xE8,0xE8,0xA0, 44 | 0xF7,0xF7,0xC0, 0xFF,0xFF,0xE0, 0x00,0x00,0x60, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 45 | }; 46 | 47 | //--------------------------------------------------------------------------------- 48 | static void myVblank(void) { 49 | //--------------------------------------------------------------------------------- 50 | vBlankOverflow = true; 51 | DC_FlushRange(EMUPALBUFF, 0x400); 52 | vblIrqHandler(); 53 | } 54 | 55 | //--------------------------------------------------------------------------------- 56 | int main(int argc, char **argv) { 57 | //--------------------------------------------------------------------------------- 58 | if (argc > 1) { 59 | enableExit = true; 60 | } 61 | setupGraphics(); 62 | soundInit(); 63 | gfxInit(); 64 | 65 | setupStream(); 66 | irqSet(IRQ_VBLANK, myVblank); 67 | setupGUI(); 68 | ejectGame(); 69 | // loadCart(0); 70 | if (initFileHelper()) { 71 | loadSettings(); 72 | loadUSBIOS(); 73 | loadJPBIOS(); 74 | loadGGBIOS(); 75 | loadCOLECOBIOS(); 76 | loadMSXBIOS(); 77 | loadSORDM5BIOS(); 78 | if (argc > 1) { 79 | loadGame(argv[1]); 80 | setMuteSoundGUI(); 81 | } 82 | } 83 | else { 84 | infoOutput("fatInitDefault() failure."); 85 | } 86 | // if ( (YM2413Init(1, 3579545, sample_rate)) ) { 87 | // drawText("YMInit failure.",23,0); 88 | // } 89 | getInput(); 90 | 91 | while (1) { 92 | waitVBlank(); 93 | // mmStreamUpdate(); 94 | checkTimeOut(); 95 | guiRunLoop(); 96 | if (powerButton) { 97 | if (!pauseEmulation) { 98 | run(); 99 | } 100 | } 101 | else { 102 | antWars(); 103 | } 104 | } 105 | // YM2413Shutdown(); 106 | return 0; 107 | } 108 | 109 | //--------------------------------------------------------------------------------- 110 | void pausVBlank(int count) { 111 | //--------------------------------------------------------------------------------- 112 | while (--count) { 113 | waitVBlank(); 114 | } 115 | } 116 | 117 | //--------------------------------------------------------------------------------- 118 | void waitVBlank() { 119 | //--------------------------------------------------------------------------------- 120 | // Workaround for bug in Bios. 121 | if (!vBlankOverflow) { 122 | swiIntrWait(1, IRQ_VBLANK); 123 | } 124 | vBlankOverflow = false; 125 | } 126 | 127 | //--------------------------------------------------------------------------------- 128 | static void checkTimeOut() { 129 | //--------------------------------------------------------------------------------- 130 | if (EMUinput) { 131 | sleepTimer = sleepTime; 132 | } 133 | else { 134 | sleepTimer--; 135 | if (sleepTimer < 0) { 136 | sleepTimer = sleepTime; 137 | // systemSleep doesn't work as expected. 138 | //systemSleep(); 139 | } 140 | } 141 | } 142 | 143 | //--------------------------------------------------------------------------------- 144 | void setEmuSpeed(int speed) { 145 | //--------------------------------------------------------------------------------- 146 | if (speed == 0) { // Normal Speed 147 | waitMaskIn = 0x00; 148 | waitMaskOut = 0x00; 149 | } 150 | else if (speed == 1) { // Double speed 151 | waitMaskIn = 0x00; 152 | waitMaskOut = 0x01; 153 | } 154 | else if (speed == 2) { // Max speed (4x) 155 | waitMaskIn = 0x00; 156 | waitMaskOut = 0x03; 157 | } 158 | else if (speed == 3) { // 50% speed 159 | waitMaskIn = 0x01; 160 | waitMaskOut = 0x00; 161 | } 162 | } 163 | 164 | //--------------------------------------------------------------------------------- 165 | static void setupGraphics() { 166 | //--------------------------------------------------------------------------------- 167 | vramSetBankA(VRAM_A_MAIN_BG); 168 | vramSetBankB(VRAM_B_MAIN_BG_0x06020000); 169 | vramSetBankC(VRAM_C_MAIN_BG_0x06040000); 170 | vramSetBankD(VRAM_D_MAIN_BG_0x06060000); 171 | vramSetBankE(VRAM_E_MAIN_SPRITE); 172 | vramSetBankF(VRAM_F_LCD); 173 | vramSetBankG(VRAM_G_LCD); 174 | vramSetBankH(VRAM_H_SUB_BG); 175 | vramSetBankI(VRAM_I_SUB_SPRITE); 176 | 177 | // Set up the main display 178 | videoSetMode(MODE_0_2D 179 | | DISPLAY_SPR_1D_LAYOUT 180 | | DISPLAY_BG0_ACTIVE 181 | | DISPLAY_BG1_ACTIVE 182 | | DISPLAY_BG2_ACTIVE 183 | | DISPLAY_BG3_ACTIVE 184 | | DISPLAY_SPR_ACTIVE 185 | | DISPLAY_WIN0_ON 186 | | DISPLAY_WIN1_ON 187 | ); 188 | 189 | // Set up the sub display 190 | videoSetModeSub(MODE_0_2D 191 | | DISPLAY_BG0_ACTIVE 192 | | DISPLAY_BG1_ACTIVE 193 | ); 194 | // Set up two backgrounds for menu 195 | REG_BG0CNT_SUB = BG_32x32 | BG_MAP_BASE(0) | BG_COLOR_16 | BG_TILE_BASE(0) | BG_PRIORITY(0); 196 | REG_BG1CNT_SUB = BG_32x32 | BG_MAP_BASE(1) | BG_COLOR_16 | BG_TILE_BASE(0) | BG_PRIORITY(0); 197 | REG_BG1HOFS_SUB = 0; 198 | REG_BG1VOFS_SUB = 0; 199 | map0sub = BG_MAP_RAM_SUB(0); 200 | map1sub = BG_MAP_RAM_SUB(1); 201 | 202 | decompress(EmuFontTiles, BG_GFX_SUB+0x1200, LZ77Vram); 203 | setupMenuPalette(); 204 | } 205 | 206 | void setupMenuPalette() { 207 | convertPalette(BG_PALETTE_SUB, guiPalette, sizeof(guiPalette)/3, gGammaValue); 208 | } 209 | 210 | //--------------------------------------------------------------------------------- 211 | static void setupStream(void) { 212 | //--------------------------------------------------------------------------------- 213 | 214 | //---------------------------------------------------------------- 215 | // initialize maxmod without any soundbank (unusual setup) 216 | //---------------------------------------------------------------- 217 | // mm_ds_system sys; 218 | sys.mod_count = 0; 219 | sys.samp_count = 0; 220 | sys.mem_bank = 0; 221 | sys.fifo_channel = FIFO_MAXMOD; 222 | mmInit( &sys ); 223 | 224 | //---------------------------------------------------------------- 225 | // open stream 226 | //---------------------------------------------------------------- 227 | // mm_stream myStream; 228 | myStream.sampling_rate = sample_rate; // sampling rate = 229 | myStream.buffer_length = buffer_size; // buffer length = 230 | // myStream.callback = mix_sound; // set callback function 231 | myStream.callback = VblSound2; // set callback function 232 | myStream.format = MM_STREAM_16BIT_STEREO; // format = stereo 16-bit 233 | myStream.timer = MM_TIMER0; // use hardware timer 0 234 | myStream.manual = false; // use manual filling 235 | mmStreamOpen( &myStream ); 236 | 237 | //---------------------------------------------------------------- 238 | // when using 'automatic' filling, your callback will be triggered 239 | // every time half of the wave buffer is processed. 240 | // 241 | // so: 242 | // 25000 (rate) 243 | // ----- = ~21 Hz for a full pass, and ~42hz for half pass 244 | // 1200 (length) 245 | //---------------------------------------------------------------- 246 | // with 'manual' filling, you must call mmStreamUpdate 247 | // periodically (and often enough to avoid buffer underruns) 248 | //---------------------------------------------------------------- 249 | } 250 | -------------------------------------------------------------------------------- /source/Main.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_HEADER 2 | #define MAIN_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern bool powerButton; 9 | extern bool gameInserted; 10 | extern uint16 *map0sub; 11 | 12 | void waitVBlank(void); 13 | 14 | /** 15 | * Waits the specified number of frames before returning. 16 | * @param count: Number of frames to wait. 17 | * @deprecated Don't use, solve it some other way. 18 | */ 19 | void pausVBlank(int count); 20 | 21 | void setEmuSpeed(int speed); 22 | void setupMenuPalette(void); 23 | 24 | #ifdef __cplusplus 25 | } // extern "C" 26 | #endif 27 | 28 | #endif // MAIN_HEADER 29 | -------------------------------------------------------------------------------- /source/MasterSystem.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "MasterSystem.h" 4 | #include "Cart.h" 5 | #include "Sound.h" 6 | #include "Gfx.h" 7 | #include "ARMZ80/ARMZ80.h" 8 | 9 | 10 | int packState(void *statePtr) { 11 | int size = 0; 12 | size += cartSaveState(statePtr+size); 13 | size += sn76496SaveState(statePtr+size, &SN76496_0); 14 | size += VDPSaveState(statePtr+size, &VDP0); 15 | size += Z80SaveState(statePtr+size, &Z80OpTable); 16 | return size; 17 | } 18 | 19 | void unpackState(const void *statePtr) { 20 | int size = 0; 21 | size += cartLoadState(statePtr+size); 22 | size += sn76496LoadState(&SN76496_0, statePtr+size); 23 | size += VDPLoadState(&VDP0, statePtr+size); 24 | size += Z80LoadState(&Z80OpTable, statePtr+size); 25 | } 26 | 27 | int getStateSize() { 28 | int size = 0; 29 | size += cartGetStateSize(); 30 | size += sn76496GetStateSize(); 31 | size += VDPGetStateSize(); 32 | size += Z80GetStateSize(); 33 | return size; 34 | } 35 | -------------------------------------------------------------------------------- /source/MasterSystem.h: -------------------------------------------------------------------------------- 1 | #ifndef MASTERSYSTEM_HEADER 2 | #define MASTERSYSTEM_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /// This runs all save state functions for each chip. 9 | int packState(void *statePtr); 10 | 11 | /// This runs all load state functions for each chip. 12 | void unpackState(const void *statePtr); 13 | 14 | /// Gets the total state size in bytes. 15 | int getStateSize(void); 16 | 17 | #ifdef __cplusplus 18 | } // extern "C" 19 | #endif 20 | 21 | #endif // MASTERSYSTEM_HEADER 22 | -------------------------------------------------------------------------------- /source/MegaTech.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "ARMZ80/ARMZ80.i" 4 | #include "PPI8255/PPI8255.i" 5 | #include "CXD1095Q/CXD1095Q.i" 6 | 7 | .global IO_Params_MT_R 8 | .global IO_Params_MT_W 9 | 10 | .global megaTechReset 11 | .global MTIORead 12 | .global MTIOWrite 13 | .global MTVDPVCounterR 14 | .global MTVDPHCounterR 15 | .global MTVDPStatR 16 | .global MTVDPDataR 17 | .global MTVDPDataW 18 | .global MTVDPCtrlW 19 | 20 | .global mtIOSelectReg 21 | 22 | .syntax unified 23 | .arm 24 | 25 | .section .text 26 | .align 2 27 | ;@---------------------------------------------------------------------------- 28 | ;@ MegaTech 29 | IO_Params_MT_R: 30 | .long 0x004000C1, MTVDPVCounterR ;@ 0x40-0x7E 31 | .long 0x004100C1, MTVDPHCounterR ;@ 0x41-0x7F 32 | .long 0x008000C1, MTVDPDataR ;@ 0x80-0xBE 33 | .long 0x008100C1, MTVDPStatR ;@ 0x81-0xBF 34 | .long 0x00C000C1, ExtIO_0_SMS_R ;@ 0xC0-0xFE 35 | .long 0x00C100C1, ExtIO_1_SMS_R ;@ 0xC1-0xFF 36 | .long 0x00000000, empty_R ;@ 0x00-0x3F 37 | IO_Params_MT_W: 38 | .long 0x000000C1, MemCtrl_SMS_W ;@ 0x00-0x3E 39 | .long 0x000100C1, IOCtrl_SMS_W ;@ 0x01-0x3F 40 | .long 0x004000C0, SN76496_W ;@ 0x40-0x7F 41 | .long 0x008000C1, MTVDPDataW ;@ 0x80-0xBE 42 | .long 0x008100C1, MTVDPCtrlW ;@ 0x81-0xBF 43 | .long 0x00FD00FF, SDSC_Debug_W ;@ 0xFD 44 | .long 0x00C000C0, ExternalIO_W ;@ 0xC0-0xFF 45 | .long 0x00000000, empty_W ;@ 46 | 47 | ;@---------------------------------------------------------------------------- 48 | megaTechReset: 49 | ;@---------------------------------------------------------------------------- 50 | stmfd sp!,{r4,lr} 51 | 52 | bl CXD1Reset 53 | ldr r0,=dipSwitch0iR 54 | str r0,[cxdptr,#cxdPortAInFptr] 55 | ldr r0,=dipSwitch1iR 56 | str r0,[cxdptr,#cxdPortBInFptr] 57 | ldr r0,=MTCartSelectW 58 | str r0,[cxdptr,#cxdPortEOutFptr] 59 | 60 | bl CXD2Reset 61 | ldr r0,=MTUserInput0R 62 | str r0,[cxdptr,#cxdPortAInFptr] 63 | ldr r0,=MTUserInput1R 64 | str r0,[cxdptr,#cxdPortBInFptr] 65 | ldr r0,=MTCartSenseR 66 | str r0,[cxdptr,#cxdPortCInFptr] 67 | ldr r0,=MTInputCtrlW 68 | str r0,[cxdptr,#cxdPortDOutFptr] 69 | ldr r0,=MTFlashW 70 | str r0,[cxdptr,#cxdPortEOutFptr] 71 | 72 | ldr r1,=dipSwitch0 73 | mov r0,#0x80 74 | strb r0,[r1] 75 | mov r0,#0x0E 76 | strb r0,[r1,#1] 77 | 78 | ldmfd sp!,{r4,lr} 79 | bx lr 80 | 81 | ;@---------------------------------------------------------------------------- 82 | MTIORead: 83 | ;@---------------------------------------------------------------------------- 84 | and r1,addy,#0xFC00 85 | cmp r1,#0x6000 86 | beq CXD0R 87 | cmp r1,#0x6400 88 | beq CXD1R 89 | cmp r1,#0x6800 90 | beq CXD2R 91 | cmp r1,#0x6C00 92 | beq CXD3R 93 | cmp r1,#0x7800 94 | beq MDIOR 95 | and r1,r1,#0xF000 96 | cmp r1,#0x3000 97 | beq BankedRAMR 98 | and r1,r1,#0xE000 99 | cmp r1,#0x8000 100 | beq MDGameR 101 | ldr r1,=cartBase 102 | ldr r1,[r1] 103 | ldrb r0,[r1,addy] 104 | bx lr 105 | ;@---------------------------------------------------------------------------- 106 | MTIOWrite: 107 | ;@---------------------------------------------------------------------------- 108 | and r1,addy,#0xFC00 109 | cmp r1,#0x6000 110 | beq CXD0W 111 | cmp r1,#0x6400 112 | beq CXD1W 113 | cmp r1,#0x6800 114 | beq CXD2W 115 | cmp r1,#0x6C00 116 | beq CXD3W 117 | cmp r1,#0x7800 118 | beq MDIOW 119 | and r1,r1,#0xF000 120 | cmp r1,#0x3000 121 | beq BankedRAMW 122 | ldr r1,=cartBase 123 | ldr r1,[r1] 124 | strb r0,[r1,addy] 125 | bx lr 126 | ;@---------------------------------------------------------------------------- 127 | CXD0R: ;@ 0x6000 128 | ;@---------------------------------------------------------------------------- 129 | mov r0,#0xFF 130 | bx lr 131 | ;@---------------------------------------------------------------------------- 132 | CXD0W: ;@ 0x6000, MD Z80 banking 133 | ;@---------------------------------------------------------------------------- 134 | // mov r11,r11 135 | ;@ Map 32kB of MD memory to Z80 0x8000. 136 | ;@ 9 writes with bit #0 sets bit 15-23 of offset. 137 | bx lr 138 | ;@---------------------------------------------------------------------------- 139 | CXD3R: ;@ 0x6C00, reset CXD1? 140 | ;@---------------------------------------------------------------------------- 141 | // mov r11,r11 142 | mov r0,#0xFF 143 | bx lr 144 | ;@---------------------------------------------------------------------------- 145 | CXD3W: ;@ 0x6C00, Coins inhibit/accepted. 146 | ;@---------------------------------------------------------------------------- 147 | // mov r11,r11 148 | ;@ Values 8-B written at startup & also 0-3 if Free Play. 149 | ;@ Values 0, 1, 3 & 2 when those coin slots are inhibitet. 150 | bx lr 151 | ;@---------------------------------------------------------------------------- 152 | MDIOW: ;@ 0x7800 & 0x7801? 153 | ;@---------------------------------------------------------------------------- 154 | mov r11,r11 ;@ MegaDrive communication ports? 155 | bx lr 156 | ;@---------------------------------------------------------------------------- 157 | MDIOR: ;@ 0x7800 & 0x7801? 158 | ;@---------------------------------------------------------------------------- 159 | mov r11,r11 ;@ MegaDrive communication ports? 160 | ;@ bit 0 & 1 tested on 7801, 7800 compared to 0x6 161 | mov r0,#0xFF 162 | tst addy,#1 163 | moveq r0,#0x06 164 | bx lr 165 | ;@---------------------------------------------------------------------------- 166 | MDGameR: 167 | bic addy,addy,r1 168 | mov addy,addy,lsr#1 169 | orr addy,addy,r1 170 | ldr r1,=cartBase 171 | ldr r1,[r1] 172 | ldrb r0,cartSelectReg 173 | and r0,r0,#0x7 174 | add r1,r1,r0,lsl#15 // 32kB rom 175 | ldrb r0,[r1,addy] 176 | bx lr 177 | ;@---------------------------------------------------------------------------- 178 | BankedRAMR: 179 | bic addy,addy,r1 180 | ldr r1,=EMU_SRAM 181 | ldrb r0,cartSelectReg 182 | and r0,r0,#0x7 183 | add r1,r1,r0,lsl#12 // 4kB page 184 | ldrb r0,[r1,addy] 185 | bx lr 186 | ;@---------------------------------------------------------------------------- 187 | BankedRAMW: 188 | bic addy,addy,r1 189 | ldr r1,=EMU_SRAM 190 | ldrb r2,cartSelectReg 191 | and r2,r2,#0x7 192 | add r1,r1,r2,lsl#12 // 4kB page 193 | strb r0,[r1,addy] 194 | bx lr 195 | 196 | ;@---------------------------------------------------------------------------- 197 | MTCartSelectW: ;@ Select which cart (& ram bank?). 198 | ;@---------------------------------------------------------------------------- 199 | strb r0,cartSelectReg 200 | // mov r11,r11 201 | bx lr 202 | ;@---------------------------------------------------------------------------- 203 | MTUserInput0R: ;@ Unknown inputs. 204 | ;@---------------------------------------------------------------------------- 205 | ldr r1,=acExtra 206 | ldr r1,[r1] 207 | mov r0,#0xFF ;@ Default output 208 | tst r1,#0x4000 ;@ NDS L 209 | bicne r0,r0,#0x01 ;@ Game Select button 210 | // bicne r0,r0,#0x02 ;@ 211 | // bicne r0,r0,#0x04 ;@ 212 | // bicne r0,r0,#0x08 ;@ 213 | tst r1,#0x1000 ;@ NDS L+Up 214 | biceq r0,r0,#0x10 ;@ Door 1 (1 open, 0 close) 215 | tst r1,#0x0800 ;@ NDS L+Left 216 | biceq r0,r0,#0x20 ;@ Door 2 (1 open, 0 close) 217 | // bicne r0,r0,#0x40 ;@ 218 | tst r1,#0x2000 ;@ NDS L+Down 219 | bicne r0,r0,#0x80 ;@ Test button (service menu) 220 | bx lr 221 | ;@---------------------------------------------------------------------------- 222 | MTUserInput1R: ;@ Coins, service & start inputs. 223 | ;@---------------------------------------------------------------------------- 224 | ldr r1,=acExtra 225 | ldr r1,[r1] 226 | mov r0,#0xFF ;@ Default output 227 | tst r1,#0x0200 ;@ NDS Select 228 | bicne r0,r0,#0x01 ;@ Coin 1 229 | tst r1,#0x0100 ;@ NDS Select+Down 230 | bicne r0,r0,#0x02 ;@ Coin 2 231 | tst r1,#0x0080 ;@ NDS Select+Up 232 | bicne r0,r0,#0x04 ;@ Coin 3 233 | tst r1,#0x0040 ;@ NDS Select+Left 234 | bicne r0,r0,#0x08 ;@ Coin 4 235 | tst r1,#0x0020 ;@ NDS Select+Right 236 | bicne r0,r0,#0x10 ;@ Service coin 237 | tst r1,#0x8000 ;@ NDS R 238 | bicne r0,r0,#0x20 ;@ Enter Button 239 | tst r1,#0x0010 ;@ NDS Start 240 | bicne r0,r0,#0x40 ;@ Start 1 241 | tst r1,#0x0008 ;@ NDS Start+ 242 | bicne r0,r0,#0x80 ;@ Start 2 243 | bx lr 244 | ;@---------------------------------------------------------------------------- 245 | MTCartSenseR: ;@ Check which carts are present. 246 | ;@---------------------------------------------------------------------------- 247 | mov r0,#0xFC ;@ Cart 0 inserted. 248 | bx lr 249 | ;@---------------------------------------------------------------------------- 250 | MTInputCtrlW: ;@ Enable/disable Joysticks? 251 | ;@---------------------------------------------------------------------------- 252 | ;@ bit 0 = Toggled several times after coin/(credit?) inserted. 253 | ;@ bit 1 = 1 (Always ?) 254 | ;@ bit 2 = Joystick enabled? (0=yes, 1=no) (Timer running.) 255 | ;@ bit 3 = ? Set/reset depending on byte 0xD in game instruction rom (no games use it?). 256 | ;@ bit 4 = Reset pin on Game side? (0=set, 1=not set) 257 | ;@ bit 5 = Game/Instruction ROM mapping? (0=instruction, 1=game), MD SMS mode? 258 | ;@ bit 6 = ? Sound off for Game side? 259 | ;@ bit 7 = IO & Mem mapped to Game side? This input to IC14 pin19 (AM16L8 the adress decoder?). 260 | mov r11,r11 261 | strb r0,mtIOSelectReg 262 | // b r0OutputToEmulator 263 | bx lr 264 | ;@ F6 46 F6 66 F6 F6 (F2) written at boot & exiting test menu (F2 if timer running). 265 | ;@ 96 86 06 02 written when entering test menu 266 | ;@ BIC 0x90 before writing SMS mapper regs, OR 0x90 after writing SMS mapper regs 267 | ;@ BIC 0xB0 before reading instruction rom, OR 0xB0 after reading instruction rom 268 | ;@ 82 written when testing alarm, 02 when turning off alarm. 269 | ;@ F2 F3 F2 F3 F2 F3 F2 F3 F2 F3 F2 F3 F2 F3 F2 F3 F2 F3 F2 F3 F2 270 | ;@ written after credit inserted 271 | ;@ F6 96 86 06 86 .-. F6 written after time up 272 | ;@ 66 F6 written when selecting game 273 | ;@---------------------------------------------------------------------------- 274 | MTFlashW: ;@ Flash screen. 275 | ;@---------------------------------------------------------------------------- 276 | ;@ bit 0 = Input. Checked after setting bit 3. 277 | ;@ bit 1 = Flash screen? 0C & 0E written 278 | ;@ bit 2 = SMS mode for game VDP (0=MD, 1=SMS)? Set/reset depending on byte 0xE & 0xF in game instruction ROM. 279 | ;@ bit 3 = Set and then wait for bit 0 to be zero. 280 | mov r11,r11 281 | // b r0OutputToEmulator 282 | // tst r0,#0x4 283 | // adrne r0,smsString 284 | // adreq r0,mdString 285 | // b debugOutputToEmulator 286 | bx lr 287 | ;@ 05 0C 04 04 0C written at boot 288 | ;@ 04 0C written when entering test menu 289 | ;@ 04 written after time up, 0C 04 0C 04 290 | ;@ 0C 0C written after credit inserted 291 | ;@---------------------------------------------------------------------------- 292 | cartSelectReg: 293 | .byte 0 294 | mtIOSelectReg: 295 | .byte 0 296 | .space 2 297 | smsString: 298 | .string "SMS\n" 299 | mdString: 300 | .string "MD\n" 301 | 302 | .align 2 303 | ;@---------------------------------------------------------------------------- 304 | MTVDPVCounterR: 305 | ;@---------------------------------------------------------------------------- 306 | ldrb r12,mtIOSelectReg 307 | tst r12,#0x80 308 | bne VDP0VCounterR 309 | b VDP1VCounterR 310 | ;@---------------------------------------------------------------------------- 311 | MTVDPHCounterR: 312 | ;@---------------------------------------------------------------------------- 313 | ldrb r12,mtIOSelectReg 314 | tst r12,#0x80 315 | bne VDP0HCounterR 316 | b VDP1HCounterR 317 | ;@---------------------------------------------------------------------------- 318 | MTVDPStatR: 319 | ;@---------------------------------------------------------------------------- 320 | ldrb r12,mtIOSelectReg 321 | tst r12,#0x80 322 | bne VDP0StatR 323 | b VDP1StatR 324 | ;@---------------------------------------------------------------------------- 325 | MTVDPDataR: 326 | ;@---------------------------------------------------------------------------- 327 | ldrb r12,mtIOSelectReg 328 | tst r12,#0x80 329 | bne VDP0DataR 330 | b VDP1DataR 331 | ;@---------------------------------------------------------------------------- 332 | MTVDPDataW: 333 | ;@---------------------------------------------------------------------------- 334 | ldrb r12,mtIOSelectReg 335 | tst r12,#0x80 336 | bne VDP0DataSMSW 337 | b VDP1DataSMSW 338 | ;@---------------------------------------------------------------------------- 339 | MTVDPCtrlW: 340 | ;@---------------------------------------------------------------------------- 341 | ldrb r12,mtIOSelectReg 342 | tst r12,#0x80 343 | bne VDP0CtrlW 344 | b VDP1CtrlW 345 | 346 | 347 | ;@---------------------------------------------------------------------------- 348 | CXD1Reset: 349 | adr cxdptr,CXD1 350 | b CXD1095QReset 351 | ;@---------------------------------------------------------------------------- 352 | CXD1R: 353 | mov r1,addy 354 | adr cxdptr,CXD1 355 | b CXD1095QR 356 | ;@---------------------------------------------------------------------------- 357 | CXD1W: 358 | mov r1,addy 359 | adr cxdptr,CXD1 360 | b CXD1095QW 361 | ;@---------------------------------------------------------------------------- 362 | CXD2Reset: 363 | adr cxdptr,CXD2 364 | b CXD1095QReset 365 | ;@---------------------------------------------------------------------------- 366 | CXD2R: 367 | mov r1,addy 368 | adr cxdptr,CXD2 369 | b CXD1095QR 370 | ;@---------------------------------------------------------------------------- 371 | CXD2W: 372 | mov r1,addy 373 | adr cxdptr,CXD2 374 | b CXD1095QW 375 | ;@---------------------------------------------------------------------------- 376 | 377 | CXD1: 378 | .space cxdSize 379 | CXD2: 380 | .space cxdSize 381 | ;@---------------------------------------------------------------------------- 382 | .end 383 | #endif // #ifdef __arm__ 384 | -------------------------------------------------------------------------------- /source/Memory.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "Equates.h" 4 | #include "ARMZ80/ARMZ80mac.h" 5 | 6 | .global empty_R 7 | .global empty_R_SMS1 8 | .global empty_W 9 | .global ram_W 10 | .global ram0_W 11 | .global ram1_W 12 | .global ram1S_W 13 | .global ram1k_W 14 | .global ram2k_W 15 | .global ram4k_W 16 | .global ram16k_W 17 | .global sram0_W 18 | .global sram1_W 19 | .global rom_R 20 | .global Korean_W 21 | .global Korean_MSX_W 22 | .global Codemaster_W 23 | .global rom_W 24 | .global biosWrite 25 | .global cart1Write 26 | .global cart2Write 27 | .global memcpy_ 28 | 29 | .syntax unified 30 | .arm 31 | 32 | .section .text 33 | .align 2 34 | ;@---------------------------------------------------------------------------- 35 | empty_R: ;@ Read bad (IO) address, error. 36 | ;@---------------------------------------------------------------------------- 37 | mov r11,r11 ;@ No$GBA breakpoint 38 | mov r0,#0xFF ;@ SMS2, GG & MD 39 | bx lr 40 | ;@---------------------------------------------------------------------------- 41 | empty_R_SMS1: ;@ Read bad (IO) address, error. 42 | ;@---------------------------------------------------------------------------- 43 | mov r11,r11 ;@ No$GBA breakpoint 44 | ldrb r0,[r9,#-1] ;@ SMS (z80pc-1) 45 | bx lr 46 | ;@---------------------------------------------------------------------------- 47 | empty_W: ;@ Write bad address (error) 48 | ;@---------------------------------------------------------------------------- 49 | mov r11,r11 ;@ No$GBA debugg 50 | mov r0,#0xBA 51 | bx lr 52 | ;@---------------------------------------------------------------------------- 53 | Korean_MSX_W: ;@ Write ROM address (bankswitch) 54 | ;@---------------------------------------------------------------------------- 55 | cmp addy,#0x0002 56 | beq BankSwitch0MSX_W 57 | cmp addy,#0x0003 58 | beq BankSwitch1MSX_W 59 | cmp addy,#0x0000 60 | beq BankSwitch2MSX_W 61 | cmp addy,#0x0001 62 | beq BankSwitch3MSX_W 63 | b rom_W 64 | ;@---------------------------------------------------------------------------- 65 | Korean_W: ;@ Write ROM address (bankswitch) 66 | ;@---------------------------------------------------------------------------- 67 | cmp addy,#0xA000 68 | beq BankSwitch2_W 69 | b rom_W 70 | ;@---------------------------------------------------------------------------- 71 | Codemaster_W: ;@ Write ROM address (bankswitch) 72 | ;@---------------------------------------------------------------------------- 73 | cmp addy,#0x8000 74 | beq BankSwitch2C_W 75 | cmp addy,#0x4000 76 | beq BankSwitch1C_W 77 | cmp addy,#0x0000 78 | beq BankSwitch0C_W 79 | ;@---------------------------------------------------------------------------- 80 | rom_W: ;@ Write ROM address (error) 81 | ;@---------------------------------------------------------------------------- 82 | mov r11,r11 ;@ No$GBA debugg 83 | mov r0,#0xB0 84 | bx lr 85 | ;@---------------------------------------------------------------------------- 86 | biosWrite: ;@ Write Bios address (error) 87 | ;@---------------------------------------------------------------------------- 88 | mov r11,r11 ;@ No$GBA debugg 89 | ldr r0,=0xB105 90 | bx lr 91 | ;@---------------------------------------------------------------------------- 92 | cart1Write: ;@ Write Cart1 address (error) 93 | ;@---------------------------------------------------------------------------- 94 | mov r11,r11 ;@ No$GBA debugg 95 | ldr r0,=0xCA271 96 | bx lr 97 | ;@---------------------------------------------------------------------------- 98 | cart2Write: ;@ Write Cart2 address (error) 99 | ;@---------------------------------------------------------------------------- 100 | mov r11,r11 ;@ No$GBA debugg 101 | ldr r0,=0xCA272 102 | bx lr 103 | ;@---------------------------------------------------------------------------- 104 | 105 | .section .itcm 106 | .align 2 107 | ;@---------------------------------------------------------------------------- 108 | ram_W: ;@ Write ram ($0000-$FFFF) 109 | ;@---------------------------------------------------------------------------- 110 | // ldr r2,=EMU_RAM 111 | // strb r0,[r2,addy] 112 | and r1,addy,#MEM_BANK_MASK 113 | add r2,z80ptr,#z80MemTbl 114 | ldr r1,[r2,r1,lsr#MEM_BANK_SHIFT] 115 | strb r0,[r1,addy] 116 | bx lr 117 | ;@---------------------------------------------------------------------------- 118 | ram0_W: ;@ Write ram ($C000-$DFFF) 119 | ;@---------------------------------------------------------------------------- 120 | ldr r1,=EMU_RAM-0xC000 121 | strb r0,[r1,addy] 122 | bx lr 123 | ;@---------------------------------------------------------------------------- 124 | ram1_W: ;@ Write ram ($E000-$FFFF), mirror. 125 | ;@---------------------------------------------------------------------------- 126 | ldr r1,=BankMap4 127 | ldrb r1,[r1] 128 | tst r1,#0x08 ;@ BIOS? 129 | ldrne r1,=EMU_RAM-0xE000 ;@ Skip forward to write with BankSwitch. 130 | strbne r0,[r1,addy] 131 | bxne lr 132 | ;@---------------------------------------------------------------------------- 133 | ram1S_W: ;@ Write ram ($E000-$FFFF), mirror. Bankswitch 134 | ;@---------------------------------------------------------------------------- 135 | ldr r1,=EMU_RAM-0xE000 136 | strb r0,[r1,addy] 137 | mov r1,#0x00080000 138 | adds r1,r1,addy,lsl#16 139 | bxmi lr 140 | 141 | subs r1,r1,#0x00040000 142 | bmi LCDGlasses 143 | beq BankSwitchR_W ;@ $FFFC 144 | cmp r1,#0x20000 145 | bhi BankSwitch2_W ;@ $FFFF 146 | beq BankSwitch1_W ;@ $FFFE 147 | bmi BankSwitch0_W ;@ $FFFD 148 | mov r11,r11 149 | bx lr 150 | ;@---------------------------------------------------------------------------- 151 | LCDGlasses: 152 | ;@---------------------------------------------------------------------------- 153 | ldr r1,=gMachine 154 | ldrb r1,[r1] 155 | cmp r1,#HW_MARK3 156 | cmpne r1,#HW_SMS1 157 | cmpne r1,#HW_MEGADRIVE 158 | bxne lr 159 | ldr r1,=g3DEnable 160 | ldrb r1,[r1] 161 | cmp r1,#0 162 | bxeq lr 163 | tst r0,#1 164 | ldreq r0,=0x7FE0 165 | movne r0,#0x001F 166 | ldr r1,=paletteMask 167 | str r0,[r1] 168 | bx lr 169 | ;@---------------------------------------------------------------------------- 170 | ram1k_W: ;@ Write ram (SG-1000 $C000-$FFFF,Coleco $6000-$7FFF), mirrored every 1k. 171 | ;@---------------------------------------------------------------------------- 172 | bic r2,addy,#0xFC00 173 | ldr r1,=EMU_RAM 174 | strb r0,[r1,r2] 175 | bx lr 176 | ;@---------------------------------------------------------------------------- 177 | ram2k_W: ;@ Write ram (SC-3000 $C000-$FFFF), mirrored every 2k. 178 | ;@---------------------------------------------------------------------------- 179 | bic r2,addy,#0xF800 180 | ldr r1,=EMU_RAM 181 | strb r0,[r1,r2] 182 | bx lr 183 | ;@---------------------------------------------------------------------------- 184 | ram4k_W: ;@ Write ram (Sord M5 $7000-$7FFF) 185 | ;@---------------------------------------------------------------------------- 186 | tst addy,#0x1000 187 | bic r2,addy,#0xF000 188 | ldr r1,=EMU_RAM 189 | strbne r0,[r1,r2] 190 | bx lr 191 | ;@---------------------------------------------------------------------------- 192 | ram16k_W: ;@ Write ram (SYS-E $C000-$FFFF), no mirroring. 193 | ;@---------------------------------------------------------------------------- 194 | bic r2,addy,#0xC000 195 | ldr r1,=EMU_RAM 196 | strb r0,[r1,r2] 197 | // mov r1,#0x00030000 ;@ This is just a test!!! 198 | // adds r1,r1,addy,lsl#16 199 | // bxmi lr 200 | 201 | // cmp r1,#0x10000 202 | // bhi BankSwitch2_W ;@ $FFFF 203 | // beq BankSwitch1_W ;@ $FFFE 204 | // bmi BankSwitch0_W ;@ $FFFD 205 | bx lr 206 | ;@---------------------------------------------------------------------------- 207 | sram0_W: ;@ Write sram bank0 ($8000-$BFFF) 208 | ;@---------------------------------------------------------------------------- 209 | ldr r1,=EMU_SRAM-0x8000 210 | strb r0,[r1,addy] 211 | bx lr 212 | ;@---------------------------------------------------------------------------- 213 | sram1_W: ;@ Write sram bank1 ($8000-$BFFF),($C000-$FFFF) 214 | ;@---------------------------------------------------------------------------- 215 | ldr r1,=EMU_SRAM-0x4000 216 | strb r0,[r1,addy] 217 | bx lr 218 | 219 | ;@---------------------------------------------------------------------------- 220 | rom_R: ;@ Rom read 221 | ;@---------------------------------------------------------------------------- 222 | and r1,addy,#MEM_BANK_MASK 223 | add r2,z80ptr,#z80MemTbl 224 | ldr r1,[r2,r1,lsr#MEM_BANK_SHIFT] 225 | ldrb r0,[r1,addy] 226 | bx lr 227 | ;@---------------------------------------------------------------------------- 228 | memcpy_: ;@ r0=dest r1=src r2=word count 229 | ;@ Exit with r0 & r1 unchanged, r2=0, r3 trashed 230 | ;@---------------------------------------------------------------------------- 231 | subs r2,r2,#1 232 | ldrpl r3,[r1,r2,lsl#2] 233 | strpl r3,[r0,r2,lsl#2] 234 | bhi memcpy_ 235 | bx lr 236 | ;@---------------------------------------------------------------------------- 237 | .end 238 | #endif // #ifdef __arm__ 239 | -------------------------------------------------------------------------------- /source/RomLoading.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "RomLoading.h" 9 | #include "FileHandling.h" 10 | #include "Shared/EmuMenu.h" 11 | #include "Shared/FileHelper.h" 12 | #include "Shared/Unzip/unzipnds.h" 13 | #include "Gui.h" 14 | #include "Equates.h" 15 | #include "Cart.h" 16 | #include "io.h" 17 | 18 | // Mega-Tech SMS games 19 | //-------------------- 20 | // After Burner 21 | // Alien Syndrome 22 | // Astro Warrior 23 | // Black Belt? 24 | // Enduro Racer? 25 | // Fantasy Zone 26 | // Fantasy Zone II: The Tears of Opa Opa? 27 | // Great Football 28 | // Great Golf 29 | // Great Soccer 30 | // Kung Fu Kid? 31 | // Out Run 32 | // Parlour Games 33 | // Power Strike II? 34 | // Shinobi 35 | // Spellcaster? 36 | 37 | const ArcadeGame megaTechGames[10]; 38 | const ArcadeGame systemeGames[10]; 39 | const ArcadeGame sgacGames[5]; 40 | 41 | static const char syseDefines[] = {AC_HANG_ON_JR, AC_SLAP_SHOOTER, AC_TRANSFORMER, AC_ASTRO_FLASH, AC_RIDDLE_OF_PYTHAGORAS, AC_OPA_OPA, AC_OPA_OPA_N, AC_FANTASY_ZONE_2, AC_TETRIS, AC_MEGUMI_RESCUE}; 42 | static const char sgacDefines[] = {AC_CHAMPION_BOXING, AC_CHAMPION_WRESTLING, AC_DOKI_DOKI_PENGUIN, AC_SUPER_DERBY, AC_SUPER_DERBY_II}; 43 | 44 | int loadArcadeROM(void *dest, const char *fName) { 45 | int i; 46 | char fNameLowercase[16]; 47 | char zipSubName[32]; 48 | 49 | gArcadeGameSet = AC_NONE; 50 | dipSwitch0 = 0; 51 | dipSwitch1 = 0; 52 | 53 | // drawtext("Checking for Arcade Roms", 23, 0); 54 | strcasel(fNameLowercase, fName); 55 | for (i = 0; i < 10; i++) { 56 | strlMerge(zipSubName, megaTechGames[i].gameName, ".zip", sizeof(zipSubName)); 57 | if (strstr(fNameLowercase, zipSubName)) { 58 | if (!loadACRoms(dest, megaTechGames, i, ARRSIZE(megaTechGames), true)) { 59 | strlcpy(currentFilename, megaTechGames[i].fullName, sizeof(currentFilename)); 60 | gEmuFlags |= MT_MODE; 61 | return megaTechGames[i].roms[0].romSize; 62 | } 63 | } 64 | } 65 | 66 | for (i = 0; i < 10; i++) { 67 | strlMerge(zipSubName, systemeGames[i].gameName, ".zip", sizeof(zipSubName)); 68 | if (strstr(fNameLowercase, zipSubName)) { 69 | if (!loadACRoms(dest, systemeGames, i, ARRSIZE(systemeGames), true)) { 70 | strlcpy(currentFilename, systemeGames[i].fullName, sizeof(currentFilename)); 71 | gEmuFlags |= SYSE_MODE; 72 | gArcadeGameSet = syseDefines[i]; 73 | return 0x80000; 74 | } 75 | } 76 | } 77 | 78 | for (i = 0; i < 5; i++) { 79 | strlMerge(zipSubName, sgacGames[i].gameName, ".zip", sizeof(zipSubName)); 80 | if (strstr(fNameLowercase, zipSubName)) { 81 | if (!loadACRoms(dest, sgacGames, i, ARRSIZE(sgacGames), true)) { 82 | strlcpy(currentFilename, sgacGames[i].fullName, sizeof(currentFilename)); 83 | gEmuFlags |= SGAC_MODE; 84 | dipSwitch0 = 0xC0; 85 | gArcadeGameSet = sgacDefines[i]; 86 | return 0x10000; 87 | } 88 | } 89 | } 90 | return 0; 91 | } 92 | 93 | void strcasel(char *dest, const char *source) { 94 | int i; 95 | 96 | strlcpy(dest, source, 16); 97 | for (i = 0; i < 16; i++) { 98 | if (dest[i] > 0x40 && dest[i] < 0x5B) dest[i] |= 0x20; 99 | } 100 | } 101 | 102 | // Game 04 - Great Golf (SMS) 103 | // Also known to have the ID# MPR-11128 instead of MPR-11129F, same contents 104 | static const ArcadeRom mt_ggolfRoms[2] = { 105 | {"mp11129f.ic1", 0x20000, 0xc6611c84}, 106 | {"epr-12368-04.ic2", 0x8000, 0x62e5579b}, 107 | }; 108 | 109 | // Game 05 - Great Soccer (SMS) - bad dump 110 | static const ArcadeRom mt_gsocrRoms[2] = { 111 | {"mp10747f.ic1", 0x20000, 0x9cf53703}, 112 | {"epr-12368-05.ic2", 0x8000, 0xbab91fcc}, 113 | }; 114 | 115 | // Game 06 - Out Run (SMS) 116 | static const ArcadeRom mt_orunRoms[2] = { 117 | {"mpr-11078.ic1", 0x40000, 0x5589d8d2}, 118 | {"epr-12368-06.ic2", 0x8000, 0xc7c74429}, 119 | }; 120 | 121 | // Game 07 - Alien Syndrome (SMS) 122 | static const ArcadeRom mt_asynRoms[2] = { 123 | {"mpr-11194.ic1", 0x40000, 0x4cc11df9}, 124 | {"epr-12368-07.ic2", 0x8000, 0x14f4a17b}, 125 | }; 126 | 127 | // Game 08 - Shinobi (SMS) 128 | static const ArcadeRom mt_shnbiRoms[2] = { 129 | {"mp11706.ic1", 0x40000, 0x0c6fac4e}, 130 | {"epr-12368-08.ic2", 0x8000, 0x103a0459}, 131 | }; 132 | 133 | // Game 09 - Fantasy Zone (SMS) 134 | // note, dump was bad, but the good (uniquely identifiable) parts matched the 'fantasy zone (world) (v1.2).bin' SMS rom 135 | // so I'm using that until it gets verified. 136 | static const ArcadeRom mt_fzRoms[2] = { 137 | {"mpr-10118.ic1", 0x20000, 0x65d7e4e0}, 138 | {"epr-12368-09.bin", 0x8000, 0x373d2a70}, 139 | }; 140 | 141 | // Game 10 - After Burner (SMS) 142 | static const ArcadeRom mt_aftrbRoms[2] = { 143 | {"mp11271.ic1", 0x80000, 0x1c951f8e}, 144 | {"epr-12368-10.ic2", 0x8000, 0x2a7cb590}, 145 | }; 146 | 147 | // Game 13 - Astro Warrior (SMS) 148 | static const ArcadeRom mt_astroRoms[2] = { 149 | {"ep13817.ic2", 0x20000, 0x299cbb74}, 150 | {"epr-12368-13.ic1", 0x8000, 0x4038cbd1}, 151 | }; 152 | 153 | // Game 19 - Great Football (SMS) 154 | static const ArcadeRom mt_gfootRoms[2] = { 155 | {"mpr-10576f.ic1", 0x20000, 0x2055825f}, 156 | {"epr-12368-19.ic2", 0x8000, 0xe27cb37a}, 157 | }; 158 | 159 | // Game 29 - Parlour Games (SMS) 160 | static const ArcadeRom mt_parlgRoms[2] = { 161 | {"mp11404.ic1", 0x20000, 0xe030e66c}, 162 | {"epr-12368-29.ic2", 0x8000, 0x534151e8}, 163 | }; 164 | 165 | 166 | // Hang-On Jr., Sega System E 167 | // Game ID# 833-5911 HANG ON JR. REV. 168 | // ROM BD # 834-5910 REV.B 169 | // 170 | // Analog control board: 834-5805 (required for game to boot) 171 | // ICs on this board are LS244 (IC1), ADC0804 (IC2), LS367 (IC3) and CD4051 (IC4). 172 | static const ArcadeRom hangonjrRoms[5] = { 173 | {"epr-7257b.ic7", 0x8000, 0xd63925a7}, 174 | {"epr-7258.ic5", 0x8000, 0xee3caab3}, 175 | {"epr-7259.ic4", 0x8000, 0xd2ba9bc9}, 176 | {"epr-7260.ic3", 0x8000, 0xe14da070}, 177 | {"epr-7261.ic2", 0x8000, 0x3810cbf5}, 178 | }; 179 | 180 | // Slap Shooter, Sega System E 181 | // ROM BD # 834-5930 182 | static const ArcadeRom slapshtrRoms[5] = { 183 | {"epr-7351.ic7", 0x8000, 0x894adb04}, 184 | {"epr-7352.ic5", 0x8000, 0x61c938b6}, 185 | {"epr-7353.ic4", 0x8000, 0x8ee2951a}, 186 | {"epr-7354.ic3", 0x8000, 0x41482aa0}, 187 | {"epr-7355.ic2", 0x8000, 0xc67e1aef}, 188 | }; 189 | 190 | // Transformers, Sega System E 191 | // Game ID# 833-5927-01 192 | // ROM BD # 834-5929-01 193 | static const ArcadeRom transfrmRoms[5] = { 194 | {"epr-7605.ic7", 0x8000, 0xccf1d123}, 195 | {"epr-7347.ic5", 0x8000, 0xdf0f639f}, 196 | {"epr-7348.ic4", 0x8000, 0x0f38ea96}, 197 | {"epr-7606.ic3", 0x8000, 0x9d485df6}, 198 | {"epr-7350.ic2", 0x8000, 0x0052165d}, 199 | }; 200 | 201 | // Astro Flash (Japan), Sega System E 202 | static const ArcadeRom astroflRoms[5] = { 203 | {"epr-7723.ic7", 0x8000, 0x66061137}, 204 | {"epr-7347.ic5", 0x8000, 0xdf0f639f}, 205 | {"epr-7348.ic4", 0x8000, 0x0f38ea96}, 206 | {"epr-7349.ic3", 0x8000, 0xf8c352d5}, 207 | {"epr-7350.ic2", 0x8000, 0x0052165d}, 208 | }; 209 | 210 | // Riddle of Pythagoras (Japan), Sega System E 211 | // Game ID# 833-6200 ピタゴラス ノ ナゾ 212 | // I/O board 834-6193 © SEGA 1986 213 | static const ArcadeRom ridleofpRoms[5] = { 214 | {"epr-10426.bin", 0x8000, 0x4404c7e7}, 215 | {"epr-10425.bin", 0x8000, 0x35964109}, 216 | {"epr-10424.bin", 0x8000, 0xfcda1dfa}, 217 | {"epr-10423.bin", 0x8000, 0x0b87244f}, 218 | {"epr-10422.bin", 0x8000, 0x14781e56}, 219 | }; 220 | 221 | // Opa Opa (MC-8123, 317-0042), Sega System E 222 | // Game ID# 833-6407-01 OPA OPA 223 | static const ArcadeRom opaopaRoms[6] = { 224 | {"epr-11054.ic7", 0x8000, 0x024b1244}, 225 | {"epr-11053.ic5", 0x8000, 0x6bc41d6e}, 226 | {"epr-11052.ic4", 0x8000, 0x395c1d0a}, 227 | {"epr-11051.ic3", 0x8000, 0x4ca132a2}, 228 | {"epr-11050.ic2", 0x8000, 0xa165e2ef}, 229 | {"317-0042.key", 0x2000, 0xd6312538}, 230 | }; 231 | 232 | // Opa Opa, Sega System E 233 | // Game ID# 833-6407 OPA OPA 234 | static const ArcadeRom opaopanRoms[5] = { 235 | {"epr-11023a.ic7", 0x8000, 0x101c5c6a}, 236 | {"epr-11022.ic5", 0x8000, 0x15203a42}, 237 | {"epr-11021.ic4", 0x8000, 0xb4e83340}, 238 | {"epr-11020.ic3", 0x8000, 0xc51aad27}, 239 | {"epr-11019.ic2", 0x8000, 0xbd0a6248}, 240 | }; 241 | 242 | // Fantasy Zone II - The Tears of Opa-Opa (MC-8123, 317-0057), Sega System E 243 | static const ArcadeRom fantzn2Roms[6] = { 244 | {"epr-11416.ic7", 0x8000, 0x76db7b7b}, 245 | {"epr-11415.ic5", 0x10000, 0x57b45681}, 246 | {"epr-11413.ic3", 0x10000, 0xa231dc85}, 247 | {"epr-11414.ic4", 0x10000, 0x6f7a9f5f}, 248 | {"epr-11412.ic2", 0x10000, 0xb14db5af}, 249 | {"317-0057.key", 0x2000, 0xee43d0f0}, 250 | }; 251 | 252 | // Tetris (Japan), Sega System E 253 | static const ArcadeRom tetrisseRoms[3] = { 254 | {"epr-12213.7", 0x8000, 0xef3c7a38}, 255 | {"epr-12212.5", 0x8000, 0x28b550bf}, 256 | {"epr-12211.4", 0x8000, 0x5aa114e9}, 257 | }; 258 | 259 | // Megumi Rescue, Sega System E 260 | static const ArcadeRom megrescuRoms[5] = { 261 | {"megumi_rescue_version_10.30_final_version_ic-7.ic7", 0x8000, 0x490d0059}, 262 | {"megumi_rescue_version_10.30_final_version_ic-7.ic5", 0x8000, 0x278caba8}, 263 | {"megumi_rescue_version_10.30_final_version_ic-7.ic4", 0x8000, 0xbda242d1}, 264 | {"megumi_rescue_version_10.30_final_version_ic-7.ic3", 0x8000, 0x56e36f85}, 265 | {"megumi_rescue_version_10.30_final_version_ic-7.ic2", 0x8000, 0x5b74c767}, 266 | }; 267 | 268 | // Champion Boxing SGAC 269 | static const ArcadeRom chboxingRoms[3] = { 270 | {"cb6105.bin", 0x4000, 0x43516f2e}, 271 | {"cb6106.bin", 0x4000, 0x65e2c750}, 272 | {"cb6107.bin", 0x2000, 0xc2f8e522}, 273 | }; 274 | 275 | // Champion Wrestling SGAC (encrypted) 276 | static const ArcadeRom chwrestlRoms[3] = { 277 | {"5732", 0x4000, 0xa4e44370}, 278 | {"5733", 0x4000, 0x4f493538}, 279 | {"5734", 0x4000, 0xd99b6301}, 280 | }; 281 | 282 | // Doki Doki Penguin Land SGAC 283 | static const ArcadeRom dokidokiRoms[3] = { 284 | {"epr-7356.ic1", 0x4000, 0x95658c31}, 285 | {"epr-7357.ic2", 0x4000, 0xe8dbad85}, 286 | {"epr-7358.ic3", 0x4000, 0xc6f26b0b}, 287 | }; 288 | 289 | // Super Derby (satellite board) SGAC 290 | static const ArcadeRom sderbysRoms[1] = { 291 | {"v1.2.ic10", 0x4000, 0xcf29b579}, 292 | }; 293 | 294 | // Super Derby II (satellite board) SGAC 295 | static const ArcadeRom sderby2sRoms[2] = { 296 | {"epr-6450d.ic10", 0x4000, 0xe56986d3}, 297 | {"epr-6504d.ic11", 0x4000, 0x7bb364b9}, 298 | }; 299 | 300 | const ArcadeGame megaTechGames[10] = { 301 | AC_GAME("mt_ggolf", "Great Golf (Mega-Tech, SMS based)", mt_ggolfRoms) 302 | AC_GAME("mt_gsocr", "Great Soccer (Mega-Tech, SMS based)", mt_gsocrRoms) 303 | AC_GAME("mt_orun", "Out Run (Mega-Tech, SMS based)", mt_orunRoms) 304 | AC_GAME("mt_asyn", "Alien Syndrome (Mega-Tech, SMS based)", mt_asynRoms) 305 | AC_GAME("mt_shnbi", "Shinobi (Mega-Tech, SMS based)", mt_shnbiRoms) 306 | AC_GAME("mt_fz", "Fantasy Zone (Mega-Tech, SMS based)", mt_fzRoms) 307 | AC_GAME("mt_aftrb", "After Burner (Mega-Tech, SMS based)", mt_aftrbRoms) 308 | AC_GAME("mt_astro", "Astro Warrior (Mega-Tech, SMS based)", mt_astroRoms) 309 | AC_GAME("mt_gfoot", "Great Football (Mega-Tech, SMS based)", mt_gfootRoms) 310 | AC_GAME("mt_parlg", "Parlour Games (Mega-Tech, SMS based)", mt_parlgRoms) 311 | }; 312 | 313 | const ArcadeGame systemeGames[10] = { 314 | AC_GAME("hangonjr", "Hang-On Jr. (Rev. B)", hangonjrRoms) 315 | AC_GAME("slapshtr", "Slap Shooter", slapshtrRoms) 316 | AC_GAME("transfrm", "Transformer", transfrmRoms) 317 | AC_GAME("astrofl", "Astro Flash (Japan)", astroflRoms) 318 | AC_GAME("ridleofp", "Riddle of Pythagoras (Japan)", ridleofpRoms) 319 | AC_GAME("opaopa", "Opa Opa (MC-8123, 317-0042)", opaopaRoms) 320 | AC_GAME("opaopan", "Opa Opa (Rev A, unprotected)", opaopanRoms) 321 | AC_GAME("fantzn2", "Fantasy Zone II - The Tears of Opa-Opa (MC-8123, 317-0057)", fantzn2Roms) 322 | AC_GAME("tetrisse", "Tetris (Japan, System E)", tetrisseRoms) 323 | AC_GAME("megrescu", "Megumi Rescue", megrescuRoms) 324 | }; 325 | 326 | const ArcadeGame sgacGames[5] = { 327 | AC_GAME("chboxing", "Champion Boxing", chboxingRoms) 328 | AC_GAME("chwrestl", "Champion Pro Wrestling", chwrestlRoms) 329 | AC_GAME("dokidoki", "Doki Doki Penguin Land", dokidokiRoms) 330 | AC_GAME("sderbys", "Super Derby (satellite board)", sderbysRoms) 331 | AC_GAME("sderby2s", "Super Derby II (satellite board)", sderby2sRoms) 332 | }; 333 | -------------------------------------------------------------------------------- /source/RomLoading.h: -------------------------------------------------------------------------------- 1 | #ifndef ROMLOADING_HEADER 2 | #define ROMLOADING_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "Shared/ArcadeRoms.h" 9 | 10 | int loadArcadeROM(void *dest, const char *fName); 11 | void strcasel(char *dest, const char *source); 12 | 13 | #ifdef __cplusplus 14 | } // extern "C" 15 | #endif 16 | 17 | #endif // ROMLOADING_HEADER 18 | -------------------------------------------------------------------------------- /source/SordM5.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "ARMZ80/ARMZ80.i" 4 | #include "SegaVDP/SegaVDP.i" 5 | #include "ARMZ80CTC/ARMZ80CTC.i" 6 | #include "PPI8255/PPI8255.i" 7 | 8 | .global sordM5Reset 9 | .global IO_Params_SordM5_R 10 | .global IO_Params_SordM5_W 11 | .global sordM5Input 12 | .global CTC0Update 13 | .global CTC0SetTrg3 14 | .global CTC0GetIrqVector 15 | .global CTC0IrqAcknowledge 16 | 17 | 18 | .syntax unified 19 | .arm 20 | 21 | .section .text 22 | .align 2 23 | ;@---------------------------------------------------------------------------- 24 | ;@ Sord M5 25 | IO_Params_SordM5_R: 26 | .long 0x000000F0, CTC0Read ;@ 0x00-0x0F 27 | .long 0x001000F1, VDP0DataR ;@ 0x10-0x1E 28 | .long 0x001100F1, VDP0StatR ;@ 0x11-0x1F 29 | .long 0x003000F7, M5KBRowRead0 ;@ 0x30,0x38 30 | .long 0x003100F7, M5KBRowRead1 ;@ 0x31,0x39 31 | .long 0x003200F7, M5KBRowRead2 ;@ 0x32,0x3A 32 | .long 0x003300F7, M5KBRowRead3 ;@ 0x33,0x3B 33 | .long 0x003400F7, M5KBRowRead4 ;@ 0x34,0x3C 34 | .long 0x003500F7, M5KBRowRead5 ;@ 0x35,0x3D 35 | .long 0x003600F7, M5KBRowRead6 ;@ 0x36,0x3E 36 | .long 0x003700F7, M5KBRowRead7 ;@ 0x37,0x3F 37 | // .long 0x004000F0, M5PortR ;@ 0x40-0x4F 38 | .long 0x005000F0, M5IOCtrlR ;@ 0x50-0x5F 39 | .long 0x007000FF, PPI1PortAR ;@ 0x70 40 | .long 0x007100FF, PPI1PortBR ;@ 0x71 41 | .long 0x007200FF, PPI1PortCR ;@ 0x72 42 | .long 0x007300FF, PPI1PortDR ;@ 0x73 43 | .long 0x00000000, empty_R ;@ everything else 44 | IO_Params_SordM5_W: 45 | .long 0x000000F0, CTC0Write ;@ 0x00-0x0F 46 | .long 0x001000F1, VDP0DataTMSW ;@ 0x10-0x1E 47 | .long 0x001100F1, VDP0CtrlW ;@ 0x11-0x1F 48 | .long 0x002000F0, SN76496_W ;@ 0x20-0x2F 49 | // .long 0x003000F0, M5KeyBoardW ;@ 0x30-0x3F 50 | // .long 0x004000F0, M5PortW ;@ 0x40 51 | .long 0x005000F0, M5IOCtrlW ;@ 0x50 52 | .long 0x007000FF, PPI1PortAW ;@ 0x70 53 | .long 0x007100FF, PPI1PortBW ;@ 0x71 54 | .long 0x007200FF, PPI1PortCW ;@ 0x72 55 | .long 0x007300FF, PPI1PortDW ;@ 0x73 56 | .long 0x00000000, empty_W ;@ everything else 57 | 58 | ;@---------------------------------------------------------------------------- 59 | sordM5Reset: 60 | ;@---------------------------------------------------------------------------- 61 | stmfd sp!,{lr} 62 | 63 | bl PPI1Reset 64 | bl CTC0Reset 65 | 66 | mov r1,#0 67 | ldr r0,=keyboardRows 68 | str r1,[r0],#4 69 | str r1,[r0],#4 70 | 71 | ldmfd sp!,{lr} 72 | bx lr 73 | 74 | ;@---------------------------------------------------------------------------- 75 | M5IOCtrlR: ;@ Printer/Cassette input 76 | ;@---------------------------------------------------------------------------- 77 | ldrb r0,sordM5Input 78 | // mov r0,#0x00 ;@ Default input 79 | // orr r0,r0,#0x01 ;@ Casette input 80 | // orr r0,r0,#0x02 ;@ Centronics busy 81 | // orr r0,r0,#0x80 ;@ Reset key 82 | bx lr 83 | ;@---------------------------------------------------------------------------- 84 | M5IOCtrlW: ;@ Printer/Cassette output 85 | ;@---------------------------------------------------------------------------- 86 | // orr r0,r0,#0x01 ;@ Casette output, centronics strobe 87 | // orr r0,r0,#0x02 ;@ Casette remote 88 | bx lr 89 | ;@---------------------------------------------------------------------------- 90 | M5KBRowRead1: ;@ Joy button(s) 91 | ;@---------------------------------------------------------------------------- 92 | ldr r1,=joy1State 93 | ldrb r0,[r1] 94 | b getKeyB 95 | ;@---------------------------------------------------------------------------- 96 | M5KBRowRead0: 97 | ;@---------------------------------------------------------------------------- 98 | ;@---------------------------------------------------------------------------- 99 | M5KBRowRead2: 100 | ;@---------------------------------------------------------------------------- 101 | ;@---------------------------------------------------------------------------- 102 | M5KBRowRead3: 103 | ;@---------------------------------------------------------------------------- 104 | ;@---------------------------------------------------------------------------- 105 | M5KBRowRead4: 106 | ;@---------------------------------------------------------------------------- 107 | ;@---------------------------------------------------------------------------- 108 | M5KBRowRead5: 109 | ;@---------------------------------------------------------------------------- 110 | ;@---------------------------------------------------------------------------- 111 | M5KBRowRead6: 112 | ;@---------------------------------------------------------------------------- 113 | mov r0,#0 114 | getKeyB: 115 | and r1,addy,#0x7 116 | ldr r2,=keyboardRows 117 | ldrb r1,[r2,r1] 118 | orr r0,r0,r1 119 | bx lr 120 | ;@---------------------------------------------------------------------------- 121 | M5KBRowRead7: ;@ Joypad 122 | ;@---------------------------------------------------------------------------- 123 | ldr r0,=joy0State 124 | ldrb r0,[r0] 125 | bx lr 126 | ;@---------------------------------------------------------------------------- 127 | CTC0Reset: 128 | ;@---------------------------------------------------------------------------- 129 | stmfd sp!,{lr} 130 | 131 | adr r0,CTC_0 132 | bl Z80CTCReset 133 | adr r0,CTC_0 134 | ldr r1,=Z80SetIRQPinCurrentCpu 135 | str r1,[r0,#ctcIrqFPtr] 136 | 137 | ldmfd sp!,{lr} 138 | bx lr 139 | ;@---------------------------------------------------------------------------- 140 | CTC0Update: ;@ r0 = cycles 141 | ;@---------------------------------------------------------------------------- 142 | adr r1,CTC_0 143 | b Z80CTCUpdate 144 | ;@---------------------------------------------------------------------------- 145 | CTC0Read: 146 | ;@---------------------------------------------------------------------------- 147 | and r1,addy,#0x03 148 | adr r0,CTC_0 149 | b Z80CTCRead 150 | ;@---------------------------------------------------------------------------- 151 | CTC0Write: ;@ r0 = data 152 | ;@---------------------------------------------------------------------------- 153 | and r1,addy,#0x03 154 | adr r2,CTC_0 155 | b Z80CTCWrite 156 | ;@---------------------------------------------------------------------------- 157 | CTC0SetTrg0: ;@ r0 = data 158 | ;@---------------------------------------------------------------------------- 159 | adr r1,CTC_0 160 | b Z80CTCSetTrg0 161 | ;@---------------------------------------------------------------------------- 162 | CTC0SetTrg1: ;@ r0 = data 163 | ;@---------------------------------------------------------------------------- 164 | adr r1,CTC_0 165 | b Z80CTCSetTrg1 166 | ;@---------------------------------------------------------------------------- 167 | CTC0SetTrg2: ;@ r0 = data 168 | ;@---------------------------------------------------------------------------- 169 | adr r1,CTC_0 170 | b Z80CTCSetTrg2 171 | ;@---------------------------------------------------------------------------- 172 | CTC0SetTrg3: ;@ r0 = data 173 | ;@---------------------------------------------------------------------------- 174 | stmfd sp!,{r1,r2,r12,lr} 175 | adr r1,CTC_0 176 | bl Z80CTCSetTrg3 177 | ldmfd sp!,{r1,r2,r12,lr} 178 | bx lr 179 | ;@---------------------------------------------------------------------------- 180 | CTC0GetIrqVector: 181 | ;@---------------------------------------------------------------------------- 182 | adr r0,CTC_0 183 | b Z80CTCGetIrqVector 184 | ;@---------------------------------------------------------------------------- 185 | CTC0IrqAcknowledge: 186 | ;@---------------------------------------------------------------------------- 187 | adr r0,CTC_0 188 | b Z80CTCIrqAcknowledge 189 | 190 | ;@---------------------------------------------------------------------------- 191 | sordM5Input: 192 | .long 0 193 | CTC_0: 194 | .space ctcSize 195 | ;@---------------------------------------------------------------------------- 196 | .end 197 | #endif // #ifdef __arm__ 198 | -------------------------------------------------------------------------------- /source/Sound.h: -------------------------------------------------------------------------------- 1 | #ifndef SOUND_HEADER 2 | #define SOUND_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "SN76496/SN76496.h" 10 | 11 | //#define sample_rate 32768 12 | #define sample_rate 55930 13 | #define buffer_size (512+10) 14 | 15 | extern SN76496 SN76496_0; 16 | void soundInit(void); 17 | void soundSetFrequency(void); 18 | void setMuteSoundGUI(void); 19 | mm_word VblSound2(mm_word length, mm_addr dest, mm_stream_formats format); 20 | 21 | #ifdef __cplusplus 22 | } // extern "C" 23 | #endif 24 | 25 | #endif // SOUND_HEADER 26 | -------------------------------------------------------------------------------- /source/Sound.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "Equates.h" 4 | #include "SN76496/SN76496.i" 5 | #include "AY38910/AY38910.i" 6 | #include "YM2413/YM2413.i" 7 | #include "SCC/SCC.i" 8 | 9 | .global soundInit 10 | .global soundReset 11 | .global soundSetFrequency 12 | .global VblSound2 13 | .global SMSJSoundControlW 14 | .global SMSJSoundControlR 15 | .global SN76496_0 16 | .global SN76496_W 17 | .global SN76496_0_W 18 | .global SN76496_1_W 19 | .global YM2413_0_AddressW 20 | .global YM2413_0_DataW 21 | .global YM2413_0_StatusR 22 | .global AY38910Index_0_W 23 | .global AY38910Data_0_W 24 | .global AY38910Data_0_R 25 | .global SCCWrite_0 26 | .global GG_Stereo_W 27 | .global SoundVariables 28 | .global setMuteSoundGUI 29 | .global setMuteSoundGame 30 | 31 | .extern pauseEmulation 32 | .extern powerButton 33 | 34 | 35 | ;@---------------------------------------------------------------------------- 36 | 37 | .syntax unified 38 | .arm 39 | 40 | .section .text 41 | .align 2 42 | ;@---------------------------------------------------------------------------- 43 | soundInit: 44 | .type soundInit STT_FUNC 45 | ;@---------------------------------------------------------------------------- 46 | stmfd sp!,{lr} 47 | 48 | bl soundSetFrequency 49 | 50 | ldmfd sp!,{lr} 51 | // bx lr 52 | 53 | ;@---------------------------------------------------------------------------- 54 | soundReset: 55 | ;@---------------------------------------------------------------------------- 56 | stmfd sp!,{r4,lr} 57 | 58 | mov r0,#0 59 | strb r0,muteSoundGame 60 | mov r0,#0xFF 61 | strb r0,muteSoundGUI 62 | mov r0,#2 63 | strb r0,SMSJSoundControl 64 | ldr r4,=gMachine 65 | ldrb r4,[r4] 66 | cmp r4,#HW_MSX 67 | beq isMSX 68 | cmp r4,#HW_SG1000 69 | cmpne r4,#HW_SGAC 70 | cmpne r4,#HW_SC3000 71 | cmpne r4,#HW_OMV 72 | cmpne r4,#HW_SG1000II ;@ ? 73 | cmpne r4,#HW_COLECO 74 | mov r0,#0 75 | moveq r0,#1 76 | ldr r1,=SN76496_0 77 | bl sn76496Reset ;@ Sound 78 | cmp r4,#HW_SYSE 79 | bne noSysE 80 | mov r0,#0 81 | ldr r1,=SN76496_1 82 | bl sn76496Reset ;@ Sound 83 | noSysE: 84 | ldr ymptr,=YM2413_0 85 | bl YM2413Reset ;@ Sound 86 | ldmfd sp!,{r4,lr} 87 | bx lr 88 | isMSX: 89 | ldr r0,=SCC_0 90 | bl SCCReset 91 | ldr r4,=AY38910_0 92 | mov r0,r4 93 | bl ay38910Reset 94 | ldr r0,=MSXJoyReadCallBack 95 | str r0,[r4,#ayPortAInFptr] 96 | ldmfd sp!,{r4,lr} 97 | bx lr 98 | ;@---------------------------------------------------------------------------- 99 | SMSJSoundControlW: 100 | ;@---------------------------------------------------------------------------- 101 | strb r0,SMSJSoundControl 102 | bx lr 103 | ;@---------------------------------------------------------------------------- 104 | SMSJSoundControlR: 105 | ;@---------------------------------------------------------------------------- 106 | ldrb r0,SMSJSoundControl 107 | and r0,r0,#0x01 108 | orr r0,r0,#0xF8 109 | bx lr 110 | ;@---------------------------------------------------------------------------- 111 | soundSetFrequency: 112 | .type soundSetFrequency STT_FUNC 113 | ;@---------------------------------------------------------------------------- 114 | stmfd sp!,{lr} 115 | ldr r1,=gEmuFlags 116 | ldrb r1,[r1] 117 | tst r1,#PALTIMING 118 | ldr r1,=3579545 ;@ NTSC freq 119 | ldrne r1,=3546893 ;@ PAL freq 120 | ldmfd sp!,{lr} 121 | bx lr 122 | 123 | ;@---------------------------------------------------------------------------- 124 | setMuteSoundGUI: 125 | .type setMuteSoundGUI STT_FUNC 126 | ;@---------------------------------------------------------------------------- 127 | ldr r1,=pauseEmulation ;@ Output silence when emulation paused. 128 | ldrb r0,[r1] 129 | ldr r1,=powerButton ;@ Output silence when power off. 130 | ldrb r1,[r1] 131 | cmp r1,#0 132 | orreq r0,r0,#0xFF 133 | strb r0,muteSoundGUI 134 | bx lr 135 | ;@---------------------------------------------------------------------------- 136 | setMuteSoundGame: ;@ For System E ? 137 | ;@---------------------------------------------------------------------------- 138 | strb r0,muteSoundGame 139 | bx lr 140 | ;@---------------------------------------------------------------------------- 141 | VblSound2: ;@ r0=length, r1=pointer 142 | ;@---------------------------------------------------------------------------- 143 | ldr r2,muteSound 144 | cmp r2,#0 145 | bne silenceMix 146 | 147 | stmfd sp!,{r0,r1,r4,r5,lr} 148 | 149 | ldr r1,=mixSpace0 150 | 151 | ldr r2,=gMachine 152 | ldrb r2,[r2] 153 | cmp r2,#HW_SYSE 154 | beq sysEMix 155 | cmp r2,#HW_MSX 156 | beq MSXMix 157 | ldrb r2,SMSJSoundControl 158 | tst r2,#0x1 159 | bne YM2413Mix 160 | // bne YM2413MixC 161 | ;@---------------------------------------------------------------------------- 162 | SMSMix: 163 | ldr r2,=SN76496_0 164 | ldmfd sp,{r0,r1} 165 | bl sn76496Mixer 166 | 167 | ldmfd sp!,{r0,r1,r4,r5,lr} 168 | bx lr 169 | 170 | ;@---------------------------------------------------------------------------- 171 | sysEMix: 172 | ldr r2,=SN76496_1 173 | bl sn76496Mixer 174 | addExtraSN76496: 175 | ldmfd sp,{r0} 176 | ldr r1,=mixSpace1 177 | ldr r2,=SN76496_0 178 | bl sn76496Mixer 179 | mix2Chips: 180 | ldmfd sp,{r0,r1} 181 | ldr r2,=mixSpace0 182 | ldr r3,=mixSpace1 183 | mixLoop02: 184 | ldrsh r4,[r2],#4 185 | ldrsh r5,[r3],#4 186 | add r4,r4,r5 187 | 188 | mov r4,r4,lsl#16-1 189 | mov r4,r4,lsr#16 190 | orr r4,r4,r4,lsl#16 191 | subs r0,r0,#1 192 | strpl r4,[r1],#4 193 | bhi mixLoop02 194 | 195 | ldmfd sp!,{r0,r1,r4,r5,lr} 196 | bx lr 197 | 198 | ;@---------------------------------------------------------------------------- 199 | YM2413Mix: 200 | ;@---------------------------------------------------------------------------- 201 | mov r0,r0,lsl#3 202 | ldr ymptr,=YM2413_0 203 | bl YM2413Mixer 204 | ldrb r2,SMSJSoundControl 205 | tst r2,#0x2 206 | bne addExtraSN76496 207 | ldmfd sp,{r0,r1} 208 | ldr r2,=mixSpace0 209 | mixLoop03: 210 | ldrsh r4,[r2],#2 211 | ldrsh r5,[r2],#2 212 | add r4,r4,r5 213 | ldrsh r5,[r2],#2 214 | add r4,r4,r5 215 | ldrsh r5,[r2],#2 216 | add r4,r4,r5 217 | ldrsh r5,[r2],#2 218 | add r4,r4,r5 219 | ldrsh r5,[r2],#2 220 | add r4,r4,r5 221 | ldrsh r5,[r2],#2 222 | add r4,r4,r5 223 | ldrsh r5,[r2],#2 224 | add r4,r4,r5 225 | ldrsh r5,[r2] 226 | add r4,r4,r5 227 | 228 | mov r4,r4,lsl#16-3 229 | mov r4,r4,lsr#16 230 | orr r4,r4,r4,lsl#16 231 | 232 | subs r0,r0,#1 233 | strpl r4,[r1],#4 234 | bhi mixLoop03 235 | 236 | ldmfd sp!,{r0,r1,r4,r5,lr} 237 | bx lr 238 | 239 | ;@---------------------------------------------------------------------------- 240 | YM2413MixC: 241 | ;@---------------------------------------------------------------------------- 242 | mov r2,r0,lsr#2 243 | mov r0,#0 244 | blx YM2413UpdateOneMono 245 | ldmfd sp,{r0,r1} 246 | ldr r2,=mixSpace0 247 | mixLoop03C: 248 | ldrh r4,[r2],#2 249 | add r4,r4,r4,lsl#16 250 | 251 | subs r0,r0,#1 252 | strpl r4,[r1],#4 253 | bhi mixLoop03C 254 | 255 | ldmfd sp!,{r0,r1,r4,r5,lr} 256 | bx lr 257 | 258 | ;@---------------------------------------------------------------------------- 259 | MSXMix: 260 | ;@---------------------------------------------------------------------------- 261 | ldr r2,=AY38910_0 262 | bl ay38910Mixer 263 | // ldrb r0,SCCEnabled 264 | // cmp r0,#0 265 | // noSCC 266 | ldmfd sp,{r0} 267 | ldr r1,=mixSpace1 268 | ldr r2,=SCC_0 269 | bl SCCMixer 270 | // b mix2Chips 271 | noSCC: 272 | ldmfd sp,{r0,r1} 273 | ldr r2,=mixSpace0 274 | ldr r3,=mixSpace1 275 | // ldr r12,soundFilter 276 | mixLoop01: 277 | ldrsh r4,[r2],#2 278 | ldrsh r5,[r3],#2 279 | add r4,r4,r5 280 | 281 | // sub r12,r12,r12,asr#2 282 | // add r12,r12,r4,lsl#16-3-2 283 | // mov r4,r12,lsr#16 284 | 285 | mov r4,r4,lsl#16-1 286 | mov r4,r4,lsr#16 287 | orr r4,r4,r4,lsl#16 288 | subs r0,r0,#1 289 | strpl r4,[r1],#4 290 | bhi mixLoop01 291 | 292 | // str r12,soundFilter 293 | ldmfd sp!,{r0,r1,r4,r5,lr} 294 | bx lr 295 | 296 | silenceMix: 297 | mov r12,r0 298 | mov r2,#0 299 | silenceLoop: 300 | subs r12,r12,#1 301 | strpl r2,[r1],#4 302 | bhi silenceLoop 303 | 304 | bx lr 305 | 306 | soundFilter: 307 | .long 0 308 | ;@---------------------------------------------------------------------------- 309 | GG_Stereo_W: 310 | ;@---------------------------------------------------------------------------- 311 | ldr r1,=SN76496_0 312 | b sn76496GGW 313 | ;@---------------------------------------------------------------------------- 314 | SN76496_W: 315 | SN76496_0_W: 316 | ;@---------------------------------------------------------------------------- 317 | ldr r1,=SN76496_0 318 | b sn76496W 319 | ;@---------------------------------------------------------------------------- 320 | SN76496_1_W: 321 | ;@---------------------------------------------------------------------------- 322 | ldr r1,=SN76496_1 323 | b sn76496W 324 | ;@---------------------------------------------------------------------------- 325 | YM2413_0_AddressW: 326 | ;@---------------------------------------------------------------------------- 327 | ldr ymptr,=YM2413_0 328 | b YM2413AddressW 329 | ;@---------------------------------------------------------------------------- 330 | YM2413_0_DataW: 331 | ;@---------------------------------------------------------------------------- 332 | ldr ymptr,=YM2413_0 333 | b YM2413DataW 334 | 335 | stmfd sp!,{r3,lr} 336 | mov r2,r0 337 | mov r1,r12 338 | mov r0,#0 339 | blx YM2413Write 340 | ldmfd sp!,{r3,lr} 341 | bx lr 342 | ;@---------------------------------------------------------------------------- 343 | YM2413_0_StatusR: 344 | ;@---------------------------------------------------------------------------- 345 | ldr ymptr,=YM2413_0 346 | b YM2413StatusR 347 | stmfd sp!,{r3,lr} 348 | mov r1,r12 349 | mov r0,#0 350 | blx YM2413Read 351 | ldmfd sp!,{r3,lr} 352 | bx lr 353 | ;@---------------------------------------------------------------------------- 354 | AY38910Index_0_W: 355 | ;@---------------------------------------------------------------------------- 356 | ldr r1,=AY38910_0 357 | b ay38910IndexW 358 | ;@---------------------------------------------------------------------------- 359 | AY38910Data_0_W: 360 | ;@---------------------------------------------------------------------------- 361 | ldr r1,=AY38910_0 362 | b ay38910DataW 363 | ;@---------------------------------------------------------------------------- 364 | AY38910Data_0_R: 365 | ;@---------------------------------------------------------------------------- 366 | ldr r0,=AY38910_0 367 | b ay38910DataR 368 | ;@---------------------------------------------------------------------------- 369 | SCCWrite_0: 370 | ;@---------------------------------------------------------------------------- 371 | mov r1,r12 372 | ldr r2,=SCC_0 373 | b SCCWrite 374 | ;@---------------------------------------------------------------------------- 375 | muteSound: 376 | muteSoundGUI: 377 | .byte 0 378 | muteSoundGame: 379 | .byte 0 380 | .space 2 381 | SMSJSoundControl: 382 | .byte 0 383 | .space 3 384 | 385 | 386 | .section .bss 387 | .align 2 388 | SoundVariables: 389 | SN76496_0: 390 | .space snSize 391 | SN76496_1: 392 | .space snSize 393 | YM2413_0: 394 | .space ymSize 395 | AY38910_0: 396 | .space aySize 397 | SCC_0: 398 | .space sccSize 399 | mixSpace0: 400 | .space 0x8000 401 | mixSpace1: 402 | .space 0x8000 403 | ;@---------------------------------------------------------------------------- 404 | .end 405 | #endif // #ifdef __arm__ 406 | -------------------------------------------------------------------------------- /source/SystemE.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "Equates.h" 4 | #include "PPI8255/PPI8255.i" 5 | 6 | .global sysEReset 7 | .global sysELatch 8 | .global IO_Params_SysE_R 9 | .global IO_Params_SysE_W 10 | 11 | // .extern coinCounter0W 12 | // .extern coinCounter1W 13 | // .extern dipSwitch0iR 14 | // .extern dipSwitch1iR 15 | 16 | .syntax unified 17 | .arm 18 | 19 | .section .text 20 | .align 2 21 | ;@---------------------------------------------------------------------------- 22 | ;@ System E 23 | IO_Params_SysE_R: 24 | .long 0x005800DD, VDP1VCounterR ;@ 0x7A 25 | .long 0x005900DD, VDP1HCounterR ;@ 0x7B 26 | .long 0x005C00DD, VDP0VCounterR ;@ 0x7E 27 | .long 0x005D00DD, VDP0HCounterR ;@ 0x7F 28 | .long 0x009800DD, VDP1DataR ;@ 0xBA 29 | .long 0x009900DD, VDP1StatR ;@ 0xBB 30 | .long 0x009C00DD, VDP0DataR ;@ 0xBE 31 | .long 0x009D00DD, VDP0StatR ;@ 0xBF 32 | .long 0x0000001F, SysE_IN0_R ;@ 0xE0 33 | .long 0x0001001F, IOPortA_R ;@ 0xE1 34 | .long 0x0002001F, SysE_Player2_R ;@ 0xE2 35 | .long 0x0010001D, dipSwitch0iR ;@ 0xF2 36 | .long 0x0011001D, dipSwitch1iR ;@ 0xF3 37 | .long 0x00D800DF, PPI1PortAR ;@ 0xF8 38 | .long 0x00D900DF, PPI1PortBR ;@ 0xF9 39 | .long 0x00DA00DF, PPI1PortCR ;@ 0xFA 40 | .long 0x00DB00DF, PPI1PortDR ;@ 0xFB 41 | .long 0x0014001C, SysEBanking_R ;@ 0xF7 42 | .long 0x00000000, empty_R ;@ everything else 43 | IO_Params_SysE_W: 44 | .long 0x005800DC, SN76496_0_W ;@ 0x7A, 0x7B 45 | .long 0x005C00DC, SN76496_1_W ;@ 0x7E, 0x7F 46 | .long 0x009800DD, VDP1DataSMSW ;@ 0xBA 47 | .long 0x009900DD, VDP1CtrlW ;@ 0xBB 48 | .long 0x009C00DD, VDP0DataSMSW ;@ 0xBE 49 | .long 0x009D00DD, VDP0CtrlW ;@ 0xBF 50 | .long 0x00D800DF, PPI1PortAW ;@ 0xF8 51 | .long 0x00D900DF, PPI1PortBW ;@ 0xF9 52 | .long 0x00DA00DF, PPI1PortCW ;@ 0xFA 53 | .long 0x00DB00DF, PPI1PortDW ;@ 0xFB 54 | .long 0x0014001C, SysEBanking_W ;@ 0xF7 55 | // .long 0x00FD00FF, SDSC_Debug_W ;@ 0xFD 56 | .long 0x00000000, empty_W ;@ everything else 57 | 58 | ;@---------------------------------------------------------------------------- 59 | sysEReset: 60 | ;@---------------------------------------------------------------------------- 61 | stmfd sp!,{r4,lr} 62 | 63 | mov r1,#0xFF 64 | strb r1,sysELatch 65 | mov r1,#0 66 | ldr r0,=SPRS 67 | strb r1,[r0] 68 | 69 | bl PPI1Reset 70 | ldr r0,=SysEOutput_W 71 | str r0,[ppiptr,#ppiPortBOutFptr] 72 | ldr r0,=SysEAnalogW 73 | str r0,[ppiptr,#ppiPortCOutFptr] 74 | 75 | ldmfd sp!,{r4,lr} 76 | bx lr 77 | ;@---------------------------------------------------------------------------- 78 | SysE_IN0_R: ;@ Coin, service, start, 0xE0 79 | ;@---------------------------------------------------------------------------- 80 | mov r0,#0xFF 81 | ldr r1,=joy0State 82 | ldrb r1,[r1] 83 | ldr r2,=joy1State 84 | ldrb r2,[r2] 85 | tst r1,#0x80 ;@ Start1 86 | bicne r0,r0,#0x40 ;@ Start1 87 | bicne r0,r0,#0x10 ;@ Start1, HangOnJr 88 | tst r2,#0x80 ;@ Start2 89 | bicne r0,r0,#0x80 ;@ Start2 90 | tst r1,#0x40 ;@ Select1 91 | bicne r0,r0,#0x01 ;@ Coin1 92 | tst r2,#0x40 ;@ Select2 93 | bicne r0,r0,#0x02 ;@ Coin2 94 | ldr r1,=acExtra 95 | ldr r1,[r1] 96 | tst r1,#0x4000 ;@ NDS L 97 | bicne r0,r0,#0x04 ;@ Service menu 98 | tst r1,#0x0020 ;@ NDS Select+Right 99 | bicne r0,r0,#0x08 ;@ Service coin 100 | bx lr 101 | ;@---------------------------------------------------------------------------- 102 | SysE_Player2_R: ;@ Player2, 0xE2 103 | ;@---------------------------------------------------------------------------- 104 | ldr r0,=joy1State 105 | ldrb r0,[r0] 106 | and r0,r0,#0x3F 107 | eor r0,r0,#0xFF 108 | bx lr 109 | 110 | ;@---------------------------------------------------------------------------- 111 | SysEOutput_W: ;@ 0xF9, PPI_PortB 112 | ;@---------------------------------------------------------------------------- 113 | ;@ Bit 0 = Coin Counter 1, bit 1 = Coin Counter 2, bit 2 = Start Lamp Hang On Jr. 114 | stmfd sp!,{r3,lr} 115 | 116 | mov r3,r0 117 | and r0,r3,#0x01 118 | bl coinCounter0W 119 | and r0,r3,#0x02 120 | bl coinCounter1W 121 | 122 | ldmfd sp!,{r3,lr} 123 | bx lr 124 | ;@---------------------------------------------------------------------------- 125 | SysEAnalogW: ;@ 0xFA 126 | ;@---------------------------------------------------------------------------- 127 | ldrb r1,[ppiptr,#ppiPortCOut] 128 | and r1,r1,#0x0F 129 | ldr r2,=gArcadeGameSet 130 | ldrb r2,[r2] 131 | cmp r2,#AC_RIDDLE_OF_PYTHAGORAS 132 | cmpne r2,#AC_MEGUMI_RESCUE 133 | ldr r2,=joy0State 134 | ldrb r2,[r2] 135 | beq pythagoras 136 | cmp r1,#0x08 137 | bne SysEAccel 138 | mov r0,#0x80 139 | tst r2,#0x04 140 | movne r0,#0x30 141 | tst r2,#0x08 142 | movne r0,#0xD0 143 | strb r0,[ppiptr,#ppiPortAIn] 144 | bx lr 145 | SysEAccel: 146 | mov r0,#0x30 147 | strb r0,[ppiptr,#ppiPortAIn] 148 | cmp r1,#0x09 149 | bxne lr 150 | tst r2,#0x10 151 | movne r0,#0xE8 152 | strb r0,[ppiptr,#ppiPortAIn] 153 | bx lr 154 | ;@---------------------------------------------------------------------------- 155 | pythagoras: 156 | mov r0,#0x00 157 | and r1,r1,#0x0C 158 | cmp r1,#0x04 159 | strb r0,[ppiptr,#ppiPortAIn] 160 | bxhi lr 161 | beq pythagorasButton 162 | tst r2,#0x01 163 | movne r0,#0x28 164 | tst r2,#0x02 165 | movne r0,#0xD8 166 | strb r0,[ppiptr,#ppiPortAIn] 167 | bx lr 168 | pythagorasButton: 169 | tst r2,#0x01 170 | movne r0,#0x00 171 | tst r2,#0x02 172 | movne r0,#0x0F 173 | tst r2,#0x10 174 | orrne r0,r0,#0x40 175 | tst r2,#0x20 176 | orrne r0,r0,#0x10 177 | strb r0,[ppiptr,#ppiPortAIn] 178 | bx lr 179 | ;@---------------------------------------------------------------------------- 180 | SysEBanking_R: ;@ 0xF7 181 | ;@---------------------------------------------------------------------------- 182 | mov r0,#0xFF 183 | ;@---------------------------------------------------------------------------- 184 | SysEBanking_W: ;@ 0xF7 185 | ;@---------------------------------------------------------------------------- 186 | stmfd sp!,{r0,lr} 187 | ldrb r1,sysELatch 188 | strb r0,sysELatch 189 | eor r1,r1,r0 190 | ands r1,r1,#0xC0 191 | blne SystemESetVRAM 192 | 193 | ldrb r0,sysELatch 194 | and r0,r0,#0x0F 195 | add r0,r0,#2 196 | bl BankSwitch2_W 197 | 198 | ldrb r0,sysELatch 199 | and r0,r0,#0x10 ;@ bit #4 controls sound mute. 200 | bl setMuteSoundGame 201 | 202 | ldmfd sp!,{r0,pc} 203 | sysELatch: 204 | .byte 0 205 | .space 3 206 | ;@---------------------------------------------------------------------------- 207 | .end 208 | #endif // #ifdef __arm__ 209 | -------------------------------------------------------------------------------- /source/cpu.h: -------------------------------------------------------------------------------- 1 | #ifndef CPU_HEADER 2 | #define CPU_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern u8 waitMaskIn; 9 | extern u8 waitMaskOut; 10 | 11 | void run(void); 12 | void runFrame(void); 13 | void cpuReset(void); 14 | 15 | #ifdef __cplusplus 16 | } // extern "C" 17 | #endif 18 | 19 | #endif // CPU_HEADER 20 | -------------------------------------------------------------------------------- /source/cpu.s: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #include "Shared/nds_asm.h" 4 | #include "Equates.h" 5 | #include "ARMZ80/ARMZ80.i" 6 | #include "SegaVDP/SegaVDP.i" 7 | 8 | #define CYCLE_PSL (228) 9 | 10 | .global waitMaskIn 11 | .global waitMaskOut 12 | 13 | .global run 14 | .global runFrame 15 | .global cpuReset 16 | 17 | .syntax unified 18 | .arm 19 | 20 | #ifdef GBA 21 | .section .ewram, "ax", %progbits ;@ For the GBA 22 | #else 23 | .section .text ;@ For anything else 24 | #endif 25 | .align 2 26 | ;@---------------------------------------------------------------------------- 27 | run: ;@ Return after X frame(s) 28 | .type run STT_FUNC 29 | ;@---------------------------------------------------------------------------- 30 | 31 | ldrh r0,waitCountIn 32 | add r0,r0,#1 33 | ands r0,r0,r0,lsr#8 34 | strb r0,waitCountIn 35 | bxne lr 36 | stmfd sp!,{r4-r11,lr} 37 | 38 | ;@---------------------------------------------------------------------------- 39 | runStart: 40 | ;@---------------------------------------------------------------------------- 41 | ldr r0,=EMUinput 42 | ldr r0,[r0] 43 | 44 | ldr r2,=yStart 45 | ldrb r1,[r2] 46 | tst r0,#0x200 ;@ L? 47 | subsne r1,#1 48 | movmi r1,#0 49 | tst r0,#0x100 ;@ R? 50 | addne r1,#1 51 | cmp r1,#224-SCREEN_HEIGHT 52 | movpl r1,#224-SCREEN_HEIGHT 53 | @ strb r1,[r2] 54 | 55 | ldr z80ptr,=Z80OpTable 56 | bl refreshEMUjoypads ;@ Z=1 if communication ok 57 | 58 | add r0,z80ptr,#z80Regs 59 | ldmia r0,{z80f-z80pc,z80sp} ;@ Restore Z80 state 60 | 61 | mov lr,pc 62 | ldr pc,selectedFrameRun 63 | ;@---------------------------------------------------------------------------- 64 | FrameLoopEnd: 65 | add r0,z80ptr,#z80Regs 66 | stmia r0,{z80f-z80pc,z80sp} ;@ Save Z80 state 67 | 68 | ldr r1,=fpsValue 69 | ldr r0,[r1] 70 | add r0,r0,#1 71 | str r0,[r1] 72 | 73 | ldr r1,=gConfigSet 74 | ldrb r1,[r1] 75 | ldr r2,=EMUinput 76 | ldr r2,[r2] 77 | and r1,r1,r2,lsr#4 ;@ R button and config FF 78 | ands r1,r1,#0x10 79 | 80 | ldrh r0,waitCountOut 81 | orrne r0,r0,#0x0300 82 | add r0,r0,#1 83 | ands r0,r0,r0,lsr#8 84 | strb r0,waitCountOut 85 | ldmfdeq sp!,{r4-r11,lr} ;@ Exit here if doing single frame: 86 | bxeq lr ;@ Return to rommenu() 87 | b runStart 88 | 89 | ;@---------------------------------------------------------------------------- 90 | selectedFrameRun: .long SMSFrameRun 91 | scanlineCycles: .long CYCLE_PSL 92 | waitCountIn: .byte 0 93 | waitMaskIn: .byte 0 94 | waitCountOut: .byte 0 95 | waitMaskOut: .byte 0 96 | 97 | ;@---------------------------------------- 98 | SM5FrameRun: 99 | stmfd sp!,{lr} 100 | SM5FrameLoop: 101 | ldr r0,scanlineCycles 102 | bl CTC0Update 103 | ldr vdpptr,=VDP0 104 | bl VDPDoScanline 105 | cmp r0,#0 106 | ldmfdne sp!,{pc} 107 | ldr r0,scanlineCycles 108 | bl Z80RunXCycles 109 | b SM5FrameLoop 110 | ;@---------------------------------------- 111 | SYSEFrameRun: 112 | stmfd sp!,{lr} 113 | SYSEFrameLoop: 114 | ldr vdpptr,=VDP1 115 | bl VDPDoScanline 116 | ldr vdpptr,=VDP0 117 | bl VDPDoScanline 118 | cmp r0,#0 119 | ldmfdne sp!,{pc} 120 | ldr r0,scanlineCycles 121 | bl Z80RunXCycles 122 | b SYSEFrameLoop 123 | ;@---------------------------------------- 124 | SMSFrameRun: 125 | stmfd sp!,{lr} 126 | SMSFrameLoop: 127 | ldr vdpptr,=VDP0 128 | bl VDPDoScanline 129 | cmp r0,#0 130 | ldmfdne sp!,{pc} 131 | ldr r0,scanlineCycles 132 | bl Z80RunXCycles 133 | b SMSFrameLoop 134 | 135 | ;@---------------------------------------------------------------------------- 136 | runFrame: ;@ Return after 1 frame 137 | .type runFrame STT_FUNC 138 | ;@---------------------------------------------------------------------------- 139 | stmfd sp!,{r4-r11,lr} 140 | ldr z80ptr,=Z80OpTable 141 | add r0,z80ptr,#z80Regs 142 | ldmia r0,{z80f-z80pc,z80sp} ;@ Restore Z80 state 143 | ;@---------------------------------------------------------------------------- 144 | s8StepLoop: 145 | ;@---------------------------------------------------------------------------- 146 | mov lr,pc 147 | ldr pc,selectedFrameRun 148 | ;@---------------------------------------------------------------------------- 149 | add r0,z80ptr,#z80Regs 150 | stmia r0,{z80f-z80pc,z80sp} ;@ Save Z80 state 151 | ldmfd sp!,{r4-r11,lr} 152 | bx lr 153 | ;@---------------------------------------------------------------------------- 154 | ;@ntsc_pal_reset: 155 | ;@--- PAL Speed - 3546893Hz / 49.7Hz / 313 = 228 156 | ;@---NTSC Speed - 3579545Hz / 59.9Hz / 262 = 228 157 | ;@---------------------------------------------------------------------------- 158 | cpuReset: ;@ Called by loadCart/resetGame 159 | ;@---------------------------------------------------------------------------- 160 | stmfd sp!,{r4,lr} 161 | 162 | ldr r4,=gMachine 163 | ldrb r4,[r4] 164 | cmp r4,#HW_SYSE 165 | mov r0,#CYCLE_PSL 166 | addeq r0,r0,r0,lsr#1 167 | str r0,scanlineCycles 168 | 169 | 170 | adr r0,SMSFrameRun 171 | cmpne r4,#HW_MEGATECH 172 | adreq r0,SYSEFrameRun 173 | cmp r4,#HW_SORDM5 174 | adreq r0,SM5FrameRun 175 | str r0,selectedFrameRun 176 | 177 | ldr r0,=Z80OpTable 178 | mov r1,#0 ;@ SMS 179 | cmp r4,#HW_MEGADRIVE 180 | // cmpne r4,#HW_MEGATECH 181 | moveq r1,#1 ;@ MD 182 | cmp r4,#HW_GG 183 | moveq r1,#2 ;@ GG 184 | bl Z80Reset 185 | 186 | ldr r0,=emptyReadPtr 187 | ldr r0,[r0] 188 | cmp r4,#HW_SORDM5 189 | ldreq r0,=CTC0GetIrqVector 190 | str r0,[z80ptr,#z80IrqVectorFunc] 191 | ldreq r0,=CTC0IrqAcknowledge 192 | streq r0,[z80ptr,#z80IrqAckFunc] 193 | 194 | ldmfd sp!,{r4,lr} 195 | bx lr 196 | 197 | ;@---------------------------------------------------------------------------- 198 | .end 199 | #endif // #ifdef __arm__ 200 | -------------------------------------------------------------------------------- /source/io.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_HEADER 2 | #define IO_HEADER 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern u32 joyCfg; 9 | extern u8 colecoKey; 10 | extern u8 sc3Keyboard; 11 | extern u8 keyboardRows[8]; 12 | extern u8 inputHW; 13 | extern u8 ym2413Enabled; 14 | extern int coinCounter0; 15 | extern int coinCounter1; 16 | extern u8 dipSwitch0; 17 | extern u8 dipSwitch1; 18 | extern u32 EMUinput; 19 | 20 | /** 21 | * Convert device input keys to target keys. 22 | * @param input NDS/GBA keys 23 | * @return The converted input. 24 | */ 25 | int convertInput(int input); 26 | 27 | #ifdef __cplusplus 28 | } // extern "C" 29 | #endif 30 | 31 | #endif // IO_HEADER 32 | -------------------------------------------------------------------------------- /source/ym2413.h: -------------------------------------------------------------------------------- 1 | #ifndef _H_YM2413_ 2 | #define _H_YM2413_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* select output bits size of output : 8 or 16 */ 9 | #define SAMPLE_BITS 16 10 | 11 | /* compiler dependence */ 12 | #ifndef OSD_CPU_H 13 | #define OSD_CPU_H 14 | typedef unsigned char UINT8; /* unsigned 8bit */ 15 | typedef unsigned short UINT16; /* unsigned 16bit */ 16 | typedef unsigned int UINT32; /* unsigned 32bit */ 17 | typedef signed char INT8; /* signed 8bit */ 18 | typedef signed short INT16; /* signed 16bit */ 19 | typedef signed int INT32; /* signed 32bit */ 20 | #endif 21 | 22 | #if (SAMPLE_BITS==16) 23 | typedef INT16 SAMP; 24 | #endif 25 | #if (SAMPLE_BITS==8) 26 | typedef INT8 SAMP; 27 | #endif 28 | 29 | 30 | int YM2413Init(int num, int clock, int rate); 31 | void YM2413Shutdown(void); 32 | void YM2413ResetChip(int which); 33 | void YM2413Write(int which, int a, int v); 34 | unsigned char YM2413Read(int which, int a); 35 | void YM2413UpdateOne(int which, INT16 *buffers, int length); 36 | void YM2413UpdateOneMono(int which, INT16 *buffers, int length); 37 | 38 | typedef void (*OPLL_UPDATEHANDLER)(int param,int min_interval_us); 39 | 40 | void YM2413SetUpdateHandler(int which, OPLL_UPDATEHANDLER UpdateHandler, int param); 41 | 42 | #ifdef __cplusplus 43 | } // extern "C" 44 | #endif 45 | 46 | #endif // _H_YM2413_ 47 | --------------------------------------------------------------------------------