├── .gitignore ├── CMakeLists.txt ├── Makefile ├── README.md ├── build.sh ├── components ├── odroid-go │ ├── CMakeLists.txt │ ├── component.mk │ ├── fonts │ │ ├── DejaVu12.h │ │ ├── DejaVuSans18.h │ │ └── DejaVuSans24.h │ ├── input.c │ ├── input.h │ ├── odroid.c │ ├── odroid.h │ ├── sdcard.c │ ├── sdcard.h │ ├── sound.c │ ├── sound.h │ ├── spi_lcd.c │ └── spi_lcd.h └── snes9x │ ├── .gitignore │ ├── .gitmodules │ ├── 65c816.h │ ├── CMakeLists.txt │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── appveyor.yml │ ├── apu.cpp │ ├── apu.h │ ├── apu_smp.cpp │ ├── apu_smp.hpp │ ├── apu_snes.hpp │ ├── clip.cpp │ ├── component.mk │ ├── conffile.cpp │ ├── conffile.h │ ├── controls.cpp │ ├── controls.h │ ├── core │ ├── oppseudo_misc.cpp │ ├── oppseudo_mov.cpp │ ├── oppseudo_pc.cpp │ ├── oppseudo_read.cpp │ └── oppseudo_rmw.cpp │ ├── cpu.cpp │ ├── cpuaddr.h │ ├── cpuexec.cpp │ ├── cpuexec.h │ ├── cpumacro.h │ ├── cpuops.cpp │ ├── cpuops.h │ ├── debug.cpp │ ├── debug.h │ ├── display.h │ ├── dma.cpp │ ├── dma.h │ ├── docs │ ├── changes.txt │ ├── control-inputs.txt │ ├── controls.txt │ ├── porting.html │ ├── portsofsnes9x.txt │ └── snapshots.txt │ ├── dsp.cpp │ ├── dsp.h │ ├── dsp1.cpp │ ├── font.h │ ├── getset.h │ ├── gfx.cpp │ ├── gfx.h │ ├── globals.cpp │ ├── language.h │ ├── logger.cpp │ ├── logger.h │ ├── memmap.cpp │ ├── memmap.h │ ├── messages.h │ ├── missing.h │ ├── pixform.h │ ├── port.h │ ├── ppu.cpp │ ├── ppu.h │ ├── snes9x.cpp │ ├── snes9x.h │ ├── stream.cpp │ ├── stream.h │ ├── tile.cpp │ └── tile.h ├── debug.sh ├── main ├── CMakeLists.txt ├── app_main.cpp ├── component.mk ├── rom_selector.cpp └── snes9x.cpp ├── sdkconfig.defaults └── tile.raw /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/* 2 | build/* 3 | *.fw 4 | sdkconfig 5 | sdkconfig.old -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 3 | set(EXTRA_COMPONENT_DIRS "components") 4 | project(snes9x-esp32) 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := snes9x-esp32 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This port is now abandoned. 2 | A new port is being worked on as part of [retro-go](https://github.com/ducalex/retro-go/) and is already in better shape than this one. 3 | 4 | # Snes9x for Odroid GO 5 | This is a port of the snes9x emulator to the Odroid Go. 6 | 7 | You will notice that I butchered the snes9x codebase and that was for multiple reasons such as: fixing compile errors, smaller binary, performance, simplicity. 8 | 9 | Once (If) I get the emulator to run at an acceptable speed I will bring the code back to as close to upstream as possible. 10 | 11 | ## Things to note: 12 | - It is very slow (currently ~4x too slow) 13 | - No sound 14 | - No saves 15 | - ROMs are limited to 2MB 16 | - No enhancement chip support (DSP will be supported eventually, SA/FX probably not) 17 | 18 | ## Device support 19 | Although only the Odroid GO is officially supported, it is confirmed to also run on a standard ESP32-**WROVER** with an ILI9341 LCD. 20 | 21 | Careful: Most ESP32 dev boards use the ESP32-**WROOM** modules and it won't work for this project (there is not enough memory). 22 | 23 | 24 | # Photo 25 | 26 | ![Super mario world](https://i.imgur.com/xmtncsX.jpg) 27 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #make -j 4 3 | release=`date +%Y%m%d`; 4 | ../odroid-go-multi-firmware/tools/mkfw/mkfw "Snes9x ($release)" tile.raw 0 16 2097152 app build/snes9x-esp32.bin 5 | mv firmware.fw snes9x.fw 6 | -------------------------------------------------------------------------------- /components/odroid-go/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCDIRS ".") 2 | set(COMPONENT_ADD_INCLUDEDIRS ".") 3 | set(COMPONENT_REQUIRES "nvs_flash spi_flash fatfs freertos") 4 | 5 | register_component() -------------------------------------------------------------------------------- /components/odroid-go/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | # This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, 5 | # this will take the sources in the src/ directory, compile them and link them into 6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, 7 | # please read the SDK documents if you need to do this. 8 | # 9 | 10 | CFLAGS += -O2 11 | 12 | #include $(IDF_PATH)/make/component_common.mk 13 | 14 | -------------------------------------------------------------------------------- /components/odroid-go/fonts/DejaVu12.h: -------------------------------------------------------------------------------- 1 | // Default font 2 | 3 | // ======================================================================== 4 | // This comes with no warranty, implied or otherwise 5 | 6 | // This data structure was designed to support Proportional fonts 7 | // fonts. Individual characters do not have to be multiples of 8 bits wide. 8 | // Any width is fine and does not need to be fixed. 9 | 10 | // The data bits are packed to minimize data requirements, but the tradeoff 11 | // is that a header is required per character. 12 | 13 | // Header Format: 14 | // ------------------------------------------------ 15 | // Character Width (Used as a marker to indicate use this format. i.e.: = 0x00) 16 | // Character Height 17 | // First Character (Reserved. 0x00) 18 | // Number Of Characters (Reserved. 0x00) 19 | 20 | // Individual Character Format: 21 | // ---------------------------- 22 | // Character Code 23 | // Adjusted Y Offset (start Y of visible pixels) 24 | // Width (width of the visible pixels) 25 | // Height (height of the visible pixels) 26 | // xOffset (start X of visible pixels) 27 | // xDelta (the distance to move the cursor. Effective width of the character.) 28 | // Data[n] 29 | 30 | // NOTE: You can remove any of these characters if they are not needed in 31 | // your application. The first character number in each Glyph indicates 32 | // the ASCII character code. Therefore, these do not have to be sequential. 33 | // Just remove all the content for a particular character to save space. 34 | // ======================================================================== 35 | 36 | // dejavu 37 | // Point Size : 12 38 | // Memory usage : 1158 bytes 39 | // # characters : 95 40 | 41 | const unsigned char tft_Dejavu12[] = 42 | { 43 | 0x00, 0x0B, 0x86, 0x04, 44 | 45 | // ' ' 46 | 0x20,0x0A,0x00,0x00,0x00,0x04, 47 | 48 | // '!' 49 | 0x21,0x01,0x01,0x09,0x02,0x05, 50 | 0xFD,0x80, 51 | // '"' 52 | 0x22,0x01,0x03,0x03,0x01,0x05, 53 | 0xB6,0x80, 54 | // '#' 55 | 0x23,0x02,0x08,0x08,0x01,0x0A, 56 | 0x12,0x14,0x7F,0x24,0x24,0xFE,0x28,0x48, 57 | // '$' 58 | 0x24,0x01,0x06,0x0B,0x02,0x08, 59 | 0x21,0xCA,0xA8,0xE0,0xE2,0xAA,0x70,0x82,0x00, 60 | // '%' 61 | 0x25,0x01,0x0A,0x09,0x00,0x0B, 62 | 0x61,0x24,0x89,0x22,0x50,0x6D,0x82,0x91,0x24,0x49,0x21,0x80, 63 | // '&' 64 | 0x26,0x01,0x09,0x09,0x01,0x0A, 65 | 0x30,0x24,0x10,0x0C,0x05,0x14,0x4A,0x19,0x8C,0x7B,0x00, 66 | // ''' 67 | 0x27,0x01,0x01,0x03,0x01,0x03, 68 | 0xE0, 69 | // '(' 70 | 0x28,0x00,0x03,0x0B,0x01,0x05, 71 | 0x69,0x49,0x24,0x48,0x80, 72 | // ')' 73 | 0x29,0x00,0x03,0x0B,0x01,0x05, 74 | 0x89,0x12,0x49,0x4A,0x00, 75 | // '*' 76 | 0x2A,0x01,0x05,0x06,0x01,0x06, 77 | 0x25,0x5C,0xEA,0x90, 78 | // '+' 79 | 0x2B,0x03,0x07,0x07,0x01,0x0A, 80 | 0x10,0x20,0x47,0xF1,0x02,0x04,0x00, 81 | // ',' 82 | 0x2C,0x08,0x01,0x03,0x01,0x04, 83 | 0xE0, 84 | // '-' 85 | 0x2D,0x06,0x03,0x01,0x01,0x04, 86 | 0xE0, 87 | // '.' 88 | 0x2E,0x08,0x01,0x02,0x01,0x04, 89 | 0xC0, 90 | // '/' 91 | 0x2F,0x01,0x04,0x0A,0x00,0x04, 92 | 0x11,0x22,0x24,0x44,0x88, 93 | // '0' 94 | 0x30,0x01,0x06,0x09,0x01,0x08, 95 | 0x79,0x28,0x61,0x86,0x18,0x52,0x78, 96 | // '1' 97 | 0x31,0x01,0x05,0x09,0x01,0x08, 98 | 0xE1,0x08,0x42,0x10,0x84,0xF8, 99 | // '2' 100 | 0x32,0x01,0x07,0x09,0x01,0x08, 101 | 0x79,0x18,0x10,0x20,0x82,0x08,0x20,0xFC, 102 | // '3' 103 | 0x33,0x01,0x06,0x09,0x01,0x08, 104 | 0x7A,0x10,0x41,0x38,0x30,0x63,0x78, 105 | // '4' 106 | 0x34,0x01,0x06,0x09,0x01,0x08, 107 | 0x18,0x62,0x92,0x4A,0x2F,0xC2,0x08, 108 | // '5' 109 | 0x35,0x01,0x06,0x09,0x01,0x08, 110 | 0xFA,0x08,0x3C,0x0C,0x10,0x63,0x78, 111 | // '6' 112 | 0x36,0x01,0x06,0x09,0x01,0x08, 113 | 0x39,0x18,0x3E,0xCE,0x18,0x53,0x78, 114 | // '7' 115 | 0x37,0x01,0x06,0x09,0x01,0x08, 116 | 0xFC,0x10,0x82,0x10,0x42,0x08,0x40, 117 | // '8' 118 | 0x38,0x01,0x06,0x09,0x01,0x08, 119 | 0x7B,0x38,0x73,0x7B,0x38,0x73,0x78, 120 | // '9' 121 | 0x39,0x01,0x06,0x09,0x01,0x08, 122 | 0x7B,0x28,0x61,0xCD,0xD0,0x62,0x70, 123 | // ':' 124 | 0x3A,0x04,0x01,0x06,0x01,0x04, 125 | 0xCC, 126 | // ';' 127 | 0x3B,0x04,0x01,0x07,0x01,0x04, 128 | 0xCE, 129 | // '<' 130 | 0x3C,0x03,0x08,0x06,0x01,0x0A, 131 | 0x03,0x1E,0xE0,0xE0,0x1E,0x03, 132 | // '=' 133 | 0x3D,0x05,0x08,0x03,0x01,0x0A, 134 | 0xFF,0x00,0xFF, 135 | // '>' 136 | 0x3E,0x03,0x08,0x06,0x01,0x0A, 137 | 0xC0,0x78,0x07,0x07,0x78,0xC0, 138 | // '?' 139 | 0x3F,0x01,0x05,0x09,0x00,0x06, 140 | 0x74,0x42,0x22,0x10,0x04,0x20, 141 | // '@' 142 | 0x40,0x01,0x0B,0x0B,0x01,0x0D, 143 | 0x1F,0x06,0x19,0x01,0x46,0x99,0x13,0x22,0x64,0x54,0x6C,0x40,0x04,0x10,0x7C,0x00, 144 | // 'A' 145 | 0x41,0x01,0x08,0x09,0x00,0x08, 146 | 0x18,0x18,0x24,0x24,0x24,0x42,0x7E,0x42,0x81, 147 | // 'B' 148 | 0x42,0x01,0x06,0x09,0x01,0x08, 149 | 0xFA,0x18,0x61,0xFA,0x18,0x61,0xF8, 150 | // 'C' 151 | 0x43,0x01,0x06,0x09,0x01,0x08, 152 | 0x39,0x18,0x20,0x82,0x08,0x11,0x38, 153 | // 'D' 154 | 0x44,0x01,0x07,0x09,0x01,0x09, 155 | 0xF9,0x0A,0x0C,0x18,0x30,0x60,0xC2,0xF8, 156 | // 'E' 157 | 0x45,0x01,0x06,0x09,0x01,0x08, 158 | 0xFE,0x08,0x20,0xFE,0x08,0x20,0xFC, 159 | // 'F' 160 | 0x46,0x01,0x05,0x09,0x01,0x07, 161 | 0xFC,0x21,0x0F,0xC2,0x10,0x80, 162 | // 'G' 163 | 0x47,0x01,0x07,0x09,0x01,0x09, 164 | 0x3C,0x86,0x04,0x08,0xF0,0x60,0xA1,0x3C, 165 | // 'H' 166 | 0x48,0x01,0x07,0x09,0x01,0x09, 167 | 0x83,0x06,0x0C,0x1F,0xF0,0x60,0xC1,0x82, 168 | // 'I' 169 | 0x49,0x01,0x01,0x09,0x01,0x03, 170 | 0xFF,0x80, 171 | // 'J' 172 | 0x4A,0x01,0x03,0x0B,0xFF,0x03, 173 | 0x24,0x92,0x49,0x27,0x00, 174 | // 'K' 175 | 0x4B,0x01,0x07,0x09,0x01,0x07, 176 | 0x85,0x12,0x45,0x0C,0x14,0x24,0x44,0x84, 177 | // 'L' 178 | 0x4C,0x01,0x05,0x09,0x01,0x06, 179 | 0x84,0x21,0x08,0x42,0x10,0xF8, 180 | // 'M' 181 | 0x4D,0x01,0x08,0x09,0x01,0x0A, 182 | 0x81,0xC3,0xC3,0xA5,0xA5,0x99,0x99,0x81,0x81, 183 | // 'N' 184 | 0x4E,0x01,0x07,0x09,0x01,0x09, 185 | 0xC3,0x86,0x8D,0x19,0x31,0x62,0xC3,0x86, 186 | // 'O' 187 | 0x4F,0x01,0x07,0x09,0x01,0x09, 188 | 0x38,0x8A,0x0C,0x18,0x30,0x60,0xA2,0x38, 189 | // 'P' 190 | 0x50,0x01,0x06,0x09,0x01,0x08, 191 | 0xFA,0x38,0x63,0xFA,0x08,0x20,0x80, 192 | // 'Q' 193 | 0x51,0x01,0x07,0x0B,0x01,0x09, 194 | 0x38,0x8A,0x0C,0x18,0x30,0x60,0xA2,0x38,0x10,0x10, 195 | // 'R' 196 | 0x52,0x01,0x07,0x09,0x01,0x08, 197 | 0xF9,0x1A,0x14,0x6F,0x91,0x21,0x42,0x82, 198 | // 'S' 199 | 0x53,0x01,0x06,0x09,0x01,0x08, 200 | 0x7B,0x18,0x30,0x78,0x30,0x63,0x78, 201 | // 'T' 202 | 0x54,0x01,0x07,0x09,0x00,0x07, 203 | 0xFE,0x20,0x40,0x81,0x02,0x04,0x08,0x10, 204 | // 'U' 205 | 0x55,0x01,0x07,0x09,0x01,0x09, 206 | 0x83,0x06,0x0C,0x18,0x30,0x60,0xA2,0x38, 207 | // 'V' 208 | 0x56,0x01,0x0A,0x09,0xFF,0x08, 209 | 0x40,0x90,0x22,0x10,0x84,0x21,0x04,0x81,0x20,0x30,0x0C,0x00, 210 | // 'W' 211 | 0x57,0x01,0x0B,0x09,0x00,0x0B, 212 | 0x84,0x28,0x89,0x11,0x27,0x22,0xA8,0x55,0x0E,0xE0,0x88,0x11,0x00, 213 | // 'X' 214 | 0x58,0x01,0x07,0x09,0x00,0x07, 215 | 0xC6,0x88,0xA1,0xC1,0x07,0x0A,0x22,0x82, 216 | // 'Y' 217 | 0x59,0x01,0x07,0x09,0x00,0x07, 218 | 0x82,0x89,0x11,0x43,0x82,0x04,0x08,0x10, 219 | // 'Z' 220 | 0x5A,0x01,0x07,0x09,0x01,0x09, 221 | 0xFE,0x04,0x10,0x41,0x04,0x10,0x40,0xFE, 222 | // '[' 223 | 0x5B,0x01,0x02,0x0B,0x02,0x05, 224 | 0xEA,0xAA,0xAC, 225 | // '\' 226 | 0x5C,0x01,0x04,0x0A,0x00,0x04, 227 | 0x88,0x44,0x42,0x22,0x11, 228 | // ']' 229 | 0x5D,0x01,0x02,0x0B,0x01,0x05, 230 | 0xD5,0x55,0x5C, 231 | // '^' 232 | 0x5E,0x01,0x08,0x03,0x01,0x0A, 233 | 0x18,0x24,0x42, 234 | // '_' 235 | 0x5F,0x0C,0x06,0x01,0x00,0x06, 236 | 0xFC, 237 | // '`' 238 | 0x60,0x00,0x03,0x02,0x01,0x06, 239 | 0x44, 240 | // 'a' 241 | 0x61,0x03,0x06,0x07,0x01,0x08, 242 | 0x7A,0x30,0x5F,0x86,0x37,0x40, 243 | // 'b' 244 | 0x62,0x00,0x06,0x0A,0x01,0x08, 245 | 0x82,0x08,0x2E,0xCA,0x18,0x61,0xCE,0xE0, 246 | // 'c' 247 | 0x63,0x03,0x05,0x07,0x01,0x07, 248 | 0x72,0x61,0x08,0x25,0xC0, 249 | // 'd' 250 | 0x64,0x00,0x06,0x0A,0x01,0x08, 251 | 0x04,0x10,0x5D,0xCE,0x18,0x61,0xCD,0xD0, 252 | // 'e' 253 | 0x65,0x03,0x06,0x07,0x01,0x08, 254 | 0x39,0x38,0x7F,0x81,0x13,0x80, 255 | // 'f' 256 | 0x66,0x00,0x04,0x0A,0x00,0x04, 257 | 0x34,0x4F,0x44,0x44,0x44, 258 | // 'g' 259 | 0x67,0x03,0x06,0x0A,0x01,0x08, 260 | 0x77,0x38,0x61,0x87,0x37,0x41,0x4C,0xE0, 261 | // 'h' 262 | 0x68,0x00,0x06,0x0A,0x01,0x08, 263 | 0x82,0x08,0x2E,0xC6,0x18,0x61,0x86,0x10, 264 | // 'i' 265 | 0x69,0x01,0x01,0x09,0x01,0x03, 266 | 0xBF,0x80, 267 | // 'j' 268 | 0x6A,0x01,0x02,0x0C,0x00,0x03, 269 | 0x45,0x55,0x56, 270 | // 'k' 271 | 0x6B,0x00,0x06,0x0A,0x01,0x07, 272 | 0x82,0x08,0x22,0x92,0x8E,0x28,0x92,0x20, 273 | // 'l' 274 | 0x6C,0x00,0x01,0x0A,0x01,0x03, 275 | 0xFF,0xC0, 276 | // 'm' 277 | 0x6D,0x03,0x09,0x07,0x01,0x0B, 278 | 0xB3,0x66,0x62,0x31,0x18,0x8C,0x46,0x22, 279 | // 'n' 280 | 0x6E,0x03,0x06,0x07,0x01,0x08, 281 | 0xBB,0x18,0x61,0x86,0x18,0x40, 282 | // 'o' 283 | 0x6F,0x03,0x06,0x07,0x01,0x08, 284 | 0x7B,0x38,0x61,0x87,0x37,0x80, 285 | // 'p' 286 | 0x70,0x03,0x06,0x0A,0x01,0x08, 287 | 0xBB,0x28,0x61,0x87,0x3B,0xA0,0x82,0x00, 288 | // 'q' 289 | 0x71,0x03,0x06,0x0A,0x01,0x08, 290 | 0x77,0x38,0x61,0x87,0x37,0x41,0x04,0x10, 291 | // 'r' 292 | 0x72,0x03,0x04,0x07,0x01,0x05, 293 | 0xBC,0x88,0x88,0x80, 294 | // 's' 295 | 0x73,0x03,0x06,0x07,0x01,0x07, 296 | 0x72,0x28,0x1C,0x0A,0x27,0x00, 297 | // 't' 298 | 0x74,0x01,0x04,0x09,0x00,0x05, 299 | 0x44,0xF4,0x44,0x44,0x30, 300 | // 'u' 301 | 0x75,0x03,0x06,0x07,0x01,0x08, 302 | 0x86,0x18,0x61,0x86,0x37,0x40, 303 | // 'v' 304 | 0x76,0x03,0x08,0x07,0xFF,0x06, 305 | 0x42,0x42,0x24,0x24,0x24,0x18,0x18, 306 | // 'w' 307 | 0x77,0x03,0x09,0x07,0x00,0x09, 308 | 0x88,0xC4,0x57,0x4A,0xA5,0x51,0x10,0x88, 309 | // 'x' 310 | 0x78,0x03,0x06,0x07,0x00,0x06, 311 | 0x85,0x24,0x8C,0x49,0x28,0x40, 312 | // 'y' 313 | 0x79,0x03,0x08,0x0A,0xFF,0x06, 314 | 0x42,0x42,0x24,0x24,0x14,0x18,0x08,0x08,0x10,0x60, 315 | // 'z' 316 | 0x7A,0x03,0x05,0x07,0x00,0x05, 317 | 0xF8,0x44,0x44,0x43,0xE0, 318 | // '{' 319 | 0x7B,0x01,0x05,0x0B,0x02,0x08, 320 | 0x19,0x08,0x42,0x60,0x84,0x21,0x06, 321 | // '|' 322 | 0x7C,0x01,0x01,0x0C,0x02,0x04, 323 | 0xFF,0xF0, 324 | // '}' 325 | 0x7D,0x01,0x05,0x0B,0x01,0x08, 326 | 0xC1,0x08,0x42,0x0C,0x84,0x21,0x30, 327 | // '~' 328 | 0x7E,0x04,0x08,0x03,0x01,0x0A, 329 | 0x00,0x71,0x8E, 330 | 331 | // Terminator 332 | 0xFF 333 | }; 334 | -------------------------------------------------------------------------------- /components/odroid-go/input.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "freertos/FreeRTOS.h" 23 | #include "freertos/semphr.h" 24 | #include "freertos/task.h" 25 | #include "driver/rtc_io.h" 26 | #include "driver/gpio.h" 27 | #include "driver/adc.h" 28 | 29 | #include "odroid.h" 30 | 31 | static odroid_input_state gamepad_state = {0}; 32 | static bool input_gamepad_initialized = false; 33 | static void (*odroid_input_callback_fn)(odroid_input_state) = NULL; 34 | 35 | 36 | void odroid_input_read_raw(uint8_t *values) 37 | { 38 | memset(values, 0, ODROID_INPUT_MAX); 39 | 40 | int joyX = adc1_get_raw(ODROID_GAMEPAD_IO_X); 41 | int joyY = adc1_get_raw(ODROID_GAMEPAD_IO_Y); 42 | 43 | if (joyX > 2048 + 1024) 44 | values[ODROID_INPUT_LEFT] = 1; 45 | else if (joyX > 1024) 46 | values[ODROID_INPUT_RIGHT] = 1; 47 | 48 | if (joyY > 2048 + 1024) 49 | values[ODROID_INPUT_UP] = 1; 50 | else if (joyY > 1024) 51 | values[ODROID_INPUT_DOWN] = 1; 52 | 53 | values[ODROID_INPUT_SELECT] = !(gpio_get_level(ODROID_GAMEPAD_IO_SELECT)); 54 | values[ODROID_INPUT_START] = !(gpio_get_level(ODROID_GAMEPAD_IO_START)); 55 | 56 | values[ODROID_INPUT_A] = !(gpio_get_level(ODROID_GAMEPAD_IO_A)); 57 | values[ODROID_INPUT_B] = !(gpio_get_level(ODROID_GAMEPAD_IO_B)); 58 | 59 | values[ODROID_INPUT_MENU] = !(gpio_get_level(ODROID_GAMEPAD_IO_MENU)); 60 | values[ODROID_INPUT_VOLUME] = !(gpio_get_level(ODROID_GAMEPAD_IO_VOLUME)); 61 | } 62 | 63 | 64 | static void odroid_input_task(void *arg) 65 | { 66 | printf("odroid_input_task: Input task started.\n"); 67 | 68 | int i, changes; 69 | 70 | while(1) 71 | { 72 | // Read hardware 73 | odroid_input_read_raw(&gamepad_state.realtime); 74 | changes = 0; 75 | 76 | // Debounce 77 | for(i = 0; i < ODROID_INPUT_MAX; ++i) 78 | { 79 | gamepad_state.debounce[i] <<= 1; 80 | 81 | gamepad_state.debounce[i] |= gamepad_state.realtime[i] ? 1 : 0; 82 | uint8_t val = gamepad_state.debounce[i] & 0x03; //0x0f; 83 | switch (val) { 84 | case 0x00: 85 | gamepad_state.values[i] = 0; 86 | break; 87 | 88 | case 0x03: //0x0f: 89 | gamepad_state.values[i] = 1; 90 | break; 91 | 92 | default: 93 | // ignore 94 | break; 95 | } 96 | 97 | if (gamepad_state.values[i] != gamepad_state.previous[i]) { 98 | changes++; 99 | } 100 | } 101 | 102 | if (changes > 0 && odroid_input_callback_fn != NULL) { 103 | (*odroid_input_callback_fn)(gamepad_state); 104 | // update previous only if there's a callback, otherwise get_state will do it; 105 | memcpy(gamepad_state.previous, gamepad_state.values, ODROID_INPUT_MAX); 106 | } 107 | 108 | // delay 109 | vTaskDelay(20 / portTICK_PERIOD_MS); 110 | } 111 | } 112 | 113 | 114 | void odroid_input_get_state(odroid_input_state *dst) 115 | { 116 | memcpy(dst, &gamepad_state, sizeof(gamepad_state)); 117 | memcpy(gamepad_state.previous, gamepad_state.values, ODROID_INPUT_MAX); 118 | } 119 | 120 | 121 | void odroid_input_set_callback(void (*callback)(odroid_input_state)) 122 | { 123 | odroid_input_callback_fn = callback; 124 | } 125 | 126 | 127 | void odroid_input_init(void) 128 | { 129 | if (input_gamepad_initialized) { 130 | return; 131 | } 132 | 133 | printf("odroid_input_init: Initializing input.\n"); 134 | 135 | gpio_set_direction(ODROID_GAMEPAD_IO_SELECT, GPIO_MODE_INPUT); 136 | gpio_set_pull_mode(ODROID_GAMEPAD_IO_SELECT, GPIO_PULLUP_ONLY); 137 | 138 | gpio_set_direction(ODROID_GAMEPAD_IO_START, GPIO_MODE_INPUT); 139 | 140 | gpio_set_direction(ODROID_GAMEPAD_IO_A, GPIO_MODE_INPUT); 141 | gpio_set_pull_mode(ODROID_GAMEPAD_IO_A, GPIO_PULLUP_ONLY); 142 | 143 | gpio_set_direction(ODROID_GAMEPAD_IO_B, GPIO_MODE_INPUT); 144 | gpio_set_pull_mode(ODROID_GAMEPAD_IO_B, GPIO_PULLUP_ONLY); 145 | 146 | adc1_config_width(ADC_WIDTH_12Bit); 147 | adc1_config_channel_atten(ODROID_GAMEPAD_IO_X, ADC_ATTEN_11db); 148 | adc1_config_channel_atten(ODROID_GAMEPAD_IO_Y, ADC_ATTEN_11db); 149 | 150 | rtc_gpio_deinit(ODROID_GAMEPAD_IO_MENU); 151 | gpio_set_direction(ODROID_GAMEPAD_IO_MENU, GPIO_MODE_INPUT); 152 | gpio_set_pull_mode(ODROID_GAMEPAD_IO_MENU, GPIO_PULLUP_ONLY); 153 | 154 | gpio_set_direction(ODROID_GAMEPAD_IO_VOLUME, GPIO_MODE_INPUT); 155 | 156 | input_gamepad_initialized = true; 157 | 158 | // Start background polling 159 | xTaskCreatePinnedToCore(&odroid_input_task, "odroid_input_task", 1024 * 2, NULL, 6, NULL, ODROID_TASKS_USE_CORE); 160 | } 161 | -------------------------------------------------------------------------------- /components/odroid-go/input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef _ODROID_INPUT_H_ 19 | #define _ODROID_INPUT_H_ 20 | 21 | #include 22 | 23 | #define ODROID_GAMEPAD_IO_X ADC1_CHANNEL_6 24 | #define ODROID_GAMEPAD_IO_Y ADC1_CHANNEL_7 25 | #define ODROID_GAMEPAD_IO_SELECT GPIO_NUM_27 26 | #define ODROID_GAMEPAD_IO_START GPIO_NUM_39 27 | #define ODROID_GAMEPAD_IO_A GPIO_NUM_32 28 | #define ODROID_GAMEPAD_IO_B GPIO_NUM_33 29 | #define ODROID_GAMEPAD_IO_MENU GPIO_NUM_13 30 | #define ODROID_GAMEPAD_IO_VOLUME GPIO_NUM_0 31 | 32 | enum 33 | { 34 | ODROID_INPUT_UP = 0, 35 | ODROID_INPUT_RIGHT, 36 | ODROID_INPUT_DOWN, 37 | ODROID_INPUT_LEFT, 38 | ODROID_INPUT_SELECT, 39 | ODROID_INPUT_START, 40 | ODROID_INPUT_A, 41 | ODROID_INPUT_B, 42 | ODROID_INPUT_MENU, 43 | ODROID_INPUT_VOLUME, 44 | 45 | ODROID_INPUT_MAX 46 | }; 47 | 48 | typedef struct 49 | { 50 | uint8_t values[ODROID_INPUT_MAX]; 51 | uint8_t previous[ODROID_INPUT_MAX]; 52 | uint8_t debounce[ODROID_INPUT_MAX]; 53 | uint8_t realtime[ODROID_INPUT_MAX]; 54 | } odroid_input_state; 55 | 56 | void odroid_input_get_state(odroid_input_state *); 57 | void odroid_input_set_callback(void (*callback)(odroid_input_state)); 58 | void odroid_input_read_raw(uint8_t *); 59 | void odroid_input_init(void); 60 | 61 | #endif -------------------------------------------------------------------------------- /components/odroid-go/odroid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "freertos/FreeRTOS.h" 19 | #include "freertos/task.h" 20 | #include "freertos/semphr.h" 21 | #include "esp_heap_caps.h" 22 | #include "driver/gpio.h" 23 | #include "odroid.h" 24 | 25 | static SemaphoreHandle_t spiLock = NULL; 26 | 27 | size_t free_bytes_total() 28 | { 29 | multi_heap_info_t info; 30 | heap_caps_get_info(&info, MALLOC_CAP_DEFAULT); 31 | return info.total_free_bytes; 32 | } 33 | 34 | size_t free_bytes_internal() 35 | { 36 | multi_heap_info_t info; 37 | heap_caps_get_info(&info, MALLOC_CAP_INTERNAL); 38 | return info.total_free_bytes; 39 | } 40 | 41 | size_t free_bytes_spiram() 42 | { 43 | multi_heap_info_t info; 44 | heap_caps_get_info(&info, MALLOC_CAP_SPIRAM); 45 | return info.total_free_bytes; 46 | } 47 | 48 | void odroid_system_init() 49 | { 50 | // SPI 51 | spiLock = xSemaphoreCreateMutex(); 52 | 53 | // LED 54 | gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT); 55 | gpio_set_level(GPIO_NUM_2, 0); 56 | 57 | // SD Card (needs to be before LCD) 58 | odroid_sdcard_init(); 59 | 60 | // LCD 61 | spi_lcd_init(); 62 | 63 | // NVS Flash 64 | // nvs_flash_init(); 65 | 66 | // Input 67 | odroid_input_init(); 68 | 69 | // Sound 70 | //odroid_sound_init(); 71 | } 72 | 73 | void odroid_system_led_set(int value) 74 | { 75 | gpio_set_level(GPIO_NUM_2, value); 76 | } 77 | 78 | void odroid_system_sleep() 79 | { 80 | 81 | } 82 | 83 | int odroid_system_battery_level() 84 | { 85 | return 0; 86 | } 87 | 88 | void odroid_fatal_error(char *error) 89 | { 90 | printf("Error: %s\n", error); 91 | spi_lcd_init(); // This is really only called if the error occurs in the SD card init 92 | spi_lcd_useFrameBuffer(false); // Send the error directly to the LCD 93 | spi_lcd_usePalette(false); 94 | spi_lcd_setFontColor(LCD_RGB(255, 0, 0)); // Red 95 | spi_lcd_clear(); 96 | spi_lcd_print(0, 0, "A fatal error occurred :("); 97 | spi_lcd_print(0, 50, error); 98 | odroid_sound_deinit(); 99 | exit(-1); 100 | } 101 | 102 | void inline odroid_spi_bus_acquire() 103 | { 104 | xSemaphoreTake(spiLock, portMAX_DELAY); 105 | } 106 | 107 | void inline odroid_spi_bus_release() 108 | { 109 | xSemaphoreGive(spiLock); 110 | } 111 | -------------------------------------------------------------------------------- /components/odroid-go/odroid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef _ODROID_H_ 19 | #define _ODROID_H_ 20 | 21 | #include "esp_heap_caps.h" 22 | #include "spi_lcd.h" 23 | #include "sdcard.h" 24 | #include "sound.h" 25 | #include "input.h" 26 | 27 | #define PIN_NUM_MISO 19 28 | #define PIN_NUM_MOSI 23 29 | #define PIN_NUM_CLK 18 30 | #define PIN_NUM_DC 21 31 | #define PIN_NUM_LCD_CS 5 32 | #define PIN_NUM_SD_CS 22 33 | #define PIN_NUM_LCD_BCKL 14 34 | #define SPI_DMA_CHANNEL 2 35 | 36 | #ifndef ODROID_TASKS_USE_CORE 37 | #define ODROID_TASKS_USE_CORE 0 38 | #endif 39 | 40 | size_t free_bytes_total(); 41 | size_t free_bytes_internal(); 42 | size_t free_bytes_spiram(); 43 | 44 | void odroid_system_init(); 45 | void odroid_system_led_set(int value); 46 | void odroid_spi_bus_acquire(); 47 | void odroid_spi_bus_release(); 48 | void odroid_fatal_error(char *error); 49 | 50 | #endif -------------------------------------------------------------------------------- /components/odroid-go/sdcard.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "esp_vfs_fat.h" 24 | #include "driver/sdmmc_host.h" 25 | #include "driver/sdspi_host.h" 26 | #include "sdmmc_cmd.h" 27 | #include "odroid.h" 28 | 29 | static bool sdcard_initialized = false; 30 | 31 | 32 | void odroid_sdcard_init() 33 | { 34 | if (sdcard_initialized) return; 35 | 36 | printf("odroid_sdcard_init: Initializing SD Card.\n"); 37 | 38 | sdmmc_host_t host = SDSPI_HOST_DEFAULT(); 39 | host.slot = HSPI_HOST; // HSPI_HOST; 40 | host.max_freq_khz = SDMMC_FREQ_DEFAULT; 41 | 42 | sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); 43 | slot_config.gpio_miso = PIN_NUM_MISO; 44 | slot_config.gpio_mosi = PIN_NUM_MOSI; 45 | slot_config.gpio_sck = PIN_NUM_CLK; 46 | slot_config.gpio_cs = PIN_NUM_SD_CS; 47 | slot_config.dma_channel = SPI_DMA_CHANNEL; 48 | 49 | esp_vfs_fat_sdmmc_mount_config_t mount_config = { 50 | .format_if_mount_failed = false, 51 | .max_files = 8 52 | }; 53 | 54 | sdmmc_card_t* card; 55 | 56 | odroid_spi_bus_acquire(); 57 | esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); 58 | odroid_spi_bus_release(); 59 | 60 | if (ret != ESP_OK) { 61 | if (ret == ESP_FAIL) { 62 | odroid_fatal_error("odroid_sdcard_init: Failed to mount filesystem."); 63 | } else { 64 | odroid_fatal_error("odroid_sdcard_init: Failed to initialize the card."); 65 | } 66 | } else { 67 | sdcard_initialized = true; 68 | } 69 | } 70 | 71 | 72 | int odroid_sdcard_read_file(char const *name, char **buffer) 73 | { 74 | odroid_spi_bus_acquire(); 75 | 76 | FILE *fp = fopen(name, "rb"); 77 | 78 | if (fp) { 79 | fseek(fp, 0, SEEK_END); 80 | int length = ftell(fp); 81 | fseek(fp, 0, SEEK_SET); 82 | *buffer = malloc(length); 83 | int read = fread(*buffer, 1, length, fp); 84 | fclose(fp); 85 | 86 | if (read != length) { 87 | printf("odroid_sdcard_read_file: Length mismatch (Got %d, expected %d)\n", read, length); 88 | } 89 | 90 | odroid_spi_bus_release(); 91 | return read; 92 | } 93 | 94 | printf("odroid_sdcard_read_file: failed to open %s\n", name); 95 | 96 | odroid_spi_bus_release(); 97 | return -1; 98 | } 99 | 100 | 101 | int odroid_sdcard_write_file(char const *name, void *source, int length) 102 | { 103 | odroid_spi_bus_acquire(); 104 | FILE *fp = fopen(name, "wb"); 105 | 106 | if (fp) { 107 | int written = fwrite(source, 1, length, fp); // Write data 108 | fclose(fp); 109 | 110 | if (written != length) { 111 | printf("odroid_sdcard_write_file: Length mismatch (Got %d, expected %d)\n", written, length); 112 | } 113 | 114 | odroid_spi_bus_release(); 115 | return written; 116 | } 117 | 118 | printf("odroid_sdcard_write_file: failed to open %s\n", name); 119 | 120 | odroid_spi_bus_release(); 121 | return -1; 122 | } 123 | 124 | 125 | int odroid_sdcard_mkdir(char const *path) 126 | { 127 | odroid_spi_bus_acquire(); 128 | int ret = mkdir(path, 0755); 129 | odroid_spi_bus_release(); 130 | 131 | return ret; 132 | } 133 | 134 | 135 | int odroid_sdcard_remove(char const *path) 136 | { 137 | odroid_spi_bus_acquire(); 138 | int ret = remove(path); 139 | odroid_spi_bus_release(); 140 | 141 | return ret; 142 | } 143 | 144 | 145 | int odroid_sdcard_list_files(char const *directory, char **buffer) 146 | { 147 | return 0; 148 | } 149 | -------------------------------------------------------------------------------- /components/odroid-go/sdcard.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef _ODROID_SDCARD_H_ 19 | #define _ODROID_SDCARD_H_ 20 | 21 | void odroid_sdcard_init(void); 22 | int odroid_sdcard_read_file(char const *name, char **buffer); 23 | int odroid_sdcard_write_file(char const *name, void *source, int length); 24 | int odroid_sdcard_mkdir(char const *path); 25 | int odroid_sdcard_remove(char const *path); 26 | //#undef fopen 27 | //#define fopen 28 | 29 | #endif -------------------------------------------------------------------------------- /components/odroid-go/sound.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "freertos/FreeRTOS.h" 19 | #include "freertos/queue.h" 20 | #include "freertos/task.h" 21 | #include "driver/i2s.h" 22 | #include "odroid.h" 23 | 24 | #define SAMPLESIZE 2 // 16bit 25 | #define SAMPLERATE 22050 26 | 27 | static bool sound_initialized = false; 28 | 29 | 30 | void odroid_sound_init(void) 31 | { 32 | if (sound_initialized) return; 33 | 34 | printf("odroid_sound_init: Initializing sound.\n"); 35 | 36 | static const i2s_config_t i2s_config = { 37 | .mode = I2S_MODE_MASTER | I2S_MODE_TX | /*I2S_MODE_PDM,*/ I2S_MODE_DAC_BUILT_IN, 38 | .sample_rate = SAMPLERATE, 39 | .bits_per_sample = SAMPLESIZE * 8, /* the DAC module will only take the 8bits from MSB */ 40 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, 41 | .communication_format = I2S_COMM_FORMAT_I2S_MSB, 42 | .intr_alloc_flags = 0, // default interrupt priority 43 | .dma_buf_count = 2, 44 | .dma_buf_len = 512, // (2) 16bit channels 45 | .use_apll = false 46 | }; 47 | 48 | esp_err_t ret = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); //install and start i2s driver 49 | 50 | if (ret != ESP_OK) { 51 | odroid_fatal_error("odroid_sound_init: Failed to initialize I2S."); 52 | } 53 | 54 | i2s_set_pin(I2S_NUM_0, NULL); //for internal DAC, this will enable both of the internal channels 55 | 56 | i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); 57 | } 58 | 59 | 60 | void odroid_sound_deinit() 61 | { 62 | i2s_driver_uninstall(I2S_NUM_0); 63 | sound_initialized = false; 64 | } 65 | 66 | 67 | size_t * odroid_sound_write(void *buffer, size_t length) 68 | { 69 | size_t bytesWritten = 0; 70 | i2s_write(I2S_NUM_0, buffer, length, &bytesWritten, portMAX_DELAY); 71 | return bytesWritten; 72 | } 73 | 74 | 75 | void odroid_sound_set_sample_rate(uint32_t rate) 76 | { 77 | i2s_set_sample_rates(I2S_NUM_0, rate); //set sample rates 78 | } 79 | 80 | 81 | void odroid_sound_set_volume(uint32_t rate) 82 | { 83 | 84 | } 85 | -------------------------------------------------------------------------------- /components/odroid-go/sound.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef _ODROID_SOUND_H_ 19 | #define _ODROID_SOUND_H_ 20 | 21 | #define ODROID_SAMPLE_RATE 22050 22 | size_t * odroid_sound_write(void *buffer, size_t length); 23 | void odroid_sound_set_sample_rate(uint32_t rate); 24 | void odroid_sound_deinit(void); 25 | void odroid_sound_init(void); 26 | 27 | #endif -------------------------------------------------------------------------------- /components/odroid-go/spi_lcd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of odroid-go-std-lib. 3 | * Copyright (c) 2019 ducalex. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, version 3. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef _SPI_LCD_H_ 19 | #define _SPI_LCD_H_ 20 | 21 | typedef struct { 22 | uint8_t charCode; 23 | int adjYOffset; 24 | int width; 25 | int height; 26 | int xOffset; 27 | int xDelta; 28 | uint16_t dataPtr; 29 | } propFont; 30 | 31 | #define MADCTL_MY 0x80 32 | #define MADCTL_MX 0x40 33 | #define MADCTL_MV 0x20 34 | #define MADCTL_ML 0x10 35 | #define MADCTL_MH 0x04 36 | #define TFT_RGB_BGR 0x08 37 | #define TFT_LED_DUTY_MAX 0x1fff 38 | #define LCD_CMD 0 39 | #define LCD_DATA 1 40 | 41 | #define LCD_RGB(r, g, b) \ 42 | (((((r / 255 * 31) & 0x1F) << 11) | (((g / 255 * 62) & 0x3F) << 5) | (((b / 255 * 31) & 0x1F))) << 8 \ 43 | | ((((r / 255 * 31) & 0x1F) << 11) | (((g / 255 * 62) & 0x3F) << 5) | (((b / 255 * 31) & 0x1F))) >> 8) & 0xFFFF 44 | 45 | #define LCD_DEFAULT_PALETTE NULL 46 | 47 | short backlight_percentage_get(void); 48 | void backlight_percentage_set(short level); 49 | 50 | void spi_lcd_init(); 51 | void spi_lcd_cmd(uint8_t cmd); 52 | void spi_lcd_write8(uint8_t data); 53 | void spi_lcd_write16(uint16_t data); 54 | void spi_lcd_write(uint8_t *data, int len, int dc); 55 | void spi_lcd_setWindow(uint16_t x, uint16_t y, uint16_t width, uint16_t height); 56 | void spi_lcd_wait_finish(); 57 | void spi_lcd_usePalette(bool use); 58 | void spi_lcd_setPalette(const int16_t *palette); 59 | void spi_lcd_clear(); 60 | void spi_lcd_drawPixel(int x, int y, uint16_t color); 61 | void spi_lcd_fill(int x, int y, int w, int h, uint16_t color); 62 | void spi_lcd_setFont(const uint8_t *font); 63 | void spi_lcd_setFontColor(uint16_t color); 64 | void spi_lcd_print(int x, int y, char *string); 65 | void spi_lcd_printf(int x, int y, char *string, ...); 66 | void spi_lcd_useFrameBuffer(bool use); 67 | void spi_lcd_fb_setPtr(void *buffer); 68 | void*spi_lcd_fb_getPtr(); 69 | void spi_lcd_fb_free(); 70 | void spi_lcd_fb_alloc(); 71 | void spi_lcd_fb_clear(); 72 | void spi_lcd_fb_flush(); // fb_flush sends the buffer to the display now, it's synchronous 73 | void spi_lcd_fb_update(); // fb_update tells the display task it's time to redraw, it's async 74 | void spi_lcd_fb_write(void *buffer); 75 | 76 | #endif -------------------------------------------------------------------------------- /components/snes9x/.gitignore: -------------------------------------------------------------------------------- 1 | # Files that can arise when using snes9x 2 | win32/snes9x.conf 3 | win32/Valid.Ext 4 | win32/stdout.txt 5 | win32/stderr.txt 6 | win32/Roms 7 | win32/Saves 8 | win32/Cheats 9 | win32/Screenshots 10 | win32/Movies 11 | win32/SPCs 12 | win32/BIOS 13 | *.smc 14 | *.sfc 15 | *.fig 16 | *.srm 17 | *.00[0123456789] 18 | *.oops 19 | *.ips 20 | *.ups 21 | *.bps 22 | *.avi 23 | *.shader 24 | *.cg 25 | *.cgp 26 | *.smv 27 | *.cht 28 | *.rtc 29 | 30 | 31 | # Included libraries in OS X that should not be ignored. 32 | !macosx/libz_u.a 33 | !macosx/libHIDUtilities_u.a 34 | 35 | # Included libraries in windows that should not be ignored. 36 | !win32/ddraw/ddraw_x86.lib 37 | !win32/ddraw/ddraw_x64.lib 38 | 39 | # Created by https://www.gitignore.io/api/c,c++,visualstudio 40 | 41 | ### C ### 42 | # Prerequisites 43 | *.d 44 | 45 | # Object files 46 | *.o 47 | *.ko 48 | *.obj 49 | *.elf 50 | 51 | # Linker output 52 | *.ilk 53 | *.map 54 | *.exp 55 | 56 | # Precompiled Headers 57 | *.gch 58 | *.pch 59 | 60 | # Libraries 61 | *.lib 62 | *.a 63 | *.la 64 | *.lo 65 | 66 | # Shared objects (inc. Windows DLLs) 67 | *.dll 68 | *.so 69 | *.so.* 70 | *.dylib 71 | 72 | # Executables 73 | *.exe 74 | *.out 75 | *.app 76 | *.i*86 77 | *.x86_64 78 | *.hex 79 | 80 | # Debug files 81 | *.dSYM/ 82 | *.su 83 | *.idb 84 | *.pdb 85 | 86 | # Kernel Module Compile Results 87 | *.mod* 88 | *.cmd 89 | modules.order 90 | Module.symvers 91 | Mkfile.old 92 | dkms.conf 93 | 94 | ### C++ ### 95 | # Prerequisites 96 | 97 | # Compiled Object files 98 | *.slo 99 | 100 | # Precompiled Headers 101 | 102 | # Compiled Dynamic libraries 103 | 104 | # Fortran module files 105 | *.mod 106 | *.smod 107 | 108 | # Compiled Static libraries 109 | *.lai 110 | 111 | # Executables 112 | 113 | ### VisualStudio ### 114 | ## Ignore Visual Studio temporary files, build results, and 115 | ## files generated by popular Visual Studio add-ons. 116 | ## 117 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 118 | 119 | # User-specific files 120 | *.suo 121 | *.user 122 | *.userosscache 123 | *.sln.docstates 124 | 125 | # User-specific files (MonoDevelop/Xamarin Studio) 126 | *.userprefs 127 | 128 | # Build results 129 | [Dd]ebug/ 130 | [Dd]ebugPublic/ 131 | [Rr]elease/ 132 | [Rr]eleases/ 133 | x64/ 134 | x86/ 135 | bld/ 136 | [Bb]in/ 137 | [Oo]bj/ 138 | [Ll]og/ 139 | 140 | # Visual Studio 2015 cache/options directory 141 | .vs/ 142 | # Uncomment if you have tasks that create the project's static files in wwwroot 143 | #wwwroot/ 144 | 145 | # MSTest test Results 146 | [Tt]est[Rr]esult*/ 147 | [Bb]uild[Ll]og.* 148 | 149 | # NUNIT 150 | *.VisualState.xml 151 | TestResult.xml 152 | 153 | # Build Results of an ATL Project 154 | [Dd]ebugPS/ 155 | [Rr]eleasePS/ 156 | dlldata.c 157 | 158 | # .NET Core 159 | project.lock.json 160 | project.fragment.lock.json 161 | artifacts/ 162 | **/Properties/launchSettings.json 163 | 164 | *_i.c 165 | *_p.c 166 | *_i.h 167 | *.meta 168 | *.pgc 169 | *.pgd 170 | *.rsp 171 | *.sbr 172 | *.tlb 173 | *.tli 174 | *.tlh 175 | *.tmp 176 | *.tmp_proj 177 | *.log 178 | *.vspscc 179 | *.vssscc 180 | .builds 181 | *.pidb 182 | *.svclog 183 | *.scc 184 | 185 | # Chutzpah Test files 186 | _Chutzpah* 187 | 188 | # Visual C++ cache files 189 | ipch/ 190 | *.aps 191 | *.ncb 192 | *.opendb 193 | *.opensdf 194 | *.sdf 195 | *.cachefile 196 | *.VC.db 197 | *.VC.VC.opendb 198 | 199 | # Visual Studio profiler 200 | *.psess 201 | *.vsp 202 | *.vspx 203 | *.sap 204 | 205 | # TFS 2012 Local Workspace 206 | $tf/ 207 | 208 | # Guidance Automation Toolkit 209 | *.gpState 210 | 211 | # ReSharper is a .NET coding add-in 212 | _ReSharper*/ 213 | *.[Rr]e[Ss]harper 214 | *.DotSettings.user 215 | 216 | # JustCode is a .NET coding add-in 217 | .JustCode 218 | 219 | # TeamCity is a build add-in 220 | _TeamCity* 221 | 222 | # DotCover is a Code Coverage Tool 223 | *.dotCover 224 | 225 | # Visual Studio code coverage results 226 | *.coverage 227 | *.coveragexml 228 | 229 | # NCrunch 230 | _NCrunch_* 231 | .*crunch*.local.xml 232 | nCrunchTemp_* 233 | 234 | # MightyMoose 235 | *.mm.* 236 | AutoTest.Net/ 237 | 238 | # Web workbench (sass) 239 | .sass-cache/ 240 | 241 | # Installshield output folder 242 | [Ee]xpress/ 243 | 244 | # DocProject is a documentation generator add-in 245 | DocProject/buildhelp/ 246 | DocProject/Help/*.HxT 247 | DocProject/Help/*.HxC 248 | DocProject/Help/*.hhc 249 | DocProject/Help/*.hhk 250 | DocProject/Help/*.hhp 251 | DocProject/Help/Html2 252 | DocProject/Help/html 253 | 254 | # Click-Once directory 255 | publish/ 256 | 257 | # Publish Web Output 258 | *.[Pp]ublish.xml 259 | *.azurePubxml 260 | # TODO: Comment the next line if you want to checkin your web deploy settings 261 | # but database connection strings (with potential passwords) will be unencrypted 262 | *.pubxml 263 | *.publishproj 264 | 265 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 266 | # checkin your Azure Web App publish settings, but sensitive information contained 267 | # in these scripts will be unencrypted 268 | PublishScripts/ 269 | 270 | # NuGet Packages 271 | *.nupkg 272 | # The packages folder can be ignored because of Package Restore 273 | **/packages/* 274 | # except build/, which is used as an MSBuild target. 275 | !**/packages/build/ 276 | # Uncomment if necessary however generally it will be regenerated when needed 277 | #!**/packages/repositories.config 278 | # NuGet v3's project.json files produces more ignorable files 279 | *.nuget.props 280 | *.nuget.targets 281 | 282 | # Microsoft Azure Build Output 283 | csx/ 284 | *.build.csdef 285 | 286 | # Microsoft Azure Emulator 287 | ecf/ 288 | rcf/ 289 | 290 | # Windows Store app package directories and files 291 | AppPackages/ 292 | BundleArtifacts/ 293 | Package.StoreAssociation.xml 294 | _pkginfo.txt 295 | 296 | # Visual Studio cache files 297 | # files ending in .cache can be ignored 298 | *.[Cc]ache 299 | # but keep track of directories ending in .cache 300 | !*.[Cc]ache/ 301 | 302 | # Others 303 | ClientBin/ 304 | ~$* 305 | *~ 306 | *.dbmdl 307 | *.dbproj.schemaview 308 | *.jfm 309 | *.pfx 310 | *.publishsettings 311 | orleans.codegen.cs 312 | 313 | # Since there are multiple workflows, uncomment next line to ignore bower_components 314 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 315 | #bower_components/ 316 | 317 | # RIA/Silverlight projects 318 | Generated_Code/ 319 | 320 | # Backup & report files from converting an old project file 321 | # to a newer Visual Studio version. Backup files are not needed, 322 | # because we have git ;-) 323 | _UpgradeReport_Files/ 324 | Backup*/ 325 | UpgradeLog*.XML 326 | UpgradeLog*.htm 327 | 328 | # SQL Server files 329 | *.mdf 330 | *.ldf 331 | *.ndf 332 | 333 | # Business Intelligence projects 334 | *.rdl.data 335 | *.bim.layout 336 | *.bim_*.settings 337 | 338 | # Microsoft Fakes 339 | FakesAssemblies/ 340 | 341 | # GhostDoc plugin setting file 342 | *.GhostDoc.xml 343 | 344 | # Node.js Tools for Visual Studio 345 | .ntvs_analysis.dat 346 | node_modules/ 347 | 348 | # Typescript v1 declaration files 349 | typings/ 350 | 351 | # Visual Studio 6 build log 352 | *.plg 353 | 354 | # Visual Studio 6 workspace options file 355 | *.opt 356 | 357 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 358 | *.vbw 359 | 360 | # Visual Studio LightSwitch build output 361 | **/*.HTMLClient/GeneratedArtifacts 362 | **/*.DesktopClient/GeneratedArtifacts 363 | **/*.DesktopClient/ModelManifest.xml 364 | **/*.Server/GeneratedArtifacts 365 | **/*.Server/ModelManifest.xml 366 | _Pvt_Extensions 367 | 368 | # Paket dependency manager 369 | .paket/paket.exe 370 | paket-files/ 371 | 372 | # FAKE - F# Make 373 | .fake/ 374 | 375 | # JetBrains Rider 376 | .idea/ 377 | *.sln.iml 378 | 379 | # CodeRush 380 | .cr/ 381 | 382 | # Python Tools for Visual Studio (PTVS) 383 | __pycache__/ 384 | *.pyc 385 | 386 | # Cake - Uncomment if you are using it 387 | # tools/** 388 | # !tools/packages.config 389 | 390 | # Telerik's JustMock configuration file 391 | *.jmconfig 392 | 393 | # BizTalk build output 394 | *.btp.cs 395 | *.btm.cs 396 | *.odx.cs 397 | *.xsd.cs 398 | 399 | # End of https://www.gitignore.io/api/c,c++,visualstudio 400 | -------------------------------------------------------------------------------- /components/snes9x/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "win32/libpng/src"] 2 | path = win32/libpng/src 3 | url = https://git.code.sf.net/p/libpng/code 4 | [submodule "win32/zlib/src"] 5 | path = win32/zlib/src 6 | url = https://github.com/madler/zlib.git 7 | [submodule "win32/DirectXMath"] 8 | path = win32/DirectXMath 9 | url = https://github.com/Microsoft/DirectXMath 10 | [submodule "shaders/SPIRV-Cross"] 11 | path = shaders/SPIRV-Cross 12 | url = https://github.com/KhronosGroup/SPIRV-Cross.git 13 | [submodule "win32/glslang/src"] 14 | path = win32/glslang/src 15 | url = https://github.com/KhronosGroup/glslang.git 16 | -------------------------------------------------------------------------------- /components/snes9x/65c816.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _65C816_H_ 8 | #define _65C816_H_ 9 | 10 | #define Carry 1 11 | #define Zero 2 12 | #define IRQ 4 13 | #define Decimal 8 14 | #define IndexFlag 16 15 | #define MemoryFlag 32 16 | #define Overflow 64 17 | #define Negative 128 18 | #define Emulation 256 19 | 20 | #define SetCarry() (ICPU._Carry = 1) 21 | #define ClearCarry() (ICPU._Carry = 0) 22 | #define SetZero() (ICPU._Zero = 0) 23 | #define ClearZero() (ICPU._Zero = 1) 24 | #define SetIRQ() (Registers.PL |= IRQ) 25 | #define ClearIRQ() (Registers.PL &= ~IRQ) 26 | #define SetDecimal() (Registers.PL |= Decimal) 27 | #define ClearDecimal() (Registers.PL &= ~Decimal) 28 | #define SetIndex() (Registers.PL |= IndexFlag) 29 | #define ClearIndex() (Registers.PL &= ~IndexFlag) 30 | #define SetMemory() (Registers.PL |= MemoryFlag) 31 | #define ClearMemory() (Registers.PL &= ~MemoryFlag) 32 | #define SetOverflow() (ICPU._Overflow = 1) 33 | #define ClearOverflow() (ICPU._Overflow = 0) 34 | #define SetNegative() (ICPU._Negative = 0x80) 35 | #define ClearNegative() (ICPU._Negative = 0) 36 | 37 | #define CheckCarry() (ICPU._Carry) 38 | #define CheckZero() (ICPU._Zero == 0) 39 | #define CheckIRQ() (Registers.PL & IRQ) 40 | #define CheckDecimal() (Registers.PL & Decimal) 41 | #define CheckIndex() (Registers.PL & IndexFlag) 42 | #define CheckMemory() (Registers.PL & MemoryFlag) 43 | #define CheckOverflow() (ICPU._Overflow) 44 | #define CheckNegative() (ICPU._Negative & 0x80) 45 | #define CheckEmulation() (Registers.P.W & Emulation) 46 | 47 | #define SetFlags(f) (Registers.P.W |= (f)) 48 | #define ClearFlags(f) (Registers.P.W &= ~(f)) 49 | #define CheckFlag(f) (Registers.PL & (f)) 50 | 51 | typedef union 52 | { 53 | #ifdef LSB_FIRST 54 | struct { uint8 l, h; } B; 55 | #else 56 | struct { uint8 h, l; } B; 57 | #endif 58 | uint16 W; 59 | } pair; 60 | 61 | typedef union 62 | { 63 | #ifdef LSB_FIRST 64 | struct { uint8 xPCl, xPCh, xPB, z; } B; 65 | struct { uint16 xPC, d; } W; 66 | #else 67 | struct { uint8 z, xPB, xPCh, xPCl; } B; 68 | struct { uint16 d, xPC; } W; 69 | #endif 70 | uint32 xPBPC; 71 | } PC_t; 72 | 73 | struct SRegisters 74 | { 75 | uint8 DB; 76 | pair P; 77 | pair A; 78 | pair D; 79 | pair S; 80 | pair X; 81 | pair Y; 82 | PC_t PC; 83 | }; 84 | 85 | #define AL A.B.l 86 | #define AH A.B.h 87 | #define XL X.B.l 88 | #define XH X.B.h 89 | #define YL Y.B.l 90 | #define YH Y.B.h 91 | #define SL S.B.l 92 | #define SH S.B.h 93 | #define DL D.B.l 94 | #define DH D.B.h 95 | #define PL P.B.l 96 | #define PH P.B.h 97 | #define PBPC PC.xPBPC 98 | #define PCw PC.W.xPC 99 | #define PCh PC.B.xPCh 100 | #define PCl PC.B.xPCl 101 | #define PB PC.B.xPB 102 | 103 | extern struct SRegisters Registers; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /components/snes9x/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCDIRS ".") 2 | set(COMPONENT_ADD_INCLUDEDIRS ".") 3 | set(COMPONENT_REQUIRES "odroid-go") 4 | register_component() 5 | component_compile_options( 6 | -fomit-frame-pointer -fno-exceptions -fno-stack-protector 7 | -finline-limit=255 8 | -fdata-sections -ffunction-sections -Wl,--gc-sections 9 | -fno-stack-protector -fno-ident -fomit-frame-pointer 10 | -falign-functions=1 -falign-jumps=1 -falign-loops=1 11 | -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops 12 | -fmerge-all-constants -fno-math-errno 13 | -fno-exceptions -fno-rtti 14 | ) 15 | -------------------------------------------------------------------------------- /components/snes9x/LICENSE: -------------------------------------------------------------------------------- 1 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 2 | 3 | (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), 4 | Jerremy Koot (jkoot@snes9x.com) 5 | 6 | (c) Copyright 2002 - 2004 Matthew Kendora 7 | 8 | (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) 9 | 10 | (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) 11 | 12 | (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) 13 | 14 | (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), 15 | Kris Bleakley (codeviolation@hotmail.com) 16 | 17 | (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), 18 | Nach (n-a-c-h@users.sourceforge.net), 19 | 20 | (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) 21 | 22 | (c) Copyright 2006 - 2007 nitsuja 23 | 24 | (c) Copyright 2009 - 2019 BearOso, 25 | OV2 26 | 27 | (c) Copyright 2017 qwertymodo 28 | 29 | (c) Copyright 2011 - 2017 Hans-Kristian Arntzen, 30 | Daniel De Matteis 31 | (Under no circumstances will commercial rights be given) 32 | 33 | 34 | BS-X C emulator code 35 | (c) Copyright 2005 - 2006 Dreamer Nom, 36 | zones 37 | 38 | C4 x86 assembler and some C emulation code 39 | (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), 40 | Nach, 41 | zsKnight (zsknight@zsnes.com) 42 | 43 | C4 C++ code 44 | (c) Copyright 2003 - 2006 Brad Jorsch, 45 | Nach 46 | 47 | DSP-1 emulator code 48 | (c) Copyright 1998 - 2006 _Demo_, 49 | Andreas Naive (andreasnaive@gmail.com), 50 | Gary Henderson, 51 | Ivar (ivar@snes9x.com), 52 | John Weidman, 53 | Kris Bleakley, 54 | Matthew Kendora, 55 | Nach, 56 | neviksti (neviksti@hotmail.com) 57 | 58 | DSP-2 emulator code 59 | (c) Copyright 2003 John Weidman, 60 | Kris Bleakley, 61 | Lord Nightmare (lord_nightmare@users.sourceforge.net), 62 | Matthew Kendora, 63 | neviksti 64 | 65 | DSP-3 emulator code 66 | (c) Copyright 2003 - 2006 John Weidman, 67 | Kris Bleakley, 68 | Lancer, 69 | z80 gaiden 70 | 71 | DSP-4 emulator code 72 | (c) Copyright 2004 - 2006 Dreamer Nom, 73 | John Weidman, 74 | Kris Bleakley, 75 | Nach, 76 | z80 gaiden 77 | 78 | OBC1 emulator code 79 | (c) Copyright 2001 - 2004 zsKnight, 80 | pagefault (pagefault@zsnes.com), 81 | Kris Bleakley 82 | Ported from x86 assembler to C by sanmaiwashi 83 | 84 | SPC7110 and RTC C++ emulator code used in 1.39-1.51 85 | (c) Copyright 2002 Matthew Kendora with research by 86 | zsKnight, 87 | John Weidman, 88 | Dark Force 89 | 90 | SPC7110 and RTC C++ emulator code used in 1.52+ 91 | (c) Copyright 2009 byuu, 92 | neviksti 93 | 94 | S-DD1 C emulator code 95 | (c) Copyright 2003 Brad Jorsch with research by 96 | Andreas Naive, 97 | John Weidman 98 | 99 | S-RTC C emulator code 100 | (c) Copyright 2001 - 2006 byuu, 101 | John Weidman 102 | 103 | ST010 C++ emulator code 104 | (c) Copyright 2003 Feather, 105 | John Weidman, 106 | Kris Bleakley, 107 | Matthew Kendora 108 | 109 | Super FX x86 assembler emulator code 110 | (c) Copyright 1998 - 2003 _Demo_, 111 | pagefault, 112 | zsKnight 113 | 114 | Super FX C emulator code 115 | (c) Copyright 1997 - 1999 Ivar, 116 | Gary Henderson, 117 | John Weidman 118 | 119 | Sound emulator code used in 1.5-1.51 120 | (c) Copyright 1998 - 2003 Brad Martin 121 | (c) Copyright 1998 - 2006 Charles Bilyue' 122 | 123 | Sound emulator code used in 1.52+ 124 | (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) 125 | 126 | S-SMP emulator code used in 1.54+ 127 | (c) Copyright 2016 byuu 128 | 129 | SH assembler code partly based on x86 assembler code 130 | (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) 131 | 132 | 2xSaI filter 133 | (c) Copyright 1999 - 2001 Derek Liauw Kie Fa 134 | 135 | HQ2x, HQ3x, HQ4x filters 136 | (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) 137 | 138 | NTSC filter 139 | (c) Copyright 2006 - 2007 Shay Green 140 | 141 | GTK+ GUI code 142 | (c) Copyright 2004 - 2019 BearOso 143 | 144 | Win32 GUI code 145 | (c) Copyright 2003 - 2006 blip, 146 | funkyass, 147 | Matthew Kendora, 148 | Nach, 149 | nitsuja 150 | (c) Copyright 2009 - 2019 OV2 151 | 152 | Mac OS GUI code 153 | (c) Copyright 1998 - 2001 John Stiles 154 | (c) Copyright 2001 - 2011 zones 155 | 156 | Libretro port 157 | (c) Copyright 2011 - 2017 Hans-Kristian Arntzen, 158 | Daniel De Matteis 159 | (Under no circumstances will commercial rights be given) 160 | 161 | 162 | Specific ports contains the works of other authors. See headers in 163 | individual files. 164 | 165 | 166 | Snes9x homepage: http://www.snes9x.com/ 167 | Snes9x source code: https://github.com/snes9xgit/snes9x/ 168 | 169 | Permission to use, copy, modify and/or distribute Snes9x in both binary 170 | and source form, for non-commercial purposes, is hereby granted without 171 | fee, providing that this license information and copyright notice appear 172 | with all copies and any derived work. 173 | 174 | This software is provided 'as-is', without any express or implied 175 | warranty. In no event shall the authors be held liable for any damages 176 | arising from the use of this software or it's derivatives. 177 | 178 | Snes9x is freeware for PERSONAL USE only. Commercial users should 179 | seek permission of the copyright holders first. Commercial use includes, 180 | but is not limited to, charging money for Snes9x or software derived from 181 | Snes9x, including Snes9x or derivatives in commercial game bundles, and/or 182 | using Snes9x as a promotion for your commercial product. 183 | 184 | The copyright holders request that bug fixes and improvements to the code 185 | should be forwarded to them so everyone can benefit from the modifications 186 | in future versions. 187 | 188 | Super NES and Super Nintendo Entertainment System are trademarks of 189 | Nintendo Co., Limited and its subsidiary companies. 190 | 191 | ------------------------------------------------------------------------------- 192 | 193 | Some parts included in Snes9x are usually available under a different license, 194 | their authors have granted exception for their use in Snes9x (and/or they are 195 | licensed as LGPL): 196 | - JMA: GPL/LGPL, see jma/license.txt 197 | - snes_ntsc: LGPL, see filter/snes_ntsc-license.txt 198 | - xBRZ: GPLv3, see filter/xbrz-license.txt 199 | -------------------------------------------------------------------------------- /components/snes9x/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | # This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default, 5 | # this will take the sources in the src/ directory, compile them and link them into 6 | # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, 7 | # please read the SDK documents if you need to do this. 8 | # 9 | 10 | 11 | include $(IDF_PATH)/make/component.mk 12 | 13 | -------------------------------------------------------------------------------- /components/snes9x/README.md: -------------------------------------------------------------------------------- 1 | # Snes9x 2 | *Snes9x - Portable Super Nintendo Entertainment System (TM) emulator* 3 | 4 | This is the official source code repository for the Snes9x project. 5 | 6 | Please check the [Wiki](https://github.com/snes9xgit/snes9x/wiki) for additional information. 7 | -------------------------------------------------------------------------------- /components/snes9x/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.60-{build} 2 | 3 | image: Visual Studio 2017 4 | 5 | environment: 6 | matrix: 7 | - generator: "Visual Studio 15" 8 | config: Release Unicode 9 | platform: Win32 10 | arch: win32 11 | output: win32\snes9x.exe 12 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 13 | 14 | - generator: "Visual Studio 15" 15 | config: Release Unicode 16 | platform: x64 17 | arch: win32-x64 18 | output: win32\snes9x-x64.exe 19 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 20 | 21 | - generator: "Visual Studio 15" 22 | config: libretro Release 23 | platform: Win32 24 | arch: libretro 25 | output: libretro\Win32\libretro Release\snes9x_libretro.dll 26 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 27 | 28 | - generator: "Visual Studio 15" 29 | config: libretro Release 30 | platform: x64 31 | arch: libretro-x64 32 | output: libretro\x64\libretro Release\snes9x_libretro.dll 33 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 34 | 35 | init: 36 | - git config --global core.autocrlf input 37 | 38 | before_build: 39 | - git submodule update --init --recursive 40 | 41 | build_script: 42 | - if "%config%"=="Release Unicode" msbuild win32\snes9xw.sln /t:build /p:Configuration="%config%";Platform="%platform%" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 43 | - if "%config%"=="libretro Release" msbuild libretro\libretro-win32.vcxproj /t:build /p:Configuration="%config%";Platform="%platform%" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 44 | 45 | after_build: 46 | - ps: $env:gitrev = git describe --tags 47 | - ps: $env:my_version = "$env:gitrev" 48 | - set package_name=snes9x-%my_version%-%arch% 49 | - if exist artifacts rmdir /s /q artifacts 50 | - mkdir artifacts 51 | - copy "%output%" artifacts 52 | - if "%config%"=="Release Unicode" 53 | copy docs\changes.txt artifacts | 54 | copy LICENSE artifacts | 55 | copy win32\docs\faqs-windows.txt artifacts | 56 | copy win32\docs\readme-windows.txt artifacts | 57 | copy data\cheats.bml artifacts 58 | - 7z a %package_name%.zip .\artifacts\* 59 | 60 | artifacts: 61 | - path: $(package_name).zip 62 | name: $(arch) 63 | -------------------------------------------------------------------------------- /components/snes9x/apu.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #include 8 | #include "snes9x.h" 9 | #include "apu.h" 10 | static const int APU_DEFAULT_INPUT_RATE = 31950; // ~59.94Hz 11 | static const int APU_SAMPLE_BLOCK = 48; 12 | static const int APU_NUMERATOR_NTSC = 15664; 13 | static const int APU_DENOMINATOR_NTSC = 328125; 14 | static const int APU_NUMERATOR_PAL = 34176; 15 | static const int APU_DENOMINATOR_PAL = 709379; 16 | 17 | namespace SNES { 18 | struct Processor 19 | { 20 | unsigned frequency; 21 | int32 clock; 22 | }; 23 | 24 | #include "apu_smp.hpp" 25 | 26 | class CPU 27 | { 28 | public: 29 | uint8 registers[4]; 30 | 31 | inline void reset () 32 | { 33 | registers[0] = registers[1] = registers[2] = registers[3] = 0; 34 | } 35 | 36 | inline void port_write (uint8 port, uint8 data) 37 | { 38 | registers[port & 3] = data; 39 | } 40 | 41 | inline uint8 port_read (uint8 port) 42 | { 43 | return registers[port & 3]; 44 | } 45 | }; 46 | CPU cpu; 47 | } // namespace SNES 48 | 49 | 50 | bool8 S9xInitSound(int buffer_ms) 51 | { 52 | return false; 53 | } 54 | 55 | bool8 S9xInitAPU(void) 56 | { 57 | return (TRUE); 58 | } 59 | 60 | void S9xDeinitAPU(void) 61 | { 62 | } 63 | 64 | uint8 S9xAPUReadPort(int port) 65 | { 66 | S9xAPUExecute(); 67 | return ((uint8)SNES::smp.port_read(port & 3)); 68 | } 69 | 70 | void S9xAPUWritePort(int port, uint8 byte) 71 | { 72 | S9xAPUExecute(); 73 | SNES::cpu.port_write(port & 3, byte); 74 | } 75 | 76 | void S9xAPUSetReferenceTime(int32 cpucycles) 77 | { 78 | } 79 | 80 | void S9xAPUExecute(void) 81 | { 82 | static uint32 remainder = 0; 83 | int32 cpucycles = CPU.Cycles; 84 | SNES::smp.clock -= (APU_NUMERATOR_NTSC * (cpucycles - 0) + remainder) / APU_DENOMINATOR_NTSC; 85 | SNES::smp.enter(); 86 | 87 | S9xAPUSetReferenceTime(CPU.Cycles); 88 | } 89 | 90 | void S9xAPUEndScanline(void) 91 | { 92 | S9xAPUExecute(); 93 | } 94 | 95 | void S9xAPUTimingSetSpeedup(int ticks) 96 | { 97 | } 98 | 99 | void S9xResetAPU(void) 100 | { 101 | SNES::cpu.reset(); 102 | SNES::smp.power(); 103 | 104 | S9xClearSamples(); 105 | } 106 | 107 | void S9xSoftResetAPU(void) 108 | { 109 | SNES::cpu.reset(); 110 | SNES::smp.reset(); 111 | 112 | S9xClearSamples(); 113 | } 114 | 115 | void S9xAPUSaveState(uint8 *block) 116 | { 117 | } 118 | 119 | void S9xAPULoadState(uint8 *block) 120 | { 121 | } 122 | 123 | void S9xAPULoadBlarggState(uint8 *oldblock) 124 | { 125 | } 126 | 127 | bool8 S9xSPCDump(const char *filename) 128 | { 129 | return (TRUE); 130 | } 131 | 132 | bool8 S9xMixSamples(uint8 *dest, int sample_count) 133 | { 134 | return true; 135 | } 136 | 137 | int S9xGetSampleCount(void) 138 | { 139 | return 0; 140 | } 141 | 142 | void S9xLandSamples(void) 143 | { 144 | } 145 | 146 | void S9xClearSamples(void) 147 | { 148 | } 149 | 150 | bool8 S9xSyncSound(void) 151 | { 152 | return true; 153 | } 154 | 155 | void S9xSetSamplesAvailableCallback(apu_callback callback, void *data) 156 | { 157 | } 158 | 159 | void S9xUpdateDynamicRate(int avail, int buffer_size) 160 | { 161 | } 162 | 163 | void S9xSetSoundControl(uint8 voice_switch) 164 | { 165 | } 166 | 167 | void S9xSetSoundMute(bool8 mute) 168 | { 169 | } 170 | 171 | void S9xDumpSPCSnapshot(void) 172 | { 173 | } 174 | -------------------------------------------------------------------------------- /components/snes9x/apu.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _APU_H_ 8 | #define _APU_H_ 9 | 10 | #include "snes9x.h" 11 | 12 | typedef void (*apu_callback) (void *); 13 | 14 | #define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65) 15 | #define SPC_FILE_SIZE (66048) 16 | 17 | bool8 S9xInitAPU (void); 18 | void S9xDeinitAPU (void); 19 | void S9xResetAPU (void); 20 | void S9xSoftResetAPU (void); 21 | uint8 S9xAPUReadPort (int); 22 | void S9xAPUWritePort (int, uint8); 23 | void S9xAPUExecute (void); 24 | void S9xAPUEndScanline (void); 25 | void S9xAPUSetReferenceTime (int32); 26 | void S9xAPUTimingSetSpeedup (int); 27 | void S9xAPULoadState (uint8 *); 28 | void S9xAPULoadBlarggState(uint8 *oldblock); 29 | void S9xAPUSaveState (uint8 *); 30 | void S9xDumpSPCSnapshot (void); 31 | bool8 S9xSPCDump (const char *); 32 | 33 | bool8 S9xInitSound (int); 34 | bool8 S9xOpenSoundDevice (void); 35 | 36 | bool8 S9xSyncSound (void); 37 | int S9xGetSampleCount (void); 38 | void S9xSetSoundControl (uint8); 39 | void S9xSetSoundMute (bool8); 40 | void S9xLandSamples (void); 41 | void S9xClearSamples (void); 42 | bool8 S9xMixSamples (uint8 *, int); 43 | void S9xSetSamplesAvailableCallback (apu_callback, void *); 44 | void S9xUpdateDynamicRate (int, int); 45 | 46 | #define DSP_INTERPOLATION_NONE 0 47 | #define DSP_INTERPOLATION_LINEAR 1 48 | #define DSP_INTERPOLATION_GAUSSIAN 2 49 | #define DSP_INTERPOLATION_CUBIC 3 50 | #define DSP_INTERPOLATION_SINC 4 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /components/snes9x/apu_smp.hpp: -------------------------------------------------------------------------------- 1 | class SMP : public Processor { 2 | public: 3 | static const uint8 iplrom[64]; 4 | uint8 *apuram; 5 | 6 | unsigned port_read(unsigned port); 7 | void port_write(unsigned port, unsigned data); 8 | 9 | unsigned mmio_read(unsigned addr); 10 | void mmio_write(unsigned addr, unsigned data); 11 | 12 | void enter(); 13 | void power(); 14 | void reset(); 15 | 16 | SMP(); 17 | ~SMP(); 18 | 19 | //private: 20 | struct Flags { 21 | bool n, v, p, b, h, i, z, c; 22 | 23 | inline operator unsigned() const { 24 | return (n << 7) | (v << 6) | (p << 5) | (b << 4) 25 | | (h << 3) | (i << 2) | (z << 1) | (c << 0); 26 | }; 27 | 28 | inline unsigned operator=(unsigned data) { 29 | n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; 30 | h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; 31 | return data; 32 | } 33 | 34 | inline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } 35 | inline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); } 36 | inline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); } 37 | }; 38 | 39 | unsigned opcode_number; 40 | unsigned opcode_cycle; 41 | 42 | uint16 rd, wr, dp, sp, ya, bit; 43 | 44 | struct Regs { 45 | uint16 pc; 46 | uint8 sp; 47 | union { 48 | uint16 ya; 49 | #ifndef __BIG_ENDIAN__ 50 | struct { uint8 a, y; } B; 51 | #else 52 | struct { uint8 y, a; } B; 53 | #endif 54 | }; 55 | uint8 x; 56 | Flags p; 57 | } regs; 58 | 59 | struct Status { 60 | //$00f1 61 | bool iplrom_enable; 62 | 63 | //$00f2 64 | unsigned dsp_addr; 65 | 66 | //$00f8,$00f9 67 | unsigned ram00f8; 68 | unsigned ram00f9; 69 | } status; 70 | 71 | template 72 | struct Timer { 73 | bool enable; 74 | uint8 target; 75 | uint8 stage1_ticks; 76 | uint8 stage2_ticks; 77 | uint8 stage3_ticks; 78 | 79 | inline void tick(); 80 | inline void tick(unsigned clocks); 81 | }; 82 | 83 | Timer<128> timer0; 84 | Timer<128> timer1; 85 | Timer< 16> timer2; 86 | 87 | inline void tick(); 88 | inline void tick(unsigned clocks); 89 | inline void op_io(); 90 | inline void op_io(unsigned clocks); 91 | inline uint8 op_read(uint16 addr); 92 | inline void op_write(uint16 addr, uint8 data); 93 | inline void op_step(); 94 | inline void op_writestack(uint8 data); 95 | inline uint8 op_readstack(); 96 | static const unsigned cycle_count_table[256]; 97 | uint64 cycle_table_cpu[256]; 98 | unsigned cycle_table_dsp[256]; 99 | uint64 cycle_step_cpu; 100 | 101 | inline uint8 op_adc (uint8 x, uint8 y); 102 | inline uint16 op_addw(uint16 x, uint16 y); 103 | inline uint8 op_and (uint8 x, uint8 y); 104 | inline uint8 op_cmp (uint8 x, uint8 y); 105 | inline uint16 op_cmpw(uint16 x, uint16 y); 106 | inline uint8 op_eor (uint8 x, uint8 y); 107 | inline uint8 op_inc (uint8 x); 108 | inline uint8 op_dec (uint8 x); 109 | inline uint8 op_or (uint8 x, uint8 y); 110 | inline uint8 op_sbc (uint8 x, uint8 y); 111 | inline uint16 op_subw(uint16 x, uint16 y); 112 | inline uint8 op_asl (uint8 x); 113 | inline uint8 op_lsr (uint8 x); 114 | inline uint8 op_rol (uint8 x); 115 | inline uint8 op_ror (uint8 x); 116 | #ifdef DEBUGGER 117 | void disassemble_opcode(char *output, uint16 addr); 118 | inline uint8 disassemble_read(uint16 addr); 119 | inline uint16 relb(int8 offset, int op_len); 120 | #endif 121 | }; 122 | 123 | extern SMP smp; 124 | -------------------------------------------------------------------------------- /components/snes9x/apu_snes.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SNES_HPP 2 | #define __SNES_HPP 3 | 4 | #include "snes9x.h" 5 | 6 | #if defined(__GNUC__) 7 | #define inline inline 8 | #define alwaysinline inline __attribute__((always_inline)) 9 | #elif defined(_MSC_VER) 10 | #define inline inline 11 | #define alwaysinline inline __forceinline 12 | #else 13 | #define inline inline 14 | #define alwaysinline inline 15 | #endif 16 | 17 | #define debugvirtual 18 | 19 | namespace SNES 20 | { 21 | 22 | struct Processor 23 | { 24 | unsigned frequency; 25 | int32 clock; 26 | }; 27 | 28 | #include "apu_smp.hpp" 29 | 30 | class CPU 31 | { 32 | public: 33 | uint8 registers[4]; 34 | 35 | inline void reset () 36 | { 37 | registers[0] = registers[1] = registers[2] = registers[3] = 0; 38 | } 39 | 40 | alwaysinline void port_write (uint8 port, uint8 data) 41 | { 42 | registers[port & 3] = data; 43 | } 44 | 45 | alwaysinline uint8 port_read (uint8 port) 46 | { 47 | return registers[port & 3]; 48 | } 49 | }; 50 | 51 | extern CPU cpu; 52 | 53 | } // namespace SNES 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /components/snes9x/clip.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #include "snes9x.h" 8 | #include "memmap.h" 9 | 10 | static uint8 region_map[6][6] = 11 | { 12 | { 0, 0x01, 0x03, 0x07, 0x0f, 0x1f }, 13 | { 0, 0, 0x02, 0x06, 0x0e, 0x1e }, 14 | { 0, 0, 0, 0x04, 0x0c, 0x1c }, 15 | { 0, 0, 0, 0, 0x08, 0x18 }, 16 | { 0, 0, 0, 0, 0, 0x10 } 17 | }; 18 | 19 | static inline uint8 CalcWindowMask (int, uint8, uint8); 20 | static inline void StoreWindowRegions (uint8, struct ClipData *, int, int16 *, uint8 *, bool8, bool8 s = FALSE); 21 | 22 | 23 | static inline uint8 CalcWindowMask (int i, uint8 W1, uint8 W2) 24 | { 25 | if (!PPU.ClipWindow1Enable[i]) 26 | { 27 | if (!PPU.ClipWindow2Enable[i]) 28 | return (0); 29 | else 30 | { 31 | if (!PPU.ClipWindow2Inside[i]) 32 | return (~W2); 33 | return (W2); 34 | } 35 | } 36 | else 37 | { 38 | if (!PPU.ClipWindow2Enable[i]) 39 | { 40 | if (!PPU.ClipWindow1Inside[i]) 41 | return (~W1); 42 | return (W1); 43 | } 44 | else 45 | { 46 | if (!PPU.ClipWindow1Inside[i]) 47 | W1 = ~W1; 48 | if (!PPU.ClipWindow2Inside[i]) 49 | W2 = ~W2; 50 | 51 | switch (PPU.ClipWindowOverlapLogic[i]) 52 | { 53 | case 0: // OR 54 | return (W1 | W2); 55 | 56 | case 1: // AND 57 | return (W1 & W2); 58 | 59 | case 2: // XOR 60 | return (W1 ^ W2); 61 | 62 | case 3: // XNOR 63 | return (~(W1 ^ W2)); 64 | } 65 | } 66 | } 67 | 68 | // Never get here 69 | return (0); 70 | } 71 | 72 | static inline void StoreWindowRegions (uint8 Mask, struct ClipData *Clip, int n_regions, int16 *windows, uint8 *drawing_modes, bool8 sub, bool8 StoreMode0) 73 | { 74 | int ct = 0; 75 | 76 | for (int j = 0; j < n_regions; j++) 77 | { 78 | int DrawMode = drawing_modes[j]; 79 | if (sub) 80 | DrawMode |= 1; 81 | if (Mask & (1 << j)) 82 | DrawMode = 0; 83 | 84 | if (!StoreMode0 && !DrawMode) 85 | continue; 86 | 87 | if (ct > 0 && Clip->Right[ct - 1] == windows[j] && Clip->DrawMode[ct - 1] == DrawMode) 88 | Clip->Right[ct - 1] = windows[j + 1]; // This region borders with and has the same drawing mode as the previous region: merge them. 89 | else 90 | { 91 | // Add a new region to the BG 92 | Clip->Left[ct] = windows[j]; 93 | Clip->Right[ct] = windows[j + 1]; 94 | Clip->DrawMode[ct] = DrawMode; 95 | ct++; 96 | } 97 | } 98 | 99 | Clip->Count = ct; 100 | } 101 | 102 | void S9xComputeClipWindows (void) 103 | { 104 | int16 windows[6] = { 0, 256, 256, 256, 256, 256 }; 105 | uint8 drawing_modes[5] = { 0, 0, 0, 0, 0 }; 106 | int n_regions = 1; 107 | int i, j; 108 | 109 | // Calculate window regions. We have at most 5 regions, because we have 6 control points 110 | // (screen edges, window 1 left & right, and window 2 left & right). 111 | 112 | if (PPU.Window1Left <= PPU.Window1Right) 113 | { 114 | if (PPU.Window1Left > 0) 115 | { 116 | windows[2] = 256; 117 | windows[1] = PPU.Window1Left; 118 | n_regions = 2; 119 | } 120 | 121 | if (PPU.Window1Right < 255) 122 | { 123 | windows[n_regions + 1] = 256; 124 | windows[n_regions] = PPU.Window1Right + 1; 125 | n_regions++; 126 | } 127 | } 128 | 129 | if (PPU.Window2Left <= PPU.Window2Right) 130 | { 131 | for (i = 0; i <= n_regions; i++) 132 | { 133 | if (PPU.Window2Left == windows[i]) 134 | break; 135 | 136 | if (PPU.Window2Left < windows[i]) 137 | { 138 | for (j = n_regions; j >= i; j--) 139 | windows[j + 1] = windows[j]; 140 | 141 | windows[i] = PPU.Window2Left; 142 | n_regions++; 143 | break; 144 | } 145 | } 146 | 147 | for (; i <= n_regions; i++) 148 | { 149 | if (PPU.Window2Right + 1 == windows[i]) 150 | break; 151 | 152 | if (PPU.Window2Right + 1 < windows[i]) 153 | { 154 | for (j = n_regions; j >= i; j--) 155 | windows[j + 1] = windows[j]; 156 | 157 | windows[i] = PPU.Window2Right + 1; 158 | n_regions++; 159 | break; 160 | } 161 | } 162 | } 163 | 164 | // Get a bitmap of which regions correspond to each window. 165 | 166 | uint8 W1, W2; 167 | 168 | if (PPU.Window1Left <= PPU.Window1Right) 169 | { 170 | for (i = 0; windows[i] != PPU.Window1Left; i++) ; 171 | for (j = i; windows[j] != PPU.Window1Right + 1; j++) ; 172 | W1 = region_map[i][j]; 173 | } 174 | else 175 | W1 = 0; 176 | 177 | if (PPU.Window2Left <= PPU.Window2Right) 178 | { 179 | for (i = 0; windows[i] != PPU.Window2Left; i++) ; 180 | for (j = i; windows[j] != PPU.Window2Right + 1; j++) ; 181 | W2 = region_map[i][j]; 182 | } 183 | else 184 | W2 = 0; 185 | 186 | // Color Window affects the drawing mode for each region. 187 | // Modes are: 3=Draw as normal, 2=clip color (math only), 1=no math (draw only), 0=nothing. 188 | 189 | uint8 CW_color = 0, CW_math = 0; 190 | uint8 CW = CalcWindowMask(5, W1, W2); 191 | 192 | switch (Memory.FillRAM[0x2130] & 0xc0) 193 | { 194 | case 0x00: CW_color = 0; break; 195 | case 0x40: CW_color = ~CW; break; 196 | case 0x80: CW_color = CW; break; 197 | case 0xc0: CW_color = 0xff; break; 198 | } 199 | 200 | switch (Memory.FillRAM[0x2130] & 0x30) 201 | { 202 | case 0x00: CW_math = 0; break; 203 | case 0x10: CW_math = ~CW; break; 204 | case 0x20: CW_math = CW; break; 205 | case 0x30: CW_math = 0xff; break; 206 | } 207 | 208 | for (i = 0; i < n_regions; i++) 209 | { 210 | if (!(CW_color & (1 << i))) 211 | drawing_modes[i] |= 1; 212 | if (!(CW_math & (1 << i))) 213 | drawing_modes[i] |= 2; 214 | } 215 | 216 | // Store backdrop clip window (draw everywhere color window allows) 217 | 218 | StoreWindowRegions(0, &IPPU.Clip[0][5], n_regions, windows, drawing_modes, FALSE, TRUE); 219 | StoreWindowRegions(0, &IPPU.Clip[1][5], n_regions, windows, drawing_modes, TRUE, TRUE); 220 | 221 | // Store per-BG and OBJ clip windows 222 | 223 | for (j = 0; j < 5; j++) 224 | { 225 | uint8 W = Settings.DisableGraphicWindows ? 0 : CalcWindowMask(j, W1, W2); 226 | for (int sub = 0; sub < 2; sub++) 227 | { 228 | if (Memory.FillRAM[sub + 0x212e] & (1 << j)) 229 | StoreWindowRegions(W, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); 230 | else 231 | StoreWindowRegions(0, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); 232 | } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /components/snes9x/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | # -finstrument-functions 7 | CXXFLAGS += -O3 -fomit-frame-pointer -fno-exceptions -fno-stack-protector -mlongcalls 8 | -finline-limit=255 -fdata-sections -ffunction-sections -Wl,--gc-sections \ 9 | -fno-ident -falign-functions=1 -falign-jumps=1 -falign-loops=1 \ 10 | -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \ 11 | -fmerge-all-constants -fno-math-errno -fno-rtti 12 | -------------------------------------------------------------------------------- /components/snes9x/conffile.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _CONFIG_H_ 8 | #define _CONFIG_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef UNZIP_SUPPORT 16 | # ifdef SYSTEM_ZIP 17 | # include 18 | # else 19 | # include "unzip/unzip.h" 20 | # endif 21 | #endif 22 | #include "snes9x.h" 23 | 24 | #ifndef MAX 25 | # define MAX(a,b) ((a) > (b)? (a) : (b)) 26 | # define MIN(a,b) ((a) < (b)? (a) : (b)) 27 | #endif 28 | 29 | class ConfigFile { 30 | public: 31 | ConfigFile(void); 32 | 33 | void Clear(void); 34 | 35 | // return false on failure 36 | bool LoadFile(const char *filename); 37 | void LoadFile(Stream *r, const char *name=NULL); 38 | 39 | // return false if key does not exist or is empty 40 | bool Exists(const char *key); 41 | 42 | // return the value / default 43 | std::string GetString(const char *key, std::string def); 44 | char *GetString(const char *key, char *out, uint32 outlen); // return NULL if it doesn't exist, out not affected 45 | const char *GetString(const char *key, const char *def=NULL); // NOTE: returned pointer becomes invalid when key is deleted/modified, or the ConfigFile is Clear()ed or deleted. 46 | char *GetStringDup(const char *key, const char *def=NULL); // Much like "strdup(GetString(key, def))" 47 | int32 GetInt(const char *key, int32 def=-1, bool *bad=NULL); 48 | uint32 GetUInt(const char *key, uint32 def=0, int base=0, bool *bad=NULL); // base = 0, 8, 10, or 16 49 | bool GetBool(const char *key, bool def=false, bool *bad=NULL); 50 | const char* GetComment(const char *key); // NOTE: returned pointer becomes invalid when key is deleted/modified, or the ConfigFile is Clear()ed or deleted. 51 | 52 | // return true if the key existed prior to setting 53 | bool SetString(const char *key, std::string val, const char *comment=""); 54 | bool SetInt(const char *key, int32 val, const char *comment=""); 55 | bool SetUInt(const char *key, uint32 val, int base=10, const char *comment=""); // base = 8, 10, or 16 56 | bool SetBool(const char *key, bool val, const char *true_val="TRUE", const char *false_val="FALSE", const char *comment=""); 57 | bool DeleteKey(const char *key); 58 | 59 | // Operation on entire sections 60 | bool DeleteSection(const char *section); 61 | typedef std::vector > secvec_t; 62 | secvec_t GetSection(const char *section); 63 | int GetSectionSize(const std::string section); 64 | 65 | // Clears all key-value pairs that didn't receive a Set command, or a Get command with autoAdd on 66 | void ClearUnused(void); 67 | 68 | // Clears all stored line numbers 69 | void ClearLines(void); 70 | 71 | bool SaveTo(const char *filename); 72 | 73 | static void SetDefaultAutoAdd(bool autoAdd); 74 | static void SetNiceAlignment(bool align); 75 | static void SetShowComments(bool show); 76 | static void SetAlphaSort(bool sort); 77 | static void SetTimeSort(bool sort); 78 | 79 | private: 80 | std::string Get(const char *key); 81 | bool Has(const char *key); 82 | 83 | class ConfigEntry { 84 | protected: 85 | int line; 86 | std::string section; 87 | std::string key; 88 | std::string val; 89 | std::string comment; 90 | mutable bool used; 91 | 92 | struct section_then_key_less { 93 | bool operator()(const ConfigEntry &a, const ConfigEntry &b); 94 | }; 95 | 96 | struct key_less { 97 | bool operator()(const ConfigEntry &a, const ConfigEntry &b) const{ 98 | if(a.section!=b.section) return a.section0) s.erase(0, i); // erase leading whitespace 120 | i=s.find_last_not_of(" \f\n\r\t\v"); 121 | if(i!=-1) s.erase(i+1); // erase trailing whitespace 122 | return; 123 | } 124 | 125 | // trims comments and leading/trailing whitespace from s, and returns any trimmed comments 126 | // make sure not to call this more than once on the same string 127 | static std::string trimCommented(std::string &s){ 128 | std::string cmt; 129 | int i; 130 | i=s.find_first_not_of(" \f\n\r\t\v"); 131 | if(i==-1){ 132 | s.clear(); 133 | return cmt; 134 | } 135 | if(i>0) s.erase(0, i); // erase leading whitespace 136 | int off=0; 137 | for(;;){ 138 | i=s.find('#',off); // find trailing comment 139 | if(i>=0) 140 | { 141 | if((int)s.length()>i+1 && s.at(i+1) == '#') { 142 | s.erase(i,1); // ignore ## and change to # 143 | off = i+1; 144 | continue; 145 | } else { 146 | int j=s.find_first_not_of(" \f\n\r\t\v",i+1); 147 | if(j!=-1) cmt = s.substr(j); // store 148 | s.erase(i); // erase trailing comment 149 | } 150 | } 151 | break; 152 | } 153 | i=s.find_last_not_of(" \f\n\r\t\v"); 154 | if(i!=-1) s.erase(i+1); // erase trailing whitespace 155 | return cmt; 156 | } 157 | 158 | public: 159 | ConfigEntry(int l, const std::string &s, const std::string &k, const std::string &v) : 160 | line(l), section(s), key(k), val(v) { 161 | trim(section); 162 | trim(key); 163 | used=false; 164 | } 165 | 166 | void parse_key(const std::string &k){ 167 | int i=k.find("::"); 168 | if(i==-1){ 169 | section="Uncategorized"; key=k; 170 | } else { 171 | section=k.substr(0,i); key=k.substr(i+2); 172 | } 173 | trim(section); 174 | trim(key); 175 | used=false; 176 | } 177 | 178 | ConfigEntry(const std::string k){ 179 | parse_key(k); 180 | } 181 | 182 | ConfigEntry(const std::string k, const std::string &v) : line(-1), val(v) { 183 | parse_key(k); 184 | } 185 | 186 | friend class ConfigFile; 187 | friend struct key_less; 188 | friend struct line_less; 189 | }; 190 | class SectionSizes { 191 | protected: 192 | std::map sections; 193 | 194 | public: 195 | uint32 GetSectionSize(const std::string section) { 196 | uint32 count=0; 197 | uint32 seclen; 198 | std::map::iterator it; 199 | for(it=sections.begin(); it!=sections.end(); it++) { 200 | seclen = MIN(section.size(),it->first.size()); 201 | if(it->first==section || !section.compare(0,seclen,it->first,0,seclen)) count+=it->second; 202 | } 203 | return count; 204 | } 205 | 206 | void IncreaseSectionSize(const std::string section) { 207 | std::map::iterator it=sections.find(section); 208 | if(it!=sections.end()) 209 | it->second++; 210 | else 211 | sections.insert(std::pair(section,1)); 212 | } 213 | 214 | void DecreaseSectionSize(const std::string section) { 215 | std::map::iterator it=sections.find(section); 216 | if(it!=sections.end()) 217 | it->second--; 218 | } 219 | 220 | void ClearSections() { 221 | sections.clear(); 222 | } 223 | 224 | void DeleteSection(const std::string section) { 225 | sections.erase(section); 226 | } 227 | 228 | }; 229 | std::set data; 230 | SectionSizes sectionSizes; 231 | int linectr; 232 | static bool defaultAutoAdd; 233 | static bool niceAlignment; 234 | static bool showComments; 235 | static bool alphaSort; 236 | static bool timeSort; 237 | }; 238 | 239 | /* Config file format: 240 | * 241 | * Comments are any lines whose first non-whitespace character is ';' or '#'. 242 | * Note that comments can also follow a value, on the same line. 243 | * To intentionally have a '#' character in the value, use ## 244 | * 245 | * All parameters fall into sections. To name a section, the first 246 | * non-whitespace character on the line will be '[', and the last will be ']'. 247 | * 248 | * Parameters are simple key=value pairs. Whitespace around the '=', and at the 249 | * beginning or end of the line is ignored. Key names may not contain '=' nor 250 | * begin with '[', however values can. If the last character of the value is 251 | * '\', the next line (sans leading/trailing whitespace) is considered part of 252 | * the value as well. Programmatically, the key "K" in section "S" is referred 253 | * to as "S::K", much like C++ namespaces. For example: 254 | * [Section1] 255 | * # this is a comment 256 | * foo = bar \ 257 | * baz\ 258 | * quux \ 259 | * ## this is not a comment! # this IS a comment 260 | * means the value of "Section1::foo" is "bar bazquux # this is not a comment!" 261 | * 262 | * Parameters may be of several types: 263 | * String - Bare characters. If the first and last characters are both '"', 264 | * they are removed (so just double them if you really want quotes 265 | * there) 266 | * Int - A decimal number from -2147483648 to 2147483647 267 | * UInt - A number in decimal, hex, or octal from 0 to 4294967295 (or 268 | * 0xffffffff, or 037777777777) 269 | * Bool - true/false, 0/1, on/off, yes/no 270 | * 271 | * Of course, the actual accepted values for a parameter may be further 272 | * restricted ;) 273 | */ 274 | 275 | 276 | /* You must write this for your port */ 277 | void S9xParsePortConfig(ConfigFile &, int pass); 278 | 279 | /* This may or may not be useful to you */ 280 | const char *S9xParseDisplayConfig(ConfigFile &, int pass); 281 | 282 | #endif 283 | -------------------------------------------------------------------------------- /components/snes9x/core/oppseudo_misc.cpp: -------------------------------------------------------------------------------- 1 | case 0x00: { 2 | op_io(); 3 | break; 4 | } 5 | 6 | case 0xef: { 7 | op_io(2); 8 | regs.pc--; 9 | break; 10 | } 11 | 12 | case 0xff: { 13 | op_io(2); 14 | regs.pc--; 15 | break; 16 | } 17 | 18 | case 0x9f: { 19 | op_io(4); 20 | regs.B.a = (regs.B.a >> 4) | (regs.B.a << 4); 21 | regs.p.n = !!(regs.B.a & 0x80); 22 | regs.p.z = (regs.B.a == 0); 23 | break; 24 | } 25 | 26 | case 0xdf: { 27 | op_io(2); 28 | if(regs.p.c || (regs.B.a) > 0x99) { 29 | regs.B.a += 0x60; 30 | regs.p.c = 1; 31 | } 32 | if(regs.p.h || (regs.B.a & 15) > 0x09) { 33 | regs.B.a += 0x06; 34 | } 35 | regs.p.n = !!(regs.B.a & 0x80); 36 | regs.p.z = (regs.B.a == 0); 37 | break; 38 | } 39 | 40 | case 0xbe: { 41 | op_io(2); 42 | if(!regs.p.c || (regs.B.a) > 0x99) { 43 | regs.B.a -= 0x60; 44 | regs.p.c = 0; 45 | } 46 | if(!regs.p.h || (regs.B.a & 15) > 0x09) { 47 | regs.B.a -= 0x06; 48 | } 49 | regs.p.n = !!(regs.B.a & 0x80); 50 | regs.p.z = (regs.B.a == 0); 51 | break; 52 | } 53 | 54 | case 0x60: { 55 | op_io(); 56 | regs.p.c = 0; 57 | break; 58 | } 59 | 60 | case 0x20: { 61 | op_io(); 62 | regs.p.p = 0; 63 | break; 64 | } 65 | 66 | case 0x80: { 67 | op_io(); 68 | regs.p.c = 1; 69 | break; 70 | } 71 | 72 | case 0x40: { 73 | op_io(); 74 | regs.p.p = 1; 75 | break; 76 | } 77 | 78 | case 0xe0: { 79 | op_io(); 80 | regs.p.v = 0; 81 | regs.p.h = 0; 82 | break; 83 | } 84 | 85 | case 0xed: { 86 | op_io(2); 87 | regs.p.c = !regs.p.c; 88 | break; 89 | } 90 | 91 | case 0xa0: { 92 | op_io(2); 93 | regs.p.i = 1; 94 | break; 95 | } 96 | 97 | case 0xc0: { 98 | op_io(2); 99 | regs.p.i = 0; 100 | break; 101 | } 102 | 103 | case 0x02: { 104 | dp = op_readpc(); 105 | rd = op_readdp(dp); 106 | rd |= 0x01; 107 | op_writedp(dp, rd); 108 | break; 109 | } 110 | 111 | case 0x12: { 112 | dp = op_readpc(); 113 | rd = op_readdp(dp); 114 | rd &= ~0x01; 115 | op_writedp(dp, rd); 116 | break; 117 | } 118 | 119 | case 0x22: { 120 | dp = op_readpc(); 121 | rd = op_readdp(dp); 122 | rd |= 0x02; 123 | op_writedp(dp, rd); 124 | break; 125 | } 126 | 127 | case 0x32: { 128 | dp = op_readpc(); 129 | rd = op_readdp(dp); 130 | rd &= ~0x02; 131 | op_writedp(dp, rd); 132 | break; 133 | } 134 | 135 | case 0x42: { 136 | dp = op_readpc(); 137 | rd = op_readdp(dp); 138 | rd |= 0x04; 139 | op_writedp(dp, rd); 140 | break; 141 | } 142 | 143 | case 0x52: { 144 | dp = op_readpc(); 145 | rd = op_readdp(dp); 146 | rd &= ~0x04; 147 | op_writedp(dp, rd); 148 | break; 149 | } 150 | 151 | case 0x62: { 152 | dp = op_readpc(); 153 | rd = op_readdp(dp); 154 | rd |= 0x08; 155 | op_writedp(dp, rd); 156 | break; 157 | } 158 | 159 | case 0x72: { 160 | dp = op_readpc(); 161 | rd = op_readdp(dp); 162 | rd &= ~0x08; 163 | op_writedp(dp, rd); 164 | break; 165 | } 166 | 167 | case 0x82: { 168 | dp = op_readpc(); 169 | rd = op_readdp(dp); 170 | rd |= 0x10; 171 | op_writedp(dp, rd); 172 | break; 173 | } 174 | 175 | case 0x92: { 176 | dp = op_readpc(); 177 | rd = op_readdp(dp); 178 | rd &= ~0x10; 179 | op_writedp(dp, rd); 180 | break; 181 | } 182 | 183 | case 0xa2: { 184 | dp = op_readpc(); 185 | rd = op_readdp(dp); 186 | rd |= 0x20; 187 | op_writedp(dp, rd); 188 | break; 189 | } 190 | 191 | case 0xb2: { 192 | dp = op_readpc(); 193 | rd = op_readdp(dp); 194 | rd &= ~0x20; 195 | op_writedp(dp, rd); 196 | break; 197 | } 198 | 199 | case 0xc2: { 200 | dp = op_readpc(); 201 | rd = op_readdp(dp); 202 | rd |= 0x40; 203 | op_writedp(dp, rd); 204 | break; 205 | } 206 | 207 | case 0xd2: { 208 | dp = op_readpc(); 209 | rd = op_readdp(dp); 210 | rd &= ~0x40; 211 | op_writedp(dp, rd); 212 | break; 213 | } 214 | 215 | case 0xe2: { 216 | dp = op_readpc(); 217 | rd = op_readdp(dp); 218 | rd |= 0x80; 219 | op_writedp(dp, rd); 220 | break; 221 | } 222 | 223 | case 0xf2: { 224 | dp = op_readpc(); 225 | rd = op_readdp(dp); 226 | rd &= ~0x80; 227 | op_writedp(dp, rd); 228 | break; 229 | } 230 | 231 | case 0x2d: { 232 | op_io(2); 233 | op_writestack(regs.B.a); 234 | break; 235 | } 236 | 237 | case 0x4d: { 238 | op_io(2); 239 | op_writestack(regs.x); 240 | break; 241 | } 242 | 243 | case 0x6d: { 244 | op_io(2); 245 | op_writestack(regs.B.y); 246 | break; 247 | } 248 | 249 | case 0x0d: { 250 | op_io(2); 251 | op_writestack(regs.p); 252 | break; 253 | } 254 | 255 | case 0xae: { 256 | op_io(2); 257 | regs.B.a = op_readstack(); 258 | break; 259 | } 260 | 261 | case 0xce: { 262 | op_io(2); 263 | regs.x = op_readstack(); 264 | break; 265 | } 266 | 267 | case 0xee: { 268 | op_io(2); 269 | regs.B.y = op_readstack(); 270 | break; 271 | } 272 | 273 | case 0x8e: { 274 | op_io(2); 275 | regs.p = op_readstack(); 276 | break; 277 | } 278 | 279 | case 0xcf: { 280 | op_io(8); 281 | ya = regs.B.y * regs.B.a; 282 | regs.B.a = ya; 283 | regs.B.y = ya >> 8; 284 | //result is set based on y (high-byte) only 285 | regs.p.n = !!(regs.B.y & 0x80); 286 | regs.p.z = (regs.B.y == 0); 287 | break; 288 | } 289 | 290 | case 0x9e: { 291 | op_io(11); 292 | ya = regs.ya; 293 | //overflow set if quotient >= 256 294 | regs.p.v = !!(regs.B.y >= regs.x); 295 | regs.p.h = !!((regs.B.y & 15) >= (regs.x & 15)); 296 | if(regs.B.y < (regs.x << 1)) { 297 | //if quotient is <= 511 (will fit into 9-bit result) 298 | regs.B.a = ya / regs.x; 299 | regs.B.y = ya % regs.x; 300 | } else { 301 | //otherwise, the quotient won't fit into regs.p.v + regs.B.a 302 | //this emulates the odd behavior of the S-SMP in this case 303 | regs.B.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); 304 | regs.B.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); 305 | } 306 | //result is set based on a (quotient) only 307 | regs.p.n = !!(regs.B.a & 0x80); 308 | regs.p.z = (regs.B.a == 0); 309 | break; 310 | } 311 | 312 | -------------------------------------------------------------------------------- /components/snes9x/core/oppseudo_rmw.cpp: -------------------------------------------------------------------------------- 1 | case 0xbc: { 2 | op_io(); 3 | regs.B.a = op_inc(regs.B.a); 4 | break; 5 | } 6 | 7 | case 0x3d: { 8 | op_io(); 9 | regs.x = op_inc(regs.x); 10 | break; 11 | } 12 | 13 | case 0xfc: { 14 | op_io(); 15 | regs.B.y = op_inc(regs.B.y); 16 | break; 17 | } 18 | 19 | case 0x9c: { 20 | op_io(); 21 | regs.B.a = op_dec(regs.B.a); 22 | break; 23 | } 24 | 25 | case 0x1d: { 26 | op_io(); 27 | regs.x = op_dec(regs.x); 28 | break; 29 | } 30 | 31 | case 0xdc: { 32 | op_io(); 33 | regs.B.y = op_dec(regs.B.y); 34 | break; 35 | } 36 | 37 | case 0x1c: { 38 | op_io(); 39 | regs.B.a = op_asl(regs.B.a); 40 | break; 41 | } 42 | 43 | case 0x5c: { 44 | op_io(); 45 | regs.B.a = op_lsr(regs.B.a); 46 | break; 47 | } 48 | 49 | case 0x3c: { 50 | op_io(); 51 | regs.B.a = op_rol(regs.B.a); 52 | break; 53 | } 54 | 55 | case 0x7c: { 56 | op_io(); 57 | regs.B.a = op_ror(regs.B.a); 58 | break; 59 | } 60 | 61 | case 0xab: { 62 | dp = op_readpc(); 63 | rd = op_readdp(dp); 64 | rd = op_inc(rd); 65 | op_writedp(dp, rd); 66 | break; 67 | } 68 | 69 | case 0x8b: { 70 | dp = op_readpc(); 71 | rd = op_readdp(dp); 72 | rd = op_dec(rd); 73 | op_writedp(dp, rd); 74 | break; 75 | } 76 | 77 | case 0x0b: { 78 | dp = op_readpc(); 79 | rd = op_readdp(dp); 80 | rd = op_asl(rd); 81 | op_writedp(dp, rd); 82 | break; 83 | } 84 | 85 | case 0x4b: { 86 | dp = op_readpc(); 87 | rd = op_readdp(dp); 88 | rd = op_lsr(rd); 89 | op_writedp(dp, rd); 90 | break; 91 | } 92 | 93 | case 0x2b: { 94 | dp = op_readpc(); 95 | rd = op_readdp(dp); 96 | rd = op_rol(rd); 97 | op_writedp(dp, rd); 98 | break; 99 | } 100 | 101 | case 0x6b: { 102 | dp = op_readpc(); 103 | rd = op_readdp(dp); 104 | rd = op_ror(rd); 105 | op_writedp(dp, rd); 106 | break; 107 | } 108 | 109 | case 0xbb: { 110 | dp = op_readpc(); 111 | op_io(); 112 | rd = op_readdp(dp + regs.x); 113 | rd = op_inc(rd); 114 | op_writedp(dp + regs.x, rd); 115 | break; 116 | } 117 | 118 | case 0x9b: { 119 | dp = op_readpc(); 120 | op_io(); 121 | rd = op_readdp(dp + regs.x); 122 | rd = op_dec(rd); 123 | op_writedp(dp + regs.x, rd); 124 | break; 125 | } 126 | 127 | case 0x1b: { 128 | dp = op_readpc(); 129 | op_io(); 130 | rd = op_readdp(dp + regs.x); 131 | rd = op_asl(rd); 132 | op_writedp(dp + regs.x, rd); 133 | break; 134 | } 135 | 136 | case 0x5b: { 137 | dp = op_readpc(); 138 | op_io(); 139 | rd = op_readdp(dp + regs.x); 140 | rd = op_lsr(rd); 141 | op_writedp(dp + regs.x, rd); 142 | break; 143 | } 144 | 145 | case 0x3b: { 146 | dp = op_readpc(); 147 | op_io(); 148 | rd = op_readdp(dp + regs.x); 149 | rd = op_rol(rd); 150 | op_writedp(dp + regs.x, rd); 151 | break; 152 | } 153 | 154 | case 0x7b: { 155 | dp = op_readpc(); 156 | op_io(); 157 | rd = op_readdp(dp + regs.x); 158 | rd = op_ror(rd); 159 | op_writedp(dp + regs.x, rd); 160 | break; 161 | } 162 | 163 | case 0xac: { 164 | dp = op_readpc(); 165 | dp |= op_readpc() << 8; 166 | rd = op_readaddr(dp); 167 | rd = op_inc(rd); 168 | op_writeaddr(dp, rd); 169 | break; 170 | } 171 | 172 | case 0x8c: { 173 | dp = op_readpc(); 174 | dp |= op_readpc() << 8; 175 | rd = op_readaddr(dp); 176 | rd = op_dec(rd); 177 | op_writeaddr(dp, rd); 178 | break; 179 | } 180 | 181 | case 0x0c: { 182 | dp = op_readpc(); 183 | dp |= op_readpc() << 8; 184 | rd = op_readaddr(dp); 185 | rd = op_asl(rd); 186 | op_writeaddr(dp, rd); 187 | break; 188 | } 189 | 190 | case 0x4c: { 191 | dp = op_readpc(); 192 | dp |= op_readpc() << 8; 193 | rd = op_readaddr(dp); 194 | rd = op_lsr(rd); 195 | op_writeaddr(dp, rd); 196 | break; 197 | } 198 | 199 | case 0x2c: { 200 | dp = op_readpc(); 201 | dp |= op_readpc() << 8; 202 | rd = op_readaddr(dp); 203 | rd = op_rol(rd); 204 | op_writeaddr(dp, rd); 205 | break; 206 | } 207 | 208 | case 0x6c: { 209 | dp = op_readpc(); 210 | dp |= op_readpc() << 8; 211 | rd = op_readaddr(dp); 212 | rd = op_ror(rd); 213 | op_writeaddr(dp, rd); 214 | break; 215 | } 216 | 217 | case 0x0e: { 218 | dp = op_readpc(); 219 | dp |= op_readpc() << 8; 220 | rd = op_readaddr(dp); 221 | regs.p.n = !!((regs.B.a - rd) & 0x80); 222 | regs.p.z = ((regs.B.a - rd) == 0); 223 | op_readaddr(dp); 224 | op_writeaddr(dp, rd | regs.B.a); 225 | break; 226 | } 227 | 228 | case 0x4e: { 229 | dp = op_readpc(); 230 | dp |= op_readpc() << 8; 231 | rd = op_readaddr(dp); 232 | regs.p.n = !!((regs.B.a - rd) & 0x80); 233 | regs.p.z = ((regs.B.a - rd) == 0); 234 | op_readaddr(dp); 235 | op_writeaddr(dp, rd &~ regs.B.a); 236 | break; 237 | } 238 | 239 | case 0x3a: { 240 | dp = op_readpc(); 241 | rd = op_readdp(dp); 242 | rd++; 243 | op_writedp(dp++, rd); 244 | rd += op_readdp(dp) << 8; 245 | op_writedp(dp, rd >> 8); 246 | regs.p.n = !!(rd & 0x8000); 247 | regs.p.z = (rd == 0); 248 | break; 249 | } 250 | 251 | case 0x1a: { 252 | dp = op_readpc(); 253 | rd = op_readdp(dp); 254 | rd--; 255 | op_writedp(dp++, rd); 256 | rd += op_readdp(dp) << 8; 257 | op_writedp(dp, rd >> 8); 258 | regs.p.n = !!(rd & 0x8000); 259 | regs.p.z = (rd == 0); 260 | break; 261 | } 262 | 263 | -------------------------------------------------------------------------------- /components/snes9x/cpu.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #include "snes9x.h" 8 | #include "memmap.h" 9 | #include "dma.h" 10 | #include "apu.h" 11 | #include "logger.h" 12 | #ifdef DEBUGGER 13 | #include "debug.h" 14 | #endif 15 | 16 | static void S9xResetCPU (void); 17 | static void S9xSoftResetCPU (void); 18 | 19 | 20 | static void S9xResetCPU (void) 21 | { 22 | S9xSoftResetCPU(); 23 | Registers.SL = 0xff; 24 | Registers.P.W = 0; 25 | Registers.A.W = 0; 26 | Registers.X.W = 0; 27 | Registers.Y.W = 0; 28 | SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); 29 | ClearFlags(Decimal); 30 | } 31 | 32 | static void S9xSoftResetCPU (void) 33 | { 34 | CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. 35 | CPU.PrevCycles = CPU.Cycles; 36 | CPU.V_Counter = 0; 37 | CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); 38 | CPU.PCBase = NULL; 39 | CPU.NMIPending = FALSE; 40 | CPU.IRQLine = FALSE; 41 | CPU.IRQTransition = FALSE; 42 | CPU.IRQExternal = FALSE; 43 | CPU.MemSpeed = SLOW_ONE_CYCLE; 44 | CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; 45 | CPU.FastROMSpeed = SLOW_ONE_CYCLE; 46 | CPU.InDMA = FALSE; 47 | CPU.InHDMA = FALSE; 48 | CPU.InDMAorHDMA = FALSE; 49 | CPU.InWRAMDMAorHDMA = FALSE; 50 | CPU.HDMARanInDMA = 0; 51 | CPU.CurrentDMAorHDMAChannel = -1; 52 | CPU.WhichEvent = HC_RENDER_EVENT; 53 | CPU.NextEvent = Timings.RenderPos; 54 | CPU.WaitingForInterrupt = FALSE; 55 | CPU.AutoSaveTimer = 0; 56 | CPU.SRAMModified = FALSE; 57 | 58 | Registers.PBPC = 0; 59 | Registers.PB = 0; 60 | Registers.PCw = S9xGetWord(0xfffc); 61 | OpenBus = Registers.PCh; 62 | Registers.D.W = 0; 63 | Registers.DB = 0; 64 | Registers.SH = 1; 65 | Registers.SL -= 3; 66 | Registers.XH = 0; 67 | Registers.YH = 0; 68 | 69 | ICPU.ShiftedPB = 0; 70 | ICPU.ShiftedDB = 0; 71 | SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); 72 | ClearFlags(Decimal); 73 | 74 | Timings.InterlaceField = FALSE; 75 | Timings.H_Max = Timings.H_Max_Master; 76 | Timings.V_Max = Timings.V_Max_Master; 77 | Timings.NMITriggerPos = 0xffff; 78 | Timings.NextIRQTimer = 0x0fffffff; 79 | Timings.IRQFlagChanging = IRQ_NONE; 80 | 81 | if (Model->_5A22 == 2) 82 | Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; 83 | else 84 | Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; 85 | 86 | S9xSetPCBase(Registers.PBPC); 87 | 88 | ICPU.S9xOpcodes = S9xOpcodesE1; 89 | ICPU.S9xOpLengths = S9xOpLengthsM1X1; 90 | 91 | S9xUnpackStatus(); 92 | } 93 | 94 | void S9xReset (void) 95 | { 96 | S9xResetLogger(); 97 | 98 | memset(Memory.RAM1, 0x55, 0x10000); 99 | memset(Memory.RAM2, 0x55, 0x10000); 100 | memset(Memory.VRAM, 0x00, 0x10000); 101 | memset(Memory.FillRAM, 0, 0x8000); 102 | 103 | S9xResetCPU(); 104 | S9xResetPPU(); 105 | S9xResetDMA(); 106 | S9xResetAPU(); 107 | 108 | if (Settings.DSP) 109 | S9xResetDSP(); 110 | } 111 | 112 | void S9xSoftReset (void) 113 | { 114 | memset(Memory.FillRAM, 0, 0x8000); 115 | 116 | S9xSoftResetCPU(); 117 | S9xSoftResetPPU(); 118 | S9xResetDMA(); 119 | S9xSoftResetAPU(); 120 | 121 | if (Settings.DSP) 122 | S9xResetDSP(); 123 | } 124 | -------------------------------------------------------------------------------- /components/snes9x/cpuexec.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _CPUEXEC_H_ 8 | #define _CPUEXEC_H_ 9 | 10 | #include "ppu.h" 11 | #ifdef DEBUGGER 12 | #include "debug.h" 13 | #endif 14 | 15 | struct SOpcodes 16 | { 17 | void (*S9xOpcode) (void); 18 | }; 19 | 20 | struct SICPU 21 | { 22 | struct SOpcodes *S9xOpcodes; 23 | uint8 *S9xOpLengths; 24 | uint8 _Carry; 25 | uint8 _Zero; 26 | uint8 _Negative; 27 | uint8 _Overflow; 28 | uint32 ShiftedPB; 29 | uint32 ShiftedDB; 30 | uint32 Frame; 31 | uint32 FrameAdvanceCount; 32 | }; 33 | 34 | extern struct SICPU ICPU; 35 | 36 | extern struct SOpcodes S9xOpcodesE1[256]; 37 | extern struct SOpcodes S9xOpcodesM1X1[256]; 38 | extern struct SOpcodes S9xOpcodesM1X0[256]; 39 | extern struct SOpcodes S9xOpcodesM0X1[256]; 40 | extern struct SOpcodes S9xOpcodesM0X0[256]; 41 | extern struct SOpcodes S9xOpcodesSlow[256]; 42 | extern uint8 S9xOpLengthsM1X1[256]; 43 | extern uint8 S9xOpLengthsM1X0[256]; 44 | extern uint8 S9xOpLengthsM0X1[256]; 45 | extern uint8 S9xOpLengthsM0X0[256]; 46 | 47 | void S9xMainLoop (void); 48 | void S9xReset (void); 49 | void S9xSoftReset (void); 50 | void S9xDoHEventProcessing (void); 51 | 52 | static inline void S9xUnpackStatus (void) 53 | { 54 | ICPU._Zero = (Registers.PL & Zero) == 0; 55 | ICPU._Negative = (Registers.PL & Negative); 56 | ICPU._Carry = (Registers.PL & Carry); 57 | ICPU._Overflow = (Registers.PL & Overflow) >> 6; 58 | } 59 | 60 | static inline void S9xPackStatus (void) 61 | { 62 | Registers.PL &= ~(Zero | Negative | Carry | Overflow); 63 | Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) | (ICPU._Negative & 0x80) | (ICPU._Overflow << 6); 64 | } 65 | 66 | static inline void S9xFixCycles (void) 67 | { 68 | if (CheckEmulation()) 69 | { 70 | ICPU.S9xOpcodes = S9xOpcodesE1; 71 | ICPU.S9xOpLengths = S9xOpLengthsM1X1; 72 | } 73 | else 74 | if (CheckMemory()) 75 | { 76 | if (CheckIndex()) 77 | { 78 | ICPU.S9xOpcodes = S9xOpcodesM1X1; 79 | ICPU.S9xOpLengths = S9xOpLengthsM1X1; 80 | } 81 | else 82 | { 83 | ICPU.S9xOpcodes = S9xOpcodesM1X0; 84 | ICPU.S9xOpLengths = S9xOpLengthsM1X0; 85 | } 86 | } 87 | else 88 | { 89 | if (CheckIndex()) 90 | { 91 | ICPU.S9xOpcodes = S9xOpcodesM0X1; 92 | ICPU.S9xOpLengths = S9xOpLengthsM0X1; 93 | } 94 | else 95 | { 96 | ICPU.S9xOpcodes = S9xOpcodesM0X0; 97 | ICPU.S9xOpLengths = S9xOpLengthsM0X0; 98 | } 99 | } 100 | } 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /components/snes9x/cpuops.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _CPUOPS_H_ 8 | #define _CPUOPS_H_ 9 | 10 | void S9xOpcode_NMI (void); 11 | void S9xOpcode_IRQ (void); 12 | 13 | #ifndef SA1_OPCODES 14 | #define CHECK_FOR_IRQ() {} // if (CPU.IRQLine) S9xOpcode_IRQ(); } 15 | #else 16 | #define CHECK_FOR_IRQ() {} 17 | #endif 18 | #endif 19 | -------------------------------------------------------------------------------- /components/snes9x/debug.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifdef DEBUGGER 8 | 9 | #ifndef _DEBUG_H_ 10 | #define _DEBUG_H_ 11 | 12 | #include 13 | 14 | struct SBreakPoint 15 | { 16 | bool8 Enabled; 17 | uint8 Bank; 18 | uint16 Address; 19 | }; 20 | 21 | #define ENSURE_TRACE_OPEN(fp, file, mode) \ 22 | if (!fp) \ 23 | { \ 24 | std::string fn = S9xGetDirectory(LOG_DIR); \ 25 | fn += SLASH_STR file; \ 26 | fp = fopen(fn.c_str(), mode); \ 27 | } 28 | 29 | extern struct SBreakPoint S9xBreakpoint[6]; 30 | 31 | void S9xDoDebug (void); 32 | void S9xTrace (void); 33 | void S9xSA1Trace (void); 34 | void S9xTraceMessage (const char *); 35 | void S9xTraceFormattedMessage (const char *, ...); 36 | void S9xPrintHVPosition (char *); 37 | void S9xDebugProcessCommand(char *); 38 | 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /components/snes9x/display.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _DISPLAY_H_ 8 | #define _DISPLAY_H_ 9 | 10 | #include "snes9x.h" 11 | 12 | enum s9x_getdirtype 13 | { 14 | DEFAULT_DIR = 0, 15 | HOME_DIR, 16 | ROMFILENAME_DIR, 17 | ROM_DIR, 18 | SRAM_DIR, 19 | SNAPSHOT_DIR, 20 | SCREENSHOT_DIR, 21 | SPC_DIR, 22 | CHEAT_DIR, 23 | PATCH_DIR, 24 | BIOS_DIR, 25 | LOG_DIR, 26 | SAT_DIR, 27 | LAST_DIR 28 | }; 29 | 30 | void S9xUsage (void); 31 | char * S9xParseArgs (char **, int); 32 | void S9xParseArgsForCheats (char **, int); 33 | void S9xLoadConfigFiles (char **, int); 34 | void S9xSetInfoString (const char *); 35 | 36 | // Routines the port has to implement even if it doesn't use them 37 | 38 | void S9xPutImage (int, int); 39 | void S9xInitDisplay (int, char **); 40 | void S9xDeinitDisplay (void); 41 | void S9xTextMode (void); 42 | void S9xGraphicsMode (void); 43 | void S9xSetPalette (void); 44 | void S9xToggleSoundChannel (int); 45 | bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *); 46 | void S9xCloseSnapshotFile (STREAM); 47 | const char * S9xStringInput (const char *); 48 | const char * S9xGetDirectory (enum s9x_getdirtype); 49 | const char * S9xGetFilename (const char *, enum s9x_getdirtype); 50 | const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype); 51 | const char * S9xChooseFilename (bool8); 52 | const char * S9xBasename (const char *); 53 | 54 | // Routines the port has to implement if it uses command-line 55 | 56 | void S9xExtraUsage (void); 57 | void S9xParseArg (char **, int &, int); 58 | 59 | // Routines the port may implement as needed 60 | 61 | void S9xExtraDisplayUsage (void); 62 | void S9xParseDisplayArg (char **, int &, int); 63 | void S9xSetTitle (const char *); 64 | void S9xInitInputDevices (void); 65 | void S9xProcessEvents (bool8); 66 | const char * S9xSelectFilename (const char *, const char *, const char *, const char *); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /components/snes9x/dma.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _DMA_H_ 8 | #define _DMA_H_ 9 | 10 | struct SDMA 11 | { 12 | bool8 ReverseTransfer; 13 | bool8 HDMAIndirectAddressing; 14 | bool8 UnusedBit43x0; 15 | bool8 AAddressFixed; 16 | bool8 AAddressDecrement; 17 | uint8 TransferMode; 18 | uint8 BAddress; 19 | uint16 AAddress; 20 | uint8 ABank; 21 | uint16 DMACount_Or_HDMAIndirectAddress; 22 | uint8 IndirectBank; 23 | uint16 Address; 24 | uint8 Repeat; 25 | uint8 LineCount; 26 | uint8 UnknownByte; 27 | uint8 DoTransfer; 28 | }; 29 | 30 | #define TransferBytes DMACount_Or_HDMAIndirectAddress 31 | #define IndirectAddress DMACount_Or_HDMAIndirectAddress 32 | 33 | extern struct SDMA DMA[8]; 34 | 35 | bool8 S9xDoDMA (uint8); 36 | void S9xStartHDMA (void); 37 | uint8 S9xDoHDMA (uint8); 38 | void S9xResetDMA (void); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /components/snes9x/docs/control-inputs.txt: -------------------------------------------------------------------------------- 1 | Control input names are completely defined by the individual ports. This 2 | document is intended to collect the rules for all ports. 3 | 4 | The various meta-characters in the rules are: 5 | # - A number. The range is determined by the context 6 | ## - A two-digit number (i.e. with leading zeros) 7 | [...] - Something optional 8 | (...) - For grouping with | 9 | | - "or", choose one of the options. 10 | <...> - A named field 11 | {...} - A list of possible values. Multiple values may be used, but they 12 | must be in the order listed and joined with +-signs. 13 | "" - 'ditto', used to indicate the same list as the above line. 14 | 15 | ================================================================================ 16 | Unix 17 | ================================================================================ 18 | 19 | Input names: 20 | Jxx:Axis# Axis # on joystick xx. Axis0 may be 21 | Up/Down, and Axis1 Left/Right. 22 | Jxx:B# Button # on joystick xx. 23 | 24 | Jxx:{M1,M2,M3,M4,M5,M6,M7,M8}+B# Used with the 'JSx Meta#' port 25 | Jxx:{M1,M2,M3,M4,M5,M6,M7,M8}+Axis# command. 26 | 27 | Jxx:X+B# Used to 'define' this key for all 28 | Jxx:X+Axis# combinations of JS Meta. 29 | 30 | Port-specific Commands: 31 | JSx Meta# Used to specify modifier keys (i.e. Shift, Control) to 32 | affect the specified joystick. For example, you could 33 | map J00:B20 to "JS0 Meta1", then map J00:B0 to "Joypad1 34 | A" and J00:M1+B0 to "Joypad1 Turbo A". '#' may range 35 | from 1-8. 36 | 37 | Jsx ToggleMeta# Like the above, but toggles the meta-state each time 38 | the button is pressed. 39 | 40 | ================================================================================ 41 | Unix/X11 42 | ================================================================================ 43 | 44 | Keyboard Input: 45 | 46 | Note that only one keyboard (K00) is currently supported. If you know how 47 | to support multiple keyboards (and can test it!), feel free to fix x11.cpp 48 | and delete this note. 49 | 50 | Keyboard modifiers are S=Shift, C=Control, A=Alt, M=Meta. Combine them in 51 | order, i.e. all 4 would be "SCAM". 52 | 53 | Kxx: Key names are as recognized by XStringToKeysym. 54 | Kxx:+ Note however that keys are mapped by keycode, 55 | so for example on a standard qwerty keyboard 56 | "K00:colon" and "K00:semicolon" are identical. 57 | 58 | Pointer Input: 59 | 60 | Note that only one mouse (M00) is currently supported. If you know how to 61 | support multiple pointing devices (and can test it!), feel free to fix 62 | x11.cpp and delete this note. 63 | 64 | Mxx:Pointer Map the mouse pointer. If someone has a mouse 65 | Mxx:Pointer# device with multiple pointers, fix x11.cpp to 66 | report that and you can use the second syntax. 67 | 68 | Mxx:B# Mouse buttons. 69 | -------------------------------------------------------------------------------- /components/snes9x/docs/controls.txt: -------------------------------------------------------------------------------- 1 | This lists the available commands, excluding the ones you get back from 2 | S9xGetAllSnes9xCommands(). The various meta-characters are: 3 | # - A number. The range is determined by the context 4 | ## - A two-digit number (i.e. with leading zeros) 5 | [...] - Something optional 6 | (...) - For grouping with | 7 | | - "or", choose one of the options. 8 | <...> - A named field 9 | {...} - A list of possible values. Multiple values may be used, but they 10 | must be in the order listed and joined with +-signs. 11 | "" - 'ditto', used to indicate the same list as the above line. 12 | 13 | Speeds are: Var, Slow, Med, and Fast. 'Var' starts slow and speeds up as the 14 | button is held. 15 | 16 | Axes are: Left/Right, Right/Left, Up/Down, Down/Up, Y/A, A/Y, X/B, B/X, L/R, 17 | and R/L. Negative is listed first (i.e. "Y/A" means negative deflection is 18 | towards Y, while "A/Y" means negative deflection is towards A). 19 | 20 | AxisToPointer, ButtonToPointer, and AxisToButtons allow for translating 21 | between different input types. There are 8 'pointers' with IDs 22 | PseudoPointerBase+0 to PseudoPointerBase+7, and 256 'buttons' with IDs 23 | PseudoButtonBase+0 to PseudoButtonBase+255. So for example, 24 | "AxisToButtons 0/255 T=50%" would take the axis data, and do 25 | S9xReportButton(PseudoButtonBase+0,1) when said axis goes past 50% in the 26 | negative direction and S9xReportButton(PseudoButtonBase+255,1) when it goes 27 | over 50% deflection in the positive direction. Similarly, it will do 28 | S9xReportButton(...,0) when the deflection drops under 50% in either 29 | direction. "ButtonToPointer 1u Slow" would move the pointer with ID 30 | PseudoPointerBase+0 up one pixel per frame as long as the button is pressed 31 | (reporting this change at the end of each frame). 32 | 33 | --------------- 34 | Button Commands 35 | --------------- 36 | 37 | Joypad# {Up, Down, Left, Right, A, B, X, Y, L, R, Start, Select} 38 | Joypad# Turbo "" 39 | Joypad# Sticky "" 40 | Joypad# StickyTurbo "" 41 | Joypad# ToggleTurbo "" 42 | Joypad# ToggleSticky "" 43 | Joypad# ToggleStickyTurbo "" 44 | 45 | Mouse# (L|R|LR) 46 | 47 | Superscope AimOffscreen 48 | Superscope {Fire, Cursor, ToggleTurbo, Pause} 49 | Superscope AimOffscreen "" 50 | 51 | Justifier# AimOffscreen 52 | Justifier# {Trigger, Start} 53 | Justifier# AimOffscreen "" 54 | 55 | ButtonToPointer #[u|d][l|r] ; NOTE: "# " is invalid 56 | 57 | ------------- 58 | Axis Commands 59 | ------------- 60 | 61 | Joypad# Axis T=#% ; T = 0.1 to 100 by tenths 62 | AxisToButtons #/# T=#% ; neg then pos, range 0-255, T as above 63 | AxisToPointer #(h|v) [-] ; NOTE: '-' inverts the axis 64 | 65 | ---------------- 66 | Pointer Commands 67 | ---------------- 68 | 69 | Pointer {Mouse1, Mouse2, Superscope, Justifier1, Justifier2} 70 | 71 | ------ 72 | Multis 73 | ------ 74 | 75 | Multis are a type of button command. The basic format of a multi is "{...}", 76 | where the '...' consists of 1 or more valid non-multi button command 77 | strings. The braces are literal, not metacharacters. Subcommands separated 78 | by commas are executed one after the next. Semicolons skip one frame before 79 | continuing subcommand execution. Semicolons may be repeated. When the multi 80 | button is pressed, each subcommand is 'pressed', and when the multi button 81 | is released each subcommand is 'released'. 82 | 83 | There are also press-only multis, defined as "+{...}". These act just like 84 | regular multis, with two differences: the multi is only run when you press 85 | the button (release is ignored), and each subcommand must be prefixed with 86 | '+' or '-' to indicate whether the the subcommand should be pressed or 87 | released. 88 | 89 | For example: {Joypad1 A,Joypad2 A;Joypad3 A;;;;;QuickSave000} 90 | This presses (or releases) A on pads 1 and 2, then waits one frame, then 91 | presses A on pad 3, then waits 5 frames, then saves to snapshot 0 (on press 92 | only). 93 | 94 | You may access the multi number in the returned s9xcommand_t structure as 95 | cmd.button.multi_idx. This may be used to assign the same multi to multiple 96 | buttons: 97 | MULTI# ; NOTE: that's a literal octothorpe 98 | -------------------------------------------------------------------------------- /components/snes9x/docs/portsofsnes9x.txt: -------------------------------------------------------------------------------- 1 | These are all the known ports of Snes9x to other consoles/handhelds/etc as of 2 | 2011/08/28. They are all supported and welcomed on the official Snes9x site. 3 | 4 | **If you know of anyone who is currently working on a port of Snes9x, or if you 5 | have some interest in making a port, please have them go to the Snes9x forums 6 | (http://www.snes9x.com/phpbb2/) and have them register an account there. After 7 | that, speak to Ryan and/or Jerremy so you can be let into the devs area and the 8 | git so you can have access to the most current code, collaborate with the other 9 | developers, make the port officialized, etc.** 10 | 11 | Ports and how to get them running are as follows: 12 | 13 | *PSP Version of Snes9x* 14 | Name: Snes9X Euphoria 15 | Latest version: R5 Beta 16 | Homepage/forum: http://code.google.com/p/snes9x-euphoria/ 17 | Maintainer: Open due to Zack discontinuing the port; he has made the source 18 | code available. If you are interested in taking over the project or starting a 19 | new port from scratch, let Ryan and/or Jerremy know ASAP. 20 | 21 | HOW TO GET IT RUNNING: 22 | *DISCLAIMER* You will have to do some Googling, including but not limited to: 23 | * Downgrading/upgrading your firmware 24 | * Checking if your PSP-2000 series can use Pandora's Battery 25 | * Checking if your PSP-3000 series can use DaveeFTW's and/or some1's Downgrader 26 | * Creating Pandora's Battery (as needed) 27 | * Finding the hacks, HENs, CFWs, etc and how to use/install them 28 | 29 | 1. Make sure your PSP is hackable in some way. This means: 30 | * All PSP-1000 series and certain PSP-2000 series can use Pandora Battery; this 31 | would be considered fully hackable. 32 | * PSP-2000 series that can't use Pandora Battery, just about all PSP-3000 33 | series, and PSP Gos are hackable via other means (DaveeFTW's and/or some1's 34 | Downgrader, etc); this would be considered partially hackable. 35 | 36 | 2. Make sure your PSP has custom firmware or a HEN that's useable (you'll have 37 | to upgrade/downgrade the firmware as necessary). (Hint: I personally prefer 38 | 5.50 GEN-D3 if your PSP can use Pandora Battery; latest version of 6.20 or 39 | 6.35 PRO CFW if your PSP can't use Pandora Battery (if you can't downgrade past 40 | 6.35, then you should be able to use 6.39 and/or 6.60 PRO).) 41 | 42 | 3. When that’s done, be sure to put the Snes9X Euphoria folder in /PSP/GAME on 43 | your PSP’s memory stick (PSP-1000/2000/3000 series) or internal memory 44 | (PSP Go). Be sure to copy the ROMs into the roms folder, saves (*.srm, etc) 45 | into the saves folder, and cheats into the cheats folder. 46 | 47 | Note: as of right now, there is no one to maintain the PSP port; I am leaving 48 | these instructions up just in case someone wants to take it over, and you can 49 | use these tips to get other homebrews going. 50 | 51 | *Wii/Gamecube version of Snes9x* 52 | Name: Snes9X GX 53 | Latest Version: 4.2.8 54 | Homepage/forum: http://code.google.com/p/snes9x-gx 55 | Maintainer: Tantric 56 | 57 | HOW TO GET IT RUNNING: 58 | *DISCLAIMER* You will have to do some Googling, including but not limited to: 59 | * Finding and installing the latest versions of: Homebrew Channel, Snes9X GX 60 | Channel (optional), and/or IOS58 installer (also optional; this is to make the 61 | Snes9X GX channel work) 62 | * Finding a modchip for your GameCube and installing it 63 | 64 | Wii: You will need the latest Homebrew Channel installed on your Wii. After 65 | that, copy and paste the apps folder onto the root of your SD card; same goes 66 | for the snes9xgx folder. After that, copy over any ROMs you have to the 67 | \snes9xgx\roms folder, save files (*.srm, etc) to the \snes9xgx\saves folder, 68 | and cheats to the \snes9xgx\cheats folder. 69 | 70 | In addition, there appears to be a channel for Snes9X GX; you will need the 71 | Homebrew Channel installed and you MUST be on System Menu 4.3 so you can be on 72 | IOS58 (or use the IOS58 installer). After that, you should be able to run the 73 | installer from the Homebrew Channel, and you'll be good to go! 74 | 75 | Gamecube: You might need a modchip. 76 | 77 | *Android and iOS (Apple iPhone/iPod Touch) version of Snes9x* 78 | Name: Snes9X EX 79 | Latest Version: 1.4.2 (iOS); 1.4.7.1 (Android) 80 | Homepage/forum: http://www.explusalpha.com/home/snes9x-ex 81 | Maintainer: Rakashazi 82 | 83 | HOW TO GET IT RUNNING: 84 | *DISCLAIMER* You will have to do some Googling, including but not limited to: 85 | * iOS (iPhone/iPod Touch) ONLY!!!: Jailbreaking your firmware 86 | 87 | Android: Due to the Android Marketplace unfairly taking down Snes9X EX, you 88 | will have to visit Rakashazi's website and download the apk either using your 89 | PC (you'll have to connect the Android to your computer, mount the SD card, 90 | then copy the apk to it) or your Android, then run package installer 91 | (or easy installer is fine too) on your Android to install the app. 92 | 93 | iOS: You’ll have to jailbreak your firmware and install the Cydia app 94 | installer. Then you’ll have to install the BigBoss repository within Cydia and 95 | search for Snes9X EX; you may also want to search for the sshd and all needed 96 | stuff for that, as it’s the only way you can put the ROMs, saves, etc onto your 97 | iPhone/iPod Touch. After that you should be able to download and run from there 98 | :) 99 | 100 | Hint: a more detailed description of copying your ROMs/saves/etc over to the 101 | iOS device can be found here: 102 | http://snes9x.com/phpbb2/viewtopic.php?t=5107 103 | 104 | *PS3 version of Snes9x* 105 | Name: Snes9X PS3 106 | Latest Version: 4.4.9 107 | Homepage/forum: https://code.google.com/p/snes9x-ps3/ (although for some 108 | reason, you may have to Google for the latest version) 109 | Maintainer: Squarepusher 110 | 111 | HOW TO GET IT RUNNING: 112 | *DISCLAIMER* You will have to do some Googling, including but not limited to: 113 | * Finding a HEN/Jailbreaker/CFW/etc onto your PS3 and installing it 114 | * (if necessary) Downgrading/Upgrading your PS3's firmware 115 | 116 | You’ll have to install a HEN/Jailbreaker/CFW/etc on your PS3 (you might have to 117 | upgrade or downgrade your PS3’s firmware as needed). After that, it should be 118 | as simple as copy the emulator, ROMs, saves, etc over to the PS3 and it should 119 | work :) 120 | 121 | *X-Box Version of Snes9x* 122 | Name: Snes9xbox 123 | Latest Version: V2 (V3 should be out soon) 124 | Homepage/forum: http://forums.xbox-scene.com/index.php?showforum=96 125 | 126 | HOW TO GET IT RUNNING: 127 | *DISCLAIMER* You will need to do some Googling, including but not limited to: 128 | * Finding a softmod (hack) or a modchip and installing/using it 129 | * Finding a replacement dashboard such as XBMC 130 | 131 | Really, it's not hard. Read the readme, and use a softmod or modchip and a 132 | replacement dashboard. After that's installed, it should be as simple as 133 | copying over the emulator, ROMs, saves, etc to the X-Box and it should work. 134 | 135 | Updated most recently by: 2011/11/2 adventure_of_link 136 | -------------------------------------------------------------------------------- /components/snes9x/docs/snapshots.txt: -------------------------------------------------------------------------------- 1 | ***** Important notice ******************************************************** 2 | This document describes the snapshot file format for Snes9x 1.52 and later, 3 | not compatible with 1.51. 4 | ******************************************************************************* 5 | 6 | Snes9x snapshot file format: (may be gzip-compressed) 7 | 8 | Begins with fixed length signature, consisting of a string, ':', a 4-digit 9 | decimal version, and a '\n'. 10 | 11 | #!s9xsnp:0006 <-- '\n' after the 6 12 | 13 | Then we have various blocks. The block format is: 3-character block name, 14 | ':', 6-digit length, ':', then the data. Blocks are written in a defined 15 | order. Structs are written packed with their members in a defined order, in 16 | big-endian order where applicable. 17 | 18 | NAM:000019:Chrono Trigger.zip 19 | 20 | Currently defined blocks (in order) are: 21 | 22 | Essential parts: 23 | NAM - ROM filename, from Memory.ROMFilename. 0-terminated string. 24 | CPU - struct SCPUState, CPU internal state variables. 25 | REG - struct SRegisters, emulated CPU registers. 26 | PPU - struct SPPU, PPU internal variables. Note that IPPU is never saved. 27 | DMA - struct SDMA, DMA/HDMA state variables. 28 | VRA - Memory.VRAM, 0x10000 bytes. 29 | RAM - Memory.RAM, 0x20000 bytes (WRAM). 30 | SRA - Memory.SRAM, 0x20000 bytes. 31 | FIL - Memory.FillRAM, 0x8000 bytes (register backing store). 32 | SND - All of sound emulated registers and state valiables. 33 | CTL - struct SControlSnapshot, controller emulation. 34 | TIM - struct STimings, variables about timings between emulated events. 35 | 36 | Optional parts: 37 | SFX - struct FxRegs_s, Super FX. 38 | SA1 - struct SSA1, SA1 internal state variables. 39 | SAR - struct SSA1Registers, SA1 emulated registers. 40 | DP1 - struct SDSP1, DSP-1. 41 | DP2 - struct SDSP2, DSP-2. 42 | DP4 - struct SDSP4, DSP-4. 43 | CX4 - Memory.C4RAM, 0x2000 bytes. 44 | ST0 - struct SST010, ST-010. 45 | OBC - struct SOBC1, OBC1 internal state variables. 46 | OBM - Memory.OBC1RAM, 0x2000 byts. 47 | S71 - struct SSPC7110Snapshot, SPC7110. 48 | SRT - struct SSRTCSnapshot, S-RTC internal state variables. 49 | CLK - struct SRTCData, S-RTC emulated registers. 50 | BSX - struct SBSX, BS-X. 51 | SHO - rendered SNES screen. 52 | MOV - struct SnapshotMovieInfo. 53 | MID - Some block of data the movie subsystem. 54 | 55 | ================== 56 | 57 | Without changing the snapshot version number: 58 | --------------------------------------------- 59 | 60 | Blocks may be safely added at the END of the file, as anything after the last 61 | block is ignored. Blocks may not be moved or removed. 62 | 63 | Blocks may not decrease in size. Say you decrease from 10 bytes to 5. Then 64 | later you increase back to 8. The only way you could safely do this is if 65 | bytes 5-7 still mean the same thing they meant when the block was 10 bytes 66 | long. 67 | 68 | Blocks may increase in size as you wish, as long as you can handle old 69 | savestates with the old shorter size. 70 | 71 | Struct members may not change in interpretation. New struct members may be 72 | added (at the END!) only if you can cope with them being binary-0 in older 73 | savestates. Struct members may not be removed or changed in size/type. 74 | 75 | With changing the snapshot version number: 76 | ------------------------------------------ 77 | 78 | Blocks may be added, moved, or removed at will. 79 | 80 | Blocks may decrease in size. 81 | 82 | Struct members may be added, moved, or deleted, and their 83 | interpretations/types may be changed. Use the 'debuted_in' and 'deleted_in' 84 | fields to indicate when the new member debuted or the old member went away. 85 | -------------------------------------------------------------------------------- /components/snes9x/dsp.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #include "snes9x.h" 8 | #include "memmap.h" 9 | #ifdef DEBUGGER 10 | #include "missing.h" 11 | #endif 12 | 13 | uint8 (*GetDSP) (uint16) = NULL; 14 | void (*SetDSP) (uint8, uint16) = NULL; 15 | 16 | 17 | void S9xResetDSP (void) 18 | { 19 | memset(&DSP1, 0, sizeof(DSP1)); 20 | DSP1.waiting4command = TRUE; 21 | DSP1.first_parameter = TRUE; 22 | } 23 | 24 | uint8 S9xGetDSP (uint16 address) 25 | { 26 | #ifdef DEBUGGER 27 | if (Settings.TraceDSP) 28 | { 29 | sprintf(String, "DSP read: 0x%04X", address); 30 | S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); 31 | } 32 | #endif 33 | 34 | return ((*GetDSP)(address)); 35 | } 36 | 37 | void S9xSetDSP (uint8 byte, uint16 address) 38 | { 39 | #ifdef DEBUGGER 40 | missing.unknowndsp_write = address; 41 | if (Settings.TraceDSP) 42 | { 43 | sprintf(String, "DSP write: 0x%04X=0x%02X", address, byte); 44 | S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); 45 | } 46 | #endif 47 | 48 | (*SetDSP)(byte, address); 49 | } 50 | -------------------------------------------------------------------------------- /components/snes9x/dsp.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _DSP1_H_ 8 | #define _DSP1_H_ 9 | 10 | enum 11 | { 12 | M_DSP1_LOROM_S, 13 | M_DSP1_LOROM_L, 14 | M_DSP1_HIROM, 15 | M_DSP2_LOROM, 16 | M_DSP3_LOROM, 17 | M_DSP4_LOROM 18 | }; 19 | 20 | struct SDSP0 21 | { 22 | uint32 maptype; 23 | uint32 boundary; 24 | }; 25 | 26 | struct SDSP1 27 | { 28 | bool8 waiting4command; 29 | bool8 first_parameter; 30 | uint8 command; 31 | uint32 in_count; 32 | uint32 in_index; 33 | uint32 out_count; 34 | uint32 out_index; 35 | uint8 parameters[512]; 36 | uint8 output[512]; 37 | 38 | int16 CentreX; 39 | int16 CentreY; 40 | int16 VOffset; 41 | 42 | int16 VPlane_C; 43 | int16 VPlane_E; 44 | 45 | // Azimuth and Zenith angles 46 | int16 SinAas; 47 | int16 CosAas; 48 | int16 SinAzs; 49 | int16 CosAzs; 50 | 51 | // Clipped Zenith angle 52 | int16 SinAZS; 53 | int16 CosAZS; 54 | int16 SecAZS_C1; 55 | int16 SecAZS_E1; 56 | int16 SecAZS_C2; 57 | int16 SecAZS_E2; 58 | 59 | int16 Nx; 60 | int16 Ny; 61 | int16 Nz; 62 | int16 Gx; 63 | int16 Gy; 64 | int16 Gz; 65 | int16 C_Les; 66 | int16 E_Les; 67 | int16 G_Les; 68 | 69 | int16 matrixA[3][3]; 70 | int16 matrixB[3][3]; 71 | int16 matrixC[3][3]; 72 | 73 | int16 Op00Multiplicand; 74 | int16 Op00Multiplier; 75 | int16 Op00Result; 76 | 77 | int16 Op20Multiplicand; 78 | int16 Op20Multiplier; 79 | int16 Op20Result; 80 | 81 | int16 Op10Coefficient; 82 | int16 Op10Exponent; 83 | int16 Op10CoefficientR; 84 | int16 Op10ExponentR; 85 | 86 | int16 Op04Angle; 87 | int16 Op04Radius; 88 | int16 Op04Sin; 89 | int16 Op04Cos; 90 | 91 | int16 Op0CA; 92 | int16 Op0CX1; 93 | int16 Op0CY1; 94 | int16 Op0CX2; 95 | int16 Op0CY2; 96 | 97 | int16 Op02FX; 98 | int16 Op02FY; 99 | int16 Op02FZ; 100 | int16 Op02LFE; 101 | int16 Op02LES; 102 | int16 Op02AAS; 103 | int16 Op02AZS; 104 | int16 Op02VOF; 105 | int16 Op02VVA; 106 | int16 Op02CX; 107 | int16 Op02CY; 108 | 109 | int16 Op0AVS; 110 | int16 Op0AA; 111 | int16 Op0AB; 112 | int16 Op0AC; 113 | int16 Op0AD; 114 | 115 | int16 Op06X; 116 | int16 Op06Y; 117 | int16 Op06Z; 118 | int16 Op06H; 119 | int16 Op06V; 120 | int16 Op06M; 121 | 122 | int16 Op01m; 123 | int16 Op01Zr; 124 | int16 Op01Xr; 125 | int16 Op01Yr; 126 | 127 | int16 Op11m; 128 | int16 Op11Zr; 129 | int16 Op11Xr; 130 | int16 Op11Yr; 131 | 132 | int16 Op21m; 133 | int16 Op21Zr; 134 | int16 Op21Xr; 135 | int16 Op21Yr; 136 | 137 | int16 Op0DX; 138 | int16 Op0DY; 139 | int16 Op0DZ; 140 | int16 Op0DF; 141 | int16 Op0DL; 142 | int16 Op0DU; 143 | 144 | int16 Op1DX; 145 | int16 Op1DY; 146 | int16 Op1DZ; 147 | int16 Op1DF; 148 | int16 Op1DL; 149 | int16 Op1DU; 150 | 151 | int16 Op2DX; 152 | int16 Op2DY; 153 | int16 Op2DZ; 154 | int16 Op2DF; 155 | int16 Op2DL; 156 | int16 Op2DU; 157 | 158 | int16 Op03F; 159 | int16 Op03L; 160 | int16 Op03U; 161 | int16 Op03X; 162 | int16 Op03Y; 163 | int16 Op03Z; 164 | 165 | int16 Op13F; 166 | int16 Op13L; 167 | int16 Op13U; 168 | int16 Op13X; 169 | int16 Op13Y; 170 | int16 Op13Z; 171 | 172 | int16 Op23F; 173 | int16 Op23L; 174 | int16 Op23U; 175 | int16 Op23X; 176 | int16 Op23Y; 177 | int16 Op23Z; 178 | 179 | int16 Op14Zr; 180 | int16 Op14Xr; 181 | int16 Op14Yr; 182 | int16 Op14U; 183 | int16 Op14F; 184 | int16 Op14L; 185 | int16 Op14Zrr; 186 | int16 Op14Xrr; 187 | int16 Op14Yrr; 188 | 189 | int16 Op0EH; 190 | int16 Op0EV; 191 | int16 Op0EX; 192 | int16 Op0EY; 193 | 194 | int16 Op0BX; 195 | int16 Op0BY; 196 | int16 Op0BZ; 197 | int16 Op0BS; 198 | 199 | int16 Op1BX; 200 | int16 Op1BY; 201 | int16 Op1BZ; 202 | int16 Op1BS; 203 | 204 | int16 Op2BX; 205 | int16 Op2BY; 206 | int16 Op2BZ; 207 | int16 Op2BS; 208 | 209 | int16 Op28X; 210 | int16 Op28Y; 211 | int16 Op28Z; 212 | int16 Op28R; 213 | 214 | int16 Op1CX; 215 | int16 Op1CY; 216 | int16 Op1CZ; 217 | int16 Op1CXBR; 218 | int16 Op1CYBR; 219 | int16 Op1CZBR; 220 | int16 Op1CXAR; 221 | int16 Op1CYAR; 222 | int16 Op1CZAR; 223 | int16 Op1CX1; 224 | int16 Op1CY1; 225 | int16 Op1CZ1; 226 | int16 Op1CX2; 227 | int16 Op1CY2; 228 | int16 Op1CZ2; 229 | 230 | uint16 Op0FRamsize; 231 | uint16 Op0FPass; 232 | 233 | int16 Op2FUnknown; 234 | int16 Op2FSize; 235 | 236 | int16 Op08X; 237 | int16 Op08Y; 238 | int16 Op08Z; 239 | int16 Op08Ll; 240 | int16 Op08Lh; 241 | 242 | int16 Op18X; 243 | int16 Op18Y; 244 | int16 Op18Z; 245 | int16 Op18R; 246 | int16 Op18D; 247 | 248 | int16 Op38X; 249 | int16 Op38Y; 250 | int16 Op38Z; 251 | int16 Op38R; 252 | int16 Op38D; 253 | }; 254 | 255 | extern struct SDSP0 DSP0; 256 | extern struct SDSP1 DSP1; 257 | 258 | uint8 S9xGetDSP (uint16); 259 | void S9xSetDSP (uint8, uint16); 260 | void S9xResetDSP (void); 261 | uint8 DSP1GetByte (uint16); 262 | void DSP1SetByte (uint8, uint16); 263 | 264 | extern uint8 (*GetDSP) (uint16); 265 | extern void (*SetDSP) (uint8, uint16); 266 | 267 | #endif 268 | -------------------------------------------------------------------------------- /components/snes9x/gfx.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _GFX_H_ 8 | #define _GFX_H_ 9 | 10 | #include "port.h" 11 | 12 | struct SGFX 13 | { 14 | uint16 *Screen; 15 | uint16 *SubScreen; 16 | uint8 *ZBuffer; 17 | uint8 *SubZBuffer; 18 | uint32 Pitch; 19 | uint32 ScreenSize; 20 | uint16 *S; 21 | uint8 *DB; 22 | uint16 *ZERO; 23 | uint32 RealPPL; // true PPL of Screen buffer 24 | uint32 PPL; // number of pixels on each of Screen buffer 25 | uint32 LinesPerTile; // number of lines in 1 tile (4 or 8 due to interlace) 26 | uint16 *ScreenColors; // screen colors for rendering main 27 | uint16 *RealScreenColors; // screen colors, ignoring color window clipping 28 | uint8 Z1; // depth for comparison 29 | uint8 Z2; // depth to save 30 | uint32 FixedColour; 31 | uint8 DoInterlace; 32 | uint8 InterlaceFrame; 33 | uint32 StartY; 34 | uint32 EndY; 35 | bool8 ClipColors; 36 | uint8 OBJWidths[128]; 37 | uint8 OBJVisibleTiles[128]; 38 | 39 | struct ClipData *Clip; 40 | 41 | struct 42 | { 43 | uint8 RTOFlags; 44 | int16 Tiles; 45 | 46 | struct 47 | { 48 | int8 Sprite; 49 | uint8 Line; 50 | } OBJ[32]; 51 | } OBJLines[SNES_HEIGHT_EXTENDED]; 52 | 53 | void (*DrawBackdropMath) (uint32, uint32, uint32); 54 | void (*DrawBackdropNomath) (uint32, uint32, uint32); 55 | void (*DrawTileMath) (uint32, uint32, uint32, uint32); 56 | void (*DrawTileNomath) (uint32, uint32, uint32, uint32); 57 | void (*DrawClippedTileMath) (uint32, uint32, uint32, uint32, uint32, uint32); 58 | void (*DrawClippedTileNomath) (uint32, uint32, uint32, uint32, uint32, uint32); 59 | void (*DrawMosaicPixelMath) (uint32, uint32, uint32, uint32, uint32, uint32); 60 | void (*DrawMosaicPixelNomath) (uint32, uint32, uint32, uint32, uint32, uint32); 61 | void (*DrawMode7BG1Math) (uint32, uint32, int); 62 | void (*DrawMode7BG1Nomath) (uint32, uint32, int); 63 | void (*DrawMode7BG2Math) (uint32, uint32, int); 64 | void (*DrawMode7BG2Nomath) (uint32, uint32, int); 65 | 66 | const char *InfoString; 67 | uint32 InfoStringTimeout; 68 | char FrameDisplayString[256]; 69 | }; 70 | 71 | struct SBG 72 | { 73 | uint8 (*ConvertTile) (uint8 *, uint32, uint32); 74 | uint8 (*ConvertTileFlip) (uint8 *, uint32, uint32); 75 | 76 | uint32 TileSizeH; 77 | uint32 TileSizeV; 78 | uint32 OffsetSizeH; 79 | uint32 OffsetSizeV; 80 | uint32 TileShift; 81 | uint32 TileAddress; 82 | uint32 NameSelect; 83 | uint32 SCBase; 84 | 85 | uint32 StartPalette; 86 | uint32 PaletteShift; 87 | uint32 PaletteMask; 88 | uint8 EnableMath; 89 | uint8 InterlaceLine; 90 | 91 | uint8 *Buffer; 92 | uint8 *BufferFlip; 93 | uint8 *Buffered; 94 | uint8 *BufferedFlip; 95 | bool8 DirectColourMode; 96 | }; 97 | 98 | struct SLineData 99 | { 100 | struct 101 | { 102 | uint16 VOffset; 103 | uint16 HOffset; 104 | } BG[4]; 105 | }; 106 | 107 | struct SLineMatrixData 108 | { 109 | short MatrixA; 110 | short MatrixB; 111 | short MatrixC; 112 | short MatrixD; 113 | short CentreX; 114 | short CentreY; 115 | short M7HOFS; 116 | short M7VOFS; 117 | }; 118 | 119 | extern uint16 BlackColourMap[256]; 120 | extern uint16 DirectColourMaps[8][256]; 121 | extern uint8 mul_brightness[16][32]; 122 | extern uint8 brightness_cap[64]; 123 | extern struct SBG BG; 124 | extern struct SGFX GFX; 125 | 126 | #define H_FLIP 0x4000 127 | #define V_FLIP 0x8000 128 | #define BLANK_TILE 2 129 | 130 | #define COLOR_ADD1_2(C1, C2) \ 131 | ((((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ 132 | ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ 133 | ((C1) & (C2) & RGB_LOW_BITS_MASK)) | ALPHA_BITS_MASK) 134 | #define COLOR_ADD_BRIGHTNESS1_2 COLOR_ADD1_2 135 | 136 | inline uint16 COLOR_ADD_BRIGHTNESS(uint16 C1, uint16 C2) 137 | { 138 | return ((brightness_cap[ (C1 >> RED_SHIFT_BITS) + (C2 >> RED_SHIFT_BITS) ] << RED_SHIFT_BITS) | 139 | (brightness_cap[((C1 >> GREEN_SHIFT_BITS) & 0x1f) + ((C2 >> GREEN_SHIFT_BITS) & 0x1f)] << GREEN_SHIFT_BITS) | 140 | // Proper 15->16bit color conversion moves the high bit of green into the low bit. 141 | #if GREEN_SHIFT_BITS == 6 142 | ((brightness_cap[((C1 >> 6) & 0x1f) + ((C2 >> 6) & 0x1f)] & 0x10) << 1) | 143 | #endif 144 | (brightness_cap[ (C1 & 0x1f) + (C2 & 0x1f)] )); 145 | } 146 | 147 | inline uint16 COLOR_ADD(uint16 C1, uint16 C2) 148 | { 149 | const int RED_MASK = 0x1F << RED_SHIFT_BITS; 150 | const int GREEN_MASK = 0x1F << GREEN_SHIFT_BITS; 151 | const int BLUE_MASK = 0x1F; 152 | 153 | int rb = C1 & (RED_MASK | BLUE_MASK); 154 | rb += C2 & (RED_MASK | BLUE_MASK); 155 | int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0)); 156 | int g = (C1 & (GREEN_MASK)) + (C2 & (GREEN_MASK)); 157 | int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f; 158 | uint16 retval = (rb & (RED_MASK | BLUE_MASK)) | (g & GREEN_MASK) | rgbsaturate; 159 | #if GREEN_SHIFT_BITS == 6 160 | retval |= (retval & 0x0400) >> 5; 161 | #endif 162 | return retval; 163 | } 164 | 165 | 166 | #define COLOR_SUB1_2(C1, C2) \ 167 | GFX.ZERO[(((C1) | RGB_HI_BITS_MASKx2) - \ 168 | ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] 169 | 170 | inline uint16 COLOR_SUB (uint16 C1, uint16 C2) 171 | { 172 | int rb1 = (C1 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | ((0x20 << 0) | (0x20 << RED_SHIFT_BITS)); 173 | int rb2 = C2 & (THIRD_COLOR_MASK | FIRST_COLOR_MASK); 174 | int rb = rb1 - rb2; 175 | int rbcarry = rb & ((0x20 << RED_SHIFT_BITS) | (0x20 << 0)); 176 | int g = ((C1 & (SECOND_COLOR_MASK)) | (0x20 << GREEN_SHIFT_BITS)) - (C2 & (SECOND_COLOR_MASK)); 177 | int rgbsaturate = (((g & (0x20 << GREEN_SHIFT_BITS)) | rbcarry) >> 5) * 0x1f; 178 | uint16 retval = ((rb & (THIRD_COLOR_MASK | FIRST_COLOR_MASK)) | (g & SECOND_COLOR_MASK)) & rgbsaturate; 179 | #if GREEN_SHIFT_BITS == 6 180 | retval |= (retval & 0x0400) >> 5; 181 | #endif 182 | return retval; 183 | } 184 | 185 | void S9xStartScreenRefresh (void); 186 | void S9xEndScreenRefresh (void); 187 | void S9xBuildDirectColourMaps (void); 188 | void RenderLine (uint8); 189 | void S9xComputeClipWindows (void); 190 | void S9xDisplayChar (uint16 *, uint8); 191 | void S9xGraphicsScreenResize (void); 192 | // called automatically unless Settings.AutoDisplayMessages is false 193 | void S9xDisplayMessages (uint16 *, int, int, int, int); 194 | 195 | // external port interface which must be implemented or initialised for each port 196 | bool8 S9xGraphicsInit (void); 197 | void S9xGraphicsDeinit (void); 198 | bool8 S9xInitUpdate (void); 199 | bool8 S9xDeinitUpdate (int, int); 200 | bool8 S9xContinueUpdate (int, int); 201 | void S9xReRefresh (void); 202 | void S9xSetPalette (void); 203 | void S9xSyncSpeed (void); 204 | 205 | // called instead of S9xDisplayString if set to non-NULL 206 | extern void (*S9xCustomDisplayString) (const char *, int, int, bool, int type); 207 | 208 | #endif 209 | -------------------------------------------------------------------------------- /components/snes9x/globals.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #include "snes9x.h" 8 | #include "memmap.h" 9 | #include "dma.h" 10 | #include "apu.h" 11 | #ifdef NETPLAY_SUPPORT 12 | #include "netplay.h" 13 | #endif 14 | #ifdef DEBUGGER 15 | #include "debug.h" 16 | #include "missing.h" 17 | #endif 18 | 19 | struct SCPUState CPU; 20 | struct SICPU ICPU; 21 | struct SRegisters Registers; 22 | struct SPPU PPU; 23 | struct InternalPPU IPPU; 24 | struct SDMA DMA[8]; 25 | struct STimings Timings; 26 | struct SGFX GFX; 27 | struct SBG BG; 28 | struct SLineData LineData[240]; 29 | struct SLineMatrixData LineMatrixData[240]; 30 | struct SDSP0 DSP0; 31 | struct SDSP1 DSP1; 32 | struct SMulti Multi; 33 | struct SSettings Settings; 34 | struct SSNESGameFixes SNESGameFixes; 35 | #ifdef NETPLAY_SUPPORT 36 | struct SNetPlay NetPlay; 37 | #endif 38 | #ifdef DEBUGGER 39 | struct Missing missing; 40 | #endif 41 | CMemory Memory; 42 | 43 | char String[513]; 44 | uint8 OpenBus = 0; 45 | uint8 *HDMAMemPointers[8]; 46 | uint16 BlackColourMap[256]; 47 | uint16 DirectColourMaps[8][256]; 48 | 49 | SnesModel M1SNES = { 1, 3, 2 }; 50 | SnesModel M2SNES = { 2, 4, 3 }; 51 | SnesModel *Model = &M1SNES; 52 | 53 | uint16 SignExtend[2] = 54 | { 55 | 0x0000, 56 | 0xff00 57 | }; 58 | 59 | int HDMA_ModeByteCounts[8] = 60 | { 61 | 1, 2, 2, 4, 4, 4, 2, 4 62 | }; 63 | 64 | uint8 mul_brightness[16][32] = 65 | { 66 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 68 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 69 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, 70 | { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 71 | 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04 }, 72 | { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 73 | 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06 }, 74 | { 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 75 | 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08 }, 76 | { 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 77 | 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a }, 78 | { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 79 | 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c }, 80 | { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 81 | 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e }, 82 | { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 83 | 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x11 }, 84 | { 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 85 | 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13 }, 86 | { 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09, 0x0a, 87 | 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15 }, 88 | { 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 89 | 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17 }, 90 | { 0x00, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 91 | 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x19 }, 92 | { 0x00, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 93 | 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1b }, 94 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 95 | 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d }, 96 | { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 97 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f } 98 | }; 99 | 100 | uint8 brightness_cap[64]; 101 | 102 | uint8 S9xOpLengthsM0X0[256] = 103 | { 104 | // 0 1 2 3 4 5 6 7 8 9 A B C D E F 105 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 106 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 107 | 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 108 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 109 | 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 110 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 111 | 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 112 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 113 | 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 114 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 115 | 3, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A 116 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B 117 | 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C 118 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D 119 | 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E 120 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F 121 | }; 122 | 123 | uint8 S9xOpLengthsM0X1[256] = 124 | { 125 | // 0 1 2 3 4 5 6 7 8 9 A B C D E F 126 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 127 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 128 | 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 129 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 130 | 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 131 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 132 | 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 133 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 134 | 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 135 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 136 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A 137 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B 138 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C 139 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D 140 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E 141 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F 142 | }; 143 | 144 | uint8 S9xOpLengthsM1X0[256] = 145 | { 146 | // 0 1 2 3 4 5 6 7 8 9 A B C D E F 147 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 148 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 149 | 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 150 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 151 | 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 152 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 153 | 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 154 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 155 | 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 156 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 157 | 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A 158 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B 159 | 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C 160 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D 161 | 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E 162 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F 163 | }; 164 | 165 | uint8 S9xOpLengthsM1X1[256] = 166 | { 167 | // 0 1 2 3 4 5 6 7 8 9 A B C D E F 168 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 169 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 170 | 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 171 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 172 | 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 173 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 174 | 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 175 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 176 | 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 177 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 178 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A 179 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B 180 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C 181 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D 182 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E 183 | 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F 184 | }; 185 | -------------------------------------------------------------------------------- /components/snes9x/language.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _LANGUAGE_H_ 8 | #define _LANGUAGE_H_ 9 | 10 | // Movie Messages 11 | #define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie" 12 | #define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot" 13 | #define MOVIE_INFO_REPLAY "Movie replay" 14 | #define MOVIE_INFO_RECORD "Movie record" 15 | #define MOVIE_INFO_RERECORD "Movie re-record" 16 | #define MOVIE_INFO_REWIND "Movie rewind" 17 | #define MOVIE_INFO_STOP "Movie stop" 18 | #define MOVIE_INFO_END "Movie end" 19 | #define MOVIE_INFO_SNAPSHOT "Movie snapshot" 20 | #define MOVIE_ERR_SNAPSHOT_INCONSISTENT "Snapshot inconsistent with movie" 21 | 22 | // Snapshot Messages 23 | #define SAVE_INFO_SNAPSHOT "Saved" 24 | #define SAVE_INFO_LOAD "Loaded" 25 | #define SAVE_INFO_OOPS "Auto-saving 'oops' snapshot" 26 | #define SAVE_ERR_WRONG_FORMAT "File not in Snes9x snapshot format" 27 | #define SAVE_ERR_WRONG_VERSION "Incompatible snapshot version" 28 | #define SAVE_ERR_ROM_NOT_FOUND "ROM image \"%s\" for snapshot not found" 29 | #define SAVE_ERR_SAVE_NOT_FOUND "Snapshot %s does not exist" 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /components/snes9x/logger.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #include "snes9x.h" 8 | #include "logger.h" 9 | 10 | static int resetno = 0; 11 | static int framecounter = 0; 12 | static FILE *video = NULL; 13 | static FILE *audio = NULL; 14 | 15 | 16 | void S9xResetLogger (void) 17 | { 18 | if (!Settings.DumpStreams) 19 | return; 20 | 21 | char buffer[128]; 22 | 23 | S9xCloseLogger(); 24 | framecounter = 0; 25 | 26 | sprintf(buffer, "videostream%d.dat", resetno); 27 | video = fopen(buffer, "wb"); 28 | if (!video) 29 | { 30 | printf("Opening %s failed. Logging cancelled.\n", buffer); 31 | return; 32 | } 33 | 34 | sprintf(buffer, "audiostream%d.dat", resetno); 35 | audio = fopen(buffer, "wb"); 36 | if (!audio) 37 | { 38 | printf("Opening %s failed. Logging cancelled.\n", buffer); 39 | fclose(video); 40 | return; 41 | } 42 | 43 | resetno++; 44 | } 45 | 46 | void S9xCloseLogger (void) 47 | { 48 | if (video) 49 | { 50 | fclose(video); 51 | video = NULL; 52 | } 53 | 54 | if (audio) 55 | { 56 | fclose(audio); 57 | audio = NULL; 58 | } 59 | } 60 | 61 | void S9xVideoLogger (void *pixels, int width, int height, int depth, int bytes_per_line) 62 | { 63 | 64 | } 65 | 66 | void S9xAudioLogger (void *samples, int length) 67 | { 68 | if (audio) 69 | { 70 | if (!fwrite(samples, 1, length, audio)) 71 | printf ("Error writing audio data.\n"); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /components/snes9x/logger.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _LOGGER_H_ 8 | #define _LOGGER_H_ 9 | 10 | void S9xResetLogger(void); 11 | void S9xCloseLogger(void); 12 | void S9xVideoLogger(void *, int, int, int, int); 13 | void S9xAudioLogger(void *, int); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /components/snes9x/memmap.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _MEMMAP_H_ 8 | #define _MEMMAP_H_ 9 | 10 | #define MEMMAP_BLOCK_SIZE (0x1000) 11 | #define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) 12 | #define MEMMAP_SHIFT (12) 13 | #define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) 14 | 15 | struct CMemory 16 | { 17 | enum 18 | { MAX_ROM_SIZE = 0x200000 }; 19 | 20 | enum file_formats 21 | { FILE_ZIP, FILE_JMA, FILE_DEFAULT }; 22 | 23 | enum 24 | { NOPE, YEAH, BIGFIRST, SMALLFIRST }; 25 | 26 | enum 27 | { MAP_TYPE_I_O, MAP_TYPE_ROM, MAP_TYPE_RAM }; 28 | 29 | enum 30 | { 31 | MAP_CPU, 32 | MAP_PPU, 33 | MAP_LOROM_SRAM, 34 | MAP_LOROM_SRAM_B, 35 | MAP_HIROM_SRAM, 36 | MAP_DSP, 37 | MAP_SA1RAM, 38 | MAP_BWRAM, 39 | MAP_BWRAM_BITMAP, 40 | MAP_BWRAM_BITMAP2, 41 | MAP_SPC7110_ROM, 42 | MAP_SPC7110_DRAM, 43 | MAP_RONLY_SRAM, 44 | MAP_C4, 45 | MAP_OBC_RAM, 46 | MAP_SETA_DSP, 47 | MAP_SETA_RISC, 48 | MAP_BSX, 49 | MAP_NONE, 50 | MAP_LAST 51 | }; 52 | 53 | uint8 NSRTHeader[32]; 54 | int32 HeaderCount; 55 | 56 | uint8 *RAM; 57 | uint8 *RAM1; 58 | uint8 *RAM2; 59 | uint8 *ROM; 60 | uint8 *SRAM; 61 | uint8 *VRAM; 62 | uint8 *FillRAM; 63 | uint8 *BWRAM; 64 | uint8 *C4RAM; 65 | uint8 *OBC1RAM; 66 | uint8 *BSRAM; 67 | uint8 *BIOSROM; 68 | 69 | uint8 *Map[MEMMAP_NUM_BLOCKS]; 70 | uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; 71 | uint8 BlockIsRAM[MEMMAP_NUM_BLOCKS]; 72 | uint8 BlockIsROM[MEMMAP_NUM_BLOCKS]; 73 | uint8 ExtendedFormat; 74 | 75 | char ROMFilename[PATH_MAX + 1]; 76 | char ROMName[ROM_NAME_LEN]; 77 | char RawROMName[ROM_NAME_LEN]; 78 | char ROMId[5]; 79 | int32 CompanyId; 80 | uint8 ROMRegion; 81 | uint8 ROMSpeed; 82 | uint8 ROMType; 83 | uint8 ROMSize; 84 | uint32 ROMChecksum; 85 | uint32 ROMComplementChecksum; 86 | uint32 ROMCRC32; 87 | unsigned char ROMSHA256[32]; 88 | int32 ROMFramesPerSecond; 89 | 90 | bool8 HiROM; 91 | bool8 LoROM; 92 | uint8 SRAMSize; 93 | uint32 SRAMMask; 94 | uint32 CalculatedSize; 95 | uint32 CalculatedChecksum; 96 | 97 | // ports can assign this to perform some custom action upon loading a ROM (such as adjusting controls) 98 | void (*PostRomInitFunc) (void); 99 | 100 | bool8 Init (void); 101 | void Deinit (void); 102 | 103 | int ScoreHiROM (bool8, int32 romoff = 0); 104 | int ScoreLoROM (bool8, int32 romoff = 0); 105 | int First512BytesCountZeroes() const; 106 | uint32 HeaderRemove (uint32, uint8 *); 107 | uint32 FileLoader (uint8 *, const char *, uint32); 108 | uint32 MemLoader (uint8 *, const char*, uint32); 109 | bool8 LoadROMMem (const uint8 *, uint32); 110 | bool8 LoadROM (const char *); 111 | bool8 LoadROMInt (int32); 112 | bool8 LoadMultiCartMem (const uint8 *, uint32, const uint8 *, uint32, const uint8 *, uint32); 113 | bool8 LoadMultiCart (const char *, const char *); 114 | bool8 LoadMultiCartInt (); 115 | bool8 LoadSufamiTurbo (); 116 | bool8 LoadBSCart (); 117 | bool8 LoadGNEXT (); 118 | bool8 LoadSRAM (const char *); 119 | bool8 SaveSRAM (const char *); 120 | void ClearSRAM (bool8 onlyNonSavedSRAM = 0); 121 | bool8 SaveMPAK (const char *); 122 | 123 | char * Safe (const char *); 124 | char * SafeANK (const char *); 125 | void ParseSNESHeader (uint8 *); 126 | void InitROM (void); 127 | 128 | uint32 map_mirror (uint32, uint32); 129 | void map_lorom (uint32, uint32, uint32, uint32, uint32); 130 | void map_hirom (uint32, uint32, uint32, uint32, uint32); 131 | void map_lorom_offset (uint32, uint32, uint32, uint32, uint32, uint32); 132 | void map_hirom_offset (uint32, uint32, uint32, uint32, uint32, uint32); 133 | void map_space (uint32, uint32, uint32, uint32, uint8 *); 134 | void map_index (uint32, uint32, uint32, uint32, int, int); 135 | void map_System (void); 136 | void map_WRAM (void); 137 | void map_LoROMSRAM (void); 138 | void map_HiROMSRAM (void); 139 | void map_DSP (void); 140 | void map_WriteProtectROM (void); 141 | void Map_Initialize (void); 142 | void Map_LoROMMap (void); 143 | void Map_NoMAD1LoROMMap (void); 144 | void Map_JumboLoROMMap (void); 145 | void Map_ROM24MBSLoROMMap (void); 146 | void Map_SRAM512KLoROMMap (void); 147 | void Map_SufamiTurboLoROMMap (void); 148 | void Map_SufamiTurboPseudoLoROMMap (void); 149 | void Map_HiROMMap (void); 150 | void Map_ExtendedHiROMMap (void); 151 | void Map_SPC7110HiROMMap (void); 152 | 153 | uint16 checksum_calc_sum (uint8 *, uint32); 154 | uint16 checksum_mirror_sum (uint8 *, uint32 &, uint32 mask = 0x800000); 155 | void Checksum_Calculate (void); 156 | 157 | bool8 match_na (const char *); 158 | bool8 match_nn (const char *); 159 | bool8 match_nc (const char *); 160 | bool8 match_id (const char *); 161 | void ApplyROMFixes (void); 162 | void CheckForAnyPatch (const char *, bool8, int32 &); 163 | 164 | void MakeRomInfoText (char *); 165 | 166 | const char * MapType (void); 167 | const char * StaticRAMSize (void); 168 | const char * Size (void); 169 | const char * Revision (void); 170 | const char * KartContents (void); 171 | const char * Country (void); 172 | const char * PublishingCompany (void); 173 | }; 174 | 175 | struct SMulti 176 | { 177 | int cartType; 178 | int32 cartSizeA, cartSizeB; 179 | int32 sramSizeA, sramSizeB; 180 | uint32 sramMaskA, sramMaskB; 181 | uint32 cartOffsetA, cartOffsetB; 182 | uint8 *sramA, *sramB; 183 | char fileNameA[PATH_MAX + 1], fileNameB[PATH_MAX + 1]; 184 | }; 185 | 186 | extern CMemory Memory; 187 | extern SMulti Multi; 188 | 189 | void S9xAutoSaveSRAM (void); 190 | bool8 LoadZip(const char *, uint32 *, uint8 *); 191 | 192 | enum s9xwrap_t 193 | { 194 | WRAP_NONE, 195 | WRAP_BANK, 196 | WRAP_PAGE 197 | }; 198 | 199 | enum s9xwriteorder_t 200 | { 201 | WRITE_01, 202 | WRITE_10 203 | }; 204 | 205 | #include "getset.h" 206 | 207 | #endif 208 | -------------------------------------------------------------------------------- /components/snes9x/messages.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _MESSAGES_H_ 8 | #define _MESSAGES_H_ 9 | 10 | // Types of message sent to S9xMessage() 11 | enum 12 | { 13 | S9X_TRACE, 14 | S9X_DEBUG, 15 | S9X_WARNING, 16 | S9X_INFO, 17 | S9X_ERROR, 18 | S9X_FATAL_ERROR 19 | }; 20 | 21 | // Individual message numbers 22 | enum 23 | { 24 | S9X_NO_INFO, 25 | S9X_ROM_INFO, 26 | S9X_HEADERS_INFO, 27 | S9X_CONFIG_INFO, 28 | S9X_ROM_CONFUSING_FORMAT_INFO, 29 | S9X_ROM_INTERLEAVED_INFO, 30 | S9X_SOUND_DEVICE_OPEN_FAILED, 31 | S9X_APU_STOPPED, 32 | S9X_USAGE, 33 | S9X_GAME_GENIE_CODE_ERROR, 34 | S9X_ACTION_REPLY_CODE_ERROR, 35 | S9X_GOLD_FINGER_CODE_ERROR, 36 | S9X_DEBUG_OUTPUT, 37 | S9X_DMA_TRACE, 38 | S9X_HDMA_TRACE, 39 | S9X_WRONG_FORMAT, 40 | S9X_WRONG_VERSION, 41 | S9X_ROM_NOT_FOUND, 42 | S9X_FREEZE_FILE_NOT_FOUND, 43 | S9X_PPU_TRACE, 44 | S9X_TRACE_DSP1, 45 | S9X_FREEZE_ROM_NAME, 46 | S9X_HEADER_WARNING, 47 | S9X_NETPLAY_NOT_SERVER, 48 | S9X_FREEZE_FILE_INFO, 49 | S9X_TURBO_MODE, 50 | S9X_SOUND_NOT_BUILT, 51 | S9X_MOVIE_INFO, 52 | S9X_WRONG_MOVIE_SNAPSHOT, 53 | S9X_NOT_A_MOVIE_SNAPSHOT, 54 | S9X_SNAPSHOT_INCONSISTENT, 55 | S9X_AVI_INFO, 56 | S9X_PRESSED_KEYS_INFO 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /components/snes9x/missing.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifdef DEBUGGER 8 | 9 | #ifndef _MISSING_H_ 10 | #define _MISSING_H_ 11 | 12 | struct MissingHDMA 13 | { 14 | uint8 used; 15 | uint8 bbus_address; 16 | uint8 abus_bank; 17 | uint16 abus_address; 18 | uint8 indirect_address; 19 | uint8 force_table_address_write; 20 | uint8 force_table_address_read; 21 | uint8 line_count_write; 22 | uint8 line_count_read; 23 | }; 24 | 25 | struct Missing 26 | { 27 | struct MissingHDMA hdma[8]; 28 | uint8 emulate6502; 29 | uint8 decimal_mode; 30 | uint8 mv_8bit_index; 31 | uint8 mv_8bit_acc; 32 | uint8 interlace; 33 | uint8 lines_239; 34 | uint8 pseudo_512; 35 | uint8 modes[8]; 36 | uint8 mode7_fx; 37 | uint8 mode7_flip; 38 | uint8 mode7_bgmode; 39 | uint8 direct; 40 | uint8 matrix_multiply; 41 | uint8 oam_read; 42 | uint8 vram_read; 43 | uint8 cgram_read; 44 | uint8 wram_read; 45 | uint8 dma_read; 46 | uint8 vram_inc; 47 | uint8 vram_full_graphic_inc; 48 | uint8 virq; 49 | uint8 hirq; 50 | uint16 virq_pos; 51 | uint16 hirq_pos; 52 | uint8 h_v_latch; 53 | uint8 h_counter_read; 54 | uint8 v_counter_read; 55 | uint8 fast_rom; 56 | uint8 window1[6]; 57 | uint8 window2[6]; 58 | uint8 sprite_priority_rotation; 59 | uint8 subscreen; 60 | uint8 subscreen_add; 61 | uint8 subscreen_sub; 62 | uint8 fixed_colour_add; 63 | uint8 fixed_colour_sub; 64 | uint8 mosaic; 65 | uint8 sprite_double_height; 66 | uint8 dma_channels; 67 | uint8 dma_this_frame; 68 | uint8 oam_address_read; 69 | uint8 bg_offset_read; 70 | uint8 matrix_read; 71 | uint8 hdma_channels; 72 | uint8 hdma_this_frame; 73 | uint16 unknownppu_read; 74 | uint16 unknownppu_write; 75 | uint16 unknowncpu_read; 76 | uint16 unknowncpu_write; 77 | uint16 unknowndsp_read; 78 | uint16 unknowndsp_write; 79 | }; 80 | 81 | extern struct Missing missing; 82 | 83 | #endif 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /components/snes9x/pixform.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _PIXFORM_H_ 8 | #define _PIXFORM_H_ 9 | 10 | /* RGB565 format */ 11 | #define BUILD_PIXEL_RGB565(R, G, B) (((int)(R) << 11) | ((int)(G) << 6) | (((int)(G) & 0x10) << 1) | (int)(B)) 12 | #define BUILD_PIXEL2_RGB565(R, G, B) (((int)(R) << 11) | ((int)(G) << 5) | (int)(B)) 13 | #define DECOMPOSE_PIXEL_RGB565(PIX, R, G, B) \ 14 | { \ 15 | (R) = (PIX) >> 11; \ 16 | (G) = ((PIX) >> 6) & 0x1f; \ 17 | (B) = (PIX)&0x1f; \ 18 | } 19 | #define SPARE_RGB_BIT_MASK_RGB565 (1 << 5) 20 | 21 | #define MAX_RED_RGB565 31 22 | #define MAX_GREEN_RGB565 63 23 | #define MAX_BLUE_RGB565 31 24 | #define RED_SHIFT_BITS_RGB565 11 25 | #define GREEN_SHIFT_BITS_RGB565 6 26 | #define RED_LOW_BIT_MASK_RGB565 0x0800 27 | #define GREEN_LOW_BIT_MASK_RGB565 0x0020 28 | #define BLUE_LOW_BIT_MASK_RGB565 0x0001 29 | #define RED_HI_BIT_MASK_RGB565 0x8000 30 | #define GREEN_HI_BIT_MASK_RGB565 0x0400 31 | #define BLUE_HI_BIT_MASK_RGB565 0x0010 32 | #define FIRST_COLOR_MASK_RGB565 0xF800 33 | #define SECOND_COLOR_MASK_RGB565 0x07E0 34 | #define THIRD_COLOR_MASK_RGB565 0x001F 35 | #define ALPHA_BITS_MASK_RGB565 0x0000 36 | 37 | /* RGB555 format */ 38 | #define BUILD_PIXEL_RGB555(R, G, B) (((int)(R) << 10) | ((int)(G) << 5) | (int)(B)) 39 | #define BUILD_PIXEL2_RGB555(R, G, B) (((int)(R) << 10) | ((int)(G) << 5) | (int)(B)) 40 | #define DECOMPOSE_PIXEL_RGB555(PIX, R, G, B) \ 41 | { \ 42 | (R) = (PIX) >> 10; \ 43 | (G) = ((PIX) >> 5) & 0x1f; \ 44 | (B) = (PIX)&0x1f; \ 45 | } 46 | #define SPARE_RGB_BIT_MASK_RGB555 (1 << 15) 47 | 48 | #define MAX_RED_RGB555 31 49 | #define MAX_GREEN_RGB555 31 50 | #define MAX_BLUE_RGB555 31 51 | #define RED_SHIFT_BITS_RGB555 10 52 | #define GREEN_SHIFT_BITS_RGB555 5 53 | #define RED_LOW_BIT_MASK_RGB555 0x0400 54 | #define GREEN_LOW_BIT_MASK_RGB555 0x0020 55 | #define BLUE_LOW_BIT_MASK_RGB555 0x0001 56 | #define RED_HI_BIT_MASK_RGB555 0x4000 57 | #define GREEN_HI_BIT_MASK_RGB555 0x0200 58 | #define BLUE_HI_BIT_MASK_RGB555 0x0010 59 | #define FIRST_COLOR_MASK_RGB555 0x7C00 60 | #define SECOND_COLOR_MASK_RGB555 0x03E0 61 | #define THIRD_COLOR_MASK_RGB555 0x001F 62 | #define ALPHA_BITS_MASK_RGB555 0x0000 63 | 64 | #define CONCAT(X, Y) X##Y 65 | 66 | // C pre-processor needs a two stage macro define to enable it to concat 67 | // to macro names together to form the name of another macro. 68 | #define BUILD_PIXEL_D(F, R, G, B) CONCAT(BUILD_PIXEL_, F) (R, G, B) 69 | #define BUILD_PIXEL2_D(F, R, G, B) CONCAT(BUILD_PIXEL2_, F) (R, G, B) 70 | #define DECOMPOSE_PIXEL_D(F, PIX, R, G, B) CONCAT(DECOMPOSE_PIXEL_, F) (PIX, R, G, B) 71 | 72 | #define BUILD_PIXEL(R, G, B) BUILD_PIXEL_D(PIXEL_FORMAT, R, G, B) 73 | #define BUILD_PIXEL2(R, G, B) BUILD_PIXEL2_D(PIXEL_FORMAT, R, G, B) 74 | #define DECOMPOSE_PIXEL(PIX, R, G, B) DECOMPOSE_PIXEL_D(PIXEL_FORMAT, PIX, R, G, B) 75 | 76 | #define MAX_RED_D(F) CONCAT(MAX_RED_, F) 77 | #define MAX_GREEN_D(F) CONCAT(MAX_GREEN_, F) 78 | #define MAX_BLUE_D(F) CONCAT(MAX_BLUE_, F) 79 | #define RED_SHIFT_BITS_D(F) CONCAT(RED_SHIFT_BITS_, F) 80 | #define GREEN_SHIFT_BITS_D(F) CONCAT(GREEN_SHIFT_BITS_, F) 81 | #define RED_LOW_BIT_MASK_D(F) CONCAT(RED_LOW_BIT_MASK_, F) 82 | #define GREEN_LOW_BIT_MASK_D(F) CONCAT(GREEN_LOW_BIT_MASK_, F) 83 | #define BLUE_LOW_BIT_MASK_D(F) CONCAT(BLUE_LOW_BIT_MASK_, F) 84 | #define RED_HI_BIT_MASK_D(F) CONCAT(RED_HI_BIT_MASK_, F) 85 | #define GREEN_HI_BIT_MASK_D(F) CONCAT(GREEN_HI_BIT_MASK_, F) 86 | #define BLUE_HI_BIT_MASK_D(F) CONCAT(BLUE_HI_BIT_MASK_, F) 87 | #define FIRST_COLOR_MASK_D(F) CONCAT(FIRST_COLOR_MASK_, F) 88 | #define SECOND_COLOR_MASK_D(F) CONCAT(SECOND_COLOR_MASK_, F) 89 | #define THIRD_COLOR_MASK_D(F) CONCAT(THIRD_COLOR_MASK_, F) 90 | #define ALPHA_BITS_MASK_D(F) CONCAT(ALPHA_BITS_MASK_, F) 91 | 92 | #define MAX_RED MAX_RED_D(PIXEL_FORMAT) 93 | #define MAX_GREEN MAX_GREEN_D(PIXEL_FORMAT) 94 | #define MAX_BLUE MAX_BLUE_D(PIXEL_FORMAT) 95 | #define RED_SHIFT_BITS RED_SHIFT_BITS_D(PIXEL_FORMAT) 96 | #define GREEN_SHIFT_BITS GREEN_SHIFT_BITS_D(PIXEL_FORMAT) 97 | #define RED_LOW_BIT_MASK RED_LOW_BIT_MASK_D(PIXEL_FORMAT) 98 | #define GREEN_LOW_BIT_MASK GREEN_LOW_BIT_MASK_D(PIXEL_FORMAT) 99 | #define BLUE_LOW_BIT_MASK BLUE_LOW_BIT_MASK_D(PIXEL_FORMAT) 100 | #define RED_HI_BIT_MASK RED_HI_BIT_MASK_D(PIXEL_FORMAT) 101 | #define GREEN_HI_BIT_MASK GREEN_HI_BIT_MASK_D(PIXEL_FORMAT) 102 | #define BLUE_HI_BIT_MASK BLUE_HI_BIT_MASK_D(PIXEL_FORMAT) 103 | #define FIRST_COLOR_MASK FIRST_COLOR_MASK_D(PIXEL_FORMAT) 104 | #define SECOND_COLOR_MASK SECOND_COLOR_MASK_D(PIXEL_FORMAT) 105 | #define THIRD_COLOR_MASK THIRD_COLOR_MASK_D(PIXEL_FORMAT) 106 | #define ALPHA_BITS_MASK ALPHA_BITS_MASK_D(PIXEL_FORMAT) 107 | 108 | #define GREEN_HI_BIT ((MAX_GREEN + 1) >> 1) 109 | #define RGB_LOW_BITS_MASK (RED_LOW_BIT_MASK | GREEN_LOW_BIT_MASK | BLUE_LOW_BIT_MASK) 110 | #define RGB_HI_BITS_MASK (RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) 111 | #define RGB_HI_BITS_MASKx2 ((RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) << 1) 112 | #define RGB_REMOVE_LOW_BITS_MASK (~RGB_LOW_BITS_MASK) 113 | #define FIRST_THIRD_COLOR_MASK (FIRST_COLOR_MASK | THIRD_COLOR_MASK) 114 | #define TWO_LOW_BITS_MASK (RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1)) 115 | #define HIGH_BITS_SHIFTED_TWO_MASK (((FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & ~TWO_LOW_BITS_MASK) >> 2) 116 | 117 | #endif // _PIXFORM_H_ 118 | -------------------------------------------------------------------------------- /components/snes9x/port.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _PORT_H_ 8 | #define _PORT_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #ifdef HAVE_STRINGS_H 17 | #include 18 | #endif 19 | #include 20 | 21 | #ifdef __WIN32__ 22 | #define NOMINMAX 1 23 | #include 24 | #endif 25 | 26 | #ifdef __WIN32__ 27 | //#define RIGHTSHIFT_IS_SAR 28 | #define RIGHTSHIFT_int8_IS_SAR 29 | #define RIGHTSHIFT_int16_IS_SAR 30 | #define RIGHTSHIFT_int32_IS_SAR 31 | #ifndef __LIBRETRO__ 32 | #define SNES_JOY_READ_CALLBACKS 33 | #endif //__LIBRETRO__ 34 | #endif 35 | 36 | #ifdef __MACOSX__ 37 | #define PIXEL_FORMAT RGB555 38 | #endif 39 | 40 | #ifndef PIXEL_FORMAT 41 | #define PIXEL_FORMAT RGB565 42 | #endif 43 | 44 | #ifndef snes9x_types_defined 45 | #define snes9x_types_defined 46 | typedef unsigned char bool8; 47 | #ifdef HAVE_STDINT_H 48 | #include 49 | typedef intptr_t pint; 50 | typedef int8_t int8; 51 | typedef uint8_t uint8; 52 | typedef int16_t int16; 53 | typedef uint16_t uint16; 54 | typedef int32_t int32; 55 | typedef uint32_t uint32; 56 | typedef int64_t int64; 57 | typedef uint64_t uint64; 58 | #else // HAVE_STDINT_H 59 | #ifdef __WIN32__ 60 | typedef intptr_t pint; 61 | typedef signed char int8; 62 | typedef unsigned char uint8; 63 | typedef signed short int16; 64 | typedef unsigned short uint16; 65 | typedef signed int int32; 66 | typedef unsigned int uint32; 67 | typedef signed __int64 int64; 68 | typedef unsigned __int64 uint64; 69 | typedef int8 int8_t; 70 | typedef uint8 uint8_t; 71 | typedef int16 int16_t; 72 | typedef uint16 uint16_t; 73 | typedef int32 int32_t; 74 | typedef uint32 uint32_t; 75 | typedef int64 int64_t; 76 | typedef uint64 uint64_t; 77 | typedef int socklen_t; 78 | #else // __WIN32__ 79 | typedef signed char int8; 80 | typedef unsigned char uint8; 81 | typedef signed short int16; 82 | typedef unsigned short uint16; 83 | typedef signed int int32; 84 | typedef unsigned int uint32; 85 | #ifdef __GNUC__ 86 | // long long is not part of ISO C++ 87 | __extension__ 88 | #endif 89 | typedef long long int64; 90 | typedef unsigned long long uint64; 91 | #ifdef PTR_NOT_INT 92 | typedef size_t pint; 93 | #else // __PTR_NOT_INT 94 | typedef size_t pint; 95 | #endif // __PTR_NOT_INT 96 | #endif // __WIN32__ 97 | #endif // HAVE_STDINT_H 98 | #endif // snes9x_types_defined 99 | 100 | #ifndef TRUE 101 | #define TRUE 1 102 | #endif 103 | #ifndef FALSE 104 | #define FALSE 0 105 | #endif 106 | 107 | #define START_EXTERN_C extern "C" { 108 | #define END_EXTERN_C } 109 | 110 | #undef PATH_MAX 111 | #define PATH_MAX 64 112 | 113 | #ifndef __WIN32__ 114 | #ifndef PATH_MAX 115 | #define PATH_MAX 1024 116 | #endif 117 | #define _MAX_DRIVE 1 118 | #define _MAX_DIR PATH_MAX 119 | #define _MAX_FNAME PATH_MAX 120 | #define _MAX_EXT PATH_MAX 121 | #define _MAX_PATH PATH_MAX 122 | #else 123 | #ifndef PATH_MAX 124 | #define PATH_MAX _MAX_PATH 125 | #endif 126 | #endif 127 | 128 | #ifndef __WIN32__ 129 | void _splitpath (const char *, char *, char *, char *, char *); 130 | void _makepath (char *, const char *, const char *, const char *, const char *); 131 | #define S9xDisplayString DisplayStringFromBottom 132 | #else // __WIN32__ 133 | #define snprintf _snprintf 134 | #define strcasecmp stricmp 135 | #define strncasecmp strnicmp 136 | #ifndef __LIBRETRO__ 137 | void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); 138 | #define S9xDisplayString WinDisplayStringFromBottom 139 | void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); 140 | #define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b) 141 | #else // __LIBRETRO__ 142 | #define S9xDisplayString DisplayStringFromBottom 143 | #endif // __LIBRETRO__ 144 | #endif // __WIN32__ 145 | 146 | inline void sstrncpy(char *dst, const char *src, size_t size) 147 | { 148 | strncpy(dst, src, size - 1); 149 | dst[size - 1] = '\0'; 150 | } 151 | 152 | #if defined(__DJGPP) || defined(__WIN32__) 153 | #define SLASH_STR "\\" 154 | #define SLASH_CHAR '\\' 155 | #else 156 | #define SLASH_STR "/" 157 | #define SLASH_CHAR '/' 158 | #endif 159 | 160 | #ifndef SIG_PF 161 | #define SIG_PF void (*) (int) 162 | #endif 163 | 164 | #ifdef __linux 165 | #define TITLE "Snes9x: Linux" 166 | #define SYS_CONFIG_FILE "/etc/snes9x/snes9x.conf" 167 | #endif 168 | 169 | #ifndef TITLE 170 | #define TITLE "Snes9x" 171 | #endif 172 | 173 | //#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) || defined(_XBOX1) || defined(__arm__) || defined(ANDROID) || defined(__aarch64__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN__) 174 | //#define LSB_FIRST 175 | //#define FAST_LSB_WORD_ACCESS 176 | //#else 177 | //#define MSB_FIRST 178 | //#endif 179 | 180 | //ESP32: 181 | #define FAST_LSB_WORD_ACCESS // comment this if it interferes with esp-idf SPI driver 182 | #define LSB_FIRST 183 | 184 | #ifdef FAST_LSB_WORD_ACCESS 185 | #define READ_WORD(s) (*(uint16 *) (s)) 186 | #define READ_3WORD(s) (*(uint32 *) (s) & 0x00ffffff) 187 | #define READ_DWORD(s) (*(uint32 *) (s)) 188 | #define WRITE_WORD(s, d) *(uint16 *) (s) = (d) 189 | #define WRITE_3WORD(s, d) *(uint16 *) (s) = (uint16) (d), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) 190 | #define WRITE_DWORD(s, d) *(uint32 *) (s) = (d) 191 | #else 192 | #define READ_WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8)) 193 | #define READ_3WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16)) 194 | #define READ_DWORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16) | (*((uint8 *) (s) + 3) << 24)) 195 | #define WRITE_WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8) 196 | #define WRITE_3WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) 197 | #define WRITE_DWORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16), *((uint8 *) (s) + 3) = (uint8) ((d) >> 24) 198 | #endif 199 | 200 | #define SWAP_WORD(s) (s) = (((s) & 0xff) << 8) | (((s) & 0xff00) >> 8) 201 | #define SWAP_DWORD(s) (s) = (((s) & 0xff) << 24) | (((s) & 0xff00) << 8) | (((s) & 0xff0000) >> 8) | (((s) & 0xff000000) >> 24) 202 | 203 | #include "pixform.h" 204 | 205 | #endif 206 | -------------------------------------------------------------------------------- /components/snes9x/snes9x.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _SNES9X_H_ 8 | #define _SNES9X_H_ 9 | 10 | #ifndef VERSION 11 | #define VERSION "1.60" 12 | #endif 13 | 14 | #include "port.h" 15 | #include "65c816.h" 16 | #include "messages.h" 17 | #define DNOSOUND 18 | #define FSTREAM FILE * 19 | #define READ_FSTREAM(p, l, s) fread(p, 1, l, s) 20 | #define WRITE_FSTREAM(p, l, s) fwrite(p, 1, l, s) 21 | #define GETS_FSTREAM(p, l, s) fgets(p, l, s) 22 | #define GETC_FSTREAM(s) fgetc(s) 23 | #define OPEN_FSTREAM(f, m) fopen(f, m) 24 | #define REOPEN_FSTREAM(f, m) fdopen(f, m) 25 | #define FIND_FSTREAM(s) ftell(s) 26 | #define REVERT_FSTREAM(s, o, p) fseek(s, o, p) 27 | #define CLOSE_FSTREAM(s) fclose(s) 28 | 29 | #include "stream.h" 30 | 31 | #define STREAM Stream * 32 | #define READ_STREAM(p, l, s) s->read(p,l) 33 | #define WRITE_STREAM(p, l, s) s->write(p,l) 34 | #define GETS_STREAM(p, l, s) s->gets(p,l) 35 | #define GETC_STREAM(s) s->get_char() 36 | #define OPEN_STREAM(f, m) openStreamFromFSTREAM(f, m) 37 | #define REOPEN_STREAM(f, m) reopenStreamFromFd(f, m) 38 | #define FIND_STREAM(s) s->pos() 39 | #define REVERT_STREAM(s, o, p) s->revert(p, o) 40 | #define CLOSE_STREAM(s) s->closeStream() 41 | 42 | #define SNES_WIDTH 256 43 | #define SNES_HEIGHT 224 44 | #define SNES_HEIGHT_EXTENDED 239 45 | #define MAX_SNES_WIDTH (SNES_WIDTH * 2) 46 | #define MAX_SNES_HEIGHT (SNES_HEIGHT_EXTENDED * 2) 47 | #define IMAGE_WIDTH (Settings.SupportHiRes ? MAX_SNES_WIDTH : SNES_WIDTH) 48 | #define IMAGE_HEIGHT (Settings.SupportHiRes ? MAX_SNES_HEIGHT : SNES_HEIGHT_EXTENDED) 49 | 50 | #define NTSC_MASTER_CLOCK 21477272.727272 // 21477272 + 8/11 exact 51 | #define PAL_MASTER_CLOCK 21281370.0 52 | 53 | #define SNES_MAX_NTSC_VCOUNTER 262 54 | #define SNES_MAX_PAL_VCOUNTER 312 55 | #define SNES_HCOUNTER_MAX 341 56 | 57 | #ifndef ALLOW_CPU_OVERCLOCK 58 | #define ONE_CYCLE 6 59 | #define SLOW_ONE_CYCLE 8 60 | #define TWO_CYCLES 12 61 | #else 62 | #define ONE_CYCLE (Settings.OneClockCycle) 63 | #define SLOW_ONE_CYCLE (Settings.OneSlowClockCycle) 64 | #define TWO_CYCLES (Settings.TwoClockCycles) 65 | #endif 66 | #define ONE_DOT_CYCLE 4 67 | 68 | #define SNES_CYCLES_PER_SCANLINE (SNES_HCOUNTER_MAX * ONE_DOT_CYCLE) 69 | #define SNES_SCANLINE_TIME (SNES_CYCLES_PER_SCANLINE / NTSC_MASTER_CLOCK) 70 | 71 | #define SNES_WRAM_REFRESH_HC_v1 530 72 | #define SNES_WRAM_REFRESH_HC_v2 538 73 | #define SNES_WRAM_REFRESH_CYCLES 40 74 | 75 | #define SNES_HBLANK_START_HC 1096 // H=274 76 | #define SNES_HDMA_START_HC 1106 // FIXME: not true 77 | #define SNES_HBLANK_END_HC 4 // H=1 78 | #define SNES_HDMA_INIT_HC 20 // FIXME: not true 79 | #define SNES_RENDER_START_HC (128 * ONE_DOT_CYCLE) // FIXME: Snes9x renders a line at a time. 80 | 81 | #define SNES_TR_MASK (1 << 4) 82 | #define SNES_TL_MASK (1 << 5) 83 | #define SNES_X_MASK (1 << 6) 84 | #define SNES_A_MASK (1 << 7) 85 | #define SNES_RIGHT_MASK (1 << 8) 86 | #define SNES_LEFT_MASK (1 << 9) 87 | #define SNES_DOWN_MASK (1 << 10) 88 | #define SNES_UP_MASK (1 << 11) 89 | #define SNES_START_MASK (1 << 12) 90 | #define SNES_SELECT_MASK (1 << 13) 91 | #define SNES_Y_MASK (1 << 14) 92 | #define SNES_B_MASK (1 << 15) 93 | 94 | #define DEBUG_MODE_FLAG (1 << 0) // debugger 95 | #define TRACE_FLAG (1 << 1) // debugger 96 | #define SINGLE_STEP_FLAG (1 << 2) // debugger 97 | #define BREAK_FLAG (1 << 3) // debugger 98 | #define SCAN_KEYS_FLAG (1 << 4) // CPU 99 | #define HALTED_FLAG (1 << 12) // APU 100 | #define FRAME_ADVANCE_FLAG (1 << 9) 101 | 102 | #define ROM_NAME_LEN 23 103 | #define AUTO_FRAMERATE 200 104 | 105 | struct SCPUState 106 | { 107 | uint32 Flags; 108 | int32 Cycles; 109 | int32 PrevCycles; 110 | int32 V_Counter; 111 | uint8 *PCBase; 112 | bool8 NMIPending; 113 | bool8 IRQLine; 114 | bool8 IRQTransition; 115 | bool8 IRQLastState; 116 | bool8 IRQExternal; 117 | int32 IRQPending; 118 | int32 MemSpeed; 119 | int32 MemSpeedx2; 120 | int32 FastROMSpeed; 121 | bool8 InDMA; 122 | bool8 InHDMA; 123 | bool8 InDMAorHDMA; 124 | bool8 InWRAMDMAorHDMA; 125 | uint8 HDMARanInDMA; 126 | int32 CurrentDMAorHDMAChannel; 127 | uint8 WhichEvent; 128 | int32 NextEvent; 129 | bool8 WaitingForInterrupt; 130 | uint32 AutoSaveTimer; 131 | bool8 SRAMModified; 132 | }; 133 | 134 | enum 135 | { 136 | HC_HBLANK_START_EVENT = 1, 137 | HC_HDMA_START_EVENT = 2, 138 | HC_HCOUNTER_MAX_EVENT = 3, 139 | HC_HDMA_INIT_EVENT = 4, 140 | HC_RENDER_EVENT = 5, 141 | HC_WRAM_REFRESH_EVENT = 6 142 | }; 143 | 144 | enum 145 | { 146 | IRQ_NONE = 0x0, 147 | IRQ_SET_FLAG = 0x1, 148 | IRQ_CLEAR_FLAG = 0x2, 149 | IRQ_TRIGGER_NMI = 0x4 150 | }; 151 | 152 | struct STimings 153 | { 154 | int32 H_Max_Master; 155 | int32 H_Max; 156 | int32 V_Max_Master; 157 | int32 V_Max; 158 | int32 HBlankStart; 159 | int32 HBlankEnd; 160 | int32 HDMAInit; 161 | int32 HDMAStart; 162 | int32 NMITriggerPos; 163 | int32 NextIRQTimer; 164 | int32 IRQTriggerCycles; 165 | int32 WRAMRefreshPos; 166 | int32 RenderPos; 167 | bool8 InterlaceField; 168 | int32 DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly. 169 | int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly. 170 | int32 IRQFlagChanging; // This value is just a hack. 171 | int32 APUSpeedup; 172 | bool8 APUAllowTimeOverflow; 173 | }; 174 | 175 | struct SSettings 176 | { 177 | bool8 TraceDMA; 178 | bool8 TraceHDMA; 179 | bool8 TraceVRAM; 180 | bool8 TraceUnknownRegisters; 181 | bool8 TraceDSP; 182 | bool8 TraceHCEvent; 183 | bool8 TraceSMP; 184 | 185 | bool8 SuperFX; 186 | uint8 DSP; 187 | bool8 SA1; 188 | bool8 C4; 189 | bool8 SDD1; 190 | bool8 SPC7110; 191 | bool8 SPC7110RTC; 192 | bool8 OBC1; 193 | uint8 SETA; 194 | bool8 BS; 195 | bool8 BSXItself; 196 | bool8 BSXBootup; 197 | bool8 MSU1; 198 | bool8 MouseMaster; 199 | bool8 SuperScopeMaster; 200 | bool8 JustifierMaster; 201 | bool8 MultiPlayer5Master; 202 | bool8 MacsRifleMaster; 203 | 204 | bool8 ForceLoROM; 205 | bool8 ForceHiROM; 206 | bool8 ForceHeader; 207 | bool8 ForceNoHeader; 208 | bool8 ForceInterleaved; 209 | bool8 ForceInterleaved2; 210 | bool8 ForceInterleaveGD24; 211 | bool8 ForceNotInterleaved; 212 | bool8 ForcePAL; 213 | bool8 ForceNTSC; 214 | bool8 PAL; 215 | uint32 FrameTimePAL; 216 | uint32 FrameTimeNTSC; 217 | uint32 FrameTime; 218 | 219 | bool8 SoundSync; 220 | bool8 SixteenBitSound; 221 | uint32 SoundPlaybackRate; 222 | uint32 SoundInputRate; 223 | bool8 Stereo; 224 | bool8 ReverseStereo; 225 | bool8 Mute; 226 | bool8 DynamicRateControl; 227 | int32 DynamicRateLimit; /* Multiplied by 1000 */ 228 | int32 InterpolationMethod; 229 | 230 | bool8 SupportHiRes; 231 | bool8 Transparency; 232 | uint8 BG_Forced; 233 | bool8 DisableGraphicWindows; 234 | 235 | bool8 DisplayTime; 236 | bool8 DisplayFrameRate; 237 | bool8 DisplayWatchedAddresses; 238 | bool8 DisplayPressedKeys; 239 | bool8 DisplayMovieFrame; 240 | bool8 AutoDisplayMessages; 241 | uint32 InitialInfoStringTimeout; 242 | uint16 DisplayColor; 243 | bool8 BilinearFilter; 244 | 245 | bool8 Multi; 246 | char CartAName[PATH_MAX + 1]; 247 | char CartBName[PATH_MAX + 1]; 248 | 249 | bool8 DisableGameSpecificHacks; 250 | bool8 BlockInvalidVRAMAccessMaster; 251 | bool8 BlockInvalidVRAMAccess; 252 | int32 HDMATimingHack; 253 | 254 | bool8 ForcedPause; 255 | bool8 Paused; 256 | bool8 StopEmulation; 257 | 258 | uint32 SkipFrames; 259 | uint32 TurboSkipFrames; 260 | uint32 AutoMaxSkipFrames; 261 | bool8 TurboMode; 262 | uint32 HighSpeedSeek; 263 | bool8 FrameAdvance; 264 | bool8 Rewinding; 265 | 266 | bool8 NetPlay; 267 | bool8 NetPlayServer; 268 | char ServerName[128]; 269 | int Port; 270 | 271 | bool8 MovieTruncate; 272 | bool8 MovieNotifyIgnored; 273 | bool8 WrongMovieStateProtection; 274 | bool8 DumpStreams; 275 | int DumpStreamsMaxFrames; 276 | 277 | bool8 TakeScreenshot; 278 | int8 StretchScreenshots; 279 | bool8 SnapshotScreenshots; 280 | char InitialSnapshotFilename[PATH_MAX + 1]; 281 | bool8 FastSavestates; 282 | 283 | bool8 ApplyCheats; 284 | bool8 NoPatch; 285 | bool8 IgnorePatchChecksum; 286 | bool8 IsPatched; 287 | int32 AutoSaveDelay; 288 | bool8 DontSaveOopsSnapshot; 289 | bool8 UpAndDown; 290 | 291 | bool8 OpenGLEnable; 292 | 293 | bool8 SeparateEchoBuffer; 294 | uint32 SuperFXClockMultiplier; 295 | int OverclockMode; 296 | int OneClockCycle; 297 | int OneSlowClockCycle; 298 | int TwoClockCycles; 299 | int MaxSpriteTilesPerLine; 300 | }; 301 | 302 | struct SSNESGameFixes 303 | { 304 | uint8 SRAMInitialValue; 305 | uint8 Uniracers; 306 | }; 307 | 308 | enum 309 | { 310 | PAUSE_NETPLAY_CONNECT = (1 << 0), 311 | PAUSE_TOGGLE_FULL_SCREEN = (1 << 1), 312 | PAUSE_EXIT = (1 << 2), 313 | PAUSE_MENU = (1 << 3), 314 | PAUSE_INACTIVE_WINDOW = (1 << 4), 315 | PAUSE_WINDOW_ICONISED = (1 << 5), 316 | PAUSE_RESTORE_GUI = (1 << 6), 317 | PAUSE_FREEZE_FILE = (1 << 7) 318 | }; 319 | 320 | void S9xSetPause(uint32); 321 | void S9xClearPause(uint32); 322 | void S9xExit(void); 323 | void S9xMessage(int, int, const char *); 324 | 325 | extern struct SSettings Settings; 326 | extern struct SCPUState CPU; 327 | extern struct STimings Timings; 328 | extern struct SSNESGameFixes SNESGameFixes; 329 | extern char String[513]; 330 | 331 | extern "C" { 332 | #include "esp_timer.h" 333 | } 334 | 335 | void time_trace(const char *file, int line); 336 | 337 | #define TIME_TRACE time_trace(__FILE__, __LINE__); 338 | #endif 339 | 340 | -------------------------------------------------------------------------------- /components/snes9x/stream.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | // Abstract the details of reading from zip files versus FILE *'s. 8 | 9 | #include 10 | #ifdef UNZIP_SUPPORT 11 | # ifdef SYSTEM_ZIP 12 | # include 13 | # else 14 | # include "unzip.h" 15 | # endif 16 | #endif 17 | #include "snes9x.h" 18 | #include "stream.h" 19 | 20 | 21 | // Generic constructor/destructor 22 | 23 | Stream::Stream (void) 24 | { 25 | return; 26 | } 27 | 28 | Stream::~Stream (void) 29 | { 30 | return; 31 | } 32 | 33 | // Generic getline function, based on gets. Reimlpement if you can do better. 34 | 35 | char * Stream::getline (void) 36 | { 37 | bool eof; 38 | std::string ret; 39 | 40 | ret = getline(eof); 41 | if (ret.size() == 0 && eof) 42 | return (NULL); 43 | 44 | return (strdup(ret.c_str())); 45 | } 46 | 47 | std::string Stream::getline (bool &eof) 48 | { 49 | char buf[1024]; 50 | std::string ret; 51 | 52 | eof = false; 53 | ret.clear(); 54 | 55 | do 56 | { 57 | if (gets(buf, sizeof(buf)) == NULL) 58 | { 59 | eof = true; 60 | break; 61 | } 62 | 63 | ret.append(buf); 64 | } 65 | while (*ret.rbegin() != '\n'); 66 | 67 | return (ret); 68 | } 69 | 70 | size_t Stream::pos_from_origin_offset(uint8 origin, int32 offset) 71 | { 72 | size_t position = 0; 73 | switch (origin) 74 | { 75 | case SEEK_SET: 76 | position = offset; 77 | break; 78 | case SEEK_END: 79 | position = size() + offset; 80 | break; 81 | case SEEK_CUR: 82 | position = pos() + offset; 83 | break; 84 | } 85 | return position; 86 | } 87 | 88 | // snes9x.h FSTREAM Stream 89 | 90 | fStream::fStream (FSTREAM f) 91 | { 92 | fp = f; 93 | } 94 | 95 | fStream::~fStream (void) 96 | { 97 | return; 98 | } 99 | 100 | int fStream::get_char (void) 101 | { 102 | return (GETC_FSTREAM(fp)); 103 | } 104 | 105 | char * fStream::gets (char *buf, size_t len) 106 | { 107 | return (GETS_FSTREAM(buf, len, fp)); 108 | } 109 | 110 | size_t fStream::read (void *buf, size_t len) 111 | { 112 | return (READ_FSTREAM(buf, len, fp)); 113 | } 114 | 115 | size_t fStream::write (void *buf, size_t len) 116 | { 117 | return (WRITE_FSTREAM(buf, len, fp)); 118 | } 119 | 120 | size_t fStream::pos (void) 121 | { 122 | return (FIND_FSTREAM(fp)); 123 | } 124 | 125 | size_t fStream::size (void) 126 | { 127 | size_t sz; 128 | REVERT_FSTREAM(fp,0L,SEEK_END); 129 | sz = FIND_FSTREAM(fp); 130 | REVERT_FSTREAM(fp,0L,SEEK_SET); 131 | return sz; 132 | } 133 | 134 | int fStream::revert (uint8 origin, int32 offset) 135 | { 136 | return (REVERT_FSTREAM(fp, offset, origin)); 137 | } 138 | 139 | void fStream::closeStream() 140 | { 141 | CLOSE_FSTREAM(fp); 142 | delete this; 143 | } 144 | 145 | // unzip Stream 146 | 147 | #ifdef UNZIP_SUPPORT 148 | 149 | unzStream::unzStream (unzFile &v) 150 | { 151 | file = v; 152 | pos_in_buf = 0; 153 | buf_pos_in_unzipped = unztell(file); 154 | bytes_in_buf = 0; 155 | 156 | // remember start pos for seeks 157 | unzGetFilePos(file, &unz_file_start_pos); 158 | } 159 | 160 | unzStream::~unzStream (void) 161 | { 162 | return; 163 | } 164 | 165 | size_t unzStream::buffer_remaining() 166 | { 167 | return bytes_in_buf - pos_in_buf; 168 | } 169 | 170 | void unzStream::fill_buffer() 171 | { 172 | buf_pos_in_unzipped = unztell(file); 173 | bytes_in_buf = unzReadCurrentFile(file, buffer, unz_BUFFSIZ); 174 | pos_in_buf = 0; 175 | } 176 | 177 | int unzStream::get_char (void) 178 | { 179 | unsigned char c; 180 | 181 | if (buffer_remaining() <= 0) 182 | { 183 | fill_buffer(); 184 | if (bytes_in_buf <= 0) 185 | return (EOF); 186 | } 187 | 188 | c = *(buffer + pos_in_buf); 189 | pos_in_buf++; 190 | 191 | return ((int) c); 192 | } 193 | 194 | char * unzStream::gets (char *buf, size_t len) 195 | { 196 | size_t i; 197 | int c; 198 | 199 | for (i = 0; i < len - 1; i++) 200 | { 201 | c = get_char(); 202 | if (c == EOF) 203 | { 204 | if (i == 0) 205 | return (NULL); 206 | break; 207 | } 208 | 209 | buf[i] = (char) c; 210 | if (buf[i] == '\n') 211 | break; 212 | } 213 | 214 | buf[i] = '\0'; 215 | 216 | return (buf); 217 | } 218 | 219 | size_t unzStream::read (void *buf, size_t len) 220 | { 221 | if (len == 0) 222 | return (len); 223 | 224 | size_t to_read = len; 225 | uint8 *read_to = (uint8 * )buf; 226 | do 227 | { 228 | size_t in_buffer = buffer_remaining(); 229 | if (to_read <= in_buffer) 230 | { 231 | memcpy(read_to, buffer + pos_in_buf, to_read); 232 | pos_in_buf += to_read; 233 | to_read = 0; 234 | break; 235 | } 236 | 237 | memcpy(read_to, buffer + pos_in_buf, in_buffer); 238 | to_read -= in_buffer; 239 | fill_buffer(); 240 | } while (bytes_in_buf); 241 | 242 | return (len - to_read); 243 | } 244 | 245 | // not supported 246 | size_t unzStream::write (void *buf, size_t len) 247 | { 248 | return (0); 249 | } 250 | 251 | size_t unzStream::pos (void) 252 | { 253 | return buf_pos_in_unzipped + pos_in_buf; 254 | } 255 | 256 | size_t unzStream::size (void) 257 | { 258 | unz_file_info info; 259 | unzGetCurrentFileInfo(file,&info,NULL,0,NULL,0,NULL,0); 260 | return info.uncompressed_size; 261 | } 262 | 263 | int unzStream::revert (uint8 origin, int32 offset) 264 | { 265 | size_t target_pos = pos_from_origin_offset(origin, offset); 266 | 267 | // new pos inside buffered data 268 | if (target_pos >= buf_pos_in_unzipped && target_pos < buf_pos_in_unzipped + bytes_in_buf) 269 | { 270 | pos_in_buf = target_pos - buf_pos_in_unzipped; 271 | } 272 | else // outside of buffer, reset file and read until pos 273 | { 274 | unzGoToFilePos(file, &unz_file_start_pos); 275 | unzOpenCurrentFile(file); // necessary to reopen after seek 276 | int times_to_read = target_pos / unz_BUFFSIZ + 1; 277 | for( int i = 0; i < times_to_read; i++) 278 | { 279 | fill_buffer(); 280 | } 281 | pos_in_buf = target_pos % unz_BUFFSIZ; 282 | } 283 | return 0; 284 | } 285 | 286 | void unzStream::closeStream() 287 | { 288 | unzClose(file); 289 | delete this; 290 | } 291 | 292 | #endif 293 | 294 | // memory Stream 295 | 296 | memStream::memStream (uint8 *source, size_t sourceSize) 297 | { 298 | mem = head = source; 299 | msize = remaining = sourceSize; 300 | readonly = false; 301 | } 302 | 303 | memStream::memStream (const uint8 *source, size_t sourceSize) 304 | { 305 | mem = head = const_cast(source); 306 | msize = remaining = sourceSize; 307 | readonly = true; 308 | } 309 | 310 | memStream::~memStream (void) 311 | { 312 | return; 313 | } 314 | 315 | int memStream::get_char (void) 316 | { 317 | if(!remaining) 318 | return EOF; 319 | 320 | remaining--; 321 | return *head++; 322 | } 323 | 324 | char * memStream::gets (char *buf, size_t len) 325 | { 326 | size_t i; 327 | int c; 328 | 329 | for (i = 0; i < len - 1; i++) 330 | { 331 | c = get_char(); 332 | if (c == EOF) 333 | { 334 | if (i == 0) 335 | return (NULL); 336 | break; 337 | } 338 | 339 | buf[i] = (char) c; 340 | if (buf[i] == '\n') 341 | break; 342 | } 343 | 344 | buf[i] = '\0'; 345 | 346 | return (buf); 347 | } 348 | 349 | size_t memStream::read (void *buf, size_t len) 350 | { 351 | size_t bytes = len < remaining ? len : remaining; 352 | memcpy(buf,head,bytes); 353 | head += bytes; 354 | remaining -= bytes; 355 | 356 | return bytes; 357 | } 358 | 359 | size_t memStream::write (void *buf, size_t len) 360 | { 361 | if(readonly) 362 | return 0; 363 | 364 | size_t bytes = len < remaining ? len : remaining; 365 | memcpy(head,buf,bytes); 366 | head += bytes; 367 | remaining -= bytes; 368 | 369 | return bytes; 370 | } 371 | 372 | size_t memStream::pos (void) 373 | { 374 | return msize - remaining; 375 | } 376 | 377 | size_t memStream::size (void) 378 | { 379 | return msize; 380 | } 381 | 382 | int memStream::revert (uint8 origin, int32 offset) 383 | { 384 | size_t pos = pos_from_origin_offset(origin, offset); 385 | 386 | if(pos > msize) 387 | return -1; 388 | 389 | head = mem + pos; 390 | remaining = msize - pos; 391 | 392 | return 0; 393 | } 394 | 395 | void memStream::closeStream() 396 | { 397 | delete [] mem; 398 | delete this; 399 | } 400 | 401 | // dummy Stream 402 | 403 | nulStream::nulStream (void) 404 | { 405 | bytes_written = 0; 406 | } 407 | 408 | nulStream::~nulStream (void) 409 | { 410 | return; 411 | } 412 | 413 | int nulStream::get_char (void) 414 | { 415 | return 0; 416 | } 417 | 418 | char * nulStream::gets (char *buf, size_t len) 419 | { 420 | *buf = '\0'; 421 | return NULL; 422 | } 423 | 424 | size_t nulStream::read (void *buf, size_t len) 425 | { 426 | return 0; 427 | } 428 | 429 | size_t nulStream::write (void *buf, size_t len) 430 | { 431 | bytes_written += len; 432 | return len; 433 | } 434 | 435 | size_t nulStream::pos (void) 436 | { 437 | return 0; 438 | } 439 | 440 | size_t nulStream::size (void) 441 | { 442 | return bytes_written; 443 | } 444 | 445 | int nulStream::revert (uint8 origin, int32 offset) 446 | { 447 | size_t target_pos = pos_from_origin_offset(origin, offset); 448 | bytes_written = target_pos; 449 | return 0; 450 | } 451 | 452 | void nulStream::closeStream() 453 | { 454 | delete this; 455 | } 456 | 457 | Stream *openStreamFromFSTREAM(const char* filename, const char* mode) 458 | { 459 | FSTREAM f = OPEN_FSTREAM(filename,mode); 460 | if(!f) 461 | return NULL; 462 | return new fStream(f); 463 | } 464 | 465 | Stream *reopenStreamFromFd(int fd, const char* mode) 466 | { 467 | FSTREAM f = REOPEN_FSTREAM(fd,mode); 468 | if(!f) 469 | return NULL; 470 | return new fStream(f); 471 | } 472 | -------------------------------------------------------------------------------- /components/snes9x/stream.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _STREAM_H_ 8 | #define _STREAM_H_ 9 | 10 | #include 11 | 12 | class Stream 13 | { 14 | public: 15 | Stream (void); 16 | virtual ~Stream (void); 17 | virtual int get_char (void) = 0; 18 | virtual char * gets (char *, size_t) = 0; 19 | virtual char * getline (void); // free() when done 20 | virtual std::string getline (bool &); 21 | virtual size_t read (void *, size_t) = 0; 22 | virtual size_t write (void *, size_t) = 0; 23 | virtual size_t pos (void) = 0; 24 | virtual size_t size (void) = 0; 25 | virtual int revert (uint8 origin, int32 offset) = 0; 26 | virtual void closeStream() = 0; 27 | 28 | protected: 29 | size_t pos_from_origin_offset(uint8 origin, int32 offset); 30 | }; 31 | 32 | class fStream : public Stream 33 | { 34 | public: 35 | fStream (FSTREAM); 36 | virtual ~fStream (void); 37 | virtual int get_char (void); 38 | virtual char * gets (char *, size_t); 39 | virtual size_t read (void *, size_t); 40 | virtual size_t write (void *, size_t); 41 | virtual size_t pos (void); 42 | virtual size_t size (void); 43 | virtual int revert (uint8 origin, int32 offset); 44 | virtual void closeStream(); 45 | 46 | private: 47 | FSTREAM fp; 48 | }; 49 | 50 | #ifdef UNZIP_SUPPORT 51 | # ifdef SYSTEM_ZIP 52 | # include 53 | # else 54 | # include "unzip.h" 55 | # endif 56 | 57 | #define unz_BUFFSIZ 1024 58 | 59 | class unzStream : public Stream 60 | { 61 | public: 62 | unzStream (unzFile &); 63 | virtual ~unzStream (void); 64 | virtual int get_char (void); 65 | virtual char * gets (char *, size_t); 66 | virtual size_t read (void *, size_t); 67 | virtual size_t write (void *, size_t); 68 | virtual size_t pos (void); 69 | virtual size_t size (void); 70 | virtual int revert (uint8 origin, int32 offset); 71 | virtual void closeStream(); 72 | 73 | private: 74 | void fill_buffer(); 75 | size_t buffer_remaining(); 76 | 77 | unzFile file; 78 | char buffer[unz_BUFFSIZ]; 79 | size_t pos_in_buf; 80 | size_t buf_pos_in_unzipped; 81 | size_t bytes_in_buf; 82 | unz_file_pos unz_file_start_pos; 83 | }; 84 | 85 | #endif 86 | 87 | class memStream : public Stream 88 | { 89 | public: 90 | memStream (uint8 *,size_t); 91 | memStream (const uint8 *,size_t); 92 | virtual ~memStream (void); 93 | virtual int get_char (void); 94 | virtual char * gets (char *, size_t); 95 | virtual size_t read (void *, size_t); 96 | virtual size_t write (void *, size_t); 97 | virtual size_t pos (void); 98 | virtual size_t size (void); 99 | virtual int revert (uint8 origin, int32 offset); 100 | virtual void closeStream(); 101 | 102 | private: 103 | uint8 *mem; 104 | size_t msize; 105 | size_t remaining; 106 | uint8 *head; 107 | bool readonly; 108 | }; 109 | 110 | /* dummy stream that always reads 0 and writes nowhere 111 | but counts bytes written 112 | */ 113 | class nulStream : public Stream 114 | { 115 | public: 116 | nulStream (void); 117 | virtual ~nulStream (void); 118 | virtual int get_char (void); 119 | virtual char * gets (char *, size_t); 120 | virtual size_t read (void *, size_t); 121 | virtual size_t write (void *, size_t); 122 | virtual size_t pos (void); 123 | virtual size_t size (void); 124 | virtual int revert (uint8 origin, int32 offset); 125 | virtual void closeStream(); 126 | 127 | private: 128 | size_t bytes_written; 129 | }; 130 | 131 | Stream *openStreamFromFSTREAM(const char* filename, const char* mode); 132 | Stream *reopenStreamFromFd(int fd, const char* mode); 133 | 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /components/snes9x/tile.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 | This file is licensed under the Snes9x License. 4 | For further information, consult the LICENSE file in the root directory. 5 | \*****************************************************************************/ 6 | 7 | #ifndef _TILE_H_ 8 | #define _TILE_H_ 9 | 10 | void S9xInitTileRenderer (void); 11 | void S9xSelectTileRenderers (int, bool8, bool8); 12 | void S9xSelectTileConverter (int, bool8, bool8, bool8); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ${IDF_PATH}/add_path.sh 3 | 4 | COMPORT=COM4 5 | BINNAME=snes9x-esp32 6 | 7 | #make 8 | make -j 8 || exit 9 | #make flash 10 | esptool.py --chip esp32 --port $COMPORT --before default_reset --after hard_reset erase_region 0x100000 2097152 || exit 11 | esptool.py --chip esp32 --port $COMPORT --baud 921600 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_freq 80m --flash_size detect 0x100000 "build/$BINNAME.bin" || exit 12 | #make monitor 13 | idf_monitor.py --port COM4 build/$BINNAME.elf 14 | -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCDIRS ".") 2 | set(COMPONENT_ADD_INCLUDEDIRS ".") 3 | register_component() -------------------------------------------------------------------------------- /main/app_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define HAVE_STRINGS_H 6 | #define HAVE_STDINT_H 7 | 8 | #include "snes9x.h" 9 | #include "memmap.h" 10 | 11 | extern "C" { 12 | #define ODROID_TASKS_USE_CORE 0 13 | #include "odroid.h" 14 | #include "esp_system.h" 15 | #include "esp_heap_caps.h" 16 | #include "freertos/FreeRTOS.h" 17 | #include "freertos/task.h" 18 | } 19 | 20 | extern char *rom_selector(); 21 | extern void snes_task(void*); 22 | 23 | 24 | extern "C" void app_main() 25 | { 26 | // I tried reducing DMA, Reserved memory, and whatnot but it just won't allocate a continuous 128K segment :( 27 | // Internal ram is a bit faster than spiram + it makes room for loading bigger ROMS 28 | Memory.RAM1 = (uint8 *) heap_caps_malloc(0x10000, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); 29 | Memory.RAM2 = (uint8 *) heap_caps_malloc(0x10000, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); 30 | 31 | //heap_caps_malloc_extmem_enable(32768); 32 | 33 | odroid_system_init(); 34 | 35 | spi_lcd_useFrameBuffer(true); 36 | 37 | char *rom_file = rom_selector(); 38 | 39 | spi_lcd_setWindow(32, 0, 256, 240); 40 | spi_lcd_print(0, 0, "Starting SNES..."); 41 | spi_lcd_fb_update(); 42 | 43 | xTaskCreatePinnedToCore(&snes_task, "snes_task", 1024 * 32, rom_file, 10, NULL, 1); 44 | vTaskDelete(NULL); 45 | } 46 | 47 | 48 | 49 | void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) 50 | { 51 | *drive = 0; 52 | 53 | const char *slash = strrchr(path, SLASH_CHAR), 54 | *dot = strrchr(path, '.'); 55 | 56 | if (dot && slash && dot < slash) 57 | dot = NULL; 58 | 59 | if (!slash) 60 | { 61 | *dir = 0; 62 | 63 | strcpy(fname, path); 64 | 65 | if (dot) 66 | { 67 | fname[dot - path] = 0; 68 | strcpy(ext, dot + 1); 69 | } 70 | else 71 | *ext = 0; 72 | } 73 | else 74 | { 75 | strcpy(dir, path); 76 | dir[slash - path] = 0; 77 | 78 | strcpy(fname, slash + 1); 79 | 80 | if (dot) 81 | { 82 | fname[dot - slash - 1] = 0; 83 | strcpy(ext, dot + 1); 84 | } 85 | else 86 | *ext = 0; 87 | } 88 | } 89 | 90 | void _makepath (char *path, const char *, const char *dir, const char *fname, const char *ext) 91 | { 92 | if (dir && *dir) 93 | { 94 | strcpy(path, dir); 95 | strcat(path, SLASH_STR); 96 | } 97 | else 98 | *path = 0; 99 | 100 | strcat(path, fname); 101 | 102 | if (ext && *ext) 103 | { 104 | strcat(path, "."); 105 | strcat(path, ext); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | COMPONENT_ADD_INCLUDEDIRS += ../components/odroid-go 7 | COMPONENT_ADD_INCLUDEDIRS += ../components/snes9x -------------------------------------------------------------------------------- /main/rom_selector.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "freertos/FreeRTOS.h" 10 | #include "freertos/task.h" 11 | #include "esp_err.h" 12 | #include "esp_attr.h" 13 | 14 | #include "odroid.h" 15 | 16 | #include "fonts/DejaVuSans18.h" 17 | #include "fonts/DejaVu12.h" 18 | } 19 | 20 | static int selected = 0; 21 | static bool a_pressed = false; 22 | static int files_count = 0; 23 | 24 | static void input_callback(odroid_input_state state) 25 | { 26 | if (state.values[ODROID_INPUT_UP]) 27 | if (--selected < 0) selected = 0; 28 | if (state.values[ODROID_INPUT_DOWN]) 29 | if (++selected >= files_count) selected = files_count - 1; 30 | if (state.values[ODROID_INPUT_A]) 31 | a_pressed = true; 32 | } 33 | 34 | char * rom_selector() 35 | { 36 | spi_lcd_setFontColor(0xFFFF); 37 | spi_lcd_setFont(tft_Dejavu18); 38 | 39 | DIR *dir; 40 | struct dirent *ent; 41 | char files[32][64]; 42 | 43 | odroid_spi_bus_acquire(); 44 | if ((dir = opendir("/sdcard/roms/snes")) != NULL) { 45 | while ((ent = readdir(dir)) != NULL) { 46 | memcpy(files[files_count++], ent->d_name, 64); 47 | } 48 | closedir (dir); 49 | } 50 | odroid_spi_bus_release(); 51 | 52 | odroid_input_set_callback(&input_callback); 53 | 54 | while(1) { 55 | if (a_pressed) { 56 | char path[128]; 57 | sprintf(path, "/sdcard/roms/snes/%s", files[selected]); 58 | spi_lcd_clear(); 59 | spi_lcd_fb_flush(); 60 | return strdup(path); 61 | } 62 | 63 | int row = 0; 64 | int offset = 0; 65 | char buffer[30]; 66 | 67 | if (selected > 10) { 68 | offset = selected - 10; 69 | } 70 | 71 | spi_lcd_clear(); 72 | spi_lcd_print(0, row++ * 20, "Please select a ROM:"); 73 | 74 | for (int i = offset; i < files_count; i++) { 75 | spi_lcd_print(5, row * 20, (char *)(selected == i ? ">" : " ")); 76 | strncpy(buffer, files[i], 30); 77 | buffer[29] = 0; 78 | spi_lcd_print(20, row++ * 20, buffer); 79 | } 80 | 81 | spi_lcd_fb_flush(); 82 | // vTaskDelay 83 | } 84 | } -------------------------------------------------------------------------------- /main/snes9x.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "snes9x.h" 14 | #include "memmap.h" 15 | #include "apu.h" 16 | #include "gfx.h" 17 | #include "controls.h" 18 | #include "logger.h" 19 | #include "display.h" 20 | #include "conffile.h" 21 | 22 | extern "C" { 23 | #define ODROID_TASKS_USE_CORE 0 24 | #include "esp_system.h" 25 | #include "esp_heap_caps.h" 26 | #include "odroid.h" 27 | #include "freertos/FreeRTOS.h" 28 | #include "freertos/task.h" 29 | } 30 | 31 | #define MAP_BUTTON(id, name) S9xMapButton((id), S9xGetCommandT((name)), false) 32 | #define MEMORY_BYTES printf("Free Memory: %d %d\n", free_bytes_internal(), free_bytes_spiram()); 33 | 34 | uint32_t timer = 0; 35 | uint32_t loops = 0; 36 | 37 | 38 | 39 | void S9xMessage (int type, int number, const char *message) 40 | { 41 | printf("%s\n", message); 42 | } 43 | 44 | void S9xExtraUsage (void) 45 | { 46 | } 47 | 48 | void S9xParseArg (char **argv, int &i, int argc) 49 | { 50 | 51 | } 52 | 53 | void S9xParsePortConfig (ConfigFile &conf, int pass) 54 | { 55 | 56 | } 57 | 58 | const char * S9xGetDirectory (enum s9x_getdirtype dirtype) 59 | { 60 | return ""; 61 | } 62 | 63 | const char * S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype) 64 | { 65 | static char s[PATH_MAX + 1]; 66 | char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; 67 | 68 | _splitpath(Memory.ROMFilename, drive, dir, fname, ext); 69 | snprintf(s, PATH_MAX + 1, "%s%s%s%s", S9xGetDirectory(dirtype), SLASH_STR, fname, ex); 70 | 71 | return (s); 72 | } 73 | 74 | const char * S9xGetFilenameInc (const char *ex, enum s9x_getdirtype dirtype) 75 | { 76 | static char s[PATH_MAX + 1]; 77 | char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; 78 | 79 | unsigned int i = 0; 80 | const char *d; 81 | struct stat buf; 82 | 83 | _splitpath(Memory.ROMFilename, drive, dir, fname, ext); 84 | d = S9xGetDirectory(dirtype); 85 | 86 | do 87 | snprintf(s, PATH_MAX + 1, "%s%s%s.%03d%s", d, SLASH_STR, fname, i++, ex); 88 | while (stat(s, &buf) == 0 && i < 1000); 89 | 90 | return (s); 91 | } 92 | 93 | const char * S9xBasename (const char *f) 94 | { 95 | const char *p; 96 | 97 | if ((p = strrchr(f, '/')) != NULL || (p = strrchr(f, '\\')) != NULL) 98 | return (p + 1); 99 | 100 | return (f); 101 | } 102 | 103 | const char * S9xChooseFilename (bool8 read_only) 104 | { 105 | return NULL; 106 | } 107 | 108 | const char * S9xChooseMovieFilename (bool8 read_only) 109 | { 110 | return NULL; 111 | } 112 | 113 | bool8 S9xOpenSnapshotFile (const char *filename, bool8 read_only, STREAM *file) 114 | { 115 | return (FALSE); 116 | } 117 | 118 | void S9xCloseSnapshotFile (STREAM file) 119 | { 120 | 121 | } 122 | 123 | bool8 S9xContinueUpdate (int width, int height) 124 | { 125 | return (TRUE); 126 | } 127 | 128 | void S9xToggleSoundChannel (int c) 129 | { 130 | 131 | } 132 | 133 | void S9xAutoSaveSRAM (void) 134 | { 135 | 136 | } 137 | 138 | static uint8_t skip = 0; 139 | void S9xSyncSpeed (void) 140 | { 141 | IPPU.RenderThisFrame = !IPPU.RenderThisFrame; 142 | //IPPU.RenderThisFrame = skip == 0; 143 | //if (skip++ == 10) skip = 0; 144 | //IPPU.RenderThisFrame = true; 145 | 146 | loops++; 147 | 148 | uint32_t time = (esp_timer_get_time() / 1000); 149 | 150 | if ((time - timer) >= 1000) { 151 | printf("Sync time avg %.2fms\n", (float)(time - timer) / loops); 152 | timer = time; 153 | loops = 0; 154 | } 155 | } 156 | 157 | bool8 S9xMapInput (const char *n, s9xcommand_t *cmd) 158 | { 159 | return false; 160 | } 161 | 162 | bool S9xPollButton (uint32 id, bool *pressed) 163 | { 164 | return false; 165 | } 166 | 167 | bool S9xPollAxis (uint32 id, int16 *value) 168 | { 169 | return false; 170 | } 171 | 172 | bool S9xPollPointer (uint32 id, int16 *x, int16 *y) 173 | { 174 | return false; 175 | } 176 | 177 | s9xcommand_t S9xGetPortCommandT (const char *n) 178 | { 179 | s9xcommand_t cmd = {}; 180 | return cmd; 181 | } 182 | 183 | void S9xSetPalette (void) 184 | { 185 | 186 | } 187 | 188 | void S9xTextMode (void) 189 | { 190 | 191 | } 192 | 193 | void S9xGraphicsMode (void) 194 | { 195 | 196 | } 197 | 198 | char * S9xGetPortCommandName (s9xcommand_t cmd) 199 | { 200 | return strdup("None"); 201 | } 202 | 203 | void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) 204 | { 205 | 206 | } 207 | 208 | void S9xSetupDefaultKeymap (void) 209 | { 210 | 211 | } 212 | 213 | void S9xInitInputDevices (void) 214 | { 215 | 216 | } 217 | 218 | void S9xSamplesAvailable(void *data) 219 | { 220 | 221 | } 222 | 223 | bool8 S9xOpenSoundDevice (void) 224 | { 225 | return FALSE; 226 | } 227 | 228 | void S9xExit (void) 229 | { 230 | exit(0); 231 | } 232 | 233 | void S9xInitDisplay (int argc, char **argv) 234 | { 235 | // Setup SNES buffers 236 | GFX.Pitch = SNES_WIDTH * 2; 237 | GFX.Screen = (uint16 *) spi_lcd_fb_getPtr(); 238 | //GFX.Screen = (uint16 *) heap_caps_calloc(GFX.Pitch * (SNES_HEIGHT_EXTENDED + 4), 1, MALLOC_CAP_SPIRAM); 239 | S9xGraphicsInit(); 240 | } 241 | 242 | void S9xDeinitDisplay (void) 243 | { 244 | 245 | } 246 | 247 | bool8 S9xInitUpdate (void) 248 | { 249 | 250 | return (TRUE); 251 | } 252 | 253 | bool8 S9xDeinitUpdate (int width, int height) 254 | { 255 | spi_lcd_fb_update(); 256 | //spi_lcd_fb_flush(); 257 | return (TRUE); 258 | } 259 | 260 | 261 | void snes_input_callback(odroid_input_state state) 262 | { 263 | for (int i = 0; i < ODROID_INPUT_MAX; i++) { 264 | S9xReportButton(i, state.values[i]); 265 | } 266 | } 267 | 268 | 269 | void snes_ppu_task(void *arg) 270 | { 271 | while(1) { 272 | if (IPPU.RefreshNow) { 273 | IPPU.RefreshNow = false; 274 | S9xUpdateScreen(); 275 | } 276 | } 277 | } 278 | 279 | 280 | void snes_task(void *arg) // IRAM_ATTR 281 | { 282 | odroid_input_set_callback(&snes_input_callback); 283 | 284 | memset(&Settings, 0, sizeof(Settings)); 285 | Settings.SupportHiRes = FALSE; 286 | Settings.Transparency = TRUE; 287 | Settings.AutoDisplayMessages = TRUE; 288 | Settings.InitialInfoStringTimeout = 120; 289 | Settings.HDMATimingHack = 100; 290 | Settings.BlockInvalidVRAMAccessMaster = TRUE; 291 | Settings.StopEmulation = TRUE; 292 | Settings.SkipFrames = AUTO_FRAMERATE; 293 | Settings.TurboSkipFrames = 15; 294 | Settings.CartAName[0] = 0; 295 | Settings.CartBName[0] = 0; 296 | 297 | S9xLoadConfigFiles(NULL, 0); 298 | 299 | if (!Memory.Init() || !S9xInitAPU()) 300 | { 301 | fprintf(stderr, "Snes9x: Memory allocation failure - not enough RAM/virtual memory available.\nExiting...\n"); 302 | Memory.Deinit(); 303 | S9xDeinitAPU(); 304 | exit(1); 305 | } 306 | 307 | bool8 loaded = FALSE; 308 | 309 | odroid_spi_bus_acquire(); 310 | loaded = Memory.LoadROM((const char*)arg); 311 | odroid_spi_bus_release(); 312 | 313 | if (!loaded) 314 | { 315 | printf("Error opening the ROM file.\n"); 316 | exit(1); 317 | } else { 318 | printf("ROM loaded!\n"); 319 | } 320 | 321 | CPU.Flags = 0; 322 | Settings.StopEmulation = FALSE; 323 | Settings.Paused = FALSE; 324 | Settings.SoundSync = FALSE; 325 | 326 | S9xInitSound(0); 327 | S9xReportControllers(); 328 | S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); 329 | S9xSetController(1, CTL_NONE, 1, 0, 0, 0); 330 | S9xInitInputDevices(); 331 | S9xInitDisplay(NULL, 0); 332 | 333 | MAP_BUTTON(ODROID_INPUT_A, "Joypad1 A"); 334 | MAP_BUTTON(ODROID_INPUT_B, "Joypad1 B"); 335 | MAP_BUTTON(ODROID_INPUT_START, "Joypad1 X"); 336 | MAP_BUTTON(ODROID_INPUT_SELECT, "Joypad1 Y"); 337 | MAP_BUTTON(ODROID_INPUT_MENU, "Joypad1 Select"); 338 | MAP_BUTTON(ODROID_INPUT_VOLUME, "Joypad1 Start"); 339 | //MAP_BUTTON(BTN_L, "Joypad1 L"); 340 | //MAP_BUTTON(BTN_R, "Joypad1 R"); 341 | MAP_BUTTON(ODROID_INPUT_LEFT, "Joypad1 Left"); 342 | MAP_BUTTON(ODROID_INPUT_RIGHT, "Joypad1 Right"); 343 | MAP_BUTTON(ODROID_INPUT_UP, "Joypad1 Up"); 344 | MAP_BUTTON(ODROID_INPUT_DOWN, "Joypad1 Down"); 345 | 346 | MEMORY_BYTES; 347 | 348 | while (1) 349 | { 350 | S9xMainLoop(); 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /tile.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducalex/snes9x-esp32/986ab104fbe1dadf3c70ce07f1b273d3523ce76f/tile.raw --------------------------------------------------------------------------------