├── .gitignore ├── MEGADRIVE-GENESIS ├── README.md └── rainbow-mega-drive-genesis-mapper.md ├── NES ├── README.md ├── asm6 │ ├── LICENSE.txt │ ├── rainbow-config.asm │ ├── rainbow-constants.asm │ └── rainbow.asm ├── cc65 │ ├── LICENSE.txt │ ├── rainbow-config.s │ ├── rainbow-constants.s │ └── rainbow.s ├── chr-rom-self-flashing.md ├── mapper-doc.md ├── mapper-registers.s ├── prg-rom-self-flashing.md └── rainbow-net-code-example.md ├── README.md └── rainbow-net.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /MEGADRIVE-GENESIS/README.md: -------------------------------------------------------------------------------- 1 | # Rainbow 2 | 3 | ## **Everything on this page is still in a very WIP state and will change** 4 | 5 | Here you'll find the Rainbow mapper documentation. 6 | 7 | | File | Description | 8 | | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------- | 9 | | [rainbow-net.md](../rainbow-net.md) | Rainbow Net Wi-Fi protocol documentation | 10 | | [rainbow-mega-drive-genesis-mapper.md](rainbow-mega-drive-genesis-mapper.md) | Mega Drive / Genesis mapper documentation | 11 | | [rainbow-mega-drive-genesis-prg-rom-self-flashing.md](rainbow-mega-drive-genesis-prg-rom-self-flashing.md) | Rainbow PRG-ROM self-flashing documentation | 12 | | [rainbow-mega-drive-genesis-chr-rom-self-flashing.md](rainbow-mega-drive-genesis-chr-rom-self-flashing.md) | Rainbow CHR-ROM self-flashing documentation | 13 | 14 | # Try it yourself 15 | 16 | If you want to try this mapper, here's what you'll need: 17 | 18 | - a custom version of [Blastem](https://brokestudio.fr/rainbow/emulators/blastem) supporting the Rainbow mapper 19 | - a [rainbow Mega Drive / Genesis boiler plate using SGDK](https://github.com/BrokeStudio/rainbow-mega-drive-genesis-boiler-plate) (using sgdk) - optional 20 | - the above documentation 21 | - there's also a [chat demo](https://github.com/BrokeStudio/rainbow-chat) available 22 | 23 | ## Notes 24 | 25 | # Contact 26 | 27 | Feel free to give your feedback, and don't hesitate to create your own ROM and server too! 28 | I'd be happy to test it on real hardware if you want. 29 | 30 | You can email me at contact@brokestudio.fr or via the contact form at https://www.brokestudio.fr/contact/ 31 | 32 | Also, you can join Broke Studio's Discord server https://discord.gg/ccDS9Au, and discuss about the Rainbow project and/or other things :) 33 | 34 | >   35 | > _Antoine GOHIN / Broke Studio_ 36 | > **mail**: contact@brokestudio.fr 37 | > **web**: https://www.brokestudio.fr 38 | > **twitter**: @Broke_Studio 39 | > **facebook**: Broke Studio 40 | > **instagram**: @broke_studio 41 | >   42 | -------------------------------------------------------------------------------- /MEGADRIVE-GENESIS/rainbow-mega-drive-genesis-mapper.md: -------------------------------------------------------------------------------- 1 | # Rainbow Mega Drive / Genesis mapper documentation 2 | 3 | ## Register ranges 4 | 5 | | Address range | Description | 6 | | ------------------ | ------------------- | 7 | | $A13000 to $A1300F | Private use | 8 | | $A13010 to $A130BF | Private use??? | 9 | | $A130C0 to $A130CF | Mega Wifi / Rainbow | 10 | | $A130D0 to $A130E7 | Mega Everdrive | 11 | | $A130E9 to $A130EB | Private use??? | 12 | | $A130EC to $A130EF | 32X signature | 13 | | $A130F0 to $A130FF | Sega mapper | 14 | 15 | ## Mapper registers 16 | 17 | | Register | Description | 18 | | -------- | ---------------------------------------- | 19 | | $A13001 | Mapper configuration | 20 | | $A130F1 | Controls SRAM access | 21 | | $A130F3 | Controls bank at $080000-$0FFFFF (512KB) | 22 | | $A130F5 | Controls bank at $100000-$17FFFF (512KB) | 23 | | $A130F7 | Controls bank at $180000-$1FFFFF (512KB) | 24 | | $A130F9 | Controls bank at $200000-$27FFFF (512KB) | 25 | | $A130FB | Controls bank at $280000-$2FFFFF (512KB) | 26 | | $A130FD | Controls bank at $300000-$37FFFF (512KB) | 27 | | $A130FF | Controls bank at $380000-$3FFFFF (512KB) | 28 | 29 | ### Mapper configuration (\$A13001) 30 | 31 | This register is writable only. 32 | On startup or reset, this register is reset to 0. 33 | 34 | ``` 35 | 7 bit 0 36 | ---- ---- 37 | .... ...C 38 | | 39 | + Mapper configuration ( 0 : SSF2 compatible mapper | 1 : Rainbow mapper ) 40 | ``` 41 | 42 | ### Banking (\$A130F3-\$A130FF) 43 | 44 | These registers are writable only. 45 | Address range $000000-$07FFFF always points to the first bank. 46 | 47 | ``` 48 | 7 bit 0 49 | ---- ---- 50 | BBBB BBBB 51 | |||| |||| 52 | ++++ ++++ Bank index 53 | - 0 to 32 when using a 128Mbit (16MB) flash memory 54 | - 0 to 64 when using a 256Mbit (32MB) flash memory 55 | - 0 to 128 when using a 512Mbit (64MB) flash memory 56 | - 0 to 255 when using a 1Gbit (128MB) flash memory 57 | ``` 58 | 59 | ### SRAM access control (\$A130F1) 60 | 61 | This register is writable only. 62 | Selects ROM/SRAM/FPGA RAM to show at $200001-$20FFFF. 63 | 64 | ``` 65 | 7 bit 0 66 | ---- ---- 67 | .... ..SS 68 | || 69 | ++ SRAM access 70 | - 00: ROM 71 | - 01: SRAM 72 | - 1x: FPGA RAM 73 | ``` 74 | 75 | ## WiFi (\$A130C1-\$A130C9) 76 | 77 | | Register | Description | 78 | | -------- | -------------------------- | 79 | | $A130C1 | Configuration | 80 | | $A130C3 | RX - Reception | 81 | | $A130C5 | TX - Transimission | 82 | | $A130C7 | RX RAM destination address | 83 | | $A130C9 | TX RAM source address | 84 | 85 | ### Configuration (\$A130C1) W 86 | 87 | This register is writable only. 88 | 89 | ``` 90 | 7 bit 0 91 | ---- ---- 92 | .... ...E 93 | | 94 | + ESP enable ( 0 : disable | 1 : enable ) 95 | ``` 96 | 97 | ### RX - Reception (\$A130C3) R/W 98 | 99 | Writing any value to this registrer acknowledge the last received message and set the bit 7 of the register to 0. 100 | The bit 7 will be to 1 again when a new message if available. 101 | 102 | Reading: 103 | 104 | ``` 105 | 7 bit 0 106 | ---- ---- 107 | DR.. .... 108 | || 109 | |+------- Data ready, this flag is set to 1 if a message is waiting to be sent on the ESP side 110 | +-------- Data received ( 0 : FPGA can receive a new message | 1 : a new message is ready ) 111 | this flag is set to 1 when the FPGA has received a new message 112 | ``` 113 | 114 | ### TX - Transimission (\$A130C5) R/W 115 | 116 | Writing any value to this register sends the message currently stored in FPGA-RAM and sets the bit 7 of the register to 0. 117 | The bit 7 will be set to 1 again when the message is sent. 118 | 119 | Reading: 120 | 121 | ``` 122 | 7 bit 0 123 | ---- ---- 124 | D... .... 125 | | 126 | +-------- Data sent ( 0 : sending data | 1 : data sent ) R 127 | this flag is set to 1 when the FPGA has sent a message 128 | ``` 129 | 130 | ### RX RAM destination address (\$A130C7) W 131 | 132 | The FPGA uses its internal RAM to store new messages from the ESP or send messages to the ESP. 133 | Only the first 2K of the total 8K of the FPGA-RAM can be used for this. 134 | Those 2K are permanently mapped at \$4800-\$4FFF. 135 | This register allows you to specify an offset of $100 bytes from $4800. 136 | 137 | ``` 138 | 7 bit 0 139 | ---- ---- 140 | .... .AAA 141 | ||| 142 | +++ Destination RAM address hi bits 143 | ``` 144 | 145 | ### TX RAM source address (\$A130C9) W 146 | 147 | The FPGA uses its internal RAM to store new messages from the ESP or send messages to the ESP. 148 | Only the first 2K of the total 8K of the FPGA-RAM can be used for this. 149 | Those 2K are permanently mapped at \$4800-\$4FFF. 150 | This register allows you to specify an offset of $100 bytes from $4800. 151 | 152 | ``` 153 | 7 bit 0 154 | ---- ---- 155 | .... .AAA 156 | ||| 157 | +++ Source RAM address hi bits -------------------------------------------------------------------------------- /NES/README.md: -------------------------------------------------------------------------------- 1 | # Rainbow for the NES 2 | 3 | Here you'll find the Rainbow mapper documentation for the NES and 6502 library for cc65 and asm6. 4 | 5 | | File / Folder | Description | 6 | | ---------------------------------------------------------- | ------------------------------------------- | 7 | | [rainbow-net.md](../rainbow-net.md) | Rainbow NET Wi-Fi protocol documentation | 8 | | [mapper-doc.md](mapper-doc.md) | Rainbow NES mapper documentation | 9 | | [prg-rom-self-flashing.md](prg-rom-self-flashing.md) | Rainbow PRG-ROM self-flashing documentation | 10 | | [chr-rom-self-flashing.md](chr-rom-self-flashing.md) | Rainbow CHR-ROM self-flashing documentation | 11 | | [rainbow-net-code-example.md](rainbow-net-code-example.md) | Rainbow Net example code | 12 | | [mapper-registers.s](mapper-registers.s) | Rainbow NES mapper registers | 13 | | [/asm6](./asm6) | ASM6 Rainbow Net lib code | 14 | | [/cc65](./cc65) | cc65 suite Rainbow Net lib code | 15 | 16 | # Try it yourself 17 | 18 | If you want to try this mapper, here are some resources: 19 | 20 | - a custom version of [Mesen2](https://brokestudio.fr/rainbow/emulators) supporting the Rainbow mapper 21 | - ~~a custom version of [FCEUX](https://brokestudio.fr/rainbow/emulators) supporting the Rainbow mapper~~ (see note below) 22 | - a mapper implementation for the [Everdrive N8 PRO](https://brokestudio.fr/rainbow/everdrive) 23 | - a bunch of [test roms](https://brokestudio.fr/rainbow/test-roms) 24 | - a [rainbow NES boiler plate](https://github.com/BrokeStudio/rainbow-nes-boiler-plate) (using cc65) 25 | - the above documentation 26 | - there's also a [chat demo](https://github.com/BrokeStudio/rainbow-chat) available 27 | 28 | # Notes 29 | 30 | - official Mesen2 already supports the Rainbow mapper, minus the Wi-Fi feature 31 | - custom Mesen2 version doesn't support secured TCP protocol 32 | - custom FCEUX version hasn't been updated for a long time and is not up to date with the latest mapper features 33 | 34 | # Contact 35 | 36 | Feel free to give your feedback, and don't hesitate to create your own ROM and server too! 37 | I'd be happy to test it on real hardware if you want. 38 | 39 | You can email me at contact@brokestudio.fr or via the contact form at https://www.brokestudio.fr/contact/ 40 | 41 | Also, you can join Broke Studio's Discord server https://discord.gg/ccDS9Au, and discuss about the Rainbow project and/or other things :) 42 | 43 | >   44 | > _Antoine GOHIN / Broke Studio_ 45 | > **mail**: contact@brokestudio.fr 46 | > **web**: https://www.brokestudio.fr 47 | > **twitter**: @Broke_Studio 48 | > **facebook**: Broke Studio 49 | > **instagram**: @broke_studio 50 | >   51 | -------------------------------------------------------------------------------- /NES/asm6/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. -------------------------------------------------------------------------------- /NES/asm6/rainbow-config.asm: -------------------------------------------------------------------------------- 1 | ; ################################################################################ 2 | ; RAINBOW CONSTANTS 3 | 4 | RNBW_BUF_IN EQU $4800 5 | RNBW_BUF_OUT EQU (RNBW_BUF_IN + 256) 6 | -------------------------------------------------------------------------------- /NES/asm6/rainbow-constants.asm: -------------------------------------------------------------------------------- 1 | ; ################################################################################ 2 | ; RAINBOW CONSTANTS 3 | 4 | ; Rainbow mapper registers 5 | RNBW_CONFIG EQU $4190 6 | RNBW_RX EQU $4191 7 | RNBW_TX EQU $4192 8 | RNBW_RX_ADD EQU $4193 9 | RNBW_TX_ADD EQU $4194 10 | 11 | ; commands to ESP 12 | 13 | ; ESP CMDS 14 | TOESP_ESP_GET_STATUS EQU 0 ; Get ESP status 15 | TOESP_DEBUG_GET_LEVEL EQU 1 ; Get debug level 16 | TOESP_DEBUG_SET_LEVEL EQU 2 ; Set debug level 17 | TOESP_DEBUG_LOG EQU 3 ; Debug / Log data 18 | TOESP_CLEAR_BUFFERS EQU 4 ; Clear RX/TX buffers 19 | TOESP_FROMESP_BUFFER_DROP_FROM_ESP EQU 5 ; Drop messages from ESP buffer (TX) 20 | TOESP_ESP_GET_FIRMWARE_VERSION EQU 6 ; Get ESP/Rainbow firmware version 21 | TOESP_ESP_FACTORY_RESET EQU 7 ; Reset ESP to factory settings 22 | TOESP_ESP_RESTART EQU 8 ; Restart ESP 23 | 24 | ; WIFI CMDS 25 | TOESP_WIFI_GET_STATUS EQU 9 ; Get Wi-Fi connection status 26 | TOESP_WIFI_GET_SSID EQU 10 ; Get Wi-Fi network SSID 27 | TOESP_WIFI_GET_IP_ADDRESS EQU 11 ; Get Wi-Fi IP address 28 | TOESP_WIFI_GET_MAC_ADDRESS EQU 59 ; Get Wi-Fi mac address 29 | TOESP_WIFI_GET_CONFIG EQU 12 ; Get Wi-Fi station / Access Point / Web Server config 30 | TOESP_WIFI_SET_CONFIG EQU 13 ; Set Wi-Fi station / Access Point / Web Server config 31 | 32 | ; ACESS POINT CMDS 33 | TOESP_AP_GET_SSID EQU 14 ; Get Access Point network SSID 34 | TOESP_AP_GET_IP_ADDRESS EQU 15 ; Get Access Point IP address 35 | 36 | ; RND CMDS 37 | TOESP_RND_GET_BYTE EQU 16 ; Get random byte 38 | TOESP_RND_GET_BYTE_RANGE EQU 17 ; Get random byte between custom min/max 39 | TOESP_RND_GET_WORD EQU 18 ; Get random word 40 | TOESP_RND_GET_WORD_RANGE EQU 19 ; Get random word between custom min/max 41 | 42 | ; SERVER CMDS 43 | TOESP_SERVER_GET_STATUS EQU 20 ; Get server connection status 44 | TOESP_SERVER_PING EQU 21 ; Get ping between ESP and server 45 | TOESP_SERVER_SET_PROTOCOL EQU 22 ; Set protocol to be used to communicate (WS/UDP/TCP) 46 | TOESP_SERVER_GET_SETTINGS EQU 23 ; Get current server host name and port 47 | TOESP_SERVER_SET_SETTINGS EQU 24 ; Set current server host name and port 48 | TOESP_SERVER_GET_SAVED_SETTINGS EQU 25 ; Get server host name and port values saved in the Rainbow config file 49 | TOESP_SERVER_SET_SAVED_SETTINGS EQU 26 ; Set server host name and port values saved in the Rainbow config file 50 | TOESP_SERVER_RESTORE_SETTINGS EQU 27 ; Restore server host name and port to values defined in the Rainbow config 51 | TOESP_SERVER_CONNECT EQU 28 ; Connect to server 52 | TOESP_SERVER_DISCONNECT EQU 29 ; Disconnect from server 53 | TOESP_SERVER_SEND_MSG EQU 30 ; Send message to rainbow server 54 | 55 | ; UDP ADDRESS POOL CMDS 56 | TOESP_UDP_ADDR_POOL_CLEAR EQU 55 ; Clear the UDP address pool 57 | TOESP_UDP_ADDR_POOL_ADD EQU 56 ; Add an IP address to the UDP address pool 58 | TOESP_UDP_ADDR_POOL_REMOVE EQU 57 ; Remove an IP address from the UDP address pool 59 | TOESP_UDP_ADDR_POOL_SEND_MSG EQU 58 ; Send a message to all the addresses in the UDP address pool 60 | 61 | ; NETWORK CMDS 62 | TOESP_NETWORK_SCAN EQU 31 ; Scan networks around synchronously or asynchronously 63 | TOESP_NETWORK_GET_SCAN_RESULT EQU 32 ; Get result of the last scan 64 | TOESP_NETWORK_GET_SCANNED_DETAILS EQU 33 ; Get scanned network details 65 | TOESP_NETWORK_GET_REGISTERED EQU 34 ; Get registered networks status 66 | TOESP_NETWORK_GET_REGISTERED_DETAILS EQU 35 ; Get registered network SSID 67 | TOESP_NETWORK_REGISTER EQU 36 ; Register network 68 | TOESP_NETWORK_UNREGISTER EQU 37 ; Unregister network 69 | TOESP_NETWORK_SET_ACTIVE EQU 38 ; Set active network 70 | 71 | ; FILE COMMANDS 72 | TOESP_FILE_OPEN EQU 39 ; Open working file 73 | TOESP_FILE_CLOSE EQU 40 ; Close working file 74 | TOESP_FILE_STATUS EQU 41 ; Get working file status 75 | TOESP_FILE_EXISTS EQU 42 ; Check if file exists 76 | TOESP_FILE_DELETE EQU 43 ; Delete a file 77 | TOESP_FILE_SET_CUR EQU 44 ; Set working file cursor position a file 78 | TOESP_FILE_READ EQU 45 ; Read working file (at specific position) 79 | TOESP_FILE_WRITE EQU 46 ; Write working file (at specific position) 80 | TOESP_FILE_APPEND EQU 47 ; Append data to working file 81 | TOESP_FILE_COUNT EQU 48 ; Count files in a specific path 82 | TOESP_FILE_GET_LIST EQU 49 ; Get list of existing files in a path 83 | TOESP_FILE_GET_FREE_ID EQU 50 ; Get an unexisting file ID in a specific path 84 | TOESP_FILE_GET_FS_INFO EQU 51 ; Get file system details (ESP flash or SD card) 85 | TOESP_FILE_GET_INFO EQU 52 ; Get file info (size + crc32) 86 | TOESP_FILE_DOWNLOAD EQU 53 ; Download a file 87 | TOESP_FILE_FORMAT EQU 54 ; Format file system and save current config 88 | 89 | ; commands from ESP 90 | 91 | ; ESP CMDS 92 | FROMESP_READY EQU 0 ; ESP is ready 93 | FROMESP_DEBUG_LEVEL EQU 1 ; Return debug configuration 94 | FROMESP_ESP_FIRMWARE_VERSION EQU 2 ; Return ESP/Rainbow firmware version 95 | FROMESP_ESP_FACTORY_RESET EQU 3 ; See ESP_FACTORY_RESET_RES constants for details on returned value 96 | 97 | ; WIFI / ACCESS POINT CMDS 98 | FROMESP_WIFI_STATUS EQU 4 ; Return Wi-Fi connection status 99 | FROMESP_SSID EQU 5 ; Return Wi-Fi / Access Point SSID 100 | FROMESP_IP_ADDRESS EQU 6 ; Return Wi-Fi / Access Point IP address 101 | FROMESP_MAC_ADDRESS EQU 28 ; Return Wi-Fi mac address 102 | FROMESP_WIFI_CONFIG EQU 7 ; Return Wi-Fi station / Access Point / Web Server status 103 | 104 | ; RND CMDS 105 | FROMESP_RND_BYTE EQU 8 ; Return random byte value 106 | FROMESP_RND_WORD EQU 9 ; Return random word value 107 | 108 | ; SERVER CMDS 109 | FROMESP_SERVER_STATUS EQU 10 ; Return server connection status 110 | FROMESP_SERVER_PING EQU 11 ; Return min, max and average round-trip time and number of lost packets 111 | FROMESP_SERVER_SETTINGS EQU 12 ; Return server settings (host name + port) 112 | FROMESP_MESSAGE_FROM_SERVER EQU 13 ; Message from server 113 | 114 | ; NETWORK CMDS 115 | FROMESP_NETWORK_SCAN_RESULT EQU 14 ; Return result of last scan 116 | FROMESP_NETWORK_SCANNED_DETAILS EQU 15 ; Return details for a scanned network 117 | FROMESP_NETWORK_REGISTERED_DETAILS EQU 16 ; Return SSID for a registered network 118 | FROMESP_NETWORK_REGISTERED EQU 17 ; Return registered networks status 119 | 120 | ; FILE CMDS 121 | FROMESP_FILE_STATUS EQU 18 ; Return working file status 122 | FROMESP_FILE_EXISTS EQU 19 ; Return if file exists or not 123 | FROMESP_FILE_DELETE EQU 20 ; See RNBW_FILE_DELETE_xxx constants for details on returned value 124 | FROMESP_FILE_LIST EQU 21 ; Return path file list 125 | FROMESP_FILE_DATA EQU 22 ; Return file data 126 | FROMESP_FILE_COUNT EQU 23 ; Return file count in a specific path 127 | FROMESP_FILE_ID EQU 24 ; Return a free file ID 128 | FROMESP_FILE_FS_INFO EQU 25 ; Return file system info 129 | FROMESP_FILE_INFO EQU 26 ; Return file info (size + CRC32) 130 | FROMESP_FILE_DOWNLOAD EQU 27 ; See RNBW_FILE_DOWNLOAD_xxx constants for details on returned value 131 | 132 | ; ESP factory reset result codes 133 | RNBW_CONFIG_FACTORY_RESET_SUCCESS EQU 0 134 | RNBW_CONFIG_FACTORY_RESET_ERROR_WHILE_SAVING_CONFIG EQU 1 135 | RNBW_CONFIG_FACTORY_RESET_ERROR_WHILE_DELETING_TWEB EQU 2 136 | RNBW_CONFIG_FACTORY_RESET_ERROR_WHILE_DELETING_WEB EQU 3 137 | 138 | ; Wi-Fi status 139 | RNBW_WIFI_NOT_CONNECTED EQU 0 140 | RNBW_WIFI_CONNECTING EQU 1 141 | RNBW_WIFI_CONNECTED EQU 2 142 | 143 | ; Wi-Fi error 144 | RNBW_WIFI_ERROR_UNKNOWN EQU 255 145 | RNBW_WIFI_ERROR_NO_ERROR EQU 0 146 | RNBW_WIFI_ERROR_NO_SSID_AVAIL EQU 1 147 | RNBW_WIFI_ERROR_CONNECTION_FAILED EQU 2 148 | RNBW_WIFI_ERROR_CONNECTION_LOST EQU 3 149 | RNBW_WIFI_ERROR_WRONG_PASSWORD EQU 4 150 | 151 | ; ESP Wi-Fi status 152 | RNBW_ESP_WIFI_NO_SHIELD EQU 255 153 | RNBW_ESP_WIFI_IDLE_STATUS EQU 0 154 | RNBW_ESP_WIFI_NO_SSID_AVAIL EQU 1 155 | RNBW_ESP_WIFI_SCAN_COMPLETED EQU 2 156 | RNBW_ESP_WIFI_CONNECTED EQU 3 157 | RNBW_ESP_WIFI_CONNECTION_FAILED EQU 4 158 | RNBW_ESP_WIFI_CONNECTION_LOST EQU 5 159 | RNBW_ESP_WIFI_WRONG_PASSWORD EQU 6 160 | RNBW_ESP_WIFI_DISCONNECTED EQU 7 161 | 162 | ; Server protocols 163 | RNBW_PROTOCOL_TCP EQU 0 164 | RNBW_PROTOCOL_TCP_SECURED EQU 1 165 | RNBW_PROTOCOL_UDP EQU 2 166 | RNBW_PROTOCOL_UDP_POOL EQU 3 167 | 168 | ; Server status 169 | RNBW_SERVER_DISCONNECTED EQU 0 170 | RNBW_SERVER_CONNECTED EQU 1 171 | 172 | ; Wi-Fi config flags 173 | RNBW_WIFI_CONFIG_FLAGS_WIFI_STATION_ENABLE EQU 1 174 | RNBW_WIFI_CONFIG_FLAGS_ACCESS_POINT_ENABLE EQU 2 175 | RNBW_WIFI_CONFIG_FLAGS_WEB_SERVER_ENABLE EQU 4 176 | 177 | ; File paths 178 | RNBW_FILE_PATH_SAVE EQU 0 179 | RNBW_FILE_PATH_ROMS EQU 1 180 | RNBW_FILE_PATH_USER EQU 2 181 | 182 | ; File constants 183 | RNBW_NUM_PATHS EQU 3 184 | RNBW_NUM_FILES EQU 64 185 | 186 | ; Network encryption types 187 | RNBW_NETWORK_ENCTYPE_WEP EQU 5 188 | RNBW_NETWORK_ENCTYPE_WPA_PSK EQU 2 189 | RNBW_NETWORK_ENCTYPE_WPA2_PSK EQU 4 190 | RNBW_NETWORK_ENCTYPE_OPEN_NETWORK EQU 7 191 | RNBW_NETWORK_ENCTYPE_WPA_WPA2_PSK EQU 8 192 | 193 | ; File config masks/flags 194 | RNBW_FILE_CONFIG_FLAGS_ACCESS_MODE_MASK EQU %00000001 195 | RNBW_FILE_CONFIG_FLAGS_ACCESS_MODE_AUTO EQU 0 196 | RNBW_FILE_CONFIG_FLAGS_ACCESS_MODE_MANUAL EQU 1 197 | RNBW_FILE_CONFIG_FLAGS_DESTINATION_MASK EQU %00000010 198 | RNBW_FILE_CONFIG_FLAGS_DESTINATION_ESP EQU 0 199 | RNBW_FILE_CONFIG_FLAGS_DESTINATION_SD EQU 2 200 | 201 | ; FILE_DELETE result codes 202 | RNBW_FILE_DELETE_SUCCESS EQU 0 203 | RNBW_FILE_DELETE_ERROR_WHILE_DELETING_FILE EQU 1 204 | RNBW_FILE_DELETE_FILE_NOT_FOUND EQU 2 205 | RNBW_FILE_DELETE_INVALID_PATH_OR_FILE EQU 3 206 | 207 | ; FILE_DOWNLOAD result codes 208 | RNBW_FILE_DOWNLOAD_SUCCESS EQU 0 209 | RNBW_FILE_DOWNLOAD_INVALID_DESTINATION EQU 1 210 | RNBW_FILE_DOWNLOAD_ERROR_WHILE_DELETING_FILE EQU 2 211 | RNBW_FILE_DOWNLOAD_UNKNOWN_OR_UNSUPPORTED_PROTOCOL EQU 3 212 | RNBW_FILE_DOWNLOAD_NETWORK_ERROR EQU 4 213 | RNBW_FILE_DOWNLOAD_HTTP_STATUS_NOT_IN_2XX EQU 5 214 | 215 | ; FILE_DOWNLOAD network error codes 216 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_CONNECTION_FAILED EQU -1 217 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_SEND_HEADER_FAILED EQU -2 218 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_SEND_PAYLOAD_FAILED EQU -3 219 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_NOT_CONNECTED EQU -4 220 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_CONNECTION_LOST EQU -5 221 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_NO_STREAM EQU -6 222 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_NO_HTTP_SERVER EQU -7 223 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_TOO_LESS_RAM EQU -8 224 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_ENCODING EQU -9 225 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_STREAM_WRITE EQU -10 226 | RNBW_FILE_DOWNLOAD_NETWORK_ERR_READ_TIMEOUT EQU -11 227 | -------------------------------------------------------------------------------- /NES/asm6/rainbow.asm: -------------------------------------------------------------------------------- 1 | ; ################################################################################ 2 | ; RAINBOW LIBRARY 3 | 4 | ; ################################################################################ 5 | ; INCLUDES 6 | 7 | .include "rainbow-lib/rainbow-config.asm" 8 | .include "rainbow-lib/rainbow-constants.asm" 9 | 10 | ; ################################################################################ 11 | ; ALIASES 12 | 13 | ; ################################################################################ 14 | ; ZEROPAGE 15 | 16 | ;.enum $0000 17 | ;rnbwTmp .dsb 2 18 | ;.ende 19 | rnbwTmp EQU $fe 20 | 21 | ; ################################################################################ 22 | ; MACROS 23 | 24 | .macro RNBW_waitRX 25 | ; wait for message to be received 26 | - 27 | bit RNBW_RX 28 | bpl - 29 | .endm 30 | 31 | .macro RNBW_waitTX 32 | ; wait for message to be sent 33 | - 34 | bit RNBW_TX 35 | bpl - 36 | .endm 37 | 38 | ; ################################################################################ 39 | ; CODE 40 | 41 | RNBW_disableIRQ: 42 | 43 | ; disable ESP IRQ 44 | lda RNBW_CONFIG 45 | and #$fd 46 | sta RNBW_CONFIG 47 | 48 | ; return 49 | rts 50 | 51 | RNBW_enableIRQ: 52 | 53 | ; enable ESP IRQ 54 | lda RNBW_CONFIG 55 | ora #$02 56 | sta RNBW_CONFIG 57 | 58 | ; return 59 | rts 60 | 61 | RNBW_sendData: 62 | ; A: message pointer lo byte 63 | ; X: message pointer hi byte 64 | 65 | sta rnbwTmp+0 66 | stx rnbwTmp+1 67 | 68 | ldy #0 69 | lda (rnbwTmp),y 70 | tax 71 | inx 72 | - 73 | lda (rnbwTmp),y 74 | sta RNBW_BUF_OUT,y 75 | iny 76 | dex 77 | bne - 78 | sta RNBW_TX 79 | 80 | - 81 | bit RNBW_TX 82 | bpl - 83 | 84 | ; return 85 | rts 86 | RNBW_waitReady: 87 | 88 | ; ask for ESP status 89 | lda #1 90 | sta RNBW_BUF_OUT+0 91 | lda #TOESP_ESP_GET_STATUS 92 | sta RNBW_BUF_OUT+1 93 | sta RNBW_TX 94 | 95 | ; wait for message to be sent 96 | - 97 | bit RNBW_TX 98 | bpl - 99 | 100 | ; wait for answer 101 | - 102 | bit RNBW_RX 103 | bpl - 104 | 105 | ; acknowledge answer 106 | sta RNBW_RX 107 | 108 | ; return 109 | rts 110 | 111 | RNBW_copyRXtoTX: 112 | 113 | ; copy RX buffer to TX buffer 114 | ldx RNBW_BUF_IN+0 115 | stx RNBW_BUF_OUT+0 116 | - 117 | lda RNBW_BUF_IN,x 118 | sta RNBW_BUF_OUT,x 119 | dex 120 | bne - 121 | 122 | ; return 123 | rts 124 | 125 | RNBW_debug_A: 126 | 127 | ; data to debug in A 128 | pha 129 | lda #2 130 | sta RNBW_BUF_OUT+0 131 | lda #TOESP_DEBUG_LOG 132 | sta RNBW_BUF_OUT+1 133 | pla 134 | sta RNBW_BUF_OUT+2 135 | sta RNBW_TX 136 | 137 | ; wait for message to be sent 138 | - 139 | bit RNBW_TX 140 | bpl - 141 | 142 | ; return 143 | rts 144 | 145 | RNBW_debug_X: 146 | 147 | ; data to debug in X 148 | lda #2 149 | sta RNBW_BUF_OUT+0 150 | lda #TOESP_DEBUG_LOG 151 | sta RNBW_BUF_OUT+1 152 | stx RNBW_BUF_OUT+2 153 | sta RNBW_TX 154 | 155 | ; wait for message to be sent 156 | - 157 | bit RNBW_TX 158 | bpl - 159 | 160 | ; return 161 | rts 162 | 163 | RNBW_debug_Y: 164 | 165 | ; data to debug in Y 166 | lda #2 167 | sta RNBW_BUF_OUT+0 168 | lda #TOESP_DEBUG_LOG 169 | sta RNBW_BUF_OUT+1 170 | sty RNBW_BUF_OUT+2 171 | sta RNBW_TX 172 | 173 | ; wait for message to be sent 174 | - 175 | bit RNBW_TX 176 | bpl - 177 | 178 | ; return 179 | rts 180 | 181 | RNBW_getWifiStatus: 182 | 183 | ; ask for wifi status 184 | lda #1 185 | sta RNBW_BUF_OUT+0 186 | lda #TOESP_WIFI_GET_STATUS 187 | sta RNBW_BUF_OUT+1 188 | sta RNBW_TX 189 | 190 | ; wait for message to be sent 191 | - 192 | bit RNBW_TX 193 | bpl - 194 | 195 | ; wait for answer 196 | - 197 | bit RNBW_RX 198 | bpl - 199 | 200 | ; return wifi status in A 201 | lda RNBW_BUF_IN+2 202 | 203 | ; acknowledge answer 204 | sta RNBW_RX 205 | 206 | ; return 207 | rts 208 | 209 | RNBW_getServerStatus: 210 | 211 | ; ask for server status 212 | lda #1 213 | sta RNBW_BUF_OUT+0 214 | lda #TOESP_SERVER_GET_STATUS 215 | sta RNBW_BUF_OUT+1 216 | sta RNBW_TX 217 | 218 | ; wait for message to be sent 219 | - 220 | bit RNBW_TX 221 | bpl - 222 | 223 | ; wait for answer 224 | - 225 | bit RNBW_RX 226 | bpl - 227 | 228 | ; return server status in A 229 | lda RNBW_BUF_IN+2 230 | 231 | ; acknowledge answer 232 | sta RNBW_RX 233 | 234 | ; return 235 | rts 236 | 237 | RNBW_getRandomByte: 238 | 239 | lda #1 240 | sta RNBW_BUF_OUT+0 241 | lda #TOESP_RND_GET_BYTE 242 | sta RNBW_BUF_OUT+1 243 | sta RNBW_TX 244 | 245 | ; wait for message to be sent 246 | - 247 | bit RNBW_TX 248 | bpl - 249 | 250 | ; wait for answer 251 | - 252 | bit RNBW_RX 253 | bpl - 254 | 255 | ; return random byte in A 256 | lda RNBW_BUF_IN+2 257 | 258 | ; acknowledge answer 259 | sta RNBW_RX 260 | 261 | ; return 262 | rts 263 | 264 | RNBW_getRandomByteRange: 265 | ; X: min 266 | ; Y: max 267 | 268 | lda #3 269 | sta RNBW_BUF_OUT+0 270 | lda #TOESP_RND_GET_BYTE_RANGE 271 | sta RNBW_BUF_OUT+1 272 | stx RNBW_BUF_OUT+2 273 | sty RNBW_BUF_OUT+3 274 | sta RNBW_TX 275 | 276 | ; wait for message to be sent 277 | - 278 | bit RNBW_TX 279 | bpl - 280 | 281 | ; wait for answer 282 | - 283 | bit RNBW_RX 284 | bpl - 285 | 286 | ; return random byte in A 287 | lda RNBW_BUF_IN+2 288 | 289 | ; acknowledge answer 290 | sta RNBW_RX 291 | 292 | ; return 293 | rts 294 | 295 | RNBW_getRandomWord: 296 | 297 | lda #1 298 | sta RNBW_BUF_OUT+0 299 | lda #TOESP_RND_GET_WORD 300 | sta RNBW_BUF_OUT+1 301 | sta RNBW_TX 302 | 303 | ; wait for message to be sent 304 | - 305 | bit RNBW_TX 306 | bpl - 307 | 308 | ; wait for answer 309 | - 310 | bit RNBW_RX 311 | bpl - 312 | 313 | ; return random word in A (hi) and X (lo) 314 | lda RNBW_BUF_IN+2 315 | ldx RNBW_BUF_IN+3 316 | 317 | ; acknowledge answer 318 | sta RNBW_RX 319 | 320 | ; return 321 | rts 322 | -------------------------------------------------------------------------------- /NES/cc65/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. -------------------------------------------------------------------------------- /NES/cc65/rainbow-config.s: -------------------------------------------------------------------------------- 1 | ; ################################################################################ 2 | ; RAINBOW CONSTANTS 3 | 4 | BUF_IN = $4800 5 | BUF_OUT = BUF_IN + 256 -------------------------------------------------------------------------------- /NES/cc65/rainbow-constants.s: -------------------------------------------------------------------------------- 1 | ; ################################################################################ 2 | ; RAINBOW CONSTANTS 3 | 4 | ; Rainbow mapper registers 5 | CONFIG = $4190 6 | RX = $4191 7 | TX = $4192 8 | RX_ADD = $4193 9 | TX_ADD = $4194 10 | 11 | ; commands to ESP 12 | .enum TO_ESP 13 | 14 | ; ESP CMDS 15 | ESP_GET_STATUS = 0 ; Get ESP status 16 | DEBUG_GET_LEVEL = 1 ; Get debug level 17 | DEBUG_SET_LEVEL = 2 ; Set debug level 18 | DEBUG_LOG = 3 ; Debug / Log data 19 | BUFFER_CLEAR_RX_TX = 4 ; Clear RX/TX buffers 20 | BUFFER_DROP_FROM_ESP = 5 ; Drop messages from ESP buffer (TX) 21 | ESP_GET_FIRMWARE_VERSION = 6 ; Get ESP/Rainbow firmware version 22 | ESP_FACTORY_RESET = 7 ; Reset ESP to factory settings 23 | ESP_RESTART = 8 ; Restart ESP 24 | 25 | ; WIFI CMDS 26 | WIFI_GET_STATUS = 9 ; Get Wi-Fi connection status 27 | WIFI_GET_SSID = 10 ; Get Wi-Fi network SSID 28 | WIFI_GET_IP_ADDRESS = 11 ; Get Wi-Fi IP address 29 | WIFI_GET_MAC_ADDRESS = 59 ; Get Wi-Fi mac address 30 | WIFI_GET_CONFIG = 12 ; Get Wi-Fi station / Access Point / Web Server config 31 | WIFI_SET_CONFIG = 13 ; Set Wi-Fi station / Access Point / Web Server config 32 | 33 | ; ACESS POINT CMDS 34 | AP_GET_SSID = 14 ; Get Access Point network SSID 35 | AP_GET_IP_ADDRESS = 15 ; Get Access Point IP address 36 | 37 | ; RND CMDS 38 | RND_GET_BYTE = 16 ; Get random byte 39 | RND_GET_BYTE_RANGE = 17 ; Get random byte between custom min/max 40 | RND_GET_WORD = 18 ; Get random word 41 | RND_GET_WORD_RANGE = 19 ; Get random word between custom min/max 42 | 43 | ; SERVER CMDS 44 | SERVER_GET_STATUS = 20 ; Get server connection status 45 | SERVER_PING = 21 ; Get ping between ESP and server 46 | SERVER_SET_PROTOCOL = 22 ; Set protocol to be used to communicate (WS/UDP/TCP) 47 | SERVER_GET_SETTINGS = 23 ; Get current server host name and port 48 | SERVER_SET_SETTINGS = 24 ; Set current server host name and port 49 | SERVER_GET_SAVED_SETTINGS = 25 ; Get server host name and port values saved in the Rainbow config file 50 | SERVER_SET_SAVED_SETTINGS = 26 ; Set server host name and port values saved in the Rainbow config file 51 | SERVER_RESTORE_SETTINGS = 27 ; Restore server host name and port to values defined in the Rainbow config 52 | SERVER_CONNECT = 28 ; Connect to server 53 | SERVER_DISCONNECT = 29 ; Disconnect from server 54 | SERVER_SEND_MESSAGE = 30 ; Send message to server 55 | 56 | ; UDP ADDRESS POOL CMDS 57 | UDP_ADDR_POOL_CLEAR = 55 ; Clear the UDP address pool 58 | UDP_ADDR_POOL_ADD = 56 ; Add an IP address to the UDP address pool 59 | UDP_ADDR_POOL_REMOVE = 57 ; Remove an IP address from the UDP address pool 60 | UDP_ADDR_POOL_SEND_MSG = 58 ; Send a message to all the addresses in the UDP address pool 61 | 62 | ; NETWORK CMDS 63 | NETWORK_SCAN = 31 ; Scan networks around synchronously or asynchronously 64 | NETWORK_GET_SCAN_RESULT = 32 ; Get result of the last scan 65 | NETWORK_GET_SCANNED_DETAILS = 33 ; Get scanned network details 66 | NETWORK_GET_REGISTERED = 34 ; Get registered networks status 67 | NETWORK_GET_REGISTERED_DETAILS = 35 ; Get registered network SSID 68 | NETWORK_REGISTER = 36 ; Register network 69 | NETWORK_UNREGISTER = 37 ; Unregister network 70 | NETWORK_SET_ACTIVE = 38 ; Set active network 71 | 72 | ; FILE COMMANDS 73 | FILE_OPEN = 39 ; Open working file 74 | FILE_CLOSE = 40 ; Close working file 75 | FILE_STATUS = 41 ; Get working file status 76 | FILE_EXISTS = 42 ; Check if file exists 77 | FILE_DELETE = 43 ; Delete a file 78 | FILE_SET_CUR = 44 ; Set working file cursor position a file 79 | FILE_READ = 45 ; Read working file (at specific position) 80 | FILE_WRITE = 46 ; Write working file (at specific position) 81 | FILE_APPEND = 47 ; Append data to working file 82 | FILE_COUNT = 48 ; Count files in a specific path 83 | FILE_GET_LIST = 49 ; Get list of existing files in a path 84 | FILE_GET_FREE_ID = 50 ; Get an unexisting file ID in a specific path 85 | FILE_GET_FS_INFO = 51 ; Get file system details (ESP flash or SD card) 86 | FILE_GET_INFO = 52 ; Get file info (size + crc32) 87 | FILE_DOWNLOAD = 53 ; Download a file 88 | FILE_FORMAT = 54 ; Format file system and save current config 89 | 90 | .endenum 91 | 92 | ; commands from ESP 93 | .enum FROM_ESP 94 | 95 | ; ESP CMDS 96 | READY = 0 ; ESP is ready 97 | DEBUG_LEVEL = 1 ; Return debug configuration 98 | ESP_FIRMWARE_VERSION = 2 ; Return ESP/Rainbow firmware version 99 | ESP_FACTORY_RESET = 3 ; See ESP_FACTORY_RESET_RES enum for details on returned value 100 | 101 | ; WIFI / ACCESS POINT CMDS 102 | WIFI_STATUS = 4 ; Return Wi-Fi connection status 103 | SSID = 5 ; Return Wi-Fi / Access Point SSID 104 | IP_ADDRESS = 6 ; Return Wi-Fi / Access Point IP address 105 | MAC_ADDRESS = 28 ; Return Wi-Fi mac address 106 | WIFI_CONFIG = 7 ; Return Wi-Fi station / Access Point / Web Server status 107 | 108 | ; RND CMDS 109 | RND_BYTE = 8 ; Return random byte value 110 | RND_WORD = 9 ; Return random word value 111 | 112 | ; SERVER CMDS 113 | SERVER_STATUS = 10 ; Return server connection status 114 | SERVER_PING = 11 ; Return min, max and average round-trip time and number of lost packets 115 | SERVER_SETTINGS = 12 ; Return server settings (host name + port) 116 | MESSAGE_FROM_SERVER = 13 ; Message from server 117 | 118 | ; NETWORK CMDS 119 | NETWORK_SCAN_RESULT = 14 ; Return result of last scan 120 | NETWORK_SCANNED_DETAILS = 15 ; Return details for a scanned network 121 | NETWORK_REGISTERED_DETAILS = 16 ; Return SSID for a registered network 122 | NETWORK_REGISTERED = 17 ; Return registered networks status 123 | 124 | ; FILE CMDS 125 | FILE_STATUS = 18 ; Return working file status 126 | FILE_EXISTS = 19 ; Return if file exists or not 127 | FILE_DELETE = 20 ; See FILE_DELETE_RES enum for details on returned value 128 | FILE_LIST = 21 ; Return path file list 129 | FILE_DATA = 22 ; Return file data 130 | FILE_COUNT = 23 ; Return file count in a specific path 131 | FILE_ID = 24 ; Return a free file ID 132 | FILE_FS_INFO = 25 ; Return file system info 133 | FILE_INFO = 26 ; Return file info (size + CRC32) 134 | FILE_DOWNLOAD = 27 ; See FILE_DOWNLOAD_RES enum for details on returned value 135 | 136 | .endenum 137 | 138 | ; ESP factory reset result codes 139 | .enum ESP_FACTORY_RESET_RES 140 | SUCCESS 141 | ERROR_WHILE_SAVING_CONFIG 142 | ERROR_WHILE_DELETING_TWEB 143 | ERROR_WHILE_DELETING_WEB 144 | .endenum 145 | 146 | ; Wi-Fi status 147 | .enum WIFI_STATUS 148 | NOT_CONNECTED 149 | CONNECTING 150 | CONNECTED 151 | .endenum 152 | 153 | ; Wi-Fi error 154 | .enum WIFI_ERROR 155 | UNKNOWN = 255 156 | NO_ERROR = 0 157 | NO_SSID_AVAIL = 1 158 | CONNECTION_FAILED = 2 159 | CONNECTION_LOST = 3 160 | WRONG_PASSWORD = 4 161 | .endenum 162 | 163 | ; ESP Wi-Fi status 164 | .enum WIFI_ESP_STATUS 165 | NO_SHIELD = 255 166 | IDLE_STATUS = 0 167 | NO_SSID_AVAIL 168 | SCAN_COMPLETED 169 | CONNECTED 170 | CONNECTION_FAILED 171 | CONNECTION_LOST 172 | WRONG_PASSWORD 173 | DISCONNECTED 174 | .endenum 175 | 176 | ; Server protocols 177 | .enum SERVER_PROTOCOLS 178 | TCP = 0 179 | TCP_SECURED = 1 180 | UDP = 2 181 | UDP_POOL = 3 182 | .endenum 183 | 184 | ; Server status 185 | .enum SERVER_STATUS 186 | DISCONNECTED 187 | CONNECTED 188 | .endenum 189 | 190 | ; Wi-Fi config flags 191 | .enum WIFI_CONFIG_FLAGS 192 | WIFI_STATION_ENABLE = 1 193 | ACCESS_POINT_ENABLE = 2 194 | WEB_SERVER_ENABLE = 4 195 | .endenum 196 | 197 | ; File paths 198 | .enum FILE_PATHS 199 | SAVE 200 | ROMS 201 | USER 202 | .endenum 203 | 204 | ; File constants 205 | NUM_PATHS = 3 206 | NUM_FILES = 64 207 | 208 | ; Network encryption types 209 | .enum NETWORK_ENCRYPTION_TYPES 210 | WEP = 5 211 | WPA_PSK = 2 212 | WPA2_PSK = 4 213 | OPEN_NETWORK = 7 214 | WPA_WPA2_PSK = 8 215 | .endenum 216 | 217 | ; File config masks/flags 218 | .enum FILE_CONFIG_FLAGS 219 | ACCESS_MODE_MASK = %00000001 220 | ACCESS_MODE_AUTO = 0 221 | ACCESS_MODE_MANUAL = 1 222 | DESTINATION_MASK = %00000010 223 | DESTINATION_ESP = 0 224 | DESTINATION_SD = 2 225 | .endenum 226 | 227 | ; FILE_DELETE result codes 228 | .enum FILE_DELETE_RES 229 | SUCCESS 230 | ERROR_WHILE_DELETING_FILE 231 | FILE_NOT_FOUND 232 | INVALID_PATH_OR_FILE 233 | .endenum 234 | 235 | ; FILE_DOWNLOAD result codes 236 | .enum FILE_DOWNLOAD_RES 237 | SUCCESS 238 | INVALID_DESTINATION 239 | ERROR_WHILE_DELETING_FILE 240 | UNKNOWN_OR_UNSUPPORTED_PROTOCOL 241 | NETWORK_ERROR 242 | HTTP_STATUS_NOT_IN_2XX 243 | .endenum 244 | 245 | ; FILE_DOWNLOAD network error codes 246 | .enum FILE_DOWNLOAD_NETWORK_ERR 247 | CONNECTION_FAILED = -1 248 | SEND_HEADER_FAILED = -2 249 | SEND_PAYLOAD_FAILED = -3 250 | NOT_CONNECTED = -4 251 | CONNECTION_LOST = -5 252 | NO_STREAM = -6 253 | NO_HTTP_SERVER = -7 254 | TOO_LESS_RAM = -8 255 | ENCODING = -9 256 | STREAM_WRITE = -10 257 | READ_TIMEOUT = -11 258 | .endenum 259 | -------------------------------------------------------------------------------- /NES/cc65/rainbow.s: -------------------------------------------------------------------------------- 1 | ; ################################################################################ 2 | ; RAINBOW LIBRARY 3 | .out "# Rainbow library..." 4 | 5 | .scope RNBW 6 | 7 | ; ################################################################################ 8 | ; INCLUDES 9 | 10 | .include "rainbow-config.s" 11 | .include "rainbow-constants.s" 12 | 13 | ; ################################################################################ 14 | ; ALIASES 15 | 16 | enableIRQ = RNBW_enableIRQ 17 | disableIRQ = RNBW_disableIRQ 18 | sendData = RNBW_sendData 19 | waitReady = RNBW_waitReady 20 | copyRXtoTX = RNBW_copyRXtoTX 21 | debugA = RNBW_debug_A 22 | debug_A = RNBW_debug_A 23 | debugX = RNBW_debug_X 24 | debug_X = RNBW_debug_X 25 | debugY = RNBW_debug_Y 26 | debug_Y = RNBW_debug_Y 27 | getRandomByte = RNBW_getRandomByte 28 | getRandomByteRange = RNBW_getRandomByteRange 29 | getRandomWord = RNBW_getRandomWord 30 | ;getRandomWordRange = RNBW_getRandomWordRange 31 | 32 | ; ################################################################################ 33 | ; ZEROPAGE 34 | 35 | .pushseg 36 | .zeropage 37 | 38 | rnbwTmp: .res 2 39 | 40 | .popseg 41 | 42 | ; ################################################################################ 43 | ; MACROS 44 | 45 | .if .not .definedmacro(RNBW_waitRX) 46 | .macro RNBW_waitRX 47 | ; wait for message to be received 48 | : 49 | bit ::RNBW::RX 50 | bpl :- 51 | .endmacro 52 | .endif 53 | 54 | .if .not .definedmacro(RNBW_waitTX) 55 | .macro RNBW_waitTX 56 | ; wait for message to be sent 57 | : 58 | bit ::RNBW::TX 59 | bpl :- 60 | .endmacro 61 | .endif 62 | 63 | ; ################################################################################ 64 | ; CODE 65 | 66 | .proc RNBW_disableIRQ 67 | 68 | ; disable ESP IRQ 69 | lda CONFIG 70 | and #$fd 71 | sta CONFIG 72 | 73 | ; return 74 | rts 75 | 76 | .endproc 77 | 78 | .proc RNBW_enableIRQ 79 | 80 | ; enable ESP IRQ 81 | lda CONFIG 82 | ora #$02 83 | sta CONFIG 84 | 85 | ; return 86 | rts 87 | 88 | .endproc 89 | 90 | .proc RNBW_sendData 91 | ; A: message pointer lo byte 92 | ; X: message pointer hi byte 93 | 94 | sta rnbwTmp+0 95 | stx rnbwTmp+1 96 | 97 | ldy #0 98 | lda (rnbwTmp),y 99 | tax 100 | inx 101 | : 102 | lda (rnbwTmp),y 103 | sta BUF_OUT,y 104 | iny 105 | dex 106 | bne :- 107 | sta TX 108 | 109 | : 110 | bit TX 111 | bpl :- 112 | 113 | ; return 114 | rts 115 | .endproc 116 | 117 | .proc RNBW_waitReady 118 | 119 | ; ask for ESP status 120 | lda #1 121 | sta BUF_OUT+0 122 | lda #TO_ESP::ESP_GET_STATUS 123 | sta BUF_OUT+1 124 | sta TX 125 | 126 | ; wait for message to be sent 127 | : 128 | bit TX 129 | bpl :- 130 | 131 | ; wait for answer 132 | : 133 | bit RX 134 | bpl :- 135 | 136 | ; acknowledge answer 137 | sta RX 138 | 139 | ; return 140 | rts 141 | 142 | .endproc 143 | 144 | .proc RNBW_copyRXtoTX 145 | 146 | ; copy RX buffer to TX buffer 147 | ldx BUF_IN+0 148 | stx BUF_OUT+0 149 | : 150 | lda BUF_IN,x 151 | sta BUF_OUT,x 152 | dex 153 | bne :- 154 | 155 | ; return 156 | rts 157 | 158 | .endproc 159 | 160 | .proc RNBW_debug_A 161 | 162 | ; data to debug in A 163 | pha 164 | lda #2 165 | sta BUF_OUT+0 166 | lda #TO_ESP::DEBUG_LOG 167 | sta BUF_OUT+1 168 | pla 169 | sta BUF_OUT+2 170 | sta TX 171 | 172 | ; wait for message to be sent 173 | : 174 | bit TX 175 | bpl :- 176 | 177 | ; return 178 | rts 179 | 180 | .endproc 181 | 182 | .proc RNBW_debug_X 183 | 184 | ; data to debug in X 185 | lda #2 186 | sta BUF_OUT+0 187 | lda #TO_ESP::DEBUG_LOG 188 | sta BUF_OUT+1 189 | stx BUF_OUT+2 190 | sta TX 191 | 192 | ; wait for message to be sent 193 | : 194 | bit TX 195 | bpl :- 196 | 197 | ; return 198 | rts 199 | 200 | .endproc 201 | 202 | .proc RNBW_debug_Y 203 | 204 | ; data to debug in Y 205 | lda #2 206 | sta BUF_OUT+0 207 | lda #TO_ESP::DEBUG_LOG 208 | sta BUF_OUT+1 209 | sty BUF_OUT+2 210 | sta TX 211 | 212 | ; wait for message to be sent 213 | : 214 | bit TX 215 | bpl :- 216 | 217 | ; return 218 | rts 219 | 220 | .endproc 221 | 222 | .proc RNBW_getWifiStatus 223 | 224 | ; ask for wifi status 225 | lda #1 226 | sta BUF_OUT+0 227 | lda #TO_ESP::WIFI_GET_STATUS 228 | sta BUF_OUT+1 229 | sta TX 230 | 231 | ; wait for message to be sent 232 | : 233 | bit TX 234 | bpl :- 235 | 236 | ; wait for answer 237 | : 238 | bit RX 239 | bpl :- 240 | 241 | ; return wifi status in A 242 | lda BUF_IN+2 243 | 244 | ; acknowledge answer 245 | sta RX 246 | 247 | ; return 248 | rts 249 | 250 | .endproc 251 | 252 | .proc RNBW_getServerStatus 253 | 254 | ; ask for server status 255 | lda #1 256 | sta BUF_OUT+0 257 | lda #TO_ESP::SERVER_GET_STATUS 258 | sta BUF_OUT+1 259 | sta TX 260 | 261 | ; wait for message to be sent 262 | : 263 | bit TX 264 | bpl :- 265 | 266 | ; wait for answer 267 | : 268 | bit RX 269 | bpl :- 270 | 271 | ; return server status in A 272 | lda BUF_IN+2 273 | 274 | ; acknowledge answer 275 | sta RX 276 | 277 | ; return 278 | rts 279 | 280 | .endproc 281 | 282 | .proc RNBW_getRandomByte 283 | 284 | lda #1 285 | sta BUF_OUT+0 286 | lda #TO_ESP::RND_GET_BYTE 287 | sta BUF_OUT+1 288 | sta TX 289 | 290 | ; wait for message to be sent 291 | : 292 | bit TX 293 | bpl :- 294 | 295 | ; wait for answer 296 | : 297 | bit RX 298 | bpl :- 299 | 300 | ; return random byte in A 301 | lda BUF_IN+2 302 | 303 | ; acknowledge answer 304 | sta RX 305 | 306 | ; return 307 | rts 308 | 309 | .endproc 310 | 311 | .proc RNBW_getRandomByteRange 312 | ; X: min 313 | ; Y: max 314 | 315 | lda #3 316 | sta BUF_OUT+0 317 | lda #TO_ESP::RND_GET_BYTE_RANGE 318 | sta BUF_OUT+1 319 | stx BUF_OUT+2 320 | sty BUF_OUT+3 321 | sta TX 322 | 323 | ; wait for message to be sent 324 | : 325 | bit TX 326 | bpl :- 327 | 328 | ; wait for answer 329 | : 330 | bit RX 331 | bpl :- 332 | 333 | ; return random byte in A 334 | lda BUF_IN+2 335 | 336 | ; acknowledge answer 337 | sta RX 338 | 339 | ; return 340 | rts 341 | 342 | .endproc 343 | 344 | .proc RNBW_getRandomWord 345 | 346 | lda #1 347 | sta BUF_OUT+0 348 | lda #TO_ESP::RND_GET_WORD 349 | sta BUF_OUT+1 350 | sta TX 351 | 352 | ; wait for message to be sent 353 | : 354 | bit TX 355 | bpl :- 356 | 357 | ; wait for answer 358 | : 359 | bit RX 360 | bpl :- 361 | 362 | ; return random word in A (hi) and X (lo) 363 | lda BUF_IN+2 364 | ldx BUF_IN+3 365 | 366 | ; acknowledge answer 367 | sta RX 368 | 369 | ; return 370 | rts 371 | 372 | .endproc 373 | /* 374 | ; can't pass 4 arguments 375 | .proc RNBW_getRandomWordRange 376 | ; X: min 377 | ; Y: max 378 | 379 | lda #3 380 | sta BUF_OUT+0 381 | lda #TO_ESP::RND_GET_WORD_RANGE 382 | sta BUF_OUT+1 383 | stx BUF_OUT+2 384 | sty BUF_OUT+3 385 | sta TX 386 | 387 | ; wait for message to be sent 388 | : 389 | bit TX 390 | bpl :- 391 | 392 | ; wait for answer 393 | : 394 | bit RX 395 | bpl :- 396 | 397 | ; return 398 | rts 399 | .endproc 400 | */ 401 | 402 | .endscope -------------------------------------------------------------------------------- /NES/chr-rom-self-flashing.md: -------------------------------------------------------------------------------- 1 | # Rainbow CHR-ROM self-flashing how-to 2 | 3 | ## Introduction 4 | 5 | This document explains how to erase/program the flash memory directly from your code. This can be useful for game saves, game updates, additional content, etc. 6 | 7 | **Since those operations are not immediate, you need to execute your code from RAM so your game/program can still run while the flash chip is being updated.** 8 | 9 | Keep in mind that flash memory chips have a limited number of cycles (which is alse called endurance in datasheets), a cycle being an erase/program process per byte. Device specifications usually give a minimum of 10 000 cycles, and a guaranteed typical endurance of 100 000 cycles. 10 | 11 | Beyond those 100 000 cycles, errors may appear while erasing/programming the chip. 12 | 13 | In this document, the term _program_ instead of _write_ will be used to match the flash datasheets. 14 | 15 | Please read [S29GL064S datasheet]() for more general informations. This may not be the exact same flash chip used on your board, but most of the information should be true for another equivalent flash chip. 16 | 17 | ## Banks init 18 | 19 | There is no need to initialize the CHR banks in any specific way to perform erase/program actions, except for the destination bank of course. 20 | 21 | For example purpose, we will be using CHR mode 0 (1 x 8K banks), and use bank at \$0000-\$1FFF as our destination bank. 22 | 23 | ``` 24 | ; set CHR mode 0 25 | lda #0 26 | sta $4120 27 | 28 | lda #0 29 | sta $4130 30 | lda destination_bank ; must be a multiple of 8 since we erase 64K sectors (8 x 8K = 64K) 31 | sta $4140 32 | ``` 33 | 34 | ## Erasing 35 | 36 | Before you can program a new byte, you need to erase it. 37 | 38 | Unfortunately you cannot erase just one byte, you can only erase 64K sectors or the entire chip. 39 | 40 | ## Sector Erase 41 | 42 | To erase a sector, you need to write specific bytes at specific addresses to send a sector-erase command to the flash memory. 43 | 44 | Since the NES can only access the CHR-ROM via PPU registers, the erase command sequence is a bit longer than for the PRG-ROM. 45 | 46 | ``` 47 | ; erase command sequence 48 | 49 | ; first write: $AA @ $0AAA 50 | lda #$0A 51 | sta $2006 52 | lda #$AA 53 | sta $2006 54 | lda #$AA 55 | sta $2007 56 | 57 | ; second write: $55 @ $0555 58 | lda #$05 59 | sta $2006 60 | lda #$55 61 | sta $2006 62 | lda #$55 63 | sta $2007 64 | 65 | ; third write: $80 @ $0AAA 66 | lda #$0A 67 | sta $2006 68 | lda #$AA 69 | sta $2006 70 | lda #$80 71 | sta $2007 72 | 73 | ; fourth write: $AA @ $0AAA 74 | lda #$0A 75 | sta $2006 76 | lda #$AA 77 | sta $2006 78 | lda #$AA 79 | sta $2007 80 | 81 | ; fifth write: $55 @ $0555 82 | lda #$05 83 | sta $2006 84 | lda #$55 85 | sta $2006 86 | lda #$55 87 | sta $2007 88 | 89 | ; actual sector erase command 90 | 91 | ; sixth write: $30 @ $0000 92 | lda #$00 93 | sta $2006 94 | sta $2006 95 | lda #$30 96 | sta $2007 97 | ``` 98 | 99 | Doing this will erase 64K of data in the sector defined by the selected bank. 100 | Using CHR mode 0 means that 8K bank value controls Amax-A13, and 64K sector is defined by Amax-A16. 101 | So to erase the first 64K sector, you can point to any 8K between 0 and 7. 102 | Erasing means that all bytes will be set to $FF. 103 | 104 | ## Chip Erase 105 | 106 | To erase the chip completely, you need to write specific bytes at specific addresses to send a chip-erase command to the flash memory. 107 | 108 | Since the NES can only access the CHR-ROM via PPU registers, the erase command sequence is a bit longer than for the PRG-ROM. 109 | 110 | ``` 111 | ; erase command sequence 112 | 113 | ; first write: $AA @ $0AAA 114 | lda #$0A 115 | sta $2006 116 | lda #$AA 117 | sta $2006 118 | lda #$AA 119 | sta $2007 120 | 121 | ; second write: $55 @ $0555 122 | lda #$05 123 | sta $2006 124 | lda #$55 125 | sta $2006 126 | lda #$55 127 | sta $2007 128 | 129 | ; third write: $80 @ $0AAA 130 | lda #$0A 131 | sta $2006 132 | lda #$AA 133 | sta $2006 134 | lda #$80 135 | sta $2007 136 | 137 | ; fourth write: $AA @ $0AAA 138 | lda #$0A 139 | sta $2006 140 | lda #$AA 141 | sta $2006 142 | lda #$AA 143 | sta $2007 144 | 145 | ; fifth write: $55 @ $0555 146 | lda #$05 147 | sta $2006 148 | lda #$55 149 | sta $2006 150 | lda #$55 151 | sta $2007 152 | 153 | ; actual chip erase command 154 | 155 | ; sixth write: $10 @ $0AAA 156 | lda #$0A 157 | sta $2006 158 | lda #$AA 159 | sta $2006 160 | lda #$10 161 | sta $2007 162 | ``` 163 | 164 | Doing this will erase all bytes of the flash memory. 165 | Erasing means that all bytes will be set to $FF. 166 | 167 | ## Programming 168 | 169 | Once you erased a sector (or the entire chip), you can now program it. 170 | 171 | ### Byte Program 172 | 173 | To program a byte, you need to write specific bytes at specific addresses to send a byte-program command to the flash memory. 174 | 175 | Since the NES can only access the CHR-ROM via PPU registers, the erase command sequence is a bit longer than for the PRG-ROM. 176 | 177 | ``` 178 | ; byte program command sequence 179 | 180 | ; first write: $AA @ $0AAA 181 | lda #$0A 182 | sta $2006 183 | lda #$AA 184 | sta $2006 185 | lda #$AA 186 | sta $2007 187 | 188 | ; second write: $55 @ $0555 189 | lda #$05 190 | sta $2006 191 | lda #$55 192 | sta $2006 193 | lda #$55 194 | sta $2007 195 | 196 | ; third write: $A0 @ $0AAA 197 | lda #$0A 198 | sta $2006 199 | lda #$AA 200 | sta $2006 201 | lda #$A0 202 | sta $2007 203 | 204 | ; program the actual value 205 | 206 | ; fourth write: program the actual value 207 | lda destination_address+0 208 | sta $2006 209 | lda destination_address+1 210 | sta $2006 211 | lda value_to_write 212 | sta $2007 213 | ``` 214 | 215 | And that is it, your new byte is programmed. 216 | You may want to verify that everything goes well though. 217 | 218 | ## Verifying 219 | 220 | After erasing or programming the flash, it is good practice to make sure that the command was sucessful. As stated in the introduction, those commands are not immediate, and you need to make sure that they worked as intended before doing something else. 221 | 222 | After erasing or programming, bit 6 will toggle on each read, so we can wait until it is stable. 223 | This is a simple naive way of doing it and it can lead to a program lock, but it is usually enough. 224 | 225 | ### Erase 226 | 227 | After sending an erase command (sector erase or chip erase), you need to wait until you can read back $ff from the sector/chip before programming it again. 228 | 229 | ``` 230 | verifyLoop: 231 | ; read once and save 232 | lda destination_address+0 233 | sta $2006 234 | lda destination_address+1 235 | sta $2006 236 | lda $2007 ; dummy read 237 | lda $2007 238 | sta $FF 239 | 240 | ; read a second time and check 241 | lda destination_address+0 242 | sta $2006 243 | lda destination_address+1 244 | sta $2006 245 | lda $2007 ; dummy read 246 | lda $2007 247 | cmp $ff 248 | bne verifyLoop 249 | ``` 250 | 251 | ## Software ID 252 | 253 | Autoselect mode commands allow you to get the chip manufacturer ID, device ID and other information. It can be used to determine the size of the PRG flash chip and sector sizes for advanced usage. We will only see how to get the manufacturer ID and the device ID. 254 | 255 | ### Entry 256 | 257 | To enter the autoselect mode, you need to write specific bytes at specific addresses. 258 | 259 | ``` 260 | ; first write: $AA @ $0AAA 261 | lda #$0A 262 | sta $2006 263 | lda #$AA 264 | sta $2006 265 | lda #$AA 266 | sta $2007 267 | 268 | ; second write: $55 @ $0555 269 | lda #$05 270 | sta $2006 271 | lda #$55 272 | sta $2006 273 | lda #$55 274 | sta $2007 275 | 276 | ; third write: $90 @ $0AAA 277 | lda #$0A 278 | sta $2006 279 | lda #$AA 280 | sta $2006 281 | lda #$90 282 | sta $2007 283 | ``` 284 | 285 | ### Read 286 | 287 | Once you are in the software ID mode, you can read the manufacturer ID and the flash chip ID. 288 | 289 | ``` 290 | lda #$00 291 | sta $2006 292 | sta $2006 293 | lda $2007 ; dummy read 294 | lda $2007 ; read $xx00 to get manufacturer ID 295 | ; Cypress: $01 296 | ; ISSI: $9D 297 | ; MX: $C2 298 | ; SST: $BF 299 | lda $2007 ; ignore read @ $xx01 300 | lda $2007 ; read $xx02 to get device ID 1, value depends on device 301 | 302 | lda #$00 303 | sta $2006 304 | lda #$1C 305 | sta $2006 306 | lda $2007 ; read $xx1C to get device ID 2, value depends on device 307 | lda $2007 ; ignore read @ $xx1D 308 | lda $2007 ; read $xx1E to get device ID 3, value depends on device 309 | ``` 310 | 311 | ## Exit 312 | 313 | To exit the _autoselect mode_, you just run this simple command. 314 | 315 | ``` 316 | ; software ID exit command 317 | 318 | ; setting the address is optional here, since the address does not matter 319 | lda #$00 320 | sta $2006 321 | sta $2006 322 | 323 | lda #$F0 324 | sta $2007 325 | ``` 326 | -------------------------------------------------------------------------------- /NES/mapper-doc.md: -------------------------------------------------------------------------------- 1 | # Rainbow mapper documentation 2 | 3 | Rainbow or RNBW is a cartridge board intended for homebrew releases with its own unique mapper assigned to iNES Mapper 682. 4 | The cartridge was initially designed with Wi-Fi capabilities in mind (Rainbow NET protocol), but can also be used without it. 5 | The board and mapper were designed by Broke Studio which also manufactures the cartridges. 6 | 7 | # Overview 8 | 9 | - Wi-Fi capabilities to allow online gaming, cartridge update, downloadable content and more... (optional, needs the Wi-Fi chip to work) 10 | - Embedded bootrom to perform multiple task (manage networks, manage files, flash the cart, ...) 11 | - On board micro SD card support 12 | - 5 PRG-ROM banking modes 13 | - 2 PRG-RAM banking modes 14 | - 5 CHR-ROM/CHR-RAM banking modes 15 | - 8K of FPGA-RAM 16 | - first 4K are shared between CPU and PPU so it can be updated during rendering and used as nametables or pattern tables or extended tiles/attributes tables or as general purpose PRG-RAM 17 | - next 2K can be used as general purpose PRG-RAM 18 | - last 2K are used to communicate with the Wi-Fi chip and can also be used as general purpose PRG-RAM 19 | - Up to 8MiB PRG-ROM 20 | - Up to 8MiB CHR-ROM 21 | - 32K or 128K of PRG-RAM 22 | - 32K or 128K of CHR-RAM 23 | - Self-flashable PRG-ROM 24 | - Self-flashable CHR-ROM 25 | - Scanline counter 26 | - Configurable IRQ 27 | - Frame detection with status bit 28 | - HBlank detection with status bit 29 | - M2 "jitter" counter 30 | - CPU cycle counter 31 | - CPU cycle parity 32 | - configurable IRQ 33 | - Nametables can be individually mapped to CIRAM/FPGA-RAM/CHR-RAM/CHR-ROM 34 | - Pattern tables can be mapped to CHR-ROM/CHR-RAM/FPGA-RAM/CIRAM 35 | - Attribute Extended Mode allows each individual 8x8 tile to have its own palette setting 36 | - Background Extended Mode allows to address up to 16384 tiles 37 | - Sprite Extended Mode allows to address up to 65535 tiles 38 | - Auto-generated OAM procedures 39 | - OAM slow clear routine 40 | - OAM slow update routine 41 | - OAM Extended bank update routine 42 | - Window Split Mode 43 | - Expansion audio: 44 | - 2 pulse channels 45 | - 1 sawtooth channel 46 | - IPCM mode that allows expansion audio on stock NES 47 | - System reset detection 48 | - resets main registers 49 | 50 | # Banks 51 | 52 | The Rainbow mapper provides: 53 | 54 | - PRG-ROM: 5 banking modes 55 | - PRG-RAM: 2 banking modes 56 | - CHR-ROM/RAM: 5 banking modes 57 | - FPGA-RAM: 1 banking mode 58 | 59 | ## PRG-ROM mode 0 60 | 61 | - CPU \$8000-\$FFFF: 32 KB switchable PRG-ROM/PRG-RAM bank 62 | 63 | ## PRG-ROM mode 1 64 | 65 | - CPU \$8000-\$BFFF: 16 KB switchable PRG-ROM/PRG-RAM bank 66 | - CPU \$C000-\$FFFF: 16 KB switchable PRG-ROM/PRG-RAM bank 67 | 68 | ## PRG-ROM mode 2 69 | 70 | - CPU \$8000-\$BFFF: 16 KB switchable PRG-ROM/PRG-RAM bank 71 | - CPU \$C000-\$DFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 72 | - CPU \$E000-\$FFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 73 | 74 | ## PRG-ROM mode 3 75 | 76 | - CPU \$8000-\$9FFF: 8 KB switchable PRG-ROM/PRG-RAM bank 77 | - CPU \$A000-\$BFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 78 | - CPU \$C000-\$DFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 79 | - CPU \$E000-\$FFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 80 | 81 | ## PRG-ROM mode 4 82 | 83 | - CPU \$8000-\$8FFF: 4 KB switchable PRG-ROM/PRG-RAM bank 84 | - CPU \$9000-\$9FFF: 4 KB switchable PRG-ROM/PRG-RAM bank 85 | - CPU \$A000-\$AFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 86 | - CPU \$B000-\$BFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 87 | - CPU \$C000-\$CFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 88 | - CPU \$D000-\$DFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 89 | - CPU \$E000-\$EFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 90 | - CPU \$F000-\$FFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 91 | 92 | ## PRG-RAM mode 0 93 | 94 | - CPU \$6000-\$7FFF: 8 KB switchable PRG-RAM/PRG-ROM/FPGA-RAM bank 95 | 96 | ## PRG-RAM mode 1 97 | 98 | - CPU \$6000-\$6FFF: 4 KB switchable PRG-RAM/ROM/FPGA-RAM bank 99 | - CPU \$7000-\$7FFF: 4 KB switchable PRG-RAM/ROM/FPGA-RAM bank 100 | 101 | ## FPGA-RAM 102 | 103 | - CPU \$4800-\$4FFF: last 2KB of the FPGA-RAM 104 | - CPU \$5000-\$5FFF: 4KB switchable FPGA-RAM bank 105 | 106 | ## CHR mode 0 107 | 108 | - PPU \$0000-\$1FFF: 8 KB switchable CHR bank 109 | 110 | ## CHR mode 1 111 | 112 | - PPU \$0000-\$0FFF: 4 KB switchable CHR bank 113 | - PPU \$1000-\$1FFF: 4 KB switchable CHR bank 114 | 115 | ## CHR mode 2 116 | 117 | - PPU \$0000-\$07FF: 2 KB switchable CHR bank 118 | - PPU \$0800-\$0FFF: 2 KB switchable CHR bank 119 | - PPU \$1000-\$17FF: 2 KB switchable CHR bank 120 | - PPU \$1800-\$1FFF: 2 KB switchable CHR bank 121 | 122 | ## CHR mode 3 123 | 124 | - PPU \$0000-\$03FF: 1 KB switchable CHR bank 125 | - PPU \$0400-\$07FF: 1 KB switchable CHR bank 126 | - PPU \$0800-\$0BFF: 1 KB switchable CHR bank 127 | - PPU \$0C00-\$0FFF: 1 KB switchable CHR bank 128 | - PPU \$1000-\$13FF: 1 KB switchable CHR bank 129 | - PPU \$1400-\$17FF: 1 KB switchable CHR bank 130 | - PPU \$1800-\$1BFF: 1 KB switchable CHR bank 131 | - PPU \$1C00-\$1FFF: 1 KB switchable CHR bank 132 | 133 | ## CHR mode 4 134 | 135 | - PPU \$0000-\$01FF: 512B switchable CHR bank 136 | - PPU \$0200-\$03FF: 512B switchable CHR bank 137 | - PPU \$0400-\$05FF: 512B switchable CHR bank 138 | - PPU \$0600-\$07FF: 512B switchable CHR bank 139 | - PPU \$0800-\$09FF: 512B switchable CHR bank 140 | - PPU \$0A00-\$0BFF: 512B switchable CHR bank 141 | - PPU \$0C00-\$0DFF: 512B switchable CHR bank 142 | - PPU \$0E00-\$0FFF: 512B switchable CHR bank 143 | - PPU \$1000-\$11FF: 512B switchable CHR bank 144 | - PPU \$1200-\$13FF: 512B switchable CHR bank 145 | - PPU \$1400-\$15FF: 512B switchable CHR bank 146 | - PPU \$1600-\$17FF: 512B switchable CHR bank 147 | - PPU \$1800-\$19FF: 512B switchable CHR bank 148 | - PPU \$1A00-\$1BFF: 512B switchable CHR bank 149 | - PPU \$1C00-\$1DFF: 512B switchable CHR bank 150 | - PPU \$1E00-\$1FFF: 512B switchable CHR bank 151 | 152 | # Registers 153 | 154 | ## Power-up and reset register status 155 | 156 | On power-up and reset, some registers are initialized/reset with specific values. 157 | 158 | | Register | Value | Note | 159 | | -------- | ----- | -------------------------------------------------------------------------------------- | 160 | | | | **PRG settings** | 161 | | \$4100 | \$00 | Set PRG-ROM mode 0 (32K banks) and PRG-RAM mode 0 (8K banks) | 162 | | \$4108 | \$00 | Set PRG-ROM 32K bank upper bits to $00 so it will address the first bank | 163 | | \$4118 | \$00 | Set PRG-ROM 32K bank lower bits to $00 so it will address the first bank | 164 | | | | **CHR settings** | 165 | | \$4120 | \$00 | Set CHR mode 0 (8K banks), CHR-ROM as pattern table, | 166 | | | | disable Sprite Extended Mode, disable Window Split Mode | 167 | | \$4130 | \$00 | Set CHR 8K bank upper bits to $00 so it will address the first bank | 168 | | \$4140 | \$00 | Set CHR 8K bank lower bits to $00 so it will address the first bank | 169 | | | | **Nametables settings (horizontal mirroring using CIRAM)** | 170 | | \$4126 | \$00 | Set nametable @ \$2000 bank to 0 | 171 | | \$4127 | \$00 | Set nametable @ \$2400 bank to 0 | 172 | | \$4128 | \$01 | Set nametable @ \$2800 bank to 1 | 173 | | \$4129 | \$01 | Set nametable @ \$2C00 bank to 1 | 174 | | \$412E | \$00 | Set Window Split Mode nametable bank to 0 | 175 | | \$412A | \$00 | Set nametable @ \$2000 chip selector to CIRAM | 176 | | \$412B | \$00 | Set nametable @ \$2400 chip selector to CIRAM | 177 | | \$412C | \$00 | Set nametable @ \$2800 chip selector to CIRAM | 178 | | \$412D | \$00 | Set nametable @ \$2C00 chip selector to CIRAM | 179 | | \$412F | \$80 | Set Window Split Mode nametable chip selector to FPGA-RAM | 180 | | | | **Auto-generated OAM procedures** | 181 | | \$4241 | \$07 | Set the OAM slow update page to 7, using $4F00 as the OAM shadow data source | 182 | | \$4242 | \$06 | Set the OAM ext update page to 6, using $4E00 as the Sprite Extended Banks data source | 183 | | | | **Scanline IRQ settings** | 184 | | \$4152 | \$00 | Disable scanline IRQ (IRQ cleared if pending) | 185 | | \$4153 | \$87 | Set scanline IRQ offset to 135 | 186 | | | | **CPU Cycle IRQ settings** | 187 | | \$415A | \$00 | Disable CPU Cycle IRQ (IRQ cleared if pending) | 188 | | | | **Vector redirection** | 189 | | \$416B | \$00 | Disable NMI and IRQ vector redirection | 190 | | | | **Wi-Fi** | 191 | | \$4190 | \$00 | Disable Wi-Fi | 192 | | | | **Audio Expansion** | 193 | | \$41A9 | \$03 | Enable EXP6 and EXP9 outputs, disable IPCM, disable EPSM | 194 | | \$41AA | \$0F | Set default master volume | 195 | 196 | ## PRG banking modes (\$4100, read/write) 197 | 198 | ``` 199 | 7 bit 0 200 | ---- ---- 201 | A... .OOO 202 | | ||| 203 | | +++- PRG-ROM banking mode 204 | | 000: 32K (mode 0) 205 | | 001: 16K + 16K (mode 1) 206 | | 010: 16K + 8K + 8K (mode 2) 207 | | 011: 8K + 8K + 8K + 8K (mode 3) 208 | | 1xx: 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K (mode 4) 209 | +--------- PRG-RAM banking mode 210 | 0: 8K 211 | 1: 4K + 4K 212 | ``` 213 | 214 | ## PRG-ROM banking (\$4108-\$410F and \$4118-\$411F, write-only) 215 | 216 | ### Bank upper bits and chip selector 217 | 218 | - \$4108 (W) 219 | - CPU \$8000-\$FFFF (mode 0) 220 | - CPU \$8000-\$BFFF (mode 1) 221 | - CPU \$8000-\$BFFF (mode 2) 222 | - CPU \$8000-\$9FFF (mode 3) 223 | - CPU \$8000-\$8FFF (mode 4) 224 | - \$4109 (W) 225 | - CPU \$9000-\$9FFF (mode 4) 226 | - \$410A (W) 227 | - CPU \$A000-\$BFFF (mode 3) 228 | - CPU \$A000-\$AFFF (mode 4) 229 | - \$410B (W) 230 | - CPU \$B000-\$BFFF (mode 4) 231 | - \$410C (W) 232 | - CPU \$C000-\$FFFF (mode 1) 233 | - CPU \$C000-\$DFFF (mode 2) 234 | - CPU \$C000-\$DFFF (mode 3) 235 | - CPU \$C000-\$CFFF (mode 4) 236 | - \$410D (W) 237 | - CPU \$D000-\$DFFF (mode 4) 238 | - \$410E (W) 239 | - CPU \$E000-\$FFFF (mode 2) 240 | - CPU \$E000-\$FFFF (mode 3) 241 | - CPU \$E000-\$EFFF (mode 4) 242 | - \$410F (W) 243 | - CPU \$F000-\$FFFF (mode 4) 244 | 245 | ``` 246 | 7 bit 0 247 | ---- ---- 248 | C... .UUU 249 | | ||| 250 | | +++- Bank index upper bits 251 | +--------- Chip selector 252 | 0: PRG-ROM 253 | 1: PRG-RAM 254 | ``` 255 | 256 | ### Bank lower bits 257 | 258 | - \$4118 (W) 259 | - CPU \$8000-\$FFFF (mode 0) 260 | - CPU \$8000-\$BFFF (mode 1) 261 | - CPU \$8000-\$BFFF (mode 2) 262 | - CPU \$8000-\$9FFF (mode 3) 263 | - CPU \$8000-\$8FFF (mode 4) 264 | - \$4119 (W) 265 | - CPU \$9000-\$9FFF (mode 4) 266 | - \$411A (W) 267 | - CPU \$A000-\$BFFF (mode 3) 268 | - CPU \$A000-\$AFFF (mode 4) 269 | - \$411B (W) 270 | - CPU \$B000-\$BFFF (mode 4) 271 | - \$411C (W) 272 | - CPU \$C000-\$FFFF (mode 1) 273 | - CPU \$C000-\$DFFF (mode 2) 274 | - CPU \$C000-\$DFFF (mode 3) 275 | - CPU \$C000-\$CFFF (mode 4) 276 | - \$411D (W) 277 | - CPU \$D000-\$DFFF (mode 4) 278 | - \$411E (W) 279 | - CPU \$E000-\$FFFF (mode 2) 280 | - CPU \$E000-\$FFFF (mode 3) 281 | - CPU \$E000-\$EFFF (mode 4) 282 | - \$411F (W) 283 | - CPU \$F000-\$FFFF (mode 4) 284 | 285 | ``` 286 | 7 bit 0 287 | ---- ---- 288 | LLLL LLLL 289 | |||| |||| 290 | ++++-++++- Bank index lower bits 291 | ``` 292 | 293 | ## PRG-RAM banking (\$4106-\$4107 and \$4116-\$4117, write-only) 294 | 295 | ### Bank upper bits and chip selector 296 | 297 | - \$4106 (W) 298 | - CPU \$6000-\$7FFF (mode 0) 299 | - CPU \$6000-\$6FFF (mode 1) 300 | - \$4107 (W) 301 | - CPU \$7000-\$7FFF (mode 1) 302 | 303 | ``` 304 | 7 bit 0 305 | ---- ---- 306 | CC.. UUUU 307 | || |||| 308 | || ++++- Bank index upper bits 309 | ++-------- Chip selector 310 | 0x: PRG-ROM 311 | 10: PRG-RAM 312 | 11: FPGA-RAM 313 | If using PRG-RAM 8K mode, then bank number is ignored since FPGA-RAM is only 8K. 314 | If using PRG-RAM 4K mode, then only the bank number lower bit is used to select the 4K page. 315 | ``` 316 | 317 | ### Bank lower bits 318 | 319 | - \$4116 (W) 320 | - CPU \$6000-\$7FFF (mode 0) 321 | - CPU \$6000-\$6FFF (mode 1) 322 | - \$4117 (W) 323 | - CPU \$7000-\$7FFF (mode 1) 324 | 325 | ``` 326 | 7 bit 0 327 | ---- ---- 328 | LLLL LLLL 329 | |||| |||| 330 | ++++-++++- Bank index lower bits 331 | ``` 332 | 333 | ## FPGA-RAM banking (\$4115, write-only) 334 | 335 | - \$4115 (W) 336 | - CPU \$5000-\$5FFF 337 | 338 | ``` 339 | 7 bit 0 340 | ---- ---- 341 | .... ...B 342 | | 343 | +- Bank index (select 4K page of FPGA-RAM) 344 | ``` 345 | 346 | ## CHR configuration 347 | 348 | Some CHR configurations involve the first 4K of FPGA-RAM. 349 | It can be used as nametables, pattern tables, 8x8 attribute tables, extended tiles (can address up to 16384 tiles). 350 | It is important to keep in mind that those first 4K of FPGA-RAM are shared between CPU and PPU so it can be updated during rendering. 351 | 352 | **/!\ Using FPGA-RAM as nametable _and_ pattern table is _not_ a good idea.** 353 | 354 | ### CHR control (banking modes / source / Sprite Extended Mode / Window Split Mode) (\$4120, read/write) 355 | 356 | ``` 357 | 7 bit 0 358 | ---- ---- 359 | CCSW .BBB 360 | |||| ||| 361 | |||| +++- CHR banking mode 362 | |||| 000: 8K CHR mode 0 (CHR bank 0 is used) 363 | |||| 001: 4K CHR mode 1 (CHR bank 0 to 1 are used) 364 | |||| 010: 2K CHR mode 2 (CHR banks 0 to 3 are used) 365 | |||| 011: 1K CHR mode 3 (CHR banks 0 to 7 are used) - see note below 366 | |||| 1xx: 512B CHR mode 4 (CHR banks 0 to 15 are used) - see note below 367 | |||+------ Window Split Mode (0: disabled, 1: enabled) 368 | ||+------- Sprite Extended Mode (0: disabled, 1: enabled), see registers $4200-$4240 369 | ++-------- Chip selector for pattern tables 370 | 00: CHR-ROM 371 | 01: CHR-RAM 372 | 10: FPGA-RAM (4K mode is forced, \$0000-\$0FFF mirrored at \$1000-\$1FFF, banking settings are ignored) 373 | 11: CIRAM 374 | 375 | Note: when using 1K and 512B CHR banking modes with 512K (or more) CHR-ROM, 376 | you also need to update the CHR bank upper bits using the appropriate registers (\$4130-\$413F) 377 | ``` 378 | 379 | ### Background Extended Mode bank upper bits (\$4121, write-only) 380 | 381 | ``` 382 | 7 bit 0 383 | ---- ---- 384 | ...U UUUU 385 | |-|||| 386 | +-++++- 387 | ``` 388 | 389 | When using Background Extended Mode, you can address up to 16384 tiles. 390 | This registers is used to select a 256K CHR offset for every tiles. 391 | 392 | ### Nametables bank ($4126-$4129, write-only) 393 | 394 | - \$4126 controls nametable at \$2000 395 | - \$4127 controls nametable at \$2400 396 | - \$4128 controls nametable at \$2800 397 | - \$4129 controls nametable at \$2C00 398 | - \$412E controls Window Split nametable 399 | 400 | ``` 401 | 7 bit 0 402 | ---- ---- 403 | BBBB BBBB 404 | |||| |||| 405 | ++++-++++- Bank index 406 | Depending on chip source (CIRAM, CHR-ROM, CHR-RAM or FPGA-RAM) used for the corresponding nametable, 407 | not all bits are used. 408 | ``` 409 | 410 | ### Nametables control ($412A-$412D, read-write) 411 | 412 | - \$412A controls nametable at \$2000 413 | - \$412B controls nametable at \$2400 414 | - \$412C controls nametable at \$2800 415 | - \$412D controls nametable at \$2C00 416 | - \$412F controls Window Split nametable 417 | 418 | ``` 419 | 7 bit 0 420 | ---- ---- 421 | CCF. DDEE 422 | ||| |||| 423 | ||| |||| 424 | ||| ||++- Extended Modes 425 | ||| || 00: Extended Modes disabled 426 | ||| || 01: Attribute Extended Mode 427 | ||| || 10: Background Extended Mode 428 | ||| || 11: Attribute Extended Mode + Background Extended Mode 429 | ||| ++--- 1K destination in 4K FPGA-RAM 430 | ||| Used when Extended mode above is not %00 431 | ||| 00: 1st 1K of FPGA-RAM 432 | ||| 01: 2nd 1K of FPGA-RAM 433 | ||| 10: 3rd 1K of FPGA-RAM 434 | ||| 11: 4th 1K of FPGA-RAM 435 | ||+------- Fill-mode (0: disable, 1: enable, see $4124 and $4125) 436 | ++-------- Chip selector (forced to FPGA-RAM for $412F) 437 | 00: CIRAM 438 | 01: CHR-RAM 439 | 10: FPGA-RAM 440 | 11: CHR-ROM 441 | ``` 442 | 443 | Note: 444 | 445 | - Window Split chip will be forced to FPGA-RAM. 446 | 447 | #### Extended Modes 448 | 449 | When using Attribute Extended Mode and/or Background Extended Mode, values written to the corresponding 1K of FPGA-RAM are used to extend the tile read from the nametable. 450 | 451 | Extended byte format: 452 | 453 | ``` 454 | 7 bit 0 455 | ---- ---- 456 | AABB BBBB 457 | |||| |||| 458 | ||++-++++- Select 4 KB CHR bank to use with specified tile (Background Extended Mode) 459 | ++-------- Select palette to use with specified tile (Attribute Extended Mode) 460 | ``` 461 | 462 | In Background extended mode, CHR banking behaves differently than normal when fetching tiles from pattern tables: 463 | 464 | - CHR banking mode (register \$4120) is ignored but not CHR source (register \$4120) 465 | - CHR banks are always 4KB in this mode 466 | - The values of the CHR banking registers \$4130-\$414F are also ignored 467 | - Bits 0-5 specified above are used for selecting a 4KB CHR bank on a per-tile basis 468 | - Bits 0-4 of register $4121 are used for selecting a 256K CHR offset for every tiles 469 | 470 | #### Chip selector 471 | 472 | | Chip selector (CC) | Value | Notes | 473 | | ------------------ | ----- | ------------------------------------------------------------------------------ | 474 | | CIRAM | %00 | Only the lower bit of the corresponding nametable bank register is used | 475 | | | | to address either one or the other nametable provided by the console. | 476 | | | | | 477 | | CHR-RAM | %01 | Corresponding nametable bank register is used to address 1KB blocks of CHR-RAM | 478 | | | | Depending on the CHR-RAM size, not all bits will be used. | 479 | | | | | 480 | | FPGA-RAM | %10 | Only the two lower bits of the corresponding nametable bank register are used | 481 | | | | to address one of the 4KB of FPGA-RAM. | 482 | | | | Those 4KB of FPGA-RAM can also be accessed by the CPU at \$5000-$5FFF (bank 0) | 483 | | | | This means that you can update the nametable during rendering. | 484 | | | | /!\ Using FPGA-RAM as nametable **and** pattern table is not a good idea. | 485 | | | | /!\ Using FPGA-RAM as nametable **and** as Extended Mode data can be done | 486 | | | | under certain circumstances: | 487 | | | | - when using FPGA-RAM as nametable at \$2000 or \$2400, you can only | 488 | | | | use 3rd and 4th 1K bank of FPGA-RAM as Extended Mode data. | 489 | | | | - when using FPGA-RAM as nametable at \$2800 or \$2C00, you can only | 490 | | | | use 1st and 2nd 1K bank of FPGA-RAM as Extended Mode data. | 491 | | | | | 492 | | CHR-ROM | %11 | Corresponding nametable bank register is used to address 1KB blocks of CHR-ROM | 493 | | | | Depending on the CHR-ROM size, not all bits will be used | 494 | 495 | #### Nametables mirroring 496 | 497 | Mirroring depends on the way you arrange registers \$4126-\$4129 and \$412A-\$412D. 498 | 499 | | Mirroring | Registers configuration | 500 | | ------------- | --------------------------------------------- | 501 | | Horizontal | \$412A.CC = \$412B.CC | 502 | | | \$412C.CC = \$412D.CC | 503 | | | \$4126 = \$4127 | 504 | | | \$4128 = \$4129 | 505 | | Vertical | \$412A.CC = \$412C.CC | 506 | | | \$412B.CC = \$412D.CC | 507 | | | \$4126 = \$4128 | 508 | | | \$4127 = \$4129 | 509 | | Diagonal | \$412A.CC = \$412D.CC | 510 | | | \$412B.CC = \$412C.CC | 511 | | | \$4126 = \$4129 | 512 | | | \$4127 = \$4128 | 513 | | Single-screen | \$412A.CC = \$412B.CC = \$412C.CC = \$412D.CC | 514 | | | \$4126 = \$4127 = \$4128 = \$4129 | 515 | | 4-screen | All 4 nametables must have different settings | 516 | 517 | ## Fill-mode (\$4124-\$4125) 518 | 519 | When a nametable fill-mode is set to 1 (see registers \$4126-\$4129, \$412E), all nametable fetches get replaced by the value of register \$4124 for the tile index and \$4125 for the attribute index. Only the nametable is affected by fill-mode. When the PPU later uses this information to fetch the corresponding tile from the pattern table, CHR banking is unaffected and continues to work normally. 520 | 521 | ### Fill-mode tile index (\$4124, write-only) 522 | 523 | ``` 524 | 7 bit 0 525 | ---- ---- 526 | TTTT TTTT 527 | |||| |||| 528 | ++++-++++- Specify tile index to use for fill-mode nametable 529 | ``` 530 | 531 | ### Fill-mode attribute index (\$4125, write-only) 532 | 533 | ``` 534 | 7 bit 0 535 | ---- ---- 536 | .... ..AA 537 | || 538 | ++- Specify background palette index to use for fill-mode nametable 539 | ``` 540 | 541 | ## CHR banking (\$4130-\$414F, write-only) 542 | 543 | ### Bank bits 544 | 545 | - \$4130 (upper bits) / \$4140 (lower bits) (W) 546 | - PPU \$0000-\$1FFF (mode 0) 547 | - PPU \$0000-\$0FFF (mode 1) 548 | - PPU \$0000-\$07FF (mode 2) 549 | - PPU \$0000-\$03FF (mode 3) 550 | - PPU \$0000-\$01FF (mode 4) 551 | - \$4131 (upper bits) / \$4141 (lower bits) (W) 552 | - PPU \$1000-\$1FFF (mode 1) 553 | - PPU \$0800-\$0FFF (mode 2) 554 | - PPU \$0400-\$07FF (mode 3) 555 | - PPU \$0200-\$03FF (mode 4) 556 | - \$4132 (upper bits) / \$4142 (lower bits) (W) 557 | - PPU \$1000-\$17FF (mode 2) 558 | - PPU \$0800-\$0BFF (mode 3) 559 | - PPU \$0400-\$05FF (mode 4) 560 | - \$4133 (upper bits) / \$4143 (lower bits) (W) 561 | - PPU \$1800-\$1FFF (mode 2) 562 | - PPU \$0C00-\$0FFF (mode 3) 563 | - PPU \$0600-\$07FF (mode 4) 564 | - \$4134 (upper bits) / \$4144 (lower bits) (W) 565 | - PPU \$1000-\$13FF (mode 3) 566 | - PPU \$0800-\$09FF (mode 4) 567 | - \$4135 (upper bits) / \$4145 (lower bits) (W) 568 | - PPU \$1400-\$17FF (mode 3) 569 | - PPU \$0A00-\$0BFF (mode 4) 570 | - \$4136 (upper bits) / \$4146 (lower bits) (W) 571 | - PPU \$1800-\$1BFF (mode 3) 572 | - PPU \$0C00-\$0DFF (mode 4) 573 | - \$4137 (upper bits) / \$4147 (lower bits) (W) 574 | - PPU \$1C00-\$1FFF (mode 3) 575 | - PPU \$0E00-\$0FFF (mode 4) 576 | - \$4138 (upper bits) / \$4148 (lower bits) (W) 577 | - PPU \$1000-\$11FF (mode 4) 578 | - \$4139 (upper bits) / \$4149 (lower bits) (W) 579 | - PPU \$1200-\$13FF (mode 4) 580 | - \$413A (upper bits) / \$414A (lower bits) (W) 581 | - PPU \$1400-\$15FF (mode 4) 582 | - \$413B (upper bits) / \$414B (lower bits) (W) 583 | - PPU \$1600-\$17FF (mode 4) 584 | - \$413C (upper bits) / \$414C (lower bits) (W) 585 | - PPU \$1800-\$19FF (mode 4) 586 | - \$413D (upper bits) / \$414D (lower bits) (W) 587 | - PPU \$1A00-\$1BFF (mode 4) 588 | - \$413E (upper bits) / \$414E (lower bits) (W) 589 | - PPU \$1C00-\$1DFF (mode 4) 590 | - \$413F (upper bits) / \$414F (lower bits) (W) 591 | - PPU \$1E00-\$1FFF (mode 4) 592 | 593 | ``` 594 | 7 bit 0 595 | ---- ---- 596 | ...B BBBB 597 | | |||| 598 | +-++++- Bank index upper bits (\$413x) 599 | ``` 600 | 601 | ``` 602 | 7 bit 0 603 | ---- ---- 604 | BBBB BBBB 605 | |||| |||| 606 | ++++-++++- Bank index lower bits (\$414x) 607 | ``` 608 | 609 | ## Sprite Extended Mode (\$4200-\$4240) 610 | 611 | In Sprite Extended Mode, CHR banking behaves differently than normal when fetching tiles from pattern tables: 612 | 613 | - CHR banking mode (register \$4120) is ignored but not CHR source (register \$4120) 614 | - CHR banks are always 4KB in this mode 615 | - The values of the CHR banking registers \$4130-\$414F are also ignored 616 | - Registers \$4200-\$423F specify the bank lower bits for each sprite (4K CHR bank selector) allowing the possibility to address 65535 sprites 617 | - Register \$4240 specify the bank upper bits for all sprites (1024K CHR bank selector) 618 | 619 | ### Sprite Extended Mode bank lower bits (\$4200-\$423F, write-only) 620 | 621 | One register per sprite. 622 | 623 | ``` 624 | 7 bit 0 625 | ---- ---- 626 | LLLL LLLL 627 | |||| |||| 628 | ++++-++++- Bank index lower bits 629 | ``` 630 | 631 | ### Sprite Extended Mode bank upper bits (\$4240, write-only) 632 | 633 | The bank upper bits are common to every sprite. 634 | 635 | ``` 636 | 7 bit 0 637 | ---- ---- 638 | .... .UUU 639 | ||| 640 | +++- Bank index upper bits 641 | ``` 642 | 643 | ## Auto-generated OAM procedures 644 | 645 | You have access to 3 routines that allow you to easily clear/update OAM data without the need to write/update your own code in RAM: 646 | 647 | - **OAM slow update** allows you to update the sprites data for each sprite only using registers $2003/$2004 (no OAM DMA) 648 | - **OAM ext update** allows you to update the sprites extended bank automatically (when using Sprites Extended Mode) 649 | 650 | All you need to do is prepare your data in a specific RAM area (see routines details), and `jsr` to the corresponding routine start address. 651 | 652 | ### OAM slow update (\$4241, write-only and \$4280, executable) 653 | 654 | To execute this routine, you just need to do `jsr $4280`. 655 | This routine will update the sprites OAM data using only registers $2003/2004, and uses **1548** cycles including the final `rts` opcode. 656 | OAM data must be written to the \$4800-\$4FFF area. 657 | 658 | Register \$4241 sets the 256 bytes page to be used, starting at \$4800 (FPGA-RAM). 659 | 660 | ``` 661 | 7 bit 0 662 | ---- ---- 663 | .... .PPP 664 | ||| 665 | +++- OAM shadow page index 666 | ``` 667 | 668 | ### OAM ext update (\$4242, write-only and \$4282, executable) 669 | 670 | To execute this routine, you just need to do `jsr $4282`. 671 | This routine will write the extended bank data for each sprite (registers \$42xx), and uses **390** cycles including the final `rts` opcode. 672 | Extended bank data must be written to the \$4800-\$4FFF area, every 4 bytes. 673 | 674 | For example: 675 | 676 | - set $4242 to 0 677 | - write sprite 0 extended bank value to \$4800 678 | - write sprite 1 extended bank value to \$4804 679 | - write sprite 2 extended bank value to \$4808 680 | 681 | and so on. 682 | 683 | Register \$4242 sets the 256 bytes page to be used, starting at \$4800 (FPGA-RAM). 684 | 685 | ``` 686 | 7 bit 0 687 | ---- ---- 688 | .... .PPP 689 | ||| 690 | +++- OAM extended banks page index 691 | ``` 692 | 693 | ## Window Split Mode (\$4170-\$4175) 694 | 695 | When Window Split Mode is enabled (see register \$4120), all VRAM fetches corresponding to the appropriate screen region will be redirected to nametable defined by registers \$412E (Window Split nametable bank) and \$412F (Window Split nametable control). 696 | 697 | Notes: 698 | 699 | - 34 background tiles are fetched per scanline. The mapper performs the split by watching which background tile is being fetched during which scanline, and if it is within the split region, replacing the normal NT data with the split data according to the absolute screen position of the tile (i.e., ignoring the coarse horizontal and vertical scroll output as part of the VRAM address for the fetch). 700 | - Since it operates on a per-tile basis horizontally, fine horizontal scrolling "carries into" the split region: setting the horizontal scroll to 1-7 will result in the split being moved to the left 1-7 pixels. Whenever scrolling exceeds a multiple of 8, the split will "snap" back to its normal position. 701 | - Horizontal scrolling for the split region operates on a per-tile basis, meaning that it will move horizontally by 8px steps. 702 | - Vertical scrolling for the split region operates like normal vertical scrolling. 0-239 are valid scroll values, whereas 240-255 will display Attribute table data as NT data for the first few scanlines. The split nametable will wrap so that the top of the nametable will appear below as you scroll (just as if vertical mirroring were employed). 703 | - FPGA-RAM is always used as the nametable in split mode (see register \$412F). 704 | 705 | ### Window Split start/stop tile ($4170-$4171, write-only) 706 | 707 | Register \$4170 defines the tile where the split starts. 708 | 709 | ``` 710 | 7 bit 0 711 | ---- ---- 712 | ...S SSSS 713 | |-|||| 714 | +-++++- Specify Window Split start tile (0-31) 715 | ``` 716 | 717 | Register \$4171 defines the tile where the split region stops. 718 | 719 | ``` 720 | 7 bit 0 721 | ---- ---- 722 | ...E EEEE 723 | |-|||| 724 | +-++++- Specify Window Split stop tile (0-31) 725 | ``` 726 | 727 | Note: 728 | 729 | - If the start tile is **smaller** than the stop tile, then the split NT region will appear in the middle of the normal NT region. 730 | - If the start tile is **higher** than the stop tile, then the normal NT region will appear in the middle of the split NT region. 731 | 732 | ### Window Split start/stop tile ($4172-$4173, write-only) 733 | 734 | Register \$4172 defines the tile where the split starts. 735 | 736 | ``` 737 | 7 bit 0 738 | ---- ---- 739 | SSSS SSSS 740 | ||||-|||| 741 | ++++-++++- Specify Window Split start position (0-256) 742 | ``` 743 | 744 | Register \$4173 defines the tile where the split region stops. 745 | 746 | ``` 747 | 7 bit 0 748 | ---- ---- 749 | EEEE EEEE 750 | ||||-|||| 751 | ++++-++++- Specify Window Split stop position (0-256) 752 | ``` 753 | 754 | Note: 755 | 756 | - If the start position is **smaller** than the stop position, then the _split NT region_ will appear in the middle of the _normal NT region_. 757 | - If the start position is **higher** than the stop position, then the _normal NT region_ will appear in the middle of the _split NT region_. 758 | 759 | ### Window Split coarse X scroll ($4174, write-only) 760 | 761 | This register controls the horizontal scrolling of the split region on a per-tile basis. 762 | 763 | ``` 764 | 7 bit 0 765 | ---- ---- 766 | ...X XXXX 767 | |-|||| 768 | +-++++- Specify Window Split coarse X scroll (0-32) 769 | ``` 770 | 771 | TODO... 772 | 773 | ### Window Split fine Y scroll ($4175, write-only) 774 | 775 | This register controls the vertical scrolling of the split region. 776 | 777 | ``` 778 | 7 bit 0 779 | ---- ---- 780 | YYYY YYYY 781 | ||||-|||| 782 | ++++-++++- Specify Window Split fine Y scroll (0-256) 783 | ``` 784 | 785 | ## Scanline/PPU IRQ (\$4150-\$4154) 786 | 787 | Scanline IRQ is very close to MMC5's. 788 | For more informations: https://www.nesdev.org/wiki/MMC5#Scanline_Detection_and_Scanline_IRQ. 789 | 790 | ### PPU IRQ latch (\$4150, read-write) 791 | 792 | Write 793 | 794 | **from MMC5 wiki page, need to test** 795 | All eight bits specify the target scanline number at which to generate a scanline IRQ. Value $00 is a special case that will not produce IRQ pending conditions, though it is possible to get an IRQ while this is set to $00 (due to the pending flag being set already.) You will need to take additional measures to fully suppress the IRQ. See the detailed discussion. 796 | 797 | ``` 798 | 7 bit 0 799 | ---- ---- 800 | LLLL LLLL 801 | |||| |||| 802 | ++++-++++- IRQ latch value 803 | ``` 804 | 805 | Read 806 | 807 | ``` 808 | 7 bit 0 809 | ---- ---- 810 | CCCC CCCC 811 | |||| |||| 812 | ++++-++++- IRQ scanline counter value 813 | ``` 814 | 815 | Reading this register will return the current scanline being rendered. 816 | This only works if rendering is enabled and if it hasn't been disabled during rendering. 817 | 818 | ### PPU IRQ enable / status (\$4151, read-write) 819 | 820 | Write 821 | 822 | Writing any value to this register will enable scanline IRQ. 823 | 824 | Read 825 | 826 | ``` 827 | 7 bit 0 828 | ---- ---- 829 | HF.. ...I 830 | || | 831 | || +- Scanline IRQ Pending flag 832 | |+-------- In-Frame flag 833 | +--------- HBlank flag 834 | ``` 835 | 836 | The Scanline IRQ Pending flag becomes set at any time that the internal scanline counter matches the value written to register \$4150. If the scanline IRQ is enabled, it will also generate /IRQ to the system. 837 | 838 | The In-Frame flag is set when the PPU is rendering a frame and cleared during vertical blank. 839 | 840 | The HBlank flag is set when the PPU is rendering pixel 256 of each scanline. 841 | 842 | Any time this register is read, the Scanline IRQ Pending flag is cleared (acknowledging the pending IRQ). 843 | 844 | ### PPU IRQ disable (\$4152, write-only) 845 | 846 | Writing any value to this register will disable scanline IRQ AND acknowledge any pending IRQ. 847 | 848 | ### PPU IRQ offset (\$4153, write-only) 849 | 850 | The IRQ offset let's you control when the IRQ is triggered to adjust the timing depending on your needs. 851 | This value corresponds to the **even PPU dot** you want to trigger the IRQ on (1 for dot 1, 2 for dot 3, 3 for dot 5, etc). 852 | 853 | The minimum value is 1 (\$01) and offset will be set to 1 if you try to set it to 0. 854 | The default value set on power-up and reset is 135 (\$87). 855 | The maximum value is 170 (\$AA) and value will be capped to 170 if you try to set it to a higher value. 856 | 857 | ``` 858 | 7 bit 0 859 | ---- ---- 860 | OOOO OOOO 861 | |||| |||| 862 | ++++-++++- IRQ offset value 863 | ``` 864 | 865 | ### PPU IRQ jitter counter (\$4154, read-only) 866 | 867 | This counter is incremented on every m2 falling edge. 868 | When an IRQ is triggered, this counter is reset to zero. 869 | It can then be read and used to adjust a delay to execute a piece of code (almost) always at the same time every time. 870 | 871 | ``` 872 | 7 bit 0 873 | ---- ---- 874 | CCCC CCCC 875 | |||| |||| 876 | ++++-++++- IRQ jitter counter 877 | ``` 878 | 879 | ### CPU cycle parity (\$4157, read-only) 880 | 881 | This bit is toggled on every falling edge of M2. 882 | 883 | ``` 884 | 7 bit 0 885 | ---- ---- 886 | P... .... 887 | | 888 | +--------- CPU cycle parity 889 | ``` 890 | 891 | ## CPU Cycle IRQ (\$4158-\$415B) 892 | 893 | This IRQ feature is a CPU cycle counting IRQ generator. 894 | When enabled, the 16-bit IRQ counter is decremented once per CPU cycle. 895 | When the IRQ counter reaches \$0000, an IRQ is generated and IRQ counter is reloaded with latched value. 896 | The IRQ line is held low until it is acknowledged. 897 | 898 | ### How to Use the IRQ Generator 899 | 900 | - Set the latch to the desired number of cycles. 901 | - Enable the IRQ generator by turning on the IRQ Enable flag of the IRQ Control register. 902 | - Within the IRQ handler, write to the IRQ acknowledge register to acknowledge the IRQ. 903 | - Optional: Go back to Step 1 for the next IRQ. 904 | 905 | ### CPU IRQ latch high byte (\$4158, write-only) 906 | 907 | This register specifies the IRQ latch value high byte. 908 | 909 | ``` 910 | 7 bit 0 911 | ---- ---- 912 | HHHH HHHH 913 | |||| |||| 914 | ++++-++++- The high eight bits of the IRQ latch 915 | ``` 916 | 917 | ### CPU IRQ latch low byte (\$4159, write-only) 918 | 919 | This register specifies the IRQ latch value low byte. 920 | 921 | ``` 922 | 7 bit 0 923 | ---- ---- 924 | LLLL LLLL 925 | |||| |||| 926 | ++++-++++- The low eight bits of the IRQ latch 927 | ``` 928 | 929 | ### CPU IRQ control (\$415A, write-only) 930 | 931 | Writing zero to this register will disable interrupts. 932 | If this register is written to with 'E' set, the IRQ counter is reloaded with the latch value. 933 | If 'E' is clear, the IRQ counter remains unchanged. 934 | The 'A' bit here has no immediate effect, and remains unused until IRQ Acknowledge is written to. 935 | It can be used to distinguish a one-shot IRQ from a repeated IRQ. 936 | If 'I' is set, the IRQ will be automatically acknowledged when reading \$4011, which makes IPCM even easier to use. 937 | 938 | ``` 939 | 7 bit 0 940 | --------- 941 | .... .IAE 942 | ||| 943 | ||+- IRQ enable (0: disabled, 1: enabled) 944 | |+-- IRQ enable after being acknowledged (see IRQ acknowledge) 945 | +--- IRQ acknowledged if $4011 is read (0: disabled, 1: enabled) 946 | ``` 947 | 948 | ### CPU IRQ acknowledge (\$415B, write-only) 949 | 950 | Writing any value to this register will acknowledge the pending IRQ. 951 | In addition, the 'A' control bit moves to the 'E' control bit, enabling or disabling IRQs. 952 | Writes to this register do not affect the current state of the IRQ counter. 953 | 954 | ``` 955 | 7 bit 0 956 | ---- ---- 957 | .... .... 958 | ``` 959 | 960 | ## FPGA-RAM auto reader/writer (\$415C-\$415F) 961 | 962 | The FPGA-RAM auto reader/writer allows you to access the FPGA-RAM without the need to set the address for each read or write. 963 | First you set the start address, then you set the increment value that will be added to the address after each read or write, and finally you read or write through one register. 964 | This mimic how the PPU registers \$2006 and \$2007 work and allow you to do faster updates when using the FPGA-RAM as nametables or pattern tables. 965 | Since the FPGA-RAM is also used to store incoming and outcoming messages for the ESP / Wi-Fi chip, you can also use the auto reader/writer to read/write messages a bit faster. 966 | The auto reader/writer address should be in the \$0000-\$1FFF range, which allows you to address the 8KB of FPGA-RAM. 967 | 968 | ### FPGA-RAM hi address (\$415C, write-only) 969 | 970 | ``` 971 | 7 bit 0 972 | ---- ---- 973 | ...H HHHH 974 | | |||| 975 | +-++++- The high five bits of the FPGA-RAM address 976 | ``` 977 | 978 | ### FPGA-RAM lo address (\$415D, write-only) 979 | 980 | ``` 981 | 7 bit 0 982 | ---- ---- 983 | LLLL LLLL 984 | |||| |||| 985 | ++++-++++- The low eight bits of the FPGA-RAM address 986 | ``` 987 | 988 | ### FPGA-RAM increment (\$415E, write-only) 989 | 990 | ``` 991 | 7 bit 0 992 | ---- ---- 993 | IIII IIII 994 | |||| |||| 995 | ++++-++++- This value will be added to the FPGA-RAM address after each read or write 996 | ``` 997 | 998 | ### FPGA-RAM data (\$415F, read/write) 999 | 1000 | ``` 1001 | 7 bit 0 1002 | ---- ---- 1003 | DDDD DDDD 1004 | |||| |||| 1005 | ++++-++++- Value read or to be written 1006 | ``` 1007 | 1008 | ## Mapper version (\$4160, read-only) 1009 | 1010 | Read this register to get mapper version. 1011 | 1012 | ``` 1013 | 7 bit 0 1014 | ---- ---- 1015 | PPPV VVVV 1016 | |||| |||| 1017 | |||+-++++- Version 1018 | +++------- Platform 1019 | ``` 1020 | 1021 | | Platform (PPP) | Description | 1022 | | -------------- | ---------------- | 1023 | | 0 | PCB | 1024 | | 1 | Emulator | 1025 | | 2 | Web emulator | 1026 | | 3 | Everdrive N8 PRO | 1027 | 1028 | | Version (vvvvv) | Description | 1029 | | --------------- | ----------------------------------------------------------- | 1030 | | 0 | Initial release | 1031 | | 1 | added register \$4150 (read current scanline counter value) | 1032 | | | added register \$4157 (read m2 status) | 1033 | | | added CIRAM as a possible source for pattern table | 1034 | | | updated register \$4242 to now select a 256 bytes page | 1035 | | | updated OAM ext routine to read every 4 bytes | 1036 | | | removed OAM clear routine | 1037 | | | improved level shifter direction timing | 1038 | | | added EPSM support | 1039 | 1040 | ## IRQ status (\$4161, read-only) 1041 | 1042 | Read this register to get the IRQ status. 1043 | It will indicate if PPU IRQ or CPU IRQ or ESP / Wi-Fi IRQ is pending (1) or not (0). 1044 | Reading this register will **NOT** acknowledge any IRQ. 1045 | 1046 | ``` 1047 | 7 bit 0 1048 | ---- ---- 1049 | PC.. ...W 1050 | || | 1051 | || +- ESP / Wi-Fi IRQ status 1052 | |+-------- CPU Cycle IRQ status 1053 | +--------- PPU Scanline IRQ status 1054 | ``` 1055 | 1056 | ## Vector redirection (\$416B-\$416F, write-only) 1057 | 1058 | Vector redirection allows you to change the default vectors of the NMI of IRQ. 1059 | No more need of a trampoline, you can just set the address, enable the redirection, and forget about it. 1060 | 1061 | ### Vector redirection control (\$416B, write-only) 1062 | 1063 | ``` 1064 | 7 bit 0 1065 | ---- ---- 1066 | .... ..IN 1067 | || 1068 | |+- NMI vector redirection enable (0: disabled, 1: enabled) 1069 | +-- IRQ vector redirection enable (0: disabled, 1: enabled) 1070 | ``` 1071 | 1072 | ### NMI vector redirection address high byte (\$416C, write-only) 1073 | 1074 | ``` 1075 | 7 bit 0 1076 | ---- ---- 1077 | HHHH HHHH 1078 | |||| |||| 1079 | ++++-++++- High 8 bits of address 1080 | ``` 1081 | 1082 | ### NMI vector redirection address low byte (\$416D, write-only) 1083 | 1084 | ``` 1085 | 7 bit 0 1086 | ---- ---- 1087 | LLLL LLLL 1088 | |||| |||| 1089 | ++++-++++- Low 8 bits of address 1090 | ``` 1091 | 1092 | ### IRQ vector redirection address high byte (\$416E, write-only) 1093 | 1094 | ``` 1095 | 7 bit 0 1096 | ---- ---- 1097 | HHHH HHHH 1098 | |||| |||| 1099 | ++++-++++- High 8 bits of address 1100 | ``` 1101 | 1102 | ### IRQ vector redirection address low byte (\$416F, write-only) 1103 | 1104 | ``` 1105 | 7 bit 0 1106 | ---- ---- 1107 | LLLL LLLL 1108 | |||| |||| 1109 | ++++-++++- Low 8 bits of address 1110 | ``` 1111 | 1112 | ## Sound / Audio Expansion (\$41A0-\$41AF) 1113 | 1114 | Channels registers work exactly like VRC6 audio expansion minus the frequency scaling register. 1115 | For more informations: https://wiki.nesdev.com/w/index.php/VRC6_audio. 1116 | 1117 | ### Pulse control (\$41A0, \$41A3, write-only) 1118 | 1119 | \$41A0 controls Pulse 1 1120 | \$41A3 controls Pulse 2 1121 | 1122 | ``` 1123 | 7 bit 0 1124 | ---- ---- 1125 | MDDD VVVV 1126 | |||| |||| 1127 | |||| ++++- Volume 1128 | |+++------ Duty Cycle 1129 | +--------- Mode (1: ignore duty) 1130 | ``` 1131 | 1132 | ### Saw Accum Rate (\$41A6, write-only) 1133 | 1134 | ``` 1135 | 7 bit 0 1136 | ---- ---- 1137 | ..AA AAAA 1138 | ++-++++- Accumulator Rate (controls volume) 1139 | ``` 1140 | 1141 | ### Freq Low (\$41A1, \$41A4, \$41A7, write-only) 1142 | 1143 | \$41A1 controls Pulse 1 1144 | \$41A4 controls Pulse 2 1145 | \$41A7 controls Saw 1146 | 1147 | ``` 1148 | 7 bit 0 1149 | ---- ---- 1150 | FFFF FFFF 1151 | |||| |||| 1152 | ++++-++++- Low 8 bits of frequency 1153 | ``` 1154 | 1155 | ### Freq High (\$41A2, \$41A5, \$41A8, write-only) 1156 | 1157 | \$41A2 controls Pulse 1 1158 | \$41A5 controls Pulse 2 1159 | \$41A8 controls Saw 1160 | 1161 | ``` 1162 | 7 bit 0 1163 | ---- ---- 1164 | E... FFFF 1165 | | |||| 1166 | | ++++- High 4 bits of frequency 1167 | +--------- Enable (0: channel disabled) 1168 | ``` 1169 | 1170 | ### Audio output control (\$41A9, write-only) 1171 | 1172 | ``` 1173 | 7 bit 0 1174 | ---- ---- 1175 | E... .ITF 1176 | | ||| 1177 | | ||+- Outputs expansion audio to EXP6 pin (0: disable, 1: enable) 1178 | | | usually used for front loader 1179 | | |+-- Outputs expansion audio to EXP9 pin (0: disable, 1: enable) 1180 | | | usually used for top loader 1181 | | +--- Outputs expansion audio data to APU register $4011 (read) 1182 | +--------- EPSM support (0: disable, 1: enable) 1183 | ``` 1184 | 1185 | ### Audio output control (\$41AA, write-only) 1186 | 1187 | ``` 1188 | 7 bit 0 1189 | ---- ---- 1190 | .... VVVV 1191 | |||| 1192 | ++++- Controls expansion audio output master volume 1193 | ``` 1194 | 1195 | ## Wi-Fi (\$4190-\$4194) 1196 | 1197 | ### Configuration (\$4190, read/write) 1198 | 1199 | This register is readable and writable. 1200 | 1201 | ``` 1202 | 7 bit 0 1203 | ---- ---- 1204 | .... ..IE 1205 | || 1206 | |+ ESP enable (0: disable, 1: enable) 1207 | +- IRQ enable (0: disable, 1: enable) 1208 | ``` 1209 | 1210 | ### RX - Reception (\$4191, read/write) 1211 | 1212 | Writing any value to this register acknowledge the last received message and set the bit 7 of the register to 0. 1213 | The bit 7 will be set to 1 again when a new message if available. 1214 | 1215 | Reading this register will return the following byte: 1216 | 1217 | ``` 1218 | 7 bit 0 1219 | ---- ---- 1220 | DR.. .... 1221 | || 1222 | |+------- Data ready, this flag is set to 1 if a message is waiting to be sent on the ESP side 1223 | +-------- Data received (0: FPGA can receive a new message, 1: a new message is ready) 1224 | This flag is set to 1 when the FPGA has received a new message 1225 | If the I flag of the ESP configuration register ($4190) is set, then the NES IRQ will be triggered 1226 | ``` 1227 | 1228 | ### TX - Transimission (\$4192, read/write) 1229 | 1230 | Writing any value to this register sends the message currently stored in FPGA-RAM and sets the bit 7 of the register to 0. 1231 | The bit 7 will be set to 1 again when the message is sent. 1232 | 1233 | Reading this register will return the following byte: 1234 | 1235 | ``` 1236 | 7 bit 0 1237 | ---- ---- 1238 | D... .... 1239 | | 1240 | +-------- Data sent (0: sending data, 1: data sent) 1241 | This flag is set to 1 when the FPGA has sent a message 1242 | ``` 1243 | 1244 | ### RX RAM destination address (\$4193, write-only) 1245 | 1246 | The FPGA uses its internal RAM to store messages received from the ESP. 1247 | Only the last 2K of the total 8K of the FPGA-RAM can be used for this. 1248 | Those 2K are permanently mapped at \$4800-\$4FFF. 1249 | This register allows you to specify a \$100 bytes page from \$4800 to be used for newly received messages. 1250 | 1251 | ``` 1252 | 7 bit 0 1253 | ---- ---- 1254 | .... .AAA 1255 | ||| 1256 | +++ Destination RAM address hi bits 1257 | ``` 1258 | 1259 | ### TX RAM source address (\$4194, write-only) 1260 | 1261 | The FPGA uses its internal RAM to store messages to be sent to the ESP. 1262 | Only the last 2K of the total 8K of the FPGA-RAM can be used for this. 1263 | Those 2K are permanently mapped at \$4800-\$4FFF. 1264 | This register allows you to specify a \$100 bytes page from \$4800 to be used for ready to be sent messages. 1265 | 1266 | ``` 1267 | 7 bit 0 1268 | ---- ---- 1269 | .... .AAA 1270 | ||| 1271 | +++ Source RAM address hi bits 1272 | ``` 1273 | 1274 | ## Recap / Cheat sheet 1275 | 1276 | | Register | Format | Access | Details | 1277 | | ------------- | ---------- | :----: | ----------------------------------------------------------------------- | 1278 | | | | | **CPU / PRG control** | 1279 | | \$4100 | `A....OOO` | R/W | PRG banking modes | 1280 | | \$4101-\$4105 | | | _Not used_ | 1281 | | \$4106 | `CC UUU` | W | PRG bank upper bits and chip selector (modes 0,1) | 1282 | | \$4107 | `CC UUU` | W | PRG bank upper bits and chip selector (mode 1) | 1283 | | \$4108 | `CC UUU` | W | PRG bank upper bits and chip selector (modes 0,1,2,3,4) | 1284 | | \$4109 | `CC UUU` | W | PRG bank upper bits and chip selector (mode 4) | 1285 | | \$410A | `CC UUU` | W | PRG bank upper bits and chip selector (modes 3,4) | 1286 | | \$410B | `CC UUU` | W | PRG bank upper bits and chip selector (mode 4) | 1287 | | \$410C | `CC UUU` | W | PRG bank upper bits and chip selector (modes 1,2,3,4) | 1288 | | \$410D | `CC UUU` | W | PRG bank upper bits and chip selector (mode 4) | 1289 | | \$410E | `CC UUU` | W | PRG bank upper bits and chip selector (modes 2,3,4) | 1290 | | \$410F | `CC UUU` | W | PRG bank upper bits and chip selector (mode 4) | 1291 | | \$4110-\$4114 | | | _Not used_ | 1292 | | \$4115 | `.......B` | W | FPGA-RAM bank bits | 1293 | | \$4116 | `LLLLLLLL` | W | PRG bank lower bits (modes 0,1) | 1294 | | \$4117 | `LLLLLLLL` | W | PRG bank lower bits (mode 1) | 1295 | | \$4118 | `LLLLLLLL` | W | PRG bank lower bits (modes 0,1,2,3,4) | 1296 | | \$4119 | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1297 | | \$411A | `LLLLLLLL` | W | PRG bank lower bits (modes 3,4) | 1298 | | \$411B | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1299 | | \$411C | `LLLLLLLL` | W | PRG bank lower bits (modes 1,2,3,4) | 1300 | | \$411D | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1301 | | \$411E | `LLLLLLLL` | W | PRG bank lower bits (modes 2,3,4) | 1302 | | \$411F | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1303 | | | | | **PPU / CHR control** | 1304 | | \$4120 | `CCSW.BBB` | R/W | PPU/CHR control (banking/source/Window Split Mode/Sprite Extended Mode) | 1305 | | \$4121 | `...UUUUU` | W | Background Extended Mode bank upper bits control | 1306 | | \$4122-\$4123 | | | _Not used_ | 1307 | | \$4124 | `TTTTTTTT` | W | Fill-mode tile index | 1308 | | \$4125 | `AAAAAAAA` | W | Fill-mode attribute index | 1309 | | \$4126 | `BBBBBBBB` | W | Nametable A bank (\$2000) | 1310 | | \$4127 | `BBBBBBBB` | W | Nametable B bank (\$2400) | 1311 | | \$4128 | `BBBBBBBB` | W | Nametable C bank (\$2800) | 1312 | | \$4129 | `BBBBBBBB` | W | Nametable D bank (\$2C00) | 1313 | | \$412A | `CCF.DDEE` | R/W | Nametable A control (\$2000) | 1314 | | \$412B | `CCF.DDEE` | R/W | Nametable B control (\$2400) | 1315 | | \$412C | `CCF.DDEE` | R/W | Nametable C control (\$2800) | 1316 | | \$412D | `CCF.DDEE` | R/W | Nametable D control (\$2C00) | 1317 | | \$412E | `BBBBBBBB` | W | Nametable W bank (Window Split) | 1318 | | \$412F | `....DDEE` | R/W | Nametable W control (Window Split) | 1319 | | \$4130 | `...UUUUU` | W | CHR bank upper bits (modes 0,1,2,3,4) | 1320 | | \$4131 | `...UUUUU` | W | CHR bank upper bits (modes 1,2,3,4) | 1321 | | \$4132 | `...UUUUU` | W | CHR bank upper bits (modes 2,3,4) | 1322 | | \$4133 | `...UUUUU` | W | CHR bank upper bits (modes 2,3,4) | 1323 | | \$4134 | `...UUUUU` | W | CHR bank upper bits (modes 3,4) | 1324 | | \$4135 | `...UUUUU` | W | CHR bank upper bits (modes 3,4) | 1325 | | \$4136 | `...UUUUU` | W | CHR bank upper bits (modes 3,4) | 1326 | | \$4137 | `...UUUUU` | W | CHR bank upper bits (modes 3,4) | 1327 | | \$4138 | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1328 | | \$4139 | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1329 | | \$413A | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1330 | | \$413B | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1331 | | \$413C | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1332 | | \$413D | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1333 | | \$413E | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1334 | | \$413F | `...UUUUU` | W | CHR bank upper bits (mode 4) | 1335 | | \$4140 | `LLLLLLLL` | W | CHR bank lower bits (modes 0,1,2,3,4) | 1336 | | \$4141 | `LLLLLLLL` | W | CHR bank lower bits (modes 1,2,3,4) | 1337 | | \$4142 | `LLLLLLLL` | W | CHR bank lower bits (modes 2,3,4) | 1338 | | \$4143 | `LLLLLLLL` | W | CHR bank lower bits (modes 2,3,4) | 1339 | | \$4144 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1340 | | \$4145 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1341 | | \$4146 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1342 | | \$4147 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1343 | | \$4148 | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1344 | | \$4149 | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1345 | | \$414A | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1346 | | \$414B | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1347 | | \$414C | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1348 | | \$414D | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1349 | | \$414E | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1350 | | \$414F | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1351 | | | | | **SCANLINE DETECTION IRQ** | 1352 | | \$4150 | `VVVVVVVV` | W | Latch value | 1353 | | \$4150 | `CCCCCCCC` | R | Current scanline value | 1354 | | \$4151 | `........` | W | Enable | 1355 | | \$4151 | `HF.....I` | R | Status (in-frame, HBlank, IRQ pending flags) | 1356 | | \$4152 | `........` | W | Disable | 1357 | | \$4153 | `OOOOOOOO` | W | Offset | 1358 | | \$4154 | `CCCCCCCC` | R | CPU cycle jitter counter | 1359 | | \$4155-\$4156 | | | _Not used_ | 1360 | | | | | **CPU CYCLE COUNTER IRQ** | 1361 | | \$4157 | `P.......` | W | CPU cycle parity | 1362 | | \$4158 | `HHHHHHHH` | W | Latch high byte | 1363 | | \$4159 | `LLLLLLLL` | W | Latch low byte | 1364 | | \$415A | `.....IEA` | W | Control | 1365 | | \$415B | `........` | W | Acknowledge | 1366 | | | | | **FPGA-RAM auto R/W** | 1367 | | \$415C | `...HHHHH` | W | FPGA-RAM address high byte | 1368 | | \$415D | `LLLLLLLL` | W | FPGA-RAM address low byte | 1369 | | \$415E | `IIIIIIII` | W | FPGA-RAM increment | 1370 | | \$415F | `DDDDDDDD` | R/W | FPGA-RAM data | 1371 | | | | | **MISCELLANEOUS** | 1372 | | \$4160 | `PPPVVVVV` | R | Mapper version | 1373 | | \$4161 | `PC.....W` | R | IRQ status | 1374 | | \$4162-\$416A | | | _Not used_ | 1375 | | | | | **VECTOR REDIRECTION** | 1376 | | \$416B | `......IN` | W | Vector redirection control | 1377 | | \$416C | `HHHHHHHH` | W | NMI vector redirection address high byte | 1378 | | \$416D | `LLLLLLLL` | W | NMI vector redirection address low byte | 1379 | | \$416E | `HHHHHHHH` | W | IRQ vector redirection address high byte | 1380 | | \$416F | `LLLLLLLL` | W | IRQ vector redirection address low byte | 1381 | | | | | **Window Split Mode** | 1382 | | \$4170 | `...SSSSS` | W | Window Split X start tile (0-31) | 1383 | | \$4171 | `...EEEEE` | W | Window Split X end tile (0-31) | 1384 | | \$4172 | `SSSSSSSS` | W | Window Split Y start (0-255) | 1385 | | \$4173 | `EEEEEEEE` | W | Window Split Y end (0-255) | 1386 | | \$4174 | `...XXXXX` | W | Window Split coarse X scroll (0-31) | 1387 | | \$4175 | `YYYYYYYY` | W | Window Split fine Y scroll (0-256) | 1388 | | \$4176-\$418F | | | _Not used_ | 1389 | | | | | **WIFI** | 1390 | | \$4190 | `......IE` | R/W | Control | 1391 | | \$4191 | `DR......` | R/W | RX data ready / acknowledge | 1392 | | \$4192 | `D.......` | R/W | TX data sent / send data | 1393 | | \$4193 | `.....AAA` | W | RX RAM destination address | 1394 | | \$4194 | `.....AAA` | W | TX RAM source address | 1395 | | \$4195-\$419F | | | _Not used_ | 1396 | | | | | **AUDIO EXPANSION** | 1397 | | \$41A0 | `MDDDVVVV` | W | Pulse 1 control | 1398 | | \$41A1 | `FFFFFFFF` | W | Pulse 1 low frequency | 1399 | | \$41A2 | `E...FFFF` | W | Pulse 1 high frequency | 1400 | | \$41A3 | `MDDDVVVV` | W | Pulse 2 control | 1401 | | \$41A4 | `FFFFFFFF` | W | Pulse 2 low frequency | 1402 | | \$41A5 | `E...FFFF` | W | Pulse 2 high frequency | 1403 | | \$41A6 | `..AAAAAA` | W | Saw accumulator rate | 1404 | | \$41A7 | `FFFFFFFF` | W | Saw low frequency | 1405 | | \$41A8 | `E...FFFF` | W | Saw high frequency | 1406 | | | | | **AUDIO OUTPUT CONTROL** | 1407 | | \$41A9 | `E....ITF` | W | Audio output control | 1408 | | \$41AA | `....VVVV` | W | Audio output master volume | 1409 | | \$41AB-\$41FF | | | _Not used_ | 1410 | | | | | **SPRITE EXTENDED MODE** | 1411 | | \$4200-\$423F | `LLLLLLLL` | W | Sprites individual bank lower bits | 1412 | | \$4240 | `.....UUU` | W | Sprites global bank upper bits | 1413 | | | | | **AUTO-GENERATED OAM PROCEDURES** | 1414 | | \$4241 | `.....PPP` | W | OAM slow update 256 bytes page index | 1415 | | \$4242 | `.....PPP` | W | OAM ext update 256 bytes page | 1416 | | \$4243-\$427F | | | _Not used_ | 1417 | | \$4280 | | X | OAM slow update | 1418 | | \$4282 | | X | OAM ext update | 1419 | | | | | **MEMORY MAPPING** | 1420 | | \$4800-\$4FFF | | | Last 2K of FPRA-RAM | 1421 | | \$5000-\$5FFF | | | Switchable 4K of FPRA-RAM | 1422 | | \$6000-\$7FFF | | | Switchable 4K or 8K depending on the PRG-RAM banking mode | 1423 | | | | | Can be assigned to PRG-RAM or PRG-ROM or FPRA-RAM | 1424 | | \$8000-\$FFFF | | | Switchable 4K or 8K or 16K or 32K depending on the PRG-ROM banking mode | 1425 | | | | | Can be assigned to PRG-RAM or PRG-ROM | 1426 | -------------------------------------------------------------------------------- /NES/mapper-registers.s: -------------------------------------------------------------------------------- 1 | ; ################################################################################ 2 | ; MAPPER REGISTERS 3 | 4 | ; PRG banking 5 | MAP_PRG_CONTROL = $4100 6 | 7 | MAP_PRG_6_HI = $4106 8 | MAP_PRG_7_HI = $4107 9 | MAP_PRG_8_HI = $4108 10 | MAP_PRG_9_HI = $4109 11 | MAP_PRG_A_HI = $410A 12 | MAP_PRG_B_HI = $410B 13 | MAP_PRG_C_HI = $410C 14 | MAP_PRG_D_HI = $410D 15 | MAP_PRG_E_HI = $410E 16 | MAP_PRG_F_HI = $410F 17 | 18 | MAP_PRG_5 = $4115 19 | MAP_PRG_5_LO = $4115 20 | MAP_PRG_6_LO = $4116 21 | MAP_PRG_7_LO = $4117 22 | MAP_PRG_8_LO = $4118 23 | MAP_PRG_9_LO = $4119 24 | MAP_PRG_A_LO = $411A 25 | MAP_PRG_B_LO = $411B 26 | MAP_PRG_C_LO = $411C 27 | MAP_PRG_D_LO = $411D 28 | MAP_PRG_E_LO = $411E 29 | MAP_PRG_F_LO = $411F 30 | 31 | ; CHR banking 32 | MAP_CHR_CONTROL = $4120 33 | MAP_BG_EXT_BANK = $4121 34 | 35 | MAP_CHR_0_HI = $4130 36 | MAP_CHR_1_HI = $4131 37 | MAP_CHR_2_HI = $4132 38 | MAP_CHR_3_HI = $4133 39 | MAP_CHR_4_HI = $4134 40 | MAP_CHR_5_HI = $4135 41 | MAP_CHR_6_HI = $4136 42 | MAP_CHR_7_HI = $4137 43 | MAP_CHR_8_HI = $4138 44 | MAP_CHR_9_HI = $4139 45 | MAP_CHR_A_HI = $413A 46 | MAP_CHR_B_HI = $413B 47 | MAP_CHR_C_HI = $413C 48 | MAP_CHR_D_HI = $413D 49 | MAP_CHR_E_HI = $413E 50 | MAP_CHR_F_HI = $413F 51 | 52 | MAP_CHR_0_LO = $4140 53 | MAP_CHR_1_LO = $4141 54 | MAP_CHR_2_LO = $4142 55 | MAP_CHR_3_LO = $4143 56 | MAP_CHR_4_LO = $4144 57 | MAP_CHR_5_LO = $4145 58 | MAP_CHR_6_LO = $4146 59 | MAP_CHR_7_LO = $4147 60 | MAP_CHR_8_LO = $4148 61 | MAP_CHR_9_LO = $4149 62 | MAP_CHR_A_LO = $414A 63 | MAP_CHR_B_LO = $414B 64 | MAP_CHR_C_LO = $414C 65 | MAP_CHR_D_LO = $414D 66 | MAP_CHR_E_LO = $414E 67 | MAP_CHR_F_LO = $414F 68 | 69 | ; Fill-mode 70 | MAP_FILL_MODE_TILE = $4124 71 | MAP_FILL_MODE_ATTR = $4125 72 | 73 | ; Nametables 74 | MAP_NT_A_BANK = $4126 75 | MAP_NT_B_BANK = $4127 76 | MAP_NT_C_BANK = $4128 77 | MAP_NT_D_BANK = $4129 78 | 79 | MAP_NT_A_CONTROL = $412A 80 | MAP_NT_B_CONTROL = $412B 81 | MAP_NT_C_CONTROL = $412C 82 | MAP_NT_D_CONTROL = $412D 83 | 84 | MAP_NT_W_BANK = $412E 85 | MAP_NT_W_CONTROL = $412F 86 | 87 | ; Scanline IRQ 88 | MAP_PPU_IRQ_LATCH = $4150 ; write 89 | MAP_PPU_IRQ_COUNTER = $4150 ; read 90 | MAP_PPU_IRQ_ENABLE = $4151 ; write 91 | MAP_PPU_IRQ_STATUS = $4151 ; read 92 | MAP_PPU_IRQ_DISABLE = $4152 93 | MAP_PPU_IRQ_OFFSET = $4153 94 | MAP_PPU_IRQ_M2_CNT = $4154 95 | 96 | ; CPU Cycle IRQ 97 | MAP_CPU_IRQ_LATCH_HI = $4158 98 | MAP_CPU_IRQ_LATCH_LO = $4159 99 | MAP_CPU_IRQ_CONTROL = $415A 100 | MAP_CPU_IRQ_ACK = $415B 101 | 102 | ; FPGA RAM auto R/W 103 | MAP_FPGA_RAM_RW_HI_ADD = $415C 104 | MAP_FPGA_RAM_RW_LO_ADD = $415D 105 | MAP_FPGA_RAM_RW_INC = $415E 106 | MAP_FPGA_RAM_RW_DATA = $415F 107 | 108 | ; Miscellaneaous 109 | MAP_CPU_M2_PARITY = $4157 110 | MAP_VERSION = $4160 111 | MAP_IRQ_STATUS = $4161 112 | 113 | ; Vector redirection 114 | MAP_VECTOR_CONTROL = $416B 115 | MAP_VECTOR_NMI_ADD_HI = $416C 116 | MAP_VECTOR_NMI_ADD_LO = $416D 117 | MAP_VECTOR_IRQ_ADD_HI = $416E 118 | MAP_VECTOR_IRQ_ADD_LO = $416F 119 | 120 | ; Window Mode 121 | MAP_WINDOW_X_START = $4170 122 | MAP_WINDOW_X_END = $4171 123 | MAP_WINDOW_Y_START = $4172 124 | MAP_WINDOW_Y_END = $4173 125 | MAP_WINDOW_X_SCROLL = $4174 126 | MAP_WINDOW_Y_SCROLL = $4175 127 | 128 | ; ESP / WiFi 129 | MAP_RNBW_CONFIG = $4190 130 | MAP_RNBW_RX = $4191 131 | MAP_RNBW_TX = $4192 132 | MAP_RNBW_RX_ADD = $4193 133 | MAP_RNBW_TX_ADD = $4194 134 | 135 | ; Audio expansion 136 | MAP_SND_P1_CTRL = $41A0 137 | MAP_SND_P1_LOW = $41A1 138 | MAP_SND_P1_HIGH = $41A2 139 | MAP_SND_P2_CTRL = $41A3 140 | MAP_SND_P2_LOW = $41A4 141 | MAP_SND_P2_HIGH = $41A5 142 | MAP_SND_SAW_ACC = $41A6 143 | MAP_SND_SAW_LOW = $41A7 144 | MAP_SND_SAW_HIGH = $41A8 145 | MAP_SND_OUTPUT_CONTROL = $41A9 146 | MAP_SND_MASTER_VOLUME = $41AA 147 | 148 | ; Sprite extended mode 149 | MAP_SPR_EXT_LOWER_BANK = $4200 ; $4200 ... $423F, one register for each sprite 150 | MAP_SPR_EXT_UPPER_BANK = $4240 151 | 152 | ; Auto-generated OAM procedures 153 | MAP_OAM_SLOW_UPDATE_PAGE= $4241 154 | MAP_OAM_EXT_UPDATE_PAGE = $4242 155 | MAP_OAM_SLOW_UPDATE = $4280 156 | MAP_OAM_EXT_UPDATE = $4282 157 | 158 | ; ################################################################################ 159 | ; MAPPER FLAGS / MASKS 160 | 161 | PRG_ROM_MODE_0 = %00000000 ; 32K 162 | PRG_ROM_MODE_1 = %00000001 ; 16K + 16K 163 | PRG_ROM_MODE_2 = %00000010 ; 16K + 8K + 8K 164 | PRG_ROM_MODE_3 = %00000011 ; 8K + 8K + 8K + 8K 165 | PRG_ROM_MODE_4 = %00000100 ; 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K 166 | PRG_ROM_MODE_MASK = %00000111 167 | PRG_ROM_MODE_CLEAR = PRG_ROM_MODE_MASK^$ff 168 | 169 | PRG_RAM_MODE_0 = %00000000 ; 8K 170 | PRG_RAM_MODE_1 = %10000000 ; 4K + 4K 171 | PRG_RAM_MODE_MASK = %10000000 172 | PRG_RAM_MODE_CLEAR = PRG_RAM_MODE_MASK^$ff 173 | 174 | CHR_CHIP_ROM = %00000000 ; CHR-ROM 175 | CHR_CHIP_RAM = %01000000 ; CHR-RAM 176 | CHR_CHIP_FPGA_RAM = %10000000 ; FPGA-RAM 177 | CHR_CHIP_MASK = %11000000 178 | CHR_CHIP_CLEAR = CHR_CHIP_MASK^$ff 179 | 180 | SPR_EXT_MODE = %00100000 181 | 182 | CHR_MODE_0 = %00000000 ; 8K mode 183 | CHR_MODE_1 = %00000001 ; 4K mode 184 | CHR_MODE_2 = %00000010 ; 2K mode 185 | CHR_MODE_3 = %00000011 ; 1K mode 186 | CHR_MODE_4 = %00000100 ; 512B mode 187 | CHR_MODE_MASK = %00000111 188 | CHR_MODE_CLEAR = CHR_MODE_MASK^$ff 189 | 190 | NT_CIRAM = %00000000 191 | NT_CHR_RAM = %01000000 192 | NT_FPGA_RAM = %10000000 193 | NT_CHR_ROM = %11000000 194 | 195 | NT_FILL_MODE = %00100000 196 | 197 | NT_EXT_BANK_0 = %00000000 198 | NT_EXT_BANK_1 = %00000100 199 | NT_EXT_BANK_2 = %00001000 200 | NT_EXT_BANK_3 = %00001100 201 | 202 | NT_NO_EXT = %00000000 203 | NT_EXT_AT = %00000001 204 | NT_EXT_BG = %00000010 205 | NT_EXT_BG_AT = %00000011 206 | 207 | NT_BANK_IDX_MASK = %00111111 208 | -------------------------------------------------------------------------------- /NES/prg-rom-self-flashing.md: -------------------------------------------------------------------------------- 1 | # Rainbow PRG-ROM self-flashing how-to 2 | 3 | ## Introduction 4 | 5 | This document explains how to erase/program the flash memory directly from your code. This can be useful for game saves, game updates, additional content, etc. 6 | 7 | **Since those operations are not immediate, you need to execute your code from RAM so your game/program can still run while the flash chip is being updated.** 8 | 9 | Keep in mind that flash memory chips have a limited number of cycles (which is alse called endurance in datasheets), a cycle being an erase/program process per byte. Device specifications usually give a minimum of 10 000 cycles, and a guaranteed typical endurance of 100 000 cycles. 10 | 11 | Beyond those 100 000 cycles, errors may appear while erasing/programming the chip. 12 | 13 | In this document, the term _program_ instead of _write_ will be used to match the flash datasheets. 14 | 15 | Please read [S29GL064S datasheet]() for more general informations. This may not be the exact same flash chip used on your board, but most of the information should be true for another equivalent flash chip. 16 | 17 | ## Banks init 18 | 19 | There is no need to initialize the PRG banks in any specific way to perform erase/program actions, except for the destination bank of course. 20 | 21 | For example purpose, we will be using PRG mode 3 (4 x 8K banks), and use bank at \$8000-\$9FFF as our destination bank. 22 | 23 | ``` 24 | ; set PRG mode 3 25 | lda #3 26 | sta $4100 27 | 28 | lda #0 29 | sta $4108 30 | lda destination_bank ; must be a multiple of 8 since we erase 64K sectors (8 x 8K = 64K) 31 | sta $4118 32 | ``` 33 | 34 | ## Erasing 35 | 36 | Before you can program a new byte, you need to erase it. 37 | 38 | Unfortunately you cannot erase just one byte, you can only erase 64K sectors or the entire chip. 39 | 40 | ### Sector Erase 41 | 42 | To erase a sector, you need to write specific bytes at specific addresses to send a sector-erase command to the flash memory. 43 | 44 | ``` 45 | ; erase command sequence 46 | lda #$AA 47 | sta $8AAA 48 | lda #$55 49 | sta $8555 50 | lda #$80 51 | sta $8AAA 52 | lda #$AA 53 | sta $8AAA 54 | lda #$55 55 | sta $8555 56 | 57 | ; actual sector erase command 58 | lda #$30 59 | sta $8000 ; 64K to erase 60 | ``` 61 | 62 | Doing this will erase 64K of data in the sector defined by the selected bank. 63 | Using PRG mode 3 means that 8K bank value controls Amax-A13, and 64K sector is defined by Amax-A16. 64 | So to erase the first 64K sector, you can point to any 8K between 0 and 7. 65 | Erasing means that all bytes will be set to $FF. 66 | 67 | ### Chip Erase 68 | 69 | To erase the chip completely, you need to write specific bytes at specific addresses to send a chip-erase command to the flash memory. 70 | 71 | ``` 72 | ; erase command sequence 73 | lda #$AA 74 | sta $8AAA 75 | lda #$55 76 | sta $8555 77 | lda #$80 78 | sta $8AAA 79 | lda #$AA 80 | sta $8AAA 81 | lda #$55 82 | sta $8555 83 | 84 | ; actual chip erase command 85 | lda #$10 86 | sta $8AAA 87 | ``` 88 | 89 | Doing this will erase all bytes of the flash memory. 90 | Erasing means that all bytes will be set to $FF. 91 | 92 | **Note:** this will also erase vector pointers at $FFFA, $FFFC, $FFFE, meaning that if NMI and/or IRQ are enabled, or if you press reset, the CPU will not be able to jump to usable code. Therefore, this command is highly **NOT** recommended unless you really know what your are doing. 93 | 94 | ## Programming 95 | 96 | Once you erased a sector (or the entire chip), you can now program it. 97 | 98 | ### Byte Program 99 | 100 | To program a byte, you need to write specific bytes at specific addresses to send a byte-program command to the flash memory. 101 | 102 | ``` 103 | ; byte program command sequence 104 | lda #$AA 105 | sta $8AAA 106 | lda #$55 107 | sta $8555 108 | lda #$A0 109 | sta $8AAA 110 | 111 | ; program the actual value 112 | ldy #0 113 | lda value_to_write 114 | sta destination_address,y 115 | ``` 116 | 117 | And that is it, your new byte is programmed. 118 | You may want to verify that everything goes well though. 119 | 120 | ## Verifying 121 | 122 | After erasing or programming the flash, it is good practice to make sure that the command was sucessful. As stated in the introduction, those commands are not immediate, and you need to make sure that they worked as intended before doing something else. 123 | 124 | After erasing or programming, bit 6 will toggle on each read, so we can wait until it is stable. 125 | This is a simple naive way of doing it and it can lead to a program lock, but it is usually enough. 126 | 127 | ``` 128 | ldy #0 129 | verifyLoop: 130 | lda destination_address,y 131 | cmp destination_address,y 132 | bne verifyLoop 133 | ``` 134 | 135 | ## Software ID 136 | 137 | _Autoselect mode_ commands allow you to get the chip manufacturer ID, device ID and other information. It can be used to determine the size of the PRG flash chip and sector sizes for advanced usage. We will only see how to get the manufacturer ID and the device ID. 138 | 139 | ### Entry 140 | 141 | To enter the _autoselect mode_, you need to write specific bytes at specific addresses. 142 | 143 | ``` 144 | ; software ID entry command sequence 145 | lda #$AA 146 | sta $8AAA 147 | lda #$55 148 | sta $8555 149 | lda #$90 150 | sta $8AAA 151 | ``` 152 | 153 | ### Read 154 | 155 | Once you are in the _autoselect mode_, you can read the manufacturer ID and the flash chip ID. 156 | 157 | ``` 158 | lda $8000 ; read $8x00 to get manufacturer ID, value depends on manufacturer 159 | ; Cypress: $01 160 | ; ISSI: $9D 161 | ; MX: $C2 162 | ; SST: $BF 163 | 164 | lda $8002 ; read $8x02 to get device ID 1, value depends on device 165 | lda $801C ; read $8x1C to get device ID 2, value depends on device 166 | lda $801E ; read $8x1E to get device ID 3, value depends on device 167 | ``` 168 | 169 | **Note:** this code must be run from RAM because once you enter _autoselect mode_, the chip will not return real Flash values when read. 170 | 171 | ### Exit 172 | 173 | To exit the _autoselect mode_, you just run this simple command. 174 | 175 | ``` 176 | ; software ID exit command 177 | lda #$F0 178 | sta $8xxx ; address does not matter here 179 | ; as long as it points to the PRG-ROM 180 | ``` 181 | -------------------------------------------------------------------------------- /NES/rainbow-net-code-example.md: -------------------------------------------------------------------------------- 1 | # NES Rainbow Net code example 2 | 3 | ## Configuration 4 | 5 | First we need to configure Rainbow Net registers. 6 | 7 | ``` 8 | ; received data will be stored in FPGA-RAM at $4800 9 | ; data to be sent must be written to FPGA-RAM at $4900 10 | lda #$00 ; $48 works too if you want it to be clearer 11 | sta $4193 ; RX high 12 | lda #$01 ; $49 works too if you want it to be clearer 13 | sta $4194 ; TX high 14 | 15 | ; Enable ESP communication 16 | lda #1 17 | sta $4190 18 | ``` 19 | 20 | ## Send and receive data 21 | 22 | Here's an example on how to send and receive data. 23 | 24 | ``` 25 | ; to send data we first need to write our message to RAM at $4900 since that's what we configured above 26 | ; let's ask the ESP for a random 16 bits number between 0x0010 and 0x2000... 27 | lda #$05 ; message length 28 | sta $4900 29 | lda #RND_GET_WORD_RANGE ; command 30 | sta $4901 31 | lda #$00 ; minimum value high byte 32 | sta $4902 33 | lda #$10 ; minimum value low byte 34 | sta $4903 35 | lda #$20 ; maximum value high byte 36 | sta $4904 37 | lda #$00 ; maximum value low byte 38 | sta $4905 39 | sta $4192 ; send the message 40 | 41 | ; now we check if the message has been sent 42 | : 43 | bit $4192 ; check TX register bit 7, should be 1 when message is sent 44 | bpl :- 45 | 46 | ; now we wait for an answer 47 | : 48 | bit $4191 ; check RX register bit 7, should be 1 when a message is received 49 | bpl :- 50 | 51 | ; let's copy the received value to zeropage 52 | ; $4800 should be the received message length 53 | ; $4801 should be the received message command (RND_WORD here) 54 | lda $4802 ; received value high byte 55 | sta $00 56 | lda $4803 ; received value low byte 57 | sta $01 58 | 59 | ; we can now acknowledge the received message 60 | ; this will tell the FPGA that he can store a new message if a new message is available 61 | sta $4192 62 | ``` 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rainbow 2 | 3 | Here you'll find the Rainbow Net protoccol documentation. 4 | 5 | | File | Description | 6 | | ----------------------------------------------- | --------------------------------------------------------------- | 7 | | [rainbow-net.md](rainbow-net.md) | Rainbow Net Wi-Fi protocol documentation | 8 | | [NES](NES) | Rainbow mapper documentation for the NES | 9 | | [Mega Drive / Genesis](MEGADRIVE-GENESIS) (WIP) | Rainbow mapper documentation for the Mega Drive / Genesis (WIP) | 10 | 11 | # Contact 12 | 13 | Feel free to give your feedback, and don't hesitate to create your own ROM and server too! 14 | I'd be happy to test it on real hardware if you want. 15 | 16 | You can email me at contact@brokestudio.fr or via the contact form at https://www.brokestudio.fr/contact/ 17 | 18 | Also, you can join Broke Studio's Discord server https://discord.gg/ccDS9Au, and discuss about the Rainbow project and/or other things :) 19 | 20 | >   21 | > _Antoine GOHIN / Broke Studio_ 22 | > **mail**: contact@brokestudio.fr 23 | > **web**: https://www.brokestudio.fr 24 | > **twitter**: @Broke_Studio 25 | > **facebook**: Broke Studio 26 | > **instagram**: @broke_studio 27 | >   28 | --------------------------------------------------------------------------------