I have ported my old project “pNesX” game console emulator to the nucleo.

Dependencies:   SDFileSystem mbed

Intro

I have ported my old project “pNesX” to the STM32 Nucleo. The pNesX is a NES emulator for the PlayStation that I have created 16 years ago!

Emulation part was almost without change, the sound part was newly added.

Parts

STM32 Nucleo F446RE
QVGA 2.2 TFT SPI (with the SD card slot)
Audio jack(TS or TRS)
USB Connector
Register 100k, 10k, 4.7k, 100
Capacitor 0.01uF, 2.2uF
Breadboard
Wires
Computer Speakers
USB GamePad

Wiring diagram

/media/uploads/beaglescout007/nucleo_ex06_emu.png

TFT J2Nucleo
VCC3V3
GNDGND
CSPB_5(D4)
ResetPA_10(D2) Pull Up(100k)
D/CPA_8(D7)
MOSIPA_7(D11)
SCKPA_5(D13)
LEDLED-100ohm-3V3
MISOPA_6(D12)
TFT J4Nucleo
SD_CSPA_9
SD_MOSIPB_15
SD_MISOPB_14
SD_SCKPB_13
AudioNucleo
TIPPA_4(A2)
USB con.Nucleo
GNDGND
+PA_12
-PA_11
5V5V

https://youtu.be/jL24IjT6LnI

Limitations

  • Since the rest of the RAM is about 50kbyte, maximum capacity of the game ROM is about 50kbyte.
  • The length of the file name up to 32 characters.
  • The number of files in the folder is up to 100.

Used Library

Committer:
beaglescout007
Date:
Sun Apr 03 07:45:29 2016 +0000
Revision:
0:3dac1f1bc9e0
Release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
beaglescout007 0:3dac1f1bc9e0 1 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 2 /* */
beaglescout007 0:3dac1f1bc9e0 3 /* K6502_RW.h : 6502 Reading/Writing Operation for NES */
beaglescout007 0:3dac1f1bc9e0 4 /* This file is included in K6502.cpp */
beaglescout007 0:3dac1f1bc9e0 5 /* */
beaglescout007 0:3dac1f1bc9e0 6 /* 1999/11/03 Racoon New preparation */
beaglescout007 0:3dac1f1bc9e0 7 /* */
beaglescout007 0:3dac1f1bc9e0 8 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 9
beaglescout007 0:3dac1f1bc9e0 10 #ifndef K6502_RW_H_INCLUDED
beaglescout007 0:3dac1f1bc9e0 11 #define K6502_RW_H_INCLUDED
beaglescout007 0:3dac1f1bc9e0 12
beaglescout007 0:3dac1f1bc9e0 13 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 14 /* Include files */
beaglescout007 0:3dac1f1bc9e0 15 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 16
beaglescout007 0:3dac1f1bc9e0 17 #include "pNesX.h"
beaglescout007 0:3dac1f1bc9e0 18 #include "pNesX_System.h"
beaglescout007 0:3dac1f1bc9e0 19
beaglescout007 0:3dac1f1bc9e0 20 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 21 /* */
beaglescout007 0:3dac1f1bc9e0 22 /* K6502_ReadZp() : Reading from the zero page */
beaglescout007 0:3dac1f1bc9e0 23 /* */
beaglescout007 0:3dac1f1bc9e0 24 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 25 static inline BYTE K6502_ReadZp( BYTE byAddr )
beaglescout007 0:3dac1f1bc9e0 26 {
beaglescout007 0:3dac1f1bc9e0 27 /*
beaglescout007 0:3dac1f1bc9e0 28 * Reading from the zero page
beaglescout007 0:3dac1f1bc9e0 29 *
beaglescout007 0:3dac1f1bc9e0 30 * Parameters
beaglescout007 0:3dac1f1bc9e0 31 * BYTE byAddr (Read)
beaglescout007 0:3dac1f1bc9e0 32 * An address inside the zero page
beaglescout007 0:3dac1f1bc9e0 33 *
beaglescout007 0:3dac1f1bc9e0 34 * Return values
beaglescout007 0:3dac1f1bc9e0 35 * Read Data
beaglescout007 0:3dac1f1bc9e0 36 */
beaglescout007 0:3dac1f1bc9e0 37
beaglescout007 0:3dac1f1bc9e0 38 return RAM[ byAddr ];
beaglescout007 0:3dac1f1bc9e0 39 }
beaglescout007 0:3dac1f1bc9e0 40
beaglescout007 0:3dac1f1bc9e0 41 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 42 /* */
beaglescout007 0:3dac1f1bc9e0 43 /* K6502_Read() : Reading operation */
beaglescout007 0:3dac1f1bc9e0 44 /* */
beaglescout007 0:3dac1f1bc9e0 45 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 46 static inline BYTE K6502_Read( WORD wAddr )
beaglescout007 0:3dac1f1bc9e0 47 {
beaglescout007 0:3dac1f1bc9e0 48 /*
beaglescout007 0:3dac1f1bc9e0 49 * Reading operation
beaglescout007 0:3dac1f1bc9e0 50 *
beaglescout007 0:3dac1f1bc9e0 51 * Parameters
beaglescout007 0:3dac1f1bc9e0 52 * WORD wAddr (Read)
beaglescout007 0:3dac1f1bc9e0 53 * Address to read
beaglescout007 0:3dac1f1bc9e0 54 *
beaglescout007 0:3dac1f1bc9e0 55 * Return values
beaglescout007 0:3dac1f1bc9e0 56 * Read data
beaglescout007 0:3dac1f1bc9e0 57 *
beaglescout007 0:3dac1f1bc9e0 58 * Remarks
beaglescout007 0:3dac1f1bc9e0 59 * 0x0000 - 0x1fff RAM ( 0x800 - 0x1fff is mirror of 0x0 - 0x7ff )
beaglescout007 0:3dac1f1bc9e0 60 * 0x2000 - 0x3fff PPU
beaglescout007 0:3dac1f1bc9e0 61 * 0x4000 - 0x5fff Sound
beaglescout007 0:3dac1f1bc9e0 62 * 0x6000 - 0x7fff SRAM ( Battery Backed )
beaglescout007 0:3dac1f1bc9e0 63 * 0x8000 - 0xffff ROM
beaglescout007 0:3dac1f1bc9e0 64 *
beaglescout007 0:3dac1f1bc9e0 65 */
beaglescout007 0:3dac1f1bc9e0 66 BYTE byRet;
beaglescout007 0:3dac1f1bc9e0 67
beaglescout007 0:3dac1f1bc9e0 68 switch ( wAddr & 0xe000 )
beaglescout007 0:3dac1f1bc9e0 69 {
beaglescout007 0:3dac1f1bc9e0 70 case 0x0000: /* RAM */
beaglescout007 0:3dac1f1bc9e0 71 return RAM[ wAddr & 0x7ff ];
beaglescout007 0:3dac1f1bc9e0 72
beaglescout007 0:3dac1f1bc9e0 73 case 0x2000: /* PPU */
beaglescout007 0:3dac1f1bc9e0 74 if ( wAddr <= 0x2006 ) /* PPU Status */
beaglescout007 0:3dac1f1bc9e0 75 {
beaglescout007 0:3dac1f1bc9e0 76 // Set return value
beaglescout007 0:3dac1f1bc9e0 77 byRet = PPU_R2;
beaglescout007 0:3dac1f1bc9e0 78
beaglescout007 0:3dac1f1bc9e0 79 // Reset a V-Blank flag
beaglescout007 0:3dac1f1bc9e0 80 PPU_R2 &= ~R2_IN_VBLANK;
beaglescout007 0:3dac1f1bc9e0 81
beaglescout007 0:3dac1f1bc9e0 82 // Reset address latch
beaglescout007 0:3dac1f1bc9e0 83 PPU_Latch_Flag = 0;
beaglescout007 0:3dac1f1bc9e0 84
beaglescout007 0:3dac1f1bc9e0 85 // Make a Nametable 0 in V-Blank
beaglescout007 0:3dac1f1bc9e0 86 if ( PPU_Scanline >= SCAN_VBLANK_START && !( PPU_R0 & R0_NMI_VB ) )
beaglescout007 0:3dac1f1bc9e0 87 {
beaglescout007 0:3dac1f1bc9e0 88 PPU_R0 &= ~R0_NAME_ADDR;
beaglescout007 0:3dac1f1bc9e0 89 PPU_NameTableBank = NAME_TABLE0;
beaglescout007 0:3dac1f1bc9e0 90 }
beaglescout007 0:3dac1f1bc9e0 91 return byRet;
beaglescout007 0:3dac1f1bc9e0 92 }
beaglescout007 0:3dac1f1bc9e0 93 else
beaglescout007 0:3dac1f1bc9e0 94 if ( wAddr == 0x2007 ) /* PPU Memory */
beaglescout007 0:3dac1f1bc9e0 95 {
beaglescout007 0:3dac1f1bc9e0 96 // Set return value;
beaglescout007 0:3dac1f1bc9e0 97 byRet = PPU_R7;
beaglescout007 0:3dac1f1bc9e0 98
beaglescout007 0:3dac1f1bc9e0 99 // Read PPU Memory
beaglescout007 0:3dac1f1bc9e0 100 PPU_R7 = PPUBANK[ PPU_Addr >> 10 ][ PPU_Addr & 0x3ff ];
beaglescout007 0:3dac1f1bc9e0 101
beaglescout007 0:3dac1f1bc9e0 102 // Increment PPU Address
beaglescout007 0:3dac1f1bc9e0 103 PPU_Addr += PPU_Increment;
beaglescout007 0:3dac1f1bc9e0 104 PPU_Addr &= 0x3fff;
beaglescout007 0:3dac1f1bc9e0 105
beaglescout007 0:3dac1f1bc9e0 106 return byRet;
beaglescout007 0:3dac1f1bc9e0 107 }
beaglescout007 0:3dac1f1bc9e0 108 break;
beaglescout007 0:3dac1f1bc9e0 109
beaglescout007 0:3dac1f1bc9e0 110 case 0x4000: /* Sound */
beaglescout007 0:3dac1f1bc9e0 111 if ( wAddr < 0x4016 )
beaglescout007 0:3dac1f1bc9e0 112 {
beaglescout007 0:3dac1f1bc9e0 113 // Return APU Register
beaglescout007 0:3dac1f1bc9e0 114 //return APU_Reg[ wAddr & 0x1f ];
beaglescout007 0:3dac1f1bc9e0 115 return ApuRead( wAddr & 0x1f );
beaglescout007 0:3dac1f1bc9e0 116 }
beaglescout007 0:3dac1f1bc9e0 117 else
beaglescout007 0:3dac1f1bc9e0 118 if ( wAddr == 0x4016 )
beaglescout007 0:3dac1f1bc9e0 119 {
beaglescout007 0:3dac1f1bc9e0 120 // Set Joypad1 data
beaglescout007 0:3dac1f1bc9e0 121 byRet = (BYTE)( ( PAD1_Latch >> PAD1_Bit ) & 1 ) | 0x40;
beaglescout007 0:3dac1f1bc9e0 122 PAD1_Bit = ( PAD1_Bit == 23 ) ? 0 : ( PAD1_Bit + 1 );
beaglescout007 0:3dac1f1bc9e0 123 return byRet;
beaglescout007 0:3dac1f1bc9e0 124 }
beaglescout007 0:3dac1f1bc9e0 125 else
beaglescout007 0:3dac1f1bc9e0 126 if ( wAddr == 0x4017 )
beaglescout007 0:3dac1f1bc9e0 127 {
beaglescout007 0:3dac1f1bc9e0 128 // Set Joypad2 data
beaglescout007 0:3dac1f1bc9e0 129 byRet = (BYTE)( ( PAD2_Latch >> PAD2_Bit ) & 1 ) | 0x40;
beaglescout007 0:3dac1f1bc9e0 130 PAD2_Bit = ( PAD2_Bit == 23 ) ? 0 : ( PAD2_Bit + 1 );
beaglescout007 0:3dac1f1bc9e0 131 return byRet;
beaglescout007 0:3dac1f1bc9e0 132 }
beaglescout007 0:3dac1f1bc9e0 133 break;
beaglescout007 0:3dac1f1bc9e0 134
beaglescout007 0:3dac1f1bc9e0 135 case 0x6000: /* SRAM */
beaglescout007 0:3dac1f1bc9e0 136 return SRAM[ wAddr & 0x1fff ];
beaglescout007 0:3dac1f1bc9e0 137
beaglescout007 0:3dac1f1bc9e0 138 case 0x8000: /* ROM BANK 0 */
beaglescout007 0:3dac1f1bc9e0 139 return ROMBANK0[ wAddr & 0x1fff ];
beaglescout007 0:3dac1f1bc9e0 140
beaglescout007 0:3dac1f1bc9e0 141 case 0xa000: /* ROM BANK 1 */
beaglescout007 0:3dac1f1bc9e0 142 return ROMBANK1[ wAddr & 0x1fff ];
beaglescout007 0:3dac1f1bc9e0 143
beaglescout007 0:3dac1f1bc9e0 144 case 0xc000: /* ROM BANK 2 */
beaglescout007 0:3dac1f1bc9e0 145 return ROMBANK2[ wAddr & 0x1fff ];
beaglescout007 0:3dac1f1bc9e0 146
beaglescout007 0:3dac1f1bc9e0 147 case 0xe000: /* ROM BANK 3 */
beaglescout007 0:3dac1f1bc9e0 148 return ROMBANK3[ wAddr & 0x1fff ];
beaglescout007 0:3dac1f1bc9e0 149 }
beaglescout007 0:3dac1f1bc9e0 150
beaglescout007 0:3dac1f1bc9e0 151 return 0;
beaglescout007 0:3dac1f1bc9e0 152 }
beaglescout007 0:3dac1f1bc9e0 153
beaglescout007 0:3dac1f1bc9e0 154 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 155 /* */
beaglescout007 0:3dac1f1bc9e0 156 /* K6502_Write() : Writing operation */
beaglescout007 0:3dac1f1bc9e0 157 /* */
beaglescout007 0:3dac1f1bc9e0 158 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 159 static inline void K6502_Write( WORD wAddr, BYTE byData )
beaglescout007 0:3dac1f1bc9e0 160 {
beaglescout007 0:3dac1f1bc9e0 161 /*
beaglescout007 0:3dac1f1bc9e0 162 * Writing operation
beaglescout007 0:3dac1f1bc9e0 163 *
beaglescout007 0:3dac1f1bc9e0 164 * Parameters
beaglescout007 0:3dac1f1bc9e0 165 * WORD wAddr (Read)
beaglescout007 0:3dac1f1bc9e0 166 * Address to write
beaglescout007 0:3dac1f1bc9e0 167 *
beaglescout007 0:3dac1f1bc9e0 168 * BYTE byData (Read)
beaglescout007 0:3dac1f1bc9e0 169 * Data to write
beaglescout007 0:3dac1f1bc9e0 170 *
beaglescout007 0:3dac1f1bc9e0 171 * Remarks
beaglescout007 0:3dac1f1bc9e0 172 * 0x0000 - 0x1fff RAM ( 0x800 - 0x1fff is mirror of 0x0 - 0x7ff )
beaglescout007 0:3dac1f1bc9e0 173 * 0x2000 - 0x3fff PPU
beaglescout007 0:3dac1f1bc9e0 174 * 0x4000 - 0x5fff Sound
beaglescout007 0:3dac1f1bc9e0 175 * 0x6000 - 0x7fff SRAM ( Battery Backed )
beaglescout007 0:3dac1f1bc9e0 176 * 0x8000 - 0xffff ROM
beaglescout007 0:3dac1f1bc9e0 177 *
beaglescout007 0:3dac1f1bc9e0 178 */
beaglescout007 0:3dac1f1bc9e0 179
beaglescout007 0:3dac1f1bc9e0 180 switch ( wAddr & 0xe000 )
beaglescout007 0:3dac1f1bc9e0 181 {
beaglescout007 0:3dac1f1bc9e0 182 case 0x0000: /* RAM */
beaglescout007 0:3dac1f1bc9e0 183 RAM[ wAddr & 0x7ff ] = byData;
beaglescout007 0:3dac1f1bc9e0 184 break;
beaglescout007 0:3dac1f1bc9e0 185
beaglescout007 0:3dac1f1bc9e0 186 case 0x2000: /* PPU */
beaglescout007 0:3dac1f1bc9e0 187 switch ( wAddr & 0x7 )
beaglescout007 0:3dac1f1bc9e0 188 {
beaglescout007 0:3dac1f1bc9e0 189 case 0: /* 0x2000 */
beaglescout007 0:3dac1f1bc9e0 190 PPU_R0 = byData;
beaglescout007 0:3dac1f1bc9e0 191 PPU_Increment = ( PPU_R0 & R0_INC_ADDR ) ? 32 : 1;
beaglescout007 0:3dac1f1bc9e0 192 PPU_NameTableBank = NAME_TABLE0 + ( PPU_R0 & R0_NAME_ADDR );
beaglescout007 0:3dac1f1bc9e0 193 PPU_BG_Base = ( PPU_R0 & R0_BG_ADDR ) ? ChrBuf + 256 * 64 : ChrBuf;
beaglescout007 0:3dac1f1bc9e0 194 PPU_SP_Base = ( PPU_R0 & R0_SP_ADDR ) ? ChrBuf + 256 * 64 : ChrBuf;
beaglescout007 0:3dac1f1bc9e0 195 PPU_SP_Height = ( PPU_R0 & R0_SP_SIZE ) ? 16 : 8;
beaglescout007 0:3dac1f1bc9e0 196 break;
beaglescout007 0:3dac1f1bc9e0 197
beaglescout007 0:3dac1f1bc9e0 198 case 1: /* 0x2001 */
beaglescout007 0:3dac1f1bc9e0 199 PPU_R1 = byData;
beaglescout007 0:3dac1f1bc9e0 200 break;
beaglescout007 0:3dac1f1bc9e0 201
beaglescout007 0:3dac1f1bc9e0 202 case 2: /* 0x2002 */
beaglescout007 0:3dac1f1bc9e0 203 PPU_R2 = byData;
beaglescout007 0:3dac1f1bc9e0 204 break;
beaglescout007 0:3dac1f1bc9e0 205
beaglescout007 0:3dac1f1bc9e0 206 case 3: /* 0x2003 */
beaglescout007 0:3dac1f1bc9e0 207 // Sprite RAM Address
beaglescout007 0:3dac1f1bc9e0 208 PPU_R3 = byData;
beaglescout007 0:3dac1f1bc9e0 209 break;
beaglescout007 0:3dac1f1bc9e0 210
beaglescout007 0:3dac1f1bc9e0 211 case 4: /* 0x2004 */
beaglescout007 0:3dac1f1bc9e0 212 // Write data to Sprite RAM
beaglescout007 0:3dac1f1bc9e0 213 SPRRAM[ PPU_R3++ ] = byData;
beaglescout007 0:3dac1f1bc9e0 214 break;
beaglescout007 0:3dac1f1bc9e0 215
beaglescout007 0:3dac1f1bc9e0 216 case 5: /* 0x2005 */
beaglescout007 0:3dac1f1bc9e0 217 // Set Scroll Register
beaglescout007 0:3dac1f1bc9e0 218 if ( PPU_Latch_Flag )
beaglescout007 0:3dac1f1bc9e0 219 {
beaglescout007 0:3dac1f1bc9e0 220 // V-Scroll Register
beaglescout007 0:3dac1f1bc9e0 221 PPU_Scr_V_Next = ( byData > 239 ) ? 0 : byData;
beaglescout007 0:3dac1f1bc9e0 222 PPU_Scr_V_Byte_Next = PPU_Scr_V_Next >> 3;
beaglescout007 0:3dac1f1bc9e0 223 PPU_Scr_V_Bit_Next = PPU_Scr_V_Next & 7;
beaglescout007 0:3dac1f1bc9e0 224 }
beaglescout007 0:3dac1f1bc9e0 225 else
beaglescout007 0:3dac1f1bc9e0 226 {
beaglescout007 0:3dac1f1bc9e0 227 // H-Scroll Register
beaglescout007 0:3dac1f1bc9e0 228 PPU_Scr_H_Next = byData;
beaglescout007 0:3dac1f1bc9e0 229 PPU_Scr_H_Byte_Next = PPU_Scr_H_Next >> 3;
beaglescout007 0:3dac1f1bc9e0 230 PPU_Scr_H_Bit_Next = PPU_Scr_H_Next & 7;
beaglescout007 0:3dac1f1bc9e0 231 }
beaglescout007 0:3dac1f1bc9e0 232 PPU_Latch_Flag ^= 1;
beaglescout007 0:3dac1f1bc9e0 233 break;
beaglescout007 0:3dac1f1bc9e0 234
beaglescout007 0:3dac1f1bc9e0 235 case 6: /* 0x2006 */
beaglescout007 0:3dac1f1bc9e0 236 // Set PPU Address
beaglescout007 0:3dac1f1bc9e0 237 if ( PPU_Latch_Flag )
beaglescout007 0:3dac1f1bc9e0 238 {
beaglescout007 0:3dac1f1bc9e0 239 // Low
beaglescout007 0:3dac1f1bc9e0 240 PPU_Addr |= byData;
beaglescout007 0:3dac1f1bc9e0 241 }
beaglescout007 0:3dac1f1bc9e0 242 else
beaglescout007 0:3dac1f1bc9e0 243 {
beaglescout007 0:3dac1f1bc9e0 244 // High
beaglescout007 0:3dac1f1bc9e0 245 PPU_Addr = ( byData & 0x3f ) << 8;
beaglescout007 0:3dac1f1bc9e0 246 }
beaglescout007 0:3dac1f1bc9e0 247 PPU_Latch_Flag ^= 1;
beaglescout007 0:3dac1f1bc9e0 248 break;
beaglescout007 0:3dac1f1bc9e0 249
beaglescout007 0:3dac1f1bc9e0 250 case 7: /* 0x2007 */
beaglescout007 0:3dac1f1bc9e0 251 // Write to PPU Memory
beaglescout007 0:3dac1f1bc9e0 252 if ( PPU_Addr < 0x2000 && NesHeader.byVRomSize == 0 )
beaglescout007 0:3dac1f1bc9e0 253 {
beaglescout007 0:3dac1f1bc9e0 254 // Pattern Data
beaglescout007 0:3dac1f1bc9e0 255 ChrBufUpdate |= ( 1 << ( PPU_Addr >> 10 ) );
beaglescout007 0:3dac1f1bc9e0 256 PPURAM[ PPU_Addr ] = byData;
beaglescout007 0:3dac1f1bc9e0 257 }
beaglescout007 0:3dac1f1bc9e0 258 else
beaglescout007 0:3dac1f1bc9e0 259 if ( PPU_Addr < 0x3f00 ) /* 0x2000 - 0x3eff */
beaglescout007 0:3dac1f1bc9e0 260 {
beaglescout007 0:3dac1f1bc9e0 261 // Name Table
beaglescout007 0:3dac1f1bc9e0 262 PPUBANK[ PPU_Addr >> 10 ][ PPU_Addr & 0x3ff ] = byData;
beaglescout007 0:3dac1f1bc9e0 263 }
beaglescout007 0:3dac1f1bc9e0 264 else
beaglescout007 0:3dac1f1bc9e0 265 if ( !( PPU_Addr & 0xf ) ) /* 0x3f00 or 0x3f10 */
beaglescout007 0:3dac1f1bc9e0 266 {
beaglescout007 0:3dac1f1bc9e0 267 // Palette mirror
beaglescout007 0:3dac1f1bc9e0 268 PPURAM[ 0x3f10 ] = PPURAM[ 0x3f14 ] = PPURAM[ 0x3f18 ] = PPURAM[ 0x3f1c ] =
beaglescout007 0:3dac1f1bc9e0 269 PPURAM[ 0x3f00 ] = PPURAM[ 0x3f04 ] = PPURAM[ 0x3f08 ] = PPURAM[ 0x3f0c ] = byData;
beaglescout007 0:3dac1f1bc9e0 270 PalTable[ 0x00 ] = PalTable[ 0x04 ] = PalTable[ 0x08 ] = PalTable[ 0x0c ] =
beaglescout007 0:3dac1f1bc9e0 271 PalTable[ 0x10 ] = PalTable[ 0x14 ] = PalTable[ 0x18 ] = PalTable[ 0x1c ] = NesPalette[ byData ]; // | 0x8000;
beaglescout007 0:3dac1f1bc9e0 272 }
beaglescout007 0:3dac1f1bc9e0 273 else
beaglescout007 0:3dac1f1bc9e0 274 if ( PPU_Addr & 3 )
beaglescout007 0:3dac1f1bc9e0 275 {
beaglescout007 0:3dac1f1bc9e0 276 // Palette
beaglescout007 0:3dac1f1bc9e0 277 PPURAM[ PPU_Addr ] = byData;
beaglescout007 0:3dac1f1bc9e0 278 PalTable[ PPU_Addr & 0x1f ] = NesPalette[ byData ];
beaglescout007 0:3dac1f1bc9e0 279 }
beaglescout007 0:3dac1f1bc9e0 280
beaglescout007 0:3dac1f1bc9e0 281 // Increment PPU Address
beaglescout007 0:3dac1f1bc9e0 282 PPU_Addr += PPU_Increment;
beaglescout007 0:3dac1f1bc9e0 283 PPU_Addr &= 0x3fff;
beaglescout007 0:3dac1f1bc9e0 284 break;
beaglescout007 0:3dac1f1bc9e0 285 }
beaglescout007 0:3dac1f1bc9e0 286 break;
beaglescout007 0:3dac1f1bc9e0 287
beaglescout007 0:3dac1f1bc9e0 288 case 0x4000: /* Sound */
beaglescout007 0:3dac1f1bc9e0 289 switch ( wAddr & 0x1f )
beaglescout007 0:3dac1f1bc9e0 290 {
beaglescout007 0:3dac1f1bc9e0 291 case 0x14: /* 0x4014 */
beaglescout007 0:3dac1f1bc9e0 292 // Sprite DMA
beaglescout007 0:3dac1f1bc9e0 293 switch ( byData >> 5 )
beaglescout007 0:3dac1f1bc9e0 294 {
beaglescout007 0:3dac1f1bc9e0 295 case 0x0: /* RAM */
beaglescout007 0:3dac1f1bc9e0 296 pNesX_MemoryCopy( SPRRAM, &RAM[ ( (WORD)byData << 8 ) & 0x7ff ], SPRRAM_SIZE );
beaglescout007 0:3dac1f1bc9e0 297 break;
beaglescout007 0:3dac1f1bc9e0 298
beaglescout007 0:3dac1f1bc9e0 299 case 0x3: /* SRAM */
beaglescout007 0:3dac1f1bc9e0 300 pNesX_MemoryCopy( SPRRAM, &SRAM[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE );
beaglescout007 0:3dac1f1bc9e0 301 break;
beaglescout007 0:3dac1f1bc9e0 302
beaglescout007 0:3dac1f1bc9e0 303 case 0x4: /* ROM BANK 0 */
beaglescout007 0:3dac1f1bc9e0 304 pNesX_MemoryCopy( SPRRAM, &ROMBANK0[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE );
beaglescout007 0:3dac1f1bc9e0 305 break;
beaglescout007 0:3dac1f1bc9e0 306
beaglescout007 0:3dac1f1bc9e0 307 case 0x5: /* ROM BANK 1 */
beaglescout007 0:3dac1f1bc9e0 308 pNesX_MemoryCopy( SPRRAM, &ROMBANK1[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE );
beaglescout007 0:3dac1f1bc9e0 309 break;
beaglescout007 0:3dac1f1bc9e0 310
beaglescout007 0:3dac1f1bc9e0 311 case 0x6: /* ROM BANK 2 */
beaglescout007 0:3dac1f1bc9e0 312 pNesX_MemoryCopy( SPRRAM, &ROMBANK2[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE );
beaglescout007 0:3dac1f1bc9e0 313 break;
beaglescout007 0:3dac1f1bc9e0 314
beaglescout007 0:3dac1f1bc9e0 315 case 0x7: /* ROM BANK 3 */
beaglescout007 0:3dac1f1bc9e0 316 pNesX_MemoryCopy( SPRRAM, &ROMBANK3[ ( (WORD)byData << 8 ) & 0x1fff ], SPRRAM_SIZE );
beaglescout007 0:3dac1f1bc9e0 317 break;
beaglescout007 0:3dac1f1bc9e0 318 }
beaglescout007 0:3dac1f1bc9e0 319 APU_Reg[ 0x14 ] = byData;
beaglescout007 0:3dac1f1bc9e0 320 break;
beaglescout007 0:3dac1f1bc9e0 321
beaglescout007 0:3dac1f1bc9e0 322 case 0x16: /* 0x4016 */
beaglescout007 0:3dac1f1bc9e0 323 // Reset joypad
beaglescout007 0:3dac1f1bc9e0 324 if ( !( APU_Reg[ 0x16 ] & 1 ) && ( byData & 1 ) )
beaglescout007 0:3dac1f1bc9e0 325 {
beaglescout007 0:3dac1f1bc9e0 326 PAD1_Bit = 0;
beaglescout007 0:3dac1f1bc9e0 327 PAD2_Bit = 0;
beaglescout007 0:3dac1f1bc9e0 328 }
beaglescout007 0:3dac1f1bc9e0 329 APU_Reg[ 0x16 ] = byData;
beaglescout007 0:3dac1f1bc9e0 330 break;
beaglescout007 0:3dac1f1bc9e0 331
beaglescout007 0:3dac1f1bc9e0 332 default:
beaglescout007 0:3dac1f1bc9e0 333 if ( wAddr <= 0x4017 )
beaglescout007 0:3dac1f1bc9e0 334 {
beaglescout007 0:3dac1f1bc9e0 335 // Write to APU Register
beaglescout007 0:3dac1f1bc9e0 336 ApuWrite( wAddr & 0x1f, byData );
beaglescout007 0:3dac1f1bc9e0 337 }
beaglescout007 0:3dac1f1bc9e0 338 break;
beaglescout007 0:3dac1f1bc9e0 339 }
beaglescout007 0:3dac1f1bc9e0 340 break;
beaglescout007 0:3dac1f1bc9e0 341
beaglescout007 0:3dac1f1bc9e0 342 case 0x6000: /* SRAM */
beaglescout007 0:3dac1f1bc9e0 343 SRAM[ wAddr & 0x1fff ] = byData;
beaglescout007 0:3dac1f1bc9e0 344 break;
beaglescout007 0:3dac1f1bc9e0 345
beaglescout007 0:3dac1f1bc9e0 346 case 0x8000: /* ROM BANK 0 */
beaglescout007 0:3dac1f1bc9e0 347 case 0xa000: /* ROM BANK 1 */
beaglescout007 0:3dac1f1bc9e0 348 case 0xc000: /* ROM BANK 2 */
beaglescout007 0:3dac1f1bc9e0 349 case 0xe000: /* ROM BANK 3 */
beaglescout007 0:3dac1f1bc9e0 350 // Write to Mapper
beaglescout007 0:3dac1f1bc9e0 351 MapperWrite( wAddr, byData );
beaglescout007 0:3dac1f1bc9e0 352 break;
beaglescout007 0:3dac1f1bc9e0 353 }
beaglescout007 0:3dac1f1bc9e0 354 }
beaglescout007 0:3dac1f1bc9e0 355
beaglescout007 0:3dac1f1bc9e0 356 // Reading/Writing operation (WORD version)
beaglescout007 0:3dac1f1bc9e0 357 static inline WORD K6502_ReadW( WORD wAddr ){ return K6502_Read( wAddr ) | (WORD)K6502_Read( wAddr + 1 ) << 8; };
beaglescout007 0:3dac1f1bc9e0 358 static inline void K6502_WriteW( WORD wAddr, WORD wData ){ K6502_Write( wAddr, wData & 0xff ); K6502_Write( wAddr + 1, wData >> 8 ); };
beaglescout007 0:3dac1f1bc9e0 359 static inline WORD K6502_ReadZpW( BYTE byAddr ){ return K6502_ReadZp( byAddr ) | ( K6502_ReadZp( byAddr + 1 ) << 8 ); };
beaglescout007 0:3dac1f1bc9e0 360
beaglescout007 0:3dac1f1bc9e0 361 #endif /* !K6502_RW_H_INCLUDED */
beaglescout007 0:3dac1f1bc9e0 362
beaglescout007 0:3dac1f1bc9e0 363