├── .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's what you'll need: 19 | 20 | - a custom version of [Mesen2 or FCEUX](https://brokestudio.fr/rainbow/emulators) supporting the Rainbow mapper 21 | - a [rainbow NES boiler plate](https://github.com/BrokeStudio/rainbow-nes-boiler-plate) (using cc65) - optional 22 | - the above documentation 23 | - there's also a [chat demo](https://github.com/BrokeStudio/rainbow-chat) available 24 | 25 | ## Notes 26 | 27 | - custom FCEUX version doesn't support all the mapper features yet 28 | - custom Mesen2 version doesn't support secured TCP protocol 29 | 30 | # Contact 31 | 32 | Feel free to give your feedback, and don't hesitate to create your own ROM and server too! 33 | I'd be happy to test it on real hardware if you want. 34 | 35 | You can email me at contact@brokestudio.fr or via the contact form at https://www.brokestudio.fr/contact/ 36 | 37 | Also, you can join Broke Studio's Discord server https://discord.gg/ccDS9Au, and discuss about the Rainbow project and/or other things :) 38 | 39 | >   40 | > _Antoine GOHIN / Broke Studio_ 41 | > **mail**: contact@brokestudio.fr 42 | > **web**: https://www.brokestudio.fr 43 | > **twitter**: @Broke_Studio 44 | > **facebook**: Broke Studio 45 | > **instagram**: @broke_studio 46 | >   47 | -------------------------------------------------------------------------------- /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 $4170 6 | RNBW_RX EQU $4171 7 | RNBW_TX EQU $4172 8 | RNBW_RX_ADD EQU $4173 9 | RNBW_TX_ADD EQU $4174 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 (**temporary**). 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/files, dump/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 | - configurable IRQ 32 | - Nametables can be individually mapped to CHR-RAM/CHR-ROM/FPGA-RAM 33 | - Pattern tables can be mapped to CHR-RAM/CHR-ROM/FPGA-RAM 34 | - Attribute Extended Mode allows each individual 8x8 tile to have its own palette setting 35 | - Background Extended Mode allows to address up to 16384 tiles 36 | - Sprite Extended Mode allows to address up to 65535 tiles 37 | - Auto-generated OAM procedures 38 | - OAM slow clear routine 39 | - OAM slow update routine 40 | - OAM Extended bank update routine 41 | - Window Split Mode 42 | - Expansion audio: 43 | - 2 pulse channels 44 | - 1 sawtooth channel 45 | - ZPCM mode that allows expansion audio on stock NES 46 | - System reset detection 47 | - resets some registers 48 | 49 | # Banks 50 | 51 | The Rainbow mapper provides: 52 | 53 | - PRG-ROM: 5 banking modes 54 | - PRG-RAM: 2 banking modes 55 | - CHR-ROM: 5 banking modes 56 | 57 | ## PRG-ROM mode 0 58 | 59 | - CPU \$8000-\$FFFF: 32 KB switchable PRG-ROM/PRG-RAM bank 60 | 61 | ## PRG-ROM mode 1 62 | 63 | - CPU \$8000-\$BFFF: 16 KB switchable PRG-ROM/PRG-RAM bank 64 | - CPU \$C000-\$FFFF: 16 KB switchable PRG-ROM/PRG-RAM bank 65 | 66 | ## PRG-ROM mode 2 67 | 68 | - CPU \$8000-\$BFFF: 16 KB switchable PRG-ROM/PRG-RAM bank 69 | - CPU \$C000-\$DFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 70 | - CPU \$E000-\$FFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 71 | 72 | ## PRG-ROM mode 3 73 | 74 | - CPU \$8000-\$9FFF: 8 KB switchable PRG-ROM/PRG-RAM bank 75 | - CPU \$A000-\$BFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 76 | - CPU \$C000-\$DFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 77 | - CPU \$E000-\$FFFF: 8 KB switchable PRG-ROM/PRG-RAM bank 78 | 79 | ## PRG-ROM mode 4 80 | 81 | - CPU \$8000-\$8FFF: 4 KB switchable PRG-ROM/PRG-RAM bank 82 | - CPU \$9000-\$9FFF: 4 KB switchable PRG-ROM/PRG-RAM bank 83 | - CPU \$A000-\$AFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 84 | - CPU \$B000-\$BFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 85 | - CPU \$C000-\$CFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 86 | - CPU \$D000-\$DFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 87 | - CPU \$E000-\$EFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 88 | - CPU \$F000-\$FFFF: 4 KB switchable PRG-ROM/PRG-RAM bank 89 | 90 | ## PRG-RAM mode 0 91 | 92 | - CPU \$6000-\$7FFF: 8 KB switchable PRG-RAM/PRG-ROM/FPGA-RAM bank 93 | 94 | ## PRG-RAM mode 1 95 | 96 | - CPU \$6000-\$6FFF: 4 KB switchable PRG-RAM/ROM/FPGA-RAM bank 97 | - CPU \$7000-\$7FFF: 4 KB switchable PRG-RAM/ROM/FPGA-RAM bank 98 | 99 | ## CHR mode 0 100 | 101 | - PPU \$0000-\$1FFF: 8 KB switchable CHR bank 102 | 103 | ## CHR mode 1 104 | 105 | - PPU \$0000-\$0FFF: 4 KB switchable CHR bank 106 | - PPU \$1000-\$1FFF: 4 KB switchable CHR bank 107 | 108 | ## CHR mode 2 109 | 110 | - PPU \$0000-\$07FF: 2 KB switchable CHR bank 111 | - PPU \$0800-\$0FFF: 2 KB switchable CHR bank 112 | - PPU \$1000-\$17FF: 2 KB switchable CHR bank 113 | - PPU \$1800-\$1FFF: 2 KB switchable CHR bank 114 | 115 | ## CHR mode 3 116 | 117 | - PPU \$0000-\$03FF: 1 KB switchable CHR bank 118 | - PPU \$0400-\$07FF: 1 KB switchable CHR bank 119 | - PPU \$0800-\$0BFF: 1 KB switchable CHR bank 120 | - PPU \$0C00-\$0FFF: 1 KB switchable CHR bank 121 | - PPU \$1000-\$13FF: 1 KB switchable CHR bank 122 | - PPU \$1400-\$17FF: 1 KB switchable CHR bank 123 | - PPU \$1800-\$1BFF: 1 KB switchable CHR bank 124 | - PPU \$1C00-\$1FFF: 1 KB switchable CHR bank 125 | 126 | ## CHR mode 4 127 | 128 | - PPU \$0000-\$01FF: 512B switchable CHR bank 129 | - PPU \$0200-\$03FF: 512B switchable CHR bank 130 | - PPU \$0400-\$05FF: 512B switchable CHR bank 131 | - PPU \$0600-\$07FF: 512B switchable CHR bank 132 | - PPU \$0800-\$09FF: 512B switchable CHR bank 133 | - PPU \$0A00-\$0BFF: 512B switchable CHR bank 134 | - PPU \$0C00-\$0DFF: 512B switchable CHR bank 135 | - PPU \$0E00-\$0FFF: 512B switchable CHR bank 136 | - PPU \$1000-\$11FF: 512B switchable CHR bank 137 | - PPU \$1200-\$13FF: 512B switchable CHR bank 138 | - PPU \$1400-\$15FF: 512B switchable CHR bank 139 | - PPU \$1600-\$17FF: 512B switchable CHR bank 140 | - PPU \$1800-\$19FF: 512B switchable CHR bank 141 | - PPU \$1A00-\$1BFF: 512B switchable CHR bank 142 | - PPU \$1C00-\$1DFF: 512B switchable CHR bank 143 | - PPU \$1E00-\$1FFF: 512B switchable CHR bank 144 | 145 | # Registers 146 | 147 | ## Power-up and reset register status 148 | 149 | On power-up and reset, some registers are initialized/reset with specific values. 150 | 151 | | Register | Value | Note | 152 | | -------- | ----- | --------------------------------------------------------------------------------------- | 153 | | | | **PRG settings** | 154 | | \$4100 | \$00 | Set PRG-ROM mode 0 (32K banks) and PRG-RAM mode 0 (8K banks) | 155 | | \$4108 | \$00 | Set PRG-ROM 32K bank upper bits to $00 so it will address the first bank | 156 | | \$4118 | \$00 | Set PRG-ROM 32K bank lower bits to $00 so it will address the first bank | 157 | | | | **CHR settings** | 158 | | \$4120 | \$00 | Set CHR mode 0 (8K banks), CHR-ROM as pattern table, | 159 | | | | disable Sprite Extended Mode, disable Window Split Mode | 160 | | \$4130 | \$00 | Set CHR-ROM 8K bank upper bits to $00 so it will address the first bank | 161 | | \$4140 | \$00 | Set CHR-ROM 8K bank lower bits to $00 so it will address the first bank | 162 | | | | **Nametables settings (horizontal mirroring using CIRAM)** | 163 | | \$4126 | \$00 | Set nametable @ \$2000 bank to 0 | 164 | | \$4127 | \$00 | Set nametable @ \$2400 bank to 0 | 165 | | \$4128 | \$01 | Set nametable @ \$2800 bank to 1 | 166 | | \$4129 | \$01 | Set nametable @ \$2C00 bank to 1 | 167 | | \$412E | \$00 | Set Window Split Mode nametable bank to 0 | 168 | | \$412A | \$00 | Set nametable @ \$2000 chip selector to CIRAM | 169 | | \$412B | \$00 | Set nametable @ \$2400 chip selector to CIRAM | 170 | | \$412C | \$00 | Set nametable @ \$2800 chip selector to CIRAM | 171 | | \$412D | \$00 | Set nametable @ \$2C00 chip selector to CIRAM | 172 | | \$412F | \$80 | Set Window Split Mode nametable chip selector to FPGA-RAM | 173 | | | | **Auto-generated OAM procedures** | 174 | | \$4241 | \$07 | Set the OAM slow update page to 7, using $4F00 as the OAM shadow data source | 175 | | \$4242 | \$1B | Set the OAM ext update page to 27, using $4EC0 as the Sprite Extended Banks data source | 176 | | | | **Scanline IRQ settings** | 177 | | \$4152 | \$00 | Disable scanline IRQ (IRQ cleared if pending) | 178 | | \$4153 | \$87 | Set scanline IRQ offset to 135 | 179 | | | | **CPU Cycle IRQ settings** | 180 | | \$415A | \$00 | Disable CPU Cycle IRQ (IRQ cleared if pending) | 181 | | | | **Wi-Fi** | 182 | | \$4190 | \$00 | Disable Wi-Fi | 183 | | | | **Audio Expansion** | 184 | | \$41A9 | \$03 | Enable EXP6 and EXP9 outputs, disable ZPCM | 185 | | \$41AA | \$0F | Set default master volume | 186 | 187 | ## PRG banking modes (\$4100, read/write) 188 | 189 | ``` 190 | 7 bit 0 191 | ---- ---- 192 | A... .OOO 193 | | ||| 194 | | +++- PRG-ROM banking mode 195 | | 000: 32K (mode 0) 196 | | 001: 16K + 16K (mode 1) 197 | | 010: 16K + 8K + 8K (mode 2) 198 | | 011: 8K + 8K + 8K + 8K (mode 3) 199 | | 1xx: 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K (mode 4) 200 | +--------- PRG-RAM banking mode 201 | 0: 8K 202 | 1: 4K + 4K 203 | ``` 204 | 205 | ## PRG-ROM banking (\$4108-\$410F and \$4118-\$411F, write-only) 206 | 207 | ### Bank upper bits and chip selector 208 | 209 | - \$4108 (W) 210 | - CPU \$8000-\$FFFF (mode 0) 211 | - CPU \$8000-\$BFFF (mode 1) 212 | - CPU \$8000-\$BFFF (mode 2) 213 | - CPU \$8000-\$9FFF (mode 3) 214 | - CPU \$8000-\$8FFF (mode 4) 215 | - \$4109 (W) 216 | - CPU \$9000-\$9FFF (mode 4) 217 | - \$410A (W) 218 | - CPU \$A000-\$BFFF (mode 3) 219 | - CPU \$A000-\$AFFF (mode 4) 220 | - \$410B (W) 221 | - CPU \$B000-\$BFFF (mode 4) 222 | - \$410C (W) 223 | - CPU \$C000-\$FFFF (mode 1) 224 | - CPU \$C000-\$DFFF (mode 2) 225 | - CPU \$C000-\$DFFF (mode 3) 226 | - CPU \$C000-\$CFFF (mode 4) 227 | - \$410D (W) 228 | - CPU \$D000-\$DFFF (mode 4) 229 | - \$410E (W) 230 | - CPU \$E000-\$FFFF (mode 2) 231 | - CPU \$E000-\$FFFF (mode 3) 232 | - CPU \$E000-\$EFFF (mode 4) 233 | - \$410F (W) 234 | - CPU \$F000-\$FFFF (mode 4) 235 | 236 | ``` 237 | 7 bit 0 238 | ---- ---- 239 | CUUU UUUU 240 | |||| |||| 241 | |+++-++++- Bank index upper bits 242 | +--------- Chip selector 243 | 0: PRG-ROM 244 | 1: PRG-RAM 245 | ``` 246 | 247 | ### Bank lower bits 248 | 249 | - \$4118 (W) 250 | - CPU \$8000-\$FFFF (mode 0) 251 | - CPU \$8000-\$BFFF (mode 1) 252 | - CPU \$8000-\$BFFF (mode 2) 253 | - CPU \$8000-\$9FFF (mode 3) 254 | - CPU \$8000-\$8FFF (mode 4) 255 | - \$4119 (W) 256 | - CPU \$9000-\$9FFF (mode 4) 257 | - \$411A (W) 258 | - CPU \$A000-\$BFFF (mode 3) 259 | - CPU \$A000-\$AFFF (mode 4) 260 | - \$411B (W) 261 | - CPU \$B000-\$BFFF (mode 4) 262 | - \$411C (W) 263 | - CPU \$C000-\$FFFF (mode 1) 264 | - CPU \$C000-\$DFFF (mode 2) 265 | - CPU \$C000-\$DFFF (mode 3) 266 | - CPU \$C000-\$CFFF (mode 4) 267 | - \$411D (W) 268 | - CPU \$D000-\$DFFF (mode 4) 269 | - \$411E (W) 270 | - CPU \$E000-\$FFFF (mode 2) 271 | - CPU \$E000-\$FFFF (mode 3) 272 | - CPU \$E000-\$EFFF (mode 4) 273 | - \$411F (W) 274 | - CPU \$F000-\$FFFF (mode 4) 275 | 276 | ``` 277 | 7 bit 0 278 | ---- ---- 279 | LLLL LLLL 280 | |||| |||| 281 | ++++-++++- Bank index lower bits 282 | ``` 283 | 284 | ## PRG-RAM banking (\$4106-\$4107 and \$4116-\$4117, write-only) 285 | 286 | ### Bank upper bits and chip selector 287 | 288 | - \$4106 (W) 289 | - CPU \$6000-\$7FFF (mode 0) 290 | - CPU \$6000-\$6FFF (mode 1) 291 | - \$4107 (W) 292 | - CPU \$7000-\$7FFF (mode 1) 293 | 294 | ``` 295 | 7 bit 0 296 | ---- ---- 297 | CuUU UUUU 298 | |||| |||| 299 | |+++-++++- Bank index upper bits (u only used in PRG-ROM mode) 300 | ++-------- Chip selector 301 | 0x: PRG-ROM (u is used for bank index) 302 | 10: PRG-RAM 303 | 11: FPGA-RAM 304 | If using PRG-RAM 8K mode, then bank number is ignored since FPGA-RAM is only 8K. 305 | If using PRG-RAM 4K mode, then only the bank number lower bit is used to select the 4K page. 306 | ``` 307 | 308 | ### Bank lower bits 309 | 310 | - \$4116 (W) 311 | - CPU \$6000-\$7FFF (mode 0) 312 | - CPU \$6000-\$6FFF (mode 1) 313 | - \$4117 (W) 314 | - CPU \$7000-\$7FFF (mode 1) 315 | 316 | ``` 317 | 7 bit 0 318 | ---- ---- 319 | LLLL LLLL 320 | |||| |||| 321 | ++++-++++- Bank index lower bits 322 | ``` 323 | 324 | ## FPGA-RAM banking (\$4115, write-only) 325 | 326 | - \$4115 (W) 327 | - CPU \$5000-\$5FFF 328 | 329 | ``` 330 | 7 bit 0 331 | ---- ---- 332 | .... ...B 333 | | 334 | +- Bank index (select 4K page of FPGA-RAM) 335 | ``` 336 | 337 | ## CHR configuration 338 | 339 | Some CHR configurations involve the first 4K of FPGA-RAM. 340 | It can be used as nametables, pattern tables, 8x8 attribute tables, extended tiles (can address up to 16384 tiles). 341 | 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. 342 | 343 | **/!\ Using FPGA-RAM as nametable _and_ pattern table is _not_ a good idea.** 344 | 345 | ### CHR control (banking modes / source / Sprite Extended Mode / Window Split Mode) (\$4120, read/write) 346 | 347 | ``` 348 | 7 bit 0 349 | ---- ---- 350 | CCSW .BBB 351 | |||| ||| 352 | |||| +++- CHR banking mode 353 | |||| 000: 8K CHR mode 0 (CHR bank 0 is used) 354 | |||| 001: 4K CHR mode 1 (CHR bank 0 to 1 are used) 355 | |||| 010: 2K CHR mode 2 (CHR banks 0 to 3 are used) 356 | |||| 011: 1K CHR mode 3 (CHR banks 0 to 7 are used) - see note below 357 | |||| 1xx: 512B CHR mode 4 (CHR banks 0 to 15 are used) - see note below 358 | |||+------ Window Split Mode (0: disabled, 1: enabled) 359 | ||+------- Sprite Extended Mode (0: disabled, 1: enabled), see registers $4200-$4240 360 | ++-------- Chip selector for pattern tables 361 | 00: CHR-ROM 362 | 01: CHR-RAM 363 | 1x: FPGA-RAM (4K mode is forced, \$0000-\$0FFF mirrored at \$1000-\$1FFF, banking settings are ignored) 364 | 365 | Note: when using 1K and 512B CHR banking modes with 512K (or more) CHR-ROM, 366 | you also need to update the CHR bank upper bits using the appropriate registers (\$4130-\$413F) 367 | ``` 368 | 369 | ### Background Extended Mode bank upper bits (\$4121, write-only) 370 | 371 | ``` 372 | 7 bit 0 373 | ---- ---- 374 | ...U UUUU 375 | |-|||| 376 | +-++++- 377 | ``` 378 | 379 | When using Background Extended Mode, you can address up to 16384 tiles. 380 | This registers is used to select a 256K CHR offset for every tiles. 381 | 382 | ### Nametables bank ($4126-$4129, write-only) 383 | 384 | - \$4126 controls nametable at \$2000 385 | - \$4127 controls nametable at \$2400 386 | - \$4128 controls nametable at \$2800 387 | - \$4129 controls nametable at \$2C00 388 | - \$412E controls Window Split nametable 389 | 390 | ``` 391 | 7 bit 0 392 | ---- ---- 393 | BBBB BBBB 394 | |||| |||| 395 | ++++-++++- Bank index 396 | Depending on chip source (CIRAM, CHR-ROM, CHR-RAM or FPGA-RAM) used for the corresponding nametable, 397 | not all bits are used. 398 | ``` 399 | 400 | ### Nametables control ($412A-$412D, read-write) 401 | 402 | - \$412A controls nametable at \$2000 403 | - \$412B controls nametable at \$2400 404 | - \$412C controls nametable at \$2800 405 | - \$412D controls nametable at \$2C00 406 | - \$412F controls Window Split nametable 407 | 408 | ``` 409 | 7 bit 0 410 | ---- ---- 411 | CCF. DDEE 412 | ||| |||| 413 | ||| |||| 414 | ||| ||++- Extended Modes 415 | ||| || 00: Extended Modes disabled 416 | ||| || 01: Attribute Extended Mode 417 | ||| || 10: Background Extended Mode 418 | ||| || 11: Attribute Extended Mode + Background Extended Mode 419 | ||| ++--- 1K destination in 4K FPGA-RAM 420 | ||| Used when Extended mode above is not %00 421 | ||| 00: 1st 1K of FPGA-RAM 422 | ||| 01: 2nd 1K of FPGA-RAM 423 | ||| 10: 3rd 1K of FPGA-RAM 424 | ||| 11: 4th 1K of FPGA-RAM 425 | ||+------- Fill-mode (0: disable, 1: enable, see $4124 and $4125) 426 | ++-------- Chip selector (forced to FPGA-RAM for $412F) 427 | 00: CIRAM 428 | 01: CHR-RAM 429 | 10: FPGA-RAM 430 | 11: CHR-ROM 431 | ``` 432 | 433 | Note: 434 | 435 | - Window Split chip will be forced to FPGA-RAM. 436 | 437 | #### Extended Modes 438 | 439 | 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. 440 | 441 | Extended byte format: 442 | 443 | ``` 444 | 7 bit 0 445 | ---- ---- 446 | AABB BBBB 447 | |||| |||| 448 | ||++-++++- Select 4 KB CHR bank to use with specified tile (Background Extended Mode) 449 | ++-------- Select palette to use with specified tile (Attribute Extended Mode) 450 | ``` 451 | 452 | In Background extended mode, CHR banking behaves differently than normal when fetching tiles from pattern tables: 453 | 454 | - CHR banking mode (register \$4120) is ignored but not CHR source (register \$4120) 455 | - CHR banks are always 4KB in this mode 456 | - The values of the CHR banking registers \$4130-\$414F are also ignored 457 | - Bits 0-5 specified above are used for selecting a 4KB CHR bank on a per-tile basis 458 | - Bits 0-4 of register $4121 are used for selecting a 256K CHR offset for every tiles 459 | 460 | #### Chip selector 461 | 462 | | Chip selector (CC) | Value | Notes | 463 | | ------------------ | ----- | ------------------------------------------------------------------------------ | 464 | | CIRAM | %00 | Only the lower bit of the corresponding nametable bank register is used | 465 | | | | to address either one or the other nametable provided by the console. | 466 | | | | | 467 | | CHR-RAM | %01 | Corresponding nametable bank register is used to address 1KB blocks of CHR-RAM | 468 | | | | Depending on the CHR-RAM size, not all bits will be used. | 469 | | | | | 470 | | FPGA-RAM | %10 | Only the two lower bits of the corresponding nametable bank register are used | 471 | | | | to address one of the 4KB of FPGA-RAM. | 472 | | | | Those 4KB of FPGA-RAM can also be accessed by the CPU at \$5000-$5FFF (bank 0) | 473 | | | | This means that you can update the nametable during rendering. | 474 | | | | /!\ Using FPGA-RAM as nametable **and** pattern table is not a good idea. | 475 | | | | /!\ Using FPGA-RAM as nametable **and** as Extended Mode data can be done | 476 | | | | under certain circumstances: | 477 | | | | - when using FPGA-RAM as nametable at \$2000 or \$2400, you can only | 478 | | | | use 3rd and 4th 1K bank of FPGA-RAM as Extended Mode data. | 479 | | | | - when using FPGA-RAM as nametable at \$2800 or \$2C00, you can only | 480 | | | | use 1st and 2nd 1K bank of FPGA-RAM as Extended Mode data. | 481 | | | | | 482 | | CHR-ROM | %11 | Corresponding nametable bank register is used to address 1KB blocks of CHR-ROM | 483 | | | | Depending on the CHR-ROM size, not all bits will be used | 484 | 485 | #### Nametables mirroring 486 | 487 | Mirroring depends on the way you arrange registers \$4126-\$4129 and \$412A-\$412D. 488 | 489 | | Mirroring | Registers configuration | 490 | | ------------- | --------------------------------------------- | 491 | | Horizontal | \$412A.CC = \$412B.CC | 492 | | | \$412C.CC = \$412D.CC | 493 | | | \$4126 = \$4127 | 494 | | | \$4128 = \$4129 | 495 | | Vertical | \$412A.CC = \$412C.CC | 496 | | | \$412B.CC = \$412D.CC | 497 | | | \$4126 = \$4128 | 498 | | | \$4127 = \$4129 | 499 | | Diagonal | \$412A.CC = \$412D.CC | 500 | | | \$412B.CC = \$412C.CC | 501 | | | \$4126 = \$4129 | 502 | | | \$4127 = \$4128 | 503 | | Single-screen | \$412A.CC = \$412B.CC = \$412C.CC = \$412D.CC | 504 | | | \$4126 = \$4127 = \$4128 = \$4129 | 505 | | 4-screen | All 4 nametables must have different settings | 506 | 507 | ## Fill-mode (\$4124-\$4125) 508 | 509 | 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. 510 | 511 | ### Fill-mode tile index (\$4124, write-only) 512 | 513 | ``` 514 | 7 bit 0 515 | ---- ---- 516 | TTTT TTTT 517 | |||| |||| 518 | ++++-++++- Specify tile index to use for fill-mode nametable 519 | ``` 520 | 521 | ### Fill-mode attribute index (\$4125, write-only) 522 | 523 | ``` 524 | 7 bit 0 525 | ---- ---- 526 | .... ..AA 527 | || 528 | ++- Specify background palette index to use for fill-mode nametable 529 | ``` 530 | 531 | ## CHR banking (\$4130-\$414F, write-only) 532 | 533 | ### Bank bits 534 | 535 | - \$4130 (upper bits) / \$4140 (lower bits) (W) 536 | - PPU \$0000-\$1FFF (mode 0) 537 | - PPU \$0000-\$0FFF (mode 1) 538 | - PPU \$0000-\$07FF (mode 2) 539 | - PPU \$0000-\$03FF (mode 3) 540 | - PPU \$0000-\$01FF (mode 4) 541 | - \$4131 (upper bits) / \$4141 (lower bits) (W) 542 | - PPU \$1000-\$1FFF (mode 1) 543 | - PPU \$0800-\$0FFF (mode 2) 544 | - PPU \$0400-\$07FF (mode 3) 545 | - PPU \$0200-\$03FF (mode 4) 546 | - \$4132 (upper bits) / \$4142 (lower bits) (W) 547 | - PPU \$1000-\$17FF (mode 2) 548 | - PPU \$0800-\$0BFF (mode 3) 549 | - PPU \$0400-\$05FF (mode 4) 550 | - \$4133 (upper bits) / \$4143 (lower bits) (W) 551 | - PPU \$1800-\$1FFF (mode 2) 552 | - PPU \$0C00-\$0FFF (mode 3) 553 | - PPU \$0600-\$07FF (mode 4) 554 | - \$4134 (upper bits) / \$4144 (lower bits) (W) 555 | - PPU \$1000-\$13FF (mode 3) 556 | - PPU \$0800-\$09FF (mode 4) 557 | - \$4135 (upper bits) / \$4145 (lower bits) (W) 558 | - PPU \$1400-\$17FF (mode 3) 559 | - PPU \$0A00-\$0BFF (mode 4) 560 | - \$4136 (upper bits) / \$4146 (lower bits) (W) 561 | - PPU \$1800-\$1BFF (mode 3) 562 | - PPU \$0C00-\$0DFF (mode 4) 563 | - \$4137 (upper bits) / \$4147 (lower bits) (W) 564 | - PPU \$1C00-\$1FFF (mode 3) 565 | - PPU \$0E00-\$0FFF (mode 4) 566 | - \$4138 (upper bits) / \$4148 (lower bits) (W) 567 | - PPU \$1000-\$11FF (mode 4) 568 | - \$4139 (upper bits) / \$4149 (lower bits) (W) 569 | - PPU \$1200-\$13FF (mode 4) 570 | - \$413A (upper bits) / \$414A (lower bits) (W) 571 | - PPU \$1400-\$15FF (mode 4) 572 | - \$413B (upper bits) / \$414B (lower bits) (W) 573 | - PPU \$1600-\$17FF (mode 4) 574 | - \$413C (upper bits) / \$414C (lower bits) (W) 575 | - PPU \$1800-\$19FF (mode 4) 576 | - \$413D (upper bits) / \$414D (lower bits) (W) 577 | - PPU \$1A00-\$1BFF (mode 4) 578 | - \$413E (upper bits) / \$414E (lower bits) (W) 579 | - PPU \$1C00-\$1DFF (mode 4) 580 | - \$413F (upper bits) / \$414F (lower bits) (W) 581 | - PPU \$1E00-\$1FFF (mode 4) 582 | 583 | ``` 584 | 7 bit 0 585 | ---- ---- 586 | BBBB BBBB 587 | |||| |||| 588 | ++++-++++- Bank index upper bits (\$413x) or lower bits (\$414x) 589 | ``` 590 | 591 | ## Sprite Extended Mode (\$4200-\$4240) 592 | 593 | In Sprite Extended Mode, CHR banking behaves differently than normal when fetching tiles from pattern tables: 594 | 595 | - CHR banking mode (register \$4120) is ignored but not CHR source (register \$4120) 596 | - CHR banks are always 4KB in this mode 597 | - The values of the CHR banking registers \$4130-\$414F are also ignored 598 | - Registers \$4200-\$423F specify the bank lower bits for each sprite (4K CHR bank selector) allowing the possibility to address 65535 sprites 599 | - Register \$4240 specify the bank upper bits for all sprites (1024K CHR bank selector) 600 | 601 | ### Sprite Extended Mode bank lower bits (\$4200-\$423F, write-only) 602 | 603 | One register per sprite. 604 | 605 | ``` 606 | 7 bit 0 607 | ---- ---- 608 | LLLL LLLL 609 | |||| |||| 610 | ++++-++++- Bank index lower bits 611 | ``` 612 | 613 | ### Sprite Extended Mode bank upper bits (\$4240, write-only) 614 | 615 | The bank upper bits are common to every sprite. 616 | 617 | ``` 618 | 7 bit 0 619 | ---- ---- 620 | .... .UUU 621 | ||| 622 | +++- Bank index upper bits 623 | ``` 624 | 625 | ## Auto-generated OAM procedures 626 | 627 | 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: 628 | 629 | - **OAM slow clear** allows you to clear the sprites by writing \$FF for each sprite Y position only using registers $2003/$2004 (no OAM DMA) 630 | - **OAM slow update** allows you to update the sprites data for each sprite only using registers $2003/$2004 (no OAM DMA) 631 | - **OAM ext update** allows you to update the sprites extended bank automatically (when using Sprites Extended Mode) 632 | 633 | 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. 634 | 635 | ### OAM slow clear (\$4286, executable) 636 | 637 | To execute this routine, you just need to do `jsr $4286`. 638 | This routine will write $FF for each sprite Y position using only registers $2003/2004, and uses **648** cycles including the final `rts` opcode. 639 | 640 | ### OAM slow update (\$4241, write-only and \$4280, executable) 641 | 642 | To execute this routine, you just need to do `jsr $4280`. 643 | This routine will update the sprites OAM data using only registers $2003/2004, and uses **1548** cycles including the final `rts` opcode. 644 | 645 | Register \$4241 sets the 256 bytes page to be used, starting at \$4800 (FPGA-RAM). 646 | 647 | ``` 648 | 7 bit 0 649 | ---- ---- 650 | .... .PPP 651 | ||| 652 | +++- OAM shadow page index 653 | ``` 654 | 655 | ### OAM ext update (\$4242, write-only and \$4282, executable) 656 | 657 | To execute this routine, you just need to do `jsr $4282`. 658 | This routine will write the extended bank data for each sprite (registers \$42xx), and uses **390** cycles including the final `rts` opcode. 659 | 660 | Register \$4242 sets the 64 bytes page to be used, starting at \$4800 (FPGA-RAM). 661 | 662 | ``` 663 | 7 bit 0 664 | ---- ---- 665 | ...P PPPP 666 | | |||| 667 | +-++++- OAM extended banks page index 668 | ``` 669 | 670 | ## Window Split Mode (\$4170-\$4175) 671 | 672 | 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). 673 | 674 | Notes: 675 | 676 | - 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). 677 | - 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. 678 | - Horizontal scrolling for the split region operates on a per-tile basis, meaning that it will move horizontally by 8px steps. 679 | - 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). 680 | - FPGA-RAM is always used as the nametable in split mode (see register \$412F). 681 | 682 | ### Window Split start/stop tile ($4170-$4171, write-only) 683 | 684 | Register \$4170 defines the tile where the split starts. 685 | 686 | ``` 687 | 7 bit 0 688 | ---- ---- 689 | ...S SSSS 690 | |-|||| 691 | +-++++- Specify Window Split start tile (0-31) 692 | ``` 693 | 694 | Register \$4171 defines the tile where the split region stops. 695 | 696 | ``` 697 | 7 bit 0 698 | ---- ---- 699 | ...E EEEE 700 | |-|||| 701 | +-++++- Specify Window Split stop tile (0-31) 702 | ``` 703 | 704 | Note: 705 | 706 | - 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. 707 | - 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. 708 | 709 | ### Window Split start/stop tile ($4172-$4173, write-only) 710 | 711 | Register \$4172 defines the tile where the split starts. 712 | 713 | ``` 714 | 7 bit 0 715 | ---- ---- 716 | SSSS SSSS 717 | ||||-|||| 718 | ++++-++++- Specify Window Split start position (0-256) 719 | ``` 720 | 721 | Register \$4173 defines the tile where the split region stops. 722 | 723 | ``` 724 | 7 bit 0 725 | ---- ---- 726 | EEEE EEEE 727 | ||||-|||| 728 | ++++-++++- Specify Window Split stop position (0-256) 729 | ``` 730 | 731 | Note: 732 | 733 | - 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_. 734 | - 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_. 735 | 736 | ### Window Split coarse X scroll ($4174, write-only) 737 | 738 | This register controls the horizontal scrolling of the split region on a per-tile basis. 739 | 740 | ``` 741 | 7 bit 0 742 | ---- ---- 743 | ...X XXXX 744 | |-|||| 745 | +-++++- Specify Window Split coarse X scroll (0-32) 746 | ``` 747 | 748 | TODO... 749 | 750 | ### Window Split fine Y scroll ($4175, write-only) 751 | 752 | This register controls the vertical scrolling of the split region. 753 | 754 | ``` 755 | 7 bit 0 756 | ---- ---- 757 | YYYY YYYY 758 | ||||-|||| 759 | ++++-++++- Specify Window Split fine Y scroll (0-256) 760 | ``` 761 | 762 | ## Scanline/PPU IRQ (\$4150-\$4154) 763 | 764 | Scanline IRQ is very close to MMC5's. 765 | For more informations: https://www.nesdev.org/wiki/MMC5#Scanline_Detection_and_Scanline_IRQ. 766 | 767 | ### PPU IRQ latch (\$4150, read-write) 768 | 769 | Write 770 | 771 | **from MMC5 wiki page, need to test** 772 | 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. 773 | 774 | ``` 775 | 7 bit 0 776 | ---- ---- 777 | LLLL LLLL 778 | |||| |||| 779 | ++++-++++- IRQ latch value 780 | ``` 781 | 782 | Read 783 | 784 | ``` 785 | 7 bit 0 786 | ---- ---- 787 | LLLL LLLL 788 | |||| |||| 789 | ++++-++++- IRQ scanline counter value 790 | ``` 791 | 792 | Reading this register will return the current scanline being rendered. 793 | This only works if rendering is enabled and if it hasn't been disabled during rendering. 794 | 795 | ### PPU IRQ enable / status (\$4151, read-write) 796 | 797 | Write 798 | 799 | Writing any value to this register will enable scanline IRQ. 800 | 801 | Read 802 | 803 | ``` 804 | 7 bit 0 805 | ---- ---- 806 | HF.. ...I 807 | || | 808 | || +- Scanline IRQ Pending flag 809 | |+-------- In-Frame flag 810 | +--------- HBlank flag 811 | ``` 812 | 813 | 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. 814 | 815 | The In-Frame flag is set when the PPU is rendering a frame and cleared during vertical blank. 816 | 817 | The HBlank flag is set when the PPU is rendering pixel 256 of each scanline. 818 | 819 | Any time this register is read, the Scanline IRQ Pending flag is cleared (acknowledging the pending IRQ). 820 | 821 | ### PPU IRQ disable (\$4152, write-only) 822 | 823 | Writing any value to this register will disable scanline IRQ AND acknowledge any pending IRQ. 824 | 825 | ### PPU IRQ offset (\$4153, write-only) 826 | 827 | The IRQ offset let's you control when the IRQ is triggered to adjust the timing depending on your needs. 828 | 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). 829 | 830 | The minimum value is 1 (\$01) and offset will be set to 1 if you try to set it to 0. 831 | The default value set on power-up and reset is 135 (\$87). 832 | The maximum value is 170 (\$AA) and value will be capped to 170 if you try to set it to a higher value. 833 | 834 | ``` 835 | 7 bit 0 836 | ---- ---- 837 | OOOO OOOO 838 | |||| |||| 839 | ++++-++++- IRQ offset value 840 | ``` 841 | 842 | ### PPU IRQ jitter counter (\$4154, read-only) 843 | 844 | This counter is incremented on every m2 falling edge. 845 | When an IRQ is triggered, this counter is reset to zero. 846 | 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. 847 | 848 | ``` 849 | 7 bit 0 850 | ---- ---- 851 | CCCC CCCC 852 | |||| |||| 853 | ++++-++++- IRQ jitter counter 854 | ``` 855 | 856 | ## CPU Cycle IRQ (\$4158-\$415B) 857 | 858 | This IRQ feature is a CPU cycle counting IRQ generator. 859 | When enabled, the 16-bit IRQ counter is decremented once per CPU cycle. 860 | When the IRQ counter reaches \$0000, an IRQ is generated and IRQ counter is reloaded with latched value. 861 | The IRQ line is held low until it is acknowledged. 862 | 863 | ### How to Use the IRQ Generator 864 | 865 | - Set the latch to the desired number of cycles. 866 | - Enable the IRQ generator by turning on the IRQ Enable flag of the IRQ Control register. 867 | - Within the IRQ handler, write to the IRQ acknowledge register to acknowledge the IRQ. 868 | - Optional: Go back to Step 1 for the next IRQ. 869 | 870 | ### CPU IRQ latch high byte (\$4158, write-only) 871 | 872 | This register specifies the IRQ latch value high byte. 873 | 874 | ``` 875 | 7 bit 0 876 | ---- ---- 877 | HHHH HHHH 878 | |||| |||| 879 | ++++-++++- The high eight bits of the IRQ latch 880 | ``` 881 | 882 | ### CPU IRQ latch low byte (\$4159, write-only) 883 | 884 | This register specifies the IRQ latch value low byte. 885 | 886 | ``` 887 | 7 bit 0 888 | ---- ---- 889 | LLLL LLLL 890 | |||| |||| 891 | ++++-++++- The low eight bits of the IRQ latch 892 | ``` 893 | 894 | ### CPU IRQ control (\$415A, write-only) 895 | 896 | Writing zero to this register will disable interrupts. 897 | If this register is written to with 'E' set, the IRQ counter is reloaded with the latch value. 898 | If 'E' is clear, the IRQ counter remains unchanged. 899 | The 'A' bit here has no immediate effect, and remains unused until IRQ Acknowledge is written to. 900 | It can be used to distinguish a one-shot IRQ from a repeated IRQ. 901 | If 'Z' is set, the IRQ will be automatically acknowledged when reading \$4011, which makes ZPCM even easier to use. 902 | 903 | ``` 904 | 7 bit 0 905 | --------- 906 | .... .ZAE 907 | ||| 908 | ||+- IRQ enable (0: disabled, 1: enabled) 909 | |+-- IRQ enable after being acknowledged (see IRQ acknowledge) 910 | +--- IRQ acknowledge if $4011 is read (0: disabled, 1: enabled) 911 | ``` 912 | 913 | ### CPU IRQ acknowledge (\$415B, write-only) 914 | 915 | Writing any value to this register will acknowledge the pending IRQ. 916 | In addition, the 'A' control bit moves to the 'E' control bit, enabling or disabling IRQs. 917 | Writes to this register do not affect the current state of the IRQ counter. 918 | 919 | ``` 920 | 7 bit 0 921 | ---- ---- 922 | .... .... 923 | ``` 924 | 925 | ## FPGA-RAM auto reader/write (\$415C-\$415F) 926 | 927 | 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. 928 | First you set the start address, then you set the increment value that will be added the to address after each read or write, and finally you read or write through one register. 929 | 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. 930 | 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. 931 | 932 | ### FPGA-RAM hi address (\$415C, write-only) 933 | 934 | ``` 935 | 7 bit 0 936 | ---- ---- 937 | ...H HHHH 938 | | |||| 939 | +-++++- The high five bits of the FPGA-RAM address 940 | ``` 941 | 942 | ### FPGA-RAM lo address (\$415D, write-only) 943 | 944 | ``` 945 | 7 bit 0 946 | ---- ---- 947 | LLLL LLLL 948 | |||| |||| 949 | ++++-++++- The low eight bits of the FPGA-RAM address 950 | ``` 951 | 952 | ### FPGA-RAM increment (\$415E, write-only) 953 | 954 | ``` 955 | 7 bit 0 956 | ---- ---- 957 | IIII IIII 958 | |||| |||| 959 | ++++-++++- This value will be added to the FPGA-RAM address after each read or write 960 | ``` 961 | 962 | ### FPGA-RAM data (\$415F, read/write) 963 | 964 | ``` 965 | 7 bit 0 966 | ---- ---- 967 | DDDD DDDD 968 | |||| |||| 969 | ++++-++++- Value read or to be written 970 | ``` 971 | 972 | ## Mapper version (\$4160, read-only) 973 | 974 | Read this register to get mapper version. 975 | 976 | ``` 977 | 7 bit 0 978 | ---- ---- 979 | PPPV VVVV 980 | |||| |||| 981 | |||+-++++- Version 982 | +++------- Platform 983 | ``` 984 | 985 | | Platform (PPP) | Description | 986 | | -------------- | ------------ | 987 | | 0 | PCB | 988 | | 1 | Emulator | 989 | | 2 | Web emulator | 990 | 991 | | Version (VVVVV) | Description | Description | 992 | | --------------- | ----------- | --------------------------------------- | 993 | | 0 | v1.0 | Initial release | 994 | 995 | ## IRQ status (\$4161, read-only) 996 | 997 | Read this register to get the IRQ status. 998 | It will indicate if PPU IRQ or CPU IRQ or ESP / Wi-Fi IRQ is pending (1) or not (0). 999 | Reading this register will **NOT** acknowledge any IRQ. 1000 | 1001 | ``` 1002 | 7 bit 0 1003 | ---- ---- 1004 | PC.. ...W 1005 | || | 1006 | || +- ESP / Wi-Fi IRQ status 1007 | |+-------- CPU Cycle IRQ status 1008 | +--------- PPU Scanline IRQ status 1009 | ``` 1010 | 1011 | ## Vector redirection (\$416B-\$416F, write-only) 1012 | 1013 | Vector redirection allows you to change the default vectors of the NMI of IRQ. 1014 | No more need of a trampoline, you can just set the address, enable the redirection, and forget about it. 1015 | 1016 | ### Vector redirection control (\$416B, write-only) 1017 | 1018 | ``` 1019 | 7 bit 0 1020 | ---- ---- 1021 | .... ..IN 1022 | || 1023 | |+- NMI vector redirection enable (0: disabled, 1: enabled) 1024 | +-- IRQ vector redirection enable (0: disabled, 1: enabled) 1025 | ``` 1026 | 1027 | ### NMI vector redirection address high bytes (\$416C, write-only) 1028 | 1029 | ``` 1030 | 7 bit 0 1031 | ---- ---- 1032 | HHHH HHHH 1033 | |||| |||| 1034 | ++++-++++- High 8 bits of address 1035 | ``` 1036 | 1037 | ### NMI vector redirection address low bytes (\$416D, write-only) 1038 | 1039 | ``` 1040 | 7 bit 0 1041 | ---- ---- 1042 | LLLL LLLL 1043 | |||| |||| 1044 | ++++-++++- Low 8 bits of address 1045 | ``` 1046 | 1047 | ### IRQ vector redirection address high bytes (\$416E, write-only) 1048 | 1049 | ``` 1050 | 7 bit 0 1051 | ---- ---- 1052 | HHHH HHHH 1053 | |||| |||| 1054 | ++++-++++- High 8 bits of address 1055 | ``` 1056 | 1057 | ### IRQ vector redirection address low bytes (\$416F, write-only) 1058 | 1059 | ``` 1060 | 7 bit 0 1061 | ---- ---- 1062 | LLLL LLLL 1063 | |||| |||| 1064 | ++++-++++- Low 8 bits of address 1065 | ``` 1066 | 1067 | ## Sound / Audio Expansion (\$41A0-\$41AF) 1068 | 1069 | Channels registers work exactly like VRC6 audio expansion minus the frequency scaling register. 1070 | For more informations: https://wiki.nesdev.com/w/index.php/VRC6_audio. 1071 | 1072 | ### Pulse control (\$41A0, \$41A3, write-only) 1073 | 1074 | \$41A0 controls Pulse 1 1075 | \$41A3 controls Pulse 2 1076 | 1077 | ``` 1078 | 7 bit 0 1079 | ---- ---- 1080 | MDDD VVVV 1081 | |||| |||| 1082 | |||| ++++- Volume 1083 | |+++------ Duty Cycle 1084 | +--------- Mode (1: ignore duty) 1085 | ``` 1086 | 1087 | ### Saw Accum Rate (\$41A6, write-only) 1088 | 1089 | ``` 1090 | 7 bit 0 1091 | ---- ---- 1092 | ..AA AAAA 1093 | ++-++++- Accumulator Rate (controls volume) 1094 | ``` 1095 | 1096 | ### Freq Low (\$41A1, \$41A4, \$41A7, write-only) 1097 | 1098 | \$41A1 controls Pulse 1 1099 | \$41A4 controls Pulse 2 1100 | \$41A7 controls Saw 1101 | 1102 | ``` 1103 | 7 bit 0 1104 | ---- ---- 1105 | FFFF FFFF 1106 | |||| |||| 1107 | ++++-++++- Low 8 bits of frequency 1108 | ``` 1109 | 1110 | ### Freq High (\$41A2, \$41A5, \$41A8, write-only) 1111 | 1112 | \$41A2 controls Pulse 1 1113 | \$41A5 controls Pulse 2 1114 | \$41A8 controls Saw 1115 | 1116 | ``` 1117 | 7 bit 0 1118 | ---- ---- 1119 | E... FFFF 1120 | | |||| 1121 | | ++++- High 4 bits of frequency 1122 | +--------- Enable (0: channel disabled) 1123 | ``` 1124 | 1125 | ### Audio output control (\$41A9, write-only) 1126 | 1127 | ``` 1128 | 7 bit 0 1129 | ---- ---- 1130 | .... .ZTF 1131 | ||| 1132 | ||+- Outputs expansion audio to EXP6 pin (0: disable, 1: enable) 1133 | | usually used for front loader 1134 | |+-- Outputs expansion audio to EXP9 pin (0: disable, 1: enable) 1135 | | usually used for top loader 1136 | +--- Outputs expansion audio data to APU register $4011 (read) 1137 | ``` 1138 | 1139 | ### Audio output control (\$41AA, write-only) 1140 | 1141 | ``` 1142 | 7 bit 0 1143 | ---- ---- 1144 | .... VVVV 1145 | |||| 1146 | ++++- Controls expansion audio output master volume 1147 | ``` 1148 | 1149 | ## Wi-Fi (\$4190-\$4194) 1150 | 1151 | ### Configuration (\$4190, read/write) 1152 | 1153 | This register is readable and writable. 1154 | 1155 | ``` 1156 | 7 bit 0 1157 | ---- ---- 1158 | .... ..IE 1159 | || 1160 | |+ ESP enable (0: disable, 1: enable) 1161 | +- IRQ enable (0: disable, 1: enable) 1162 | ``` 1163 | 1164 | ### RX - Reception (\$4191, read/write) 1165 | 1166 | Writing any value to this register acknowledge the last received message and set the bit 7 of the register to 0. 1167 | The bit 7 will be set to 1 again when a new message if available. 1168 | 1169 | Reading this register will return the following byte: 1170 | 1171 | ``` 1172 | 7 bit 0 1173 | ---- ---- 1174 | DR.. .... 1175 | || 1176 | |+------- Data ready, this flag is set to 1 if a message is waiting to be sent on the ESP side 1177 | +-------- Data received (0: FPGA can receive a new message, 1: a new message is ready) 1178 | This flag is set to 1 when the FPGA has received a new message 1179 | If the I flag of the ESP configuration register ($4190) is set, then the NES IRQ will be triggered 1180 | ``` 1181 | 1182 | ### TX - Transimission (\$4192, read/write) 1183 | 1184 | Writing any value to this register sends the message currently stored in FPGA-RAM and sets the bit 7 of the register to 0. 1185 | The bit 7 will be set to 1 again when the message is sent. 1186 | 1187 | Reading this register will return the following byte: 1188 | 1189 | ``` 1190 | 7 bit 0 1191 | ---- ---- 1192 | D... .... 1193 | | 1194 | +-------- Data sent (0: sending data, 1: data sent) 1195 | This flag is set to 1 when the FPGA has sent a message 1196 | ``` 1197 | 1198 | ### RX RAM destination address (\$4193, write-only) 1199 | 1200 | The FPGA uses its internal RAM to store messages received from the ESP. 1201 | Only the last 2K of the total 8K of the FPGA-RAM can be used for this. 1202 | Those 2K are permanently mapped at \$4800-\$4FFF. 1203 | This register allows you to specify a \$100 bytes page from \$4800 to be used for newly received messages. 1204 | 1205 | ``` 1206 | 7 bit 0 1207 | ---- ---- 1208 | .... .AAA 1209 | ||| 1210 | +++ Destination RAM address hi bits 1211 | ``` 1212 | 1213 | ### TX RAM source address (\$4194, write-only) 1214 | 1215 | The FPGA uses its internal RAM to store messages to be sent to the ESP. 1216 | Only the first 2K of the total 8K of the FPGA-RAM can be used for this. 1217 | Those 2K are permanently mapped at \$4800-\$4FFF. 1218 | This register allows you to specify a \$100 bytes page from \$4800 to be used for ready to be sent messages. 1219 | 1220 | ``` 1221 | 7 bit 0 1222 | ---- ---- 1223 | .... .AAA 1224 | ||| 1225 | +++ Source RAM address hi bits 1226 | ``` 1227 | 1228 | ## Recap / Cheat sheet 1229 | 1230 | | Register | Format | Access | Details | 1231 | | ------------- | ---------- | :----: | ----------------------------------------------------------------------- | 1232 | | | | | **CPU / PRG control** | 1233 | | \$4100 | `A....OOO` | R/W | PRG banking modes | 1234 | | \$4101-\$4105 | | | _Not used_ | 1235 | | \$4106 | `CuUUUUUU` | W | PRG bank upper bits and chip selector (modes 0,1) | 1236 | | \$4107 | `CuUUUUUU` | W | PRG bank upper bits and chip selector (mode 1) | 1237 | | \$4108 | `CUUUUUUU` | W | PRG bank upper bits and chip selector (modes 0,1,2,3,4) | 1238 | | \$4109 | `CUUUUUUU` | W | PRG bank upper bits and chip selector (mode 4) | 1239 | | \$410A | `CUUUUUUU` | W | PRG bank upper bits and chip selector (modes 3,4) | 1240 | | \$410B | `CUUUUUUU` | W | PRG bank upper bits and chip selector (mode 4) | 1241 | | \$410C | `CUUUUUUU` | W | PRG bank upper bits and chip selector (modes 1,2,3,4) | 1242 | | \$410D | `CUUUUUUU` | W | PRG bank upper bits and chip selector (mode 4) | 1243 | | \$410E | `CUUUUUUU` | W | PRG bank upper bits and chip selector (modes 2,3,4) | 1244 | | \$410F | `CUUUUUUU` | W | PRG bank upper bits and chip selector (mode 4) | 1245 | | \$4110-\$4114 | | | _Not used_ | 1246 | | \$4115 | `.......B` | W | FPGA-RAM bank bits | 1247 | | \$4116 | `LLLLLLLL` | W | PRG bank lower bits (modes 0,1) | 1248 | | \$4117 | `LLLLLLLL` | W | PRG bank lower bits (mode 1) | 1249 | | \$4118 | `LLLLLLLL` | W | PRG bank lower bits (modes 0,1,2,3,4) | 1250 | | \$4119 | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1251 | | \$411A | `LLLLLLLL` | W | PRG bank lower bits (modes 3,4) | 1252 | | \$411B | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1253 | | \$411C | `LLLLLLLL` | W | PRG bank lower bits (modes 1,2,3,4) | 1254 | | \$411D | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1255 | | \$411E | `LLLLLLLL` | W | PRG bank lower bits (modes 2,3,4) | 1256 | | \$411F | `LLLLLLLL` | W | PRG bank lower bits (mode 4) | 1257 | | | | | **PPU / CHR control** | 1258 | | \$4120 | `CCSW.BBB` | R/W | PPU/CHR control (banking/source/Window Split Mode/Sprite Extended Mode) | 1259 | | \$4121 | `...UUUUU` | W | Background Extended Mode bank upper bits control | 1260 | | \$4122-\$4123 | | | _Not used_ | 1261 | | \$4124 | `TTTTTTTT` | W | Fill-mode tile index | 1262 | | \$4125 | `AAAAAAAA` | W | Fill-mode attribute index | 1263 | | \$4126 | `BBBBBBBB` | W | Nametable A bank (\$2000) | 1264 | | \$4127 | `BBBBBBBB` | W | Nametable B bank (\$2400) | 1265 | | \$4128 | `BBBBBBBB` | W | Nametable C bank (\$2800) | 1266 | | \$4129 | `BBBBBBBB` | W | Nametable D bank (\$2C00) | 1267 | | \$412A | `CCF.DDEE` | R/W | Nametable A control (\$2000) | 1268 | | \$412B | `CCF.DDEE` | R/W | Nametable B control (\$2400) | 1269 | | \$412C | `CCF.DDEE` | R/W | Nametable C control (\$2800) | 1270 | | \$412D | `CCF.DDEE` | R/W | Nametable D control (\$2C00) | 1271 | | \$412E | `BBBBBBBB` | W | Nametable W bank (Window Split) | 1272 | | \$412F | `....DDEE` | R/W | Nametable W control (Window Split) | 1273 | | \$4130 | `UUUUUUUU` | W | CHR bank upper bits (modes 0,1,2,3,4) | 1274 | | \$4131 | `UUUUUUUU` | W | CHR bank upper bits (modes 1,2,3,4) | 1275 | | \$4132 | `UUUUUUUU` | W | CHR bank upper bits (modes 2,3,4) | 1276 | | \$4133 | `UUUUUUUU` | W | CHR bank upper bits (modes 2,3,4) | 1277 | | \$4134 | `UUUUUUUU` | W | CHR bank upper bits (modes 3,4) | 1278 | | \$4135 | `UUUUUUUU` | W | CHR bank upper bits (modes 3,4) | 1279 | | \$4136 | `UUUUUUUU` | W | CHR bank upper bits (modes 3,4) | 1280 | | \$4137 | `UUUUUUUU` | W | CHR bank upper bits (modes 3,4) | 1281 | | \$4138 | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1282 | | \$4139 | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1283 | | \$413A | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1284 | | \$413B | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1285 | | \$413C | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1286 | | \$413D | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1287 | | \$413E | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1288 | | \$413F | `UUUUUUUU` | W | CHR bank upper bits (mode 4) | 1289 | | \$4140 | `LLLLLLLL` | W | CHR bank lower bits (modes 0,1,2,3,4) | 1290 | | \$4141 | `LLLLLLLL` | W | CHR bank lower bits (modes 1,2,3,4) | 1291 | | \$4142 | `LLLLLLLL` | W | CHR bank lower bits (modes 2,3,4) | 1292 | | \$4143 | `LLLLLLLL` | W | CHR bank lower bits (modes 2,3,4) | 1293 | | \$4144 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1294 | | \$4145 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1295 | | \$4146 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1296 | | \$4147 | `LLLLLLLL` | W | CHR bank lower bits (modes 3,4) | 1297 | | \$4148 | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1298 | | \$4149 | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1299 | | \$414A | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1300 | | \$414B | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1301 | | \$414C | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1302 | | \$414D | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1303 | | \$414E | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1304 | | \$414F | `LLLLLLLL` | W | CHR bank lower bits (mode 4) | 1305 | | | | | **SCANLINE DETECTION IRQ** | 1306 | | \$4150 | `VVVVVVVV` | W | Latch value | 1307 | | \$4151 | `HF.....I` | R/W | Enable / Status | 1308 | | \$4152 | `........` | W | Disable | 1309 | | \$4153 | `OOOOOOOO` | W | Offset | 1310 | | \$4154 | `CCCCCCCC` | R | Jitter counter | 1311 | | \$4155-\$4157 | | | _Not used_ | 1312 | | | | | **CPU CYCLE COUNTER IRQ** | 1313 | | \$4158 | `HHHHHHHH` | W | Latch high byte | 1314 | | \$4159 | `LLLLLLLL` | W | Latch low byte | 1315 | | \$415A | `.....ZEA` | W | Control | 1316 | | \$415B | `........` | W | Acknowledge | 1317 | | | | | **FPGA-RAM auto R/W** | 1318 | | \$415C | `...HHHHH` | W | FPGA-RAM address high bytes | 1319 | | \$415D | `LLLLLLLL` | W | FPGA-RAM address low bytes | 1320 | | \$415E | `IIIIIIII` | W | FPGA-RAM increment | 1321 | | \$415F | `DDDDDDDD` | R/W | FPGA-RAM data | 1322 | | | | | **MISCELLANEOUS** | 1323 | | \$4160 | `PPPVVVVV` | R | Mapper version | 1324 | | \$4161 | `PC.....W` | R | IRQ status | 1325 | | \$4162-\$416A | | | _Not used_ | 1326 | | | | | **VECTOR REDIRECTION** | 1327 | | \$416B | `......IN` | W | Vector redirection control | 1328 | | \$416C | `HHHHHHHH` | W | NMI vector redirection address high bytes | 1329 | | \$416D | `LLLLLLLL` | W | NMI vector redirection address low bytes | 1330 | | \$416E | `HHHHHHHH` | W | IRQ vector redirection address high bytes | 1331 | | \$416F | `LLLLLLLL` | W | IRQ vector redirection address low bytes | 1332 | | | | | **Window Split Mode** | 1333 | | \$4170 | `...SSSSS` | W | Window Split X start tile (0-31) | 1334 | | \$4171 | `...EEEEE` | W | Window Split X end tile (0-31) | 1335 | | \$4172 | `SSSSSSSS` | W | Window Split Y start (0-255) | 1336 | | \$4173 | `EEEEEEEE` | W | Window Split Y end (0-255) | 1337 | | \$4174 | `...XXXXX` | W | Window Split coarse X scroll (0-31) | 1338 | | \$4175 | `YYYYYYYY` | W | Window Split fine Y scroll (0-256) | 1339 | | \$4176-\$418F | | | _Not used_ | 1340 | | | | | **WIFI** | 1341 | | \$4190 | `......IE` | R/W | Control | 1342 | | \$4191 | `DR......` | R/W | RX data ready / acknowledge | 1343 | | \$4192 | `D.......` | R/W | TX data sent / send data | 1344 | | \$4193 | `.....AAA` | W | RX RAM destination address | 1345 | | \$4194 | `.....AAA` | W | TX RAM source address | 1346 | | \$4195-\$419F | | | _Not used_ | 1347 | | | | | **AUDIO EXPANSION** | 1348 | | \$41A0 | `MDDDVVVV` | W | Pulse 1 control | 1349 | | \$41A1 | `FFFFFFFF` | W | Pulse 1 low frequency | 1350 | | \$41A2 | `E...FFFF` | W | Pulse 1 high frequency | 1351 | | \$41A3 | `MDDDVVVV` | W | Pulse 2 control | 1352 | | \$41A4 | `FFFFFFFF` | W | Pulse 2 low frequency | 1353 | | \$41A5 | `E...FFFF` | W | Pulse 2 high frequency | 1354 | | \$41A6 | `..AAAAAA` | W | Saw accumulator rate | 1355 | | \$41A7 | `FFFFFFFF` | W | Saw low frequency | 1356 | | \$41A8 | `E...FFFF` | W | Saw high frequency | 1357 | | | | | **AUDIO OUTPUT CONTROL** | 1358 | | \$41A9 | `.....ZTF` | W | Audio output control | 1359 | | \$41AA | `....VVVV` | W | Audio output master volume | 1360 | | \$41AB-\$41FF | | | _Not used_ | 1361 | | | | | **SPRITE EXTENDED MODE** | 1362 | | \$4200-\$423F | `LLLLLLLL` | W | Sprites individual bank lower bits | 1363 | | \$4240 | `.....UUU` | W | Sprites global bank upper bits | 1364 | | | | | **AUTO-GENERATED OAM PROCEDURES** | 1365 | | \$4241 | `.....PPP` | W | OAM slow update 256 bytes page index | 1366 | | \$4242 | `...PPPPP` | W | OAM ext update 64 bytes page | 1367 | | \$4243-\$427F | | | _Not used_ | 1368 | | \$4280 | | X | OAM slow update | 1369 | | \$4282 | | X | OAM ext update | 1370 | | \$4286 | | X | OAM slow clear | 1371 | -------------------------------------------------------------------------------- /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_BSRAM_RW_HI_ADD = $415C 104 | MAP_BSRAM_RW_LO_ADD = $415D 105 | MAP_BSRAM_RW_INC = $415E 106 | MAP_BSRAM_RW_DATA = $415F 107 | 108 | ; Miscellaneaous 109 | MAP_VERSION = $4160 110 | MAP_IRQ_STATUS = $4161 111 | 112 | ; Vector redirection 113 | MAP_VECTOR_CONTROL = $416B 114 | MAP_VECTOR_NMI_ADD_HI = $416C 115 | MAP_VECTOR_NMI_ADD_LO = $416D 116 | MAP_VECTOR_IRQ_ADD_HI = $416E 117 | MAP_VECTOR_IRQ_ADD_LO = $416F 118 | 119 | ; Window Mode 120 | MAP_WINDOW_X_START = $4170 121 | MAP_WINDOW_X_END = $4171 122 | MAP_WINDOW_Y_START = $4172 123 | MAP_WINDOW_Y_END = $4173 124 | MAP_WINDOW_X_SCROLL = $4174 125 | MAP_WINDOW_Y_SCROLL = $4175 126 | 127 | ; ESP / WiFi 128 | MAP_RNBW_CONFIG = $4190 129 | MAP_RNBW_RX = $4191 130 | MAP_RNBW_TX = $4192 131 | MAP_RNBW_RX_ADD = $4193 132 | MAP_RNBW_TX_ADD = $4194 133 | 134 | ; Audio expansion 135 | MAP_SND_P1_CTRL = $41A0 136 | MAP_SND_P1_LOW = $41A1 137 | MAP_SND_P1_HIGH = $41A2 138 | MAP_SND_P2_CTRL = $41A3 139 | MAP_SND_P2_LOW = $41A4 140 | MAP_SND_P2_HIGH = $41A5 141 | MAP_SND_SAW_ACC = $41A6 142 | MAP_SND_SAW_LOW = $41A7 143 | MAP_SND_SAW_HIGH = $41A8 144 | MAP_SND_OUTPUT_CONTROL = $41A9 145 | MAP_SND_MASTER_VOLUME = $41AA 146 | 147 | ; Sprite extended mode 148 | MAP_SPR_EXT_LOWER_BANK = $4200 ; $4200 ... $423F, one register for each sprite 149 | MAP_SPR_EXT_UPPER_BANK = $4240 150 | 151 | ; Auto-generated OAM procedures 152 | MAP_OAM_SLOW_UPDATE = $4280 153 | MAP_OAM_EXT_UPDATE = $4282 154 | MAP_OAM_SLOW_CLEAR = $4286 155 | 156 | ; ################################################################################ 157 | ; MAPPER FLAGS / MASKS 158 | 159 | PRG_ROM_MODE_0 = %00000000 ; 32K 160 | PRG_ROM_MODE_1 = %00000001 ; 16K + 16K 161 | PRG_ROM_MODE_2 = %00000010 ; 16K + 8K + 8K 162 | PRG_ROM_MODE_3 = %00000011 ; 8K + 8K + 8K + 8K 163 | PRG_ROM_MODE_4 = %00000100 ; 4K + 4K + 4K + 4K + 4K + 4K + 4K + 4K 164 | PRG_ROM_MODE_MASK = %00000111 165 | PRG_ROM_MODE_CLEAR = PRG_ROM_MODE_MASK^$ff 166 | 167 | PRG_RAM_MODE_0 = %00000000 ; 8K 168 | PRG_RAM_MODE_1 = %10000000 ; 4K + 4K 169 | PRG_RAM_MODE_MASK = %10000000 170 | PRG_RAM_MODE_CLEAR = PRG_RAM_MODE_MASK^$ff 171 | 172 | CHR_CHIP_ROM = %00000000 ; CHR-ROM 173 | CHR_CHIP_RAM = %01000000 ; CHR-RAM 174 | CHR_CHIP_FPGA_RAM = %10000000 ; FPGA-RAM 175 | CHR_CHIP_MASK = %11000000 176 | CHR_CHIP_CLEAR = CHR_CHIP_MASK^$ff 177 | 178 | SPR_EXT_MODE = %00100000 179 | 180 | CHR_MODE_0 = %00000000 ; 8K mode 181 | CHR_MODE_1 = %00000001 ; 4K mode 182 | CHR_MODE_2 = %00000010 ; 2K mode 183 | CHR_MODE_3 = %00000011 ; 1K mode 184 | CHR_MODE_4 = %00000100 ; 512B mode 185 | CHR_MODE_MASK = %00000111 186 | CHR_MODE_CLEAR = CHR_MODE_MASK^$ff 187 | 188 | NT_CIRAM = %00000000 189 | NT_CHR_RAM = %01000000 190 | NT_FPGA_RAM = %10000000 191 | NT_CHR_ROM = %11000000 192 | 193 | NT_FILL_MODE = %00100000 194 | 195 | NT_EXT_BANK_0 = %00000000 196 | NT_EXT_BANK_1 = %00000100 197 | NT_EXT_BANK_2 = %00001000 198 | NT_EXT_BANK_3 = %00001100 199 | 200 | NT_NO_EXT = %00000000 201 | NT_EXT_AT = %00000001 202 | NT_EXT_BG = %00000010 203 | NT_EXT_BG_AT = %00000011 204 | 205 | NT_BANK_IDX_MASK = %00111111 206 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------