test

Dependencies:   SDFileSystem mbed-dev

Fork of Nucleo_Ex06_EMU by woodstock .

Committer:
charliex
Date:
Sat May 27 02:17:37 2017 +0000
Revision:
4:53ef91c87d74
test

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charliex 4:53ef91c87d74 1 /*===================================================================*/
charliex 4:53ef91c87d74 2 /* */
charliex 4:53ef91c87d74 3 /* pNesX.cpp : NES Emulator for PSX */
charliex 4:53ef91c87d74 4 /* */
charliex 4:53ef91c87d74 5 /* 1999/11/03 Racoon New preparation */
charliex 4:53ef91c87d74 6 /* 2016/ 1/20 Racoon Some optimization. */
charliex 4:53ef91c87d74 7 /* */
charliex 4:53ef91c87d74 8 /*===================================================================*/
charliex 4:53ef91c87d74 9
charliex 4:53ef91c87d74 10 /*-------------------------------------------------------------------
charliex 4:53ef91c87d74 11 * File List :
charliex 4:53ef91c87d74 12 *
charliex 4:53ef91c87d74 13 * [NES Hardware]
charliex 4:53ef91c87d74 14 * pNesX.cpp
charliex 4:53ef91c87d74 15 * pNesX.h
charliex 4:53ef91c87d74 16 * K6502_rw.h
charliex 4:53ef91c87d74 17 * pNesX_Apu.cpp (Added)
charliex 4:53ef91c87d74 18 *
charliex 4:53ef91c87d74 19 * [Mapper function]
charliex 4:53ef91c87d74 20 * pNesX_Mapper.cpp
charliex 4:53ef91c87d74 21 * pNesX_Mapper.h
charliex 4:53ef91c87d74 22 *
charliex 4:53ef91c87d74 23 * [The function which depends on a system]
charliex 4:53ef91c87d74 24 * pNesX_System_ooo.cpp (ooo is a system name. psx, win, Nucleo...)
charliex 4:53ef91c87d74 25 * pNesX_System.h
charliex 4:53ef91c87d74 26 *
charliex 4:53ef91c87d74 27 * [CPU]
charliex 4:53ef91c87d74 28 * K6502.cpp
charliex 4:53ef91c87d74 29 * K6502.h
charliex 4:53ef91c87d74 30 *
charliex 4:53ef91c87d74 31 * [Others]
charliex 4:53ef91c87d74 32 * pNesX_Types.h
charliex 4:53ef91c87d74 33 *
charliex 4:53ef91c87d74 34 --------------------------------------------------------------------*/
charliex 4:53ef91c87d74 35
charliex 4:53ef91c87d74 36 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 37 /* Include files */
charliex 4:53ef91c87d74 38 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 39
charliex 4:53ef91c87d74 40 #include "mbed.h"
charliex 4:53ef91c87d74 41 #include "pNesX.h"
charliex 4:53ef91c87d74 42 #include "pNesX_System.h"
charliex 4:53ef91c87d74 43 #include "pNesX_Mapper.h"
charliex 4:53ef91c87d74 44 #include "K6502.h"
charliex 4:53ef91c87d74 45 /*
charliex 4:53ef91c87d74 46 * Board Resources
charliex 4:53ef91c87d74 47 */
charliex 4:53ef91c87d74 48 extern DigitalOut bLED1;
charliex 4:53ef91c87d74 49 extern DigitalOut bLED2;
charliex 4:53ef91c87d74 50
charliex 4:53ef91c87d74 51 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 52 /* NES resources */
charliex 4:53ef91c87d74 53 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 54
charliex 4:53ef91c87d74 55 /* RAM */
charliex 4:53ef91c87d74 56 BYTE RAM[ RAM_SIZE ];
charliex 4:53ef91c87d74 57
charliex 4:53ef91c87d74 58 /* SRAM */
charliex 4:53ef91c87d74 59 BYTE SRAM[ SRAM_SIZE ];
charliex 4:53ef91c87d74 60
charliex 4:53ef91c87d74 61 /* ROM */
charliex 4:53ef91c87d74 62 BYTE *ROM;
charliex 4:53ef91c87d74 63
charliex 4:53ef91c87d74 64 /* ROM BANK ( 8Kb * 4 ) */
charliex 4:53ef91c87d74 65 BYTE *ROMBANK0;
charliex 4:53ef91c87d74 66 BYTE *ROMBANK1;
charliex 4:53ef91c87d74 67 BYTE *ROMBANK2;
charliex 4:53ef91c87d74 68 BYTE *ROMBANK3;
charliex 4:53ef91c87d74 69
charliex 4:53ef91c87d74 70 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 71 /* PPU resources */
charliex 4:53ef91c87d74 72 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 73
charliex 4:53ef91c87d74 74 /* PPU RAM */
charliex 4:53ef91c87d74 75 BYTE PPURAM[ PPURAM_SIZE ];
charliex 4:53ef91c87d74 76
charliex 4:53ef91c87d74 77 /* VROM */
charliex 4:53ef91c87d74 78 BYTE *VROM;
charliex 4:53ef91c87d74 79
charliex 4:53ef91c87d74 80 /* PPU BANK ( 1Kb * 16 ) */
charliex 4:53ef91c87d74 81 BYTE *PPUBANK[ 16 ];
charliex 4:53ef91c87d74 82
charliex 4:53ef91c87d74 83 /* Sprite RAM */
charliex 4:53ef91c87d74 84 BYTE SPRRAM[ SPRRAM_SIZE ];
charliex 4:53ef91c87d74 85
charliex 4:53ef91c87d74 86 /* PPU Register */
charliex 4:53ef91c87d74 87 BYTE PPU_R0;
charliex 4:53ef91c87d74 88 BYTE PPU_R1;
charliex 4:53ef91c87d74 89 BYTE PPU_R2;
charliex 4:53ef91c87d74 90 BYTE PPU_R3;
charliex 4:53ef91c87d74 91 BYTE PPU_R7;
charliex 4:53ef91c87d74 92
charliex 4:53ef91c87d74 93 /* Flag for PPU Address and Scroll Latch */
charliex 4:53ef91c87d74 94 BYTE PPU_Latch_Flag;
charliex 4:53ef91c87d74 95
charliex 4:53ef91c87d74 96 /* Vertical scroll value */
charliex 4:53ef91c87d74 97 BYTE PPU_Scr_V;
charliex 4:53ef91c87d74 98 BYTE PPU_Scr_V_Next;
charliex 4:53ef91c87d74 99 BYTE PPU_Scr_V_Byte;
charliex 4:53ef91c87d74 100 BYTE PPU_Scr_V_Byte_Next;
charliex 4:53ef91c87d74 101 BYTE PPU_Scr_V_Bit;
charliex 4:53ef91c87d74 102 BYTE PPU_Scr_V_Bit_Next;
charliex 4:53ef91c87d74 103
charliex 4:53ef91c87d74 104 /* Horizontal scroll value */
charliex 4:53ef91c87d74 105 BYTE PPU_Scr_H;
charliex 4:53ef91c87d74 106 BYTE PPU_Scr_H_Next;
charliex 4:53ef91c87d74 107 BYTE PPU_Scr_H_Byte;
charliex 4:53ef91c87d74 108 BYTE PPU_Scr_H_Byte_Next;
charliex 4:53ef91c87d74 109 BYTE PPU_Scr_H_Bit;
charliex 4:53ef91c87d74 110 BYTE PPU_Scr_H_Bit_Next;
charliex 4:53ef91c87d74 111
charliex 4:53ef91c87d74 112 /* PPU Address */
charliex 4:53ef91c87d74 113 WORD PPU_Addr;
charliex 4:53ef91c87d74 114
charliex 4:53ef91c87d74 115 /* The increase value of the PPU Address */
charliex 4:53ef91c87d74 116 WORD PPU_Increment;
charliex 4:53ef91c87d74 117
charliex 4:53ef91c87d74 118 /* Current Scanline */
charliex 4:53ef91c87d74 119 WORD PPU_Scanline;
charliex 4:53ef91c87d74 120
charliex 4:53ef91c87d74 121 /* Scanline Table */
charliex 4:53ef91c87d74 122 //BYTE PPU_ScanTable[ 263 ];
charliex 4:53ef91c87d74 123
charliex 4:53ef91c87d74 124 /* Name Table Bank */
charliex 4:53ef91c87d74 125 BYTE PPU_NameTableBank;
charliex 4:53ef91c87d74 126
charliex 4:53ef91c87d74 127 /* BG Base Address */
charliex 4:53ef91c87d74 128 BYTE *PPU_BG_Base;
charliex 4:53ef91c87d74 129
charliex 4:53ef91c87d74 130 /* Sprite Base Address */
charliex 4:53ef91c87d74 131 BYTE *PPU_SP_Base;
charliex 4:53ef91c87d74 132
charliex 4:53ef91c87d74 133 /* Sprite Height */
charliex 4:53ef91c87d74 134 WORD PPU_SP_Height;
charliex 4:53ef91c87d74 135
charliex 4:53ef91c87d74 136 /* Sprite #0 Scanline Hit Position */
charliex 4:53ef91c87d74 137 int SpriteHitPos;
charliex 4:53ef91c87d74 138
charliex 4:53ef91c87d74 139 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 140 /* Display and Others resouces */
charliex 4:53ef91c87d74 141 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 142
charliex 4:53ef91c87d74 143 /* Frame Skip */
charliex 4:53ef91c87d74 144 WORD FrameSkip;
charliex 4:53ef91c87d74 145 WORD FrameCnt;
charliex 4:53ef91c87d74 146 bool FrameDraw;
charliex 4:53ef91c87d74 147
charliex 4:53ef91c87d74 148 /* Display Line Buffer */
charliex 4:53ef91c87d74 149 WORD LineData[2][ NES_DISP_WIDTH ];
charliex 4:53ef91c87d74 150 WORD *pDrawData;
charliex 4:53ef91c87d74 151 int LineDataIdx;
charliex 4:53ef91c87d74 152
charliex 4:53ef91c87d74 153 /* Character Buffer */
charliex 4:53ef91c87d74 154 BYTE ChrBuf[ 256 * 2 * 8 * 8 ];
charliex 4:53ef91c87d74 155
charliex 4:53ef91c87d74 156 /* Update flag for ChrBuf */
charliex 4:53ef91c87d74 157 BYTE ChrBufUpdate;
charliex 4:53ef91c87d74 158
charliex 4:53ef91c87d74 159 /* Palette Table */
charliex 4:53ef91c87d74 160 WORD PalTable[ 32 ];
charliex 4:53ef91c87d74 161
charliex 4:53ef91c87d74 162 /* Table for Mirroring */
charliex 4:53ef91c87d74 163 const BYTE PPU_MirrorTable[][ 4 ] =
charliex 4:53ef91c87d74 164 {
charliex 4:53ef91c87d74 165 { NAME_TABLE0, NAME_TABLE0, NAME_TABLE1, NAME_TABLE1 },
charliex 4:53ef91c87d74 166 { NAME_TABLE0, NAME_TABLE1, NAME_TABLE0, NAME_TABLE1 },
charliex 4:53ef91c87d74 167 { NAME_TABLE1, NAME_TABLE1, NAME_TABLE1, NAME_TABLE1 },
charliex 4:53ef91c87d74 168 { NAME_TABLE0, NAME_TABLE0, NAME_TABLE0, NAME_TABLE0 }
charliex 4:53ef91c87d74 169 };
charliex 4:53ef91c87d74 170
charliex 4:53ef91c87d74 171 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 172 /* APU and Pad resources */
charliex 4:53ef91c87d74 173 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 174
charliex 4:53ef91c87d74 175 /* APU Register */
charliex 4:53ef91c87d74 176 BYTE APU_Reg[ 0x18 ];
charliex 4:53ef91c87d74 177
charliex 4:53ef91c87d74 178 /* Pad data */
charliex 4:53ef91c87d74 179 DWORD PAD1_Latch;
charliex 4:53ef91c87d74 180 DWORD PAD2_Latch;
charliex 4:53ef91c87d74 181 DWORD PAD_System;
charliex 4:53ef91c87d74 182 DWORD PAD1_Bit;
charliex 4:53ef91c87d74 183 DWORD PAD2_Bit;
charliex 4:53ef91c87d74 184
charliex 4:53ef91c87d74 185 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 186 /* Mapper Function */
charliex 4:53ef91c87d74 187 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 188
charliex 4:53ef91c87d74 189 /* Initialize Mapper */
charliex 4:53ef91c87d74 190 void (*MapperInit)();
charliex 4:53ef91c87d74 191 /* Write to Mapper */
charliex 4:53ef91c87d74 192 void (*MapperWrite)( WORD wAddr, BYTE byData );
charliex 4:53ef91c87d74 193 /* Callback at VSync */
charliex 4:53ef91c87d74 194 void (*MapperVSync)();
charliex 4:53ef91c87d74 195 /* Callback at HSync */
charliex 4:53ef91c87d74 196 void (*MapperHSync)();
charliex 4:53ef91c87d74 197
charliex 4:53ef91c87d74 198 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 199 /* ROM information */
charliex 4:53ef91c87d74 200 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 201
charliex 4:53ef91c87d74 202 /* .nes File Header */
charliex 4:53ef91c87d74 203 struct NesHeader_tag NesHeader;
charliex 4:53ef91c87d74 204
charliex 4:53ef91c87d74 205 /* Mapper Number */
charliex 4:53ef91c87d74 206 BYTE MapperNo;
charliex 4:53ef91c87d74 207
charliex 4:53ef91c87d74 208 /* Mirroring 0:Horizontal 1:Vertical */
charliex 4:53ef91c87d74 209 BYTE ROM_Mirroring;
charliex 4:53ef91c87d74 210 /* It has SRAM */
charliex 4:53ef91c87d74 211 BYTE ROM_SRAM;
charliex 4:53ef91c87d74 212 /* It has Trainer */
charliex 4:53ef91c87d74 213 BYTE ROM_Trainer;
charliex 4:53ef91c87d74 214 /* Four screen VRAM */
charliex 4:53ef91c87d74 215 BYTE ROM_FourScr;
charliex 4:53ef91c87d74 216
charliex 4:53ef91c87d74 217 /*===================================================================*/
charliex 4:53ef91c87d74 218 /* */
charliex 4:53ef91c87d74 219 /* pNesX_Init() : Initialize pNesX */
charliex 4:53ef91c87d74 220 /* */
charliex 4:53ef91c87d74 221 /*===================================================================*/
charliex 4:53ef91c87d74 222 void pNesX_Init()
charliex 4:53ef91c87d74 223 {
charliex 4:53ef91c87d74 224 /*
charliex 4:53ef91c87d74 225 * Initialize pNesX
charliex 4:53ef91c87d74 226 *
charliex 4:53ef91c87d74 227 * Remarks
charliex 4:53ef91c87d74 228 * Initialize K6502 and Scanline Table.
charliex 4:53ef91c87d74 229 */
charliex 4:53ef91c87d74 230
charliex 4:53ef91c87d74 231 // Initialize 6502
charliex 4:53ef91c87d74 232 K6502_Init();
charliex 4:53ef91c87d74 233 }
charliex 4:53ef91c87d74 234
charliex 4:53ef91c87d74 235 /*===================================================================*/
charliex 4:53ef91c87d74 236 /* */
charliex 4:53ef91c87d74 237 /* pNesX_Fin() : Completion treatment */
charliex 4:53ef91c87d74 238 /* */
charliex 4:53ef91c87d74 239 /*===================================================================*/
charliex 4:53ef91c87d74 240 void pNesX_Fin()
charliex 4:53ef91c87d74 241 {
charliex 4:53ef91c87d74 242 /*
charliex 4:53ef91c87d74 243 * Completion treatment
charliex 4:53ef91c87d74 244 *
charliex 4:53ef91c87d74 245 * Remarks
charliex 4:53ef91c87d74 246 * Release resources
charliex 4:53ef91c87d74 247 */
charliex 4:53ef91c87d74 248
charliex 4:53ef91c87d74 249 // Release a memory for ROM
charliex 4:53ef91c87d74 250 pNesX_ReleaseRom();
charliex 4:53ef91c87d74 251 }
charliex 4:53ef91c87d74 252
charliex 4:53ef91c87d74 253 /*===================================================================*/
charliex 4:53ef91c87d74 254 /* */
charliex 4:53ef91c87d74 255 /* pNesX_Load() : Load a cassette */
charliex 4:53ef91c87d74 256 /* */
charliex 4:53ef91c87d74 257 /*===================================================================*/
charliex 4:53ef91c87d74 258 int pNesX_Load( const char *pszFileName )
charliex 4:53ef91c87d74 259 {
charliex 4:53ef91c87d74 260 /*
charliex 4:53ef91c87d74 261 * Load a cassette
charliex 4:53ef91c87d74 262 *
charliex 4:53ef91c87d74 263 * Parameters
charliex 4:53ef91c87d74 264 * const char *pszFileName (Read)
charliex 4:53ef91c87d74 265 * File name of ROM image
charliex 4:53ef91c87d74 266 *
charliex 4:53ef91c87d74 267 * Return values
charliex 4:53ef91c87d74 268 * 0 : It was finished normally.
charliex 4:53ef91c87d74 269 * -1 : An error occurred.
charliex 4:53ef91c87d74 270 *
charliex 4:53ef91c87d74 271 * Remarks
charliex 4:53ef91c87d74 272 * Read a ROM image in the memory.
charliex 4:53ef91c87d74 273 * Reset pNesX.
charliex 4:53ef91c87d74 274 */
charliex 4:53ef91c87d74 275
charliex 4:53ef91c87d74 276 // Release a memory for ROM
charliex 4:53ef91c87d74 277 pNesX_ReleaseRom();
charliex 4:53ef91c87d74 278
charliex 4:53ef91c87d74 279 // Read a ROM image in the memory
charliex 4:53ef91c87d74 280 if ( pNesX_ReadRom( pszFileName ) < 0 )
charliex 4:53ef91c87d74 281 return -1;
charliex 4:53ef91c87d74 282
charliex 4:53ef91c87d74 283 // Reset pNesX
charliex 4:53ef91c87d74 284 if ( pNesX_Reset() < 0 )
charliex 4:53ef91c87d74 285 return -1;
charliex 4:53ef91c87d74 286
charliex 4:53ef91c87d74 287 // Successful
charliex 4:53ef91c87d74 288 return 0;
charliex 4:53ef91c87d74 289 }
charliex 4:53ef91c87d74 290
charliex 4:53ef91c87d74 291 /*===================================================================*/
charliex 4:53ef91c87d74 292 /* */
charliex 4:53ef91c87d74 293 /* pNesX_Reset() : Reset pNesX */
charliex 4:53ef91c87d74 294 /* */
charliex 4:53ef91c87d74 295 /*===================================================================*/
charliex 4:53ef91c87d74 296 int pNesX_Reset()
charliex 4:53ef91c87d74 297 {
charliex 4:53ef91c87d74 298 /*
charliex 4:53ef91c87d74 299 * Reset pNesX
charliex 4:53ef91c87d74 300 *
charliex 4:53ef91c87d74 301 * Return values
charliex 4:53ef91c87d74 302 * 0 : Normally
charliex 4:53ef91c87d74 303 * -1 : Non support mapper
charliex 4:53ef91c87d74 304 *
charliex 4:53ef91c87d74 305 * Remarks
charliex 4:53ef91c87d74 306 * Initialize Resources, PPU and Mapper.
charliex 4:53ef91c87d74 307 * Reset CPU.
charliex 4:53ef91c87d74 308 */
charliex 4:53ef91c87d74 309
charliex 4:53ef91c87d74 310 int nIdx;
charliex 4:53ef91c87d74 311
charliex 4:53ef91c87d74 312 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 313 /* Get information on the cassette */
charliex 4:53ef91c87d74 314 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 315
charliex 4:53ef91c87d74 316 // Get Mapper Number
charliex 4:53ef91c87d74 317 MapperNo = NesHeader.byInfo1 >> 4;
charliex 4:53ef91c87d74 318
charliex 4:53ef91c87d74 319 // Check bit counts of Mapper No.
charliex 4:53ef91c87d74 320 for ( nIdx = 4; nIdx < 8 && NesHeader.byReserve[ nIdx ] == 0; ++nIdx )
charliex 4:53ef91c87d74 321 ;
charliex 4:53ef91c87d74 322
charliex 4:53ef91c87d74 323 if ( nIdx == 8 )
charliex 4:53ef91c87d74 324 {
charliex 4:53ef91c87d74 325 // Mapper Number is 8bits
charliex 4:53ef91c87d74 326 MapperNo |= ( NesHeader.byInfo2 & 0xf0 );
charliex 4:53ef91c87d74 327 }
charliex 4:53ef91c87d74 328
charliex 4:53ef91c87d74 329 // Get information on the ROM
charliex 4:53ef91c87d74 330 ROM_Mirroring = NesHeader.byInfo1 & 1;
charliex 4:53ef91c87d74 331 ROM_SRAM = NesHeader.byInfo1 & 2;
charliex 4:53ef91c87d74 332 ROM_Trainer = NesHeader.byInfo1 & 4;
charliex 4:53ef91c87d74 333 ROM_FourScr = NesHeader.byInfo1 & 8;
charliex 4:53ef91c87d74 334
charliex 4:53ef91c87d74 335 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 336 /* Initialize resources */
charliex 4:53ef91c87d74 337 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 338
charliex 4:53ef91c87d74 339 // Clear RAM
charliex 4:53ef91c87d74 340 pNesX_MemorySet( RAM, 0, sizeof RAM );
charliex 4:53ef91c87d74 341
charliex 4:53ef91c87d74 342 // Reset frame skip and frame count
charliex 4:53ef91c87d74 343 FrameSkip = 2; // 0:full 1:half 2:2/3 3:1/3
charliex 4:53ef91c87d74 344 FrameCnt = 0;
charliex 4:53ef91c87d74 345
charliex 4:53ef91c87d74 346
charliex 4:53ef91c87d74 347 // Reset update flag of ChrBuf
charliex 4:53ef91c87d74 348 ChrBufUpdate = 0xff;
charliex 4:53ef91c87d74 349
charliex 4:53ef91c87d74 350 // Reset palette table
charliex 4:53ef91c87d74 351 pNesX_MemorySet( PalTable, 0, sizeof PalTable );
charliex 4:53ef91c87d74 352
charliex 4:53ef91c87d74 353 // Reset APU register
charliex 4:53ef91c87d74 354 pNesX_MemorySet( APU_Reg, 0, sizeof APU_Reg );
charliex 4:53ef91c87d74 355
charliex 4:53ef91c87d74 356 // Reset joypad
charliex 4:53ef91c87d74 357 PAD1_Latch = PAD2_Latch = PAD_System = 0;
charliex 4:53ef91c87d74 358 PAD1_Bit = PAD2_Bit = 0;
charliex 4:53ef91c87d74 359
charliex 4:53ef91c87d74 360 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 361 /* Initialize PPU */
charliex 4:53ef91c87d74 362 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 363
charliex 4:53ef91c87d74 364 pNesX_SetupPPU();
charliex 4:53ef91c87d74 365
charliex 4:53ef91c87d74 366 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 367 /* Initialize Mapper */
charliex 4:53ef91c87d74 368 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 369
charliex 4:53ef91c87d74 370 // Get Mapper Table Index
charliex 4:53ef91c87d74 371 for ( nIdx = 0; MapperTable[ nIdx ].nMapperNo != -1; ++nIdx )
charliex 4:53ef91c87d74 372 {
charliex 4:53ef91c87d74 373 if ( MapperTable[ nIdx ].nMapperNo == MapperNo )
charliex 4:53ef91c87d74 374 break;
charliex 4:53ef91c87d74 375 }
charliex 4:53ef91c87d74 376
charliex 4:53ef91c87d74 377 if ( MapperTable[ nIdx ].nMapperNo == -1 )
charliex 4:53ef91c87d74 378 {
charliex 4:53ef91c87d74 379 // Non support mapper
charliex 4:53ef91c87d74 380 return -1;
charliex 4:53ef91c87d74 381 }
charliex 4:53ef91c87d74 382
charliex 4:53ef91c87d74 383 // Set up a mapper initialization function
charliex 4:53ef91c87d74 384 MapperTable[ nIdx ].pMapperInit();
charliex 4:53ef91c87d74 385
charliex 4:53ef91c87d74 386 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 387 /* Reset CPU */
charliex 4:53ef91c87d74 388 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 389
charliex 4:53ef91c87d74 390 K6502_Reset();
charliex 4:53ef91c87d74 391
charliex 4:53ef91c87d74 392 // Successful
charliex 4:53ef91c87d74 393 return 0;
charliex 4:53ef91c87d74 394 }
charliex 4:53ef91c87d74 395
charliex 4:53ef91c87d74 396 /*===================================================================*/
charliex 4:53ef91c87d74 397 /* */
charliex 4:53ef91c87d74 398 /* pNesX_SetupPPU() : Initialize PPU */
charliex 4:53ef91c87d74 399 /* */
charliex 4:53ef91c87d74 400 /*===================================================================*/
charliex 4:53ef91c87d74 401 void pNesX_SetupPPU()
charliex 4:53ef91c87d74 402 {
charliex 4:53ef91c87d74 403 /*
charliex 4:53ef91c87d74 404 * Initialize PPU
charliex 4:53ef91c87d74 405 *
charliex 4:53ef91c87d74 406 */
charliex 4:53ef91c87d74 407 int nPage;
charliex 4:53ef91c87d74 408
charliex 4:53ef91c87d74 409 // Clear PPU and Sprite Memory
charliex 4:53ef91c87d74 410 pNesX_MemorySet( PPURAM, 0, sizeof PPURAM );
charliex 4:53ef91c87d74 411 pNesX_MemorySet( SPRRAM, 0, sizeof SPRRAM );
charliex 4:53ef91c87d74 412
charliex 4:53ef91c87d74 413 // Reset PPU Register
charliex 4:53ef91c87d74 414 PPU_R0 = PPU_R1 = PPU_R2 = PPU_R3 = PPU_R7 = 0;
charliex 4:53ef91c87d74 415
charliex 4:53ef91c87d74 416 // Reset latch flag
charliex 4:53ef91c87d74 417 PPU_Latch_Flag = 0;
charliex 4:53ef91c87d74 418
charliex 4:53ef91c87d74 419 // Reset Scroll values
charliex 4:53ef91c87d74 420 PPU_Scr_V = PPU_Scr_V_Next = PPU_Scr_V_Byte = PPU_Scr_V_Byte_Next = PPU_Scr_V_Bit = PPU_Scr_V_Bit_Next = 0;
charliex 4:53ef91c87d74 421 PPU_Scr_H = PPU_Scr_H_Next = PPU_Scr_H_Byte = PPU_Scr_H_Byte_Next = PPU_Scr_H_Bit = PPU_Scr_H_Bit_Next = 0;
charliex 4:53ef91c87d74 422
charliex 4:53ef91c87d74 423 // Reset PPU address
charliex 4:53ef91c87d74 424 PPU_Addr = 0;
charliex 4:53ef91c87d74 425
charliex 4:53ef91c87d74 426 // Reset scanline
charliex 4:53ef91c87d74 427 PPU_Scanline = 0;
charliex 4:53ef91c87d74 428
charliex 4:53ef91c87d74 429 // Reset hit position of sprite #0
charliex 4:53ef91c87d74 430 SpriteHitPos = 0;
charliex 4:53ef91c87d74 431
charliex 4:53ef91c87d74 432 // Reset information on PPU_R0
charliex 4:53ef91c87d74 433 PPU_Increment = 1;
charliex 4:53ef91c87d74 434 PPU_NameTableBank = NAME_TABLE0;
charliex 4:53ef91c87d74 435 PPU_BG_Base = ChrBuf;
charliex 4:53ef91c87d74 436 PPU_SP_Base = ChrBuf + 256 * 64;
charliex 4:53ef91c87d74 437 PPU_SP_Height = 8;
charliex 4:53ef91c87d74 438
charliex 4:53ef91c87d74 439 // Reset PPU banks
charliex 4:53ef91c87d74 440 for ( nPage = 0; nPage < 16; ++nPage )
charliex 4:53ef91c87d74 441 PPUBANK[ nPage ] = &PPURAM[ nPage * 0x400 ];
charliex 4:53ef91c87d74 442
charliex 4:53ef91c87d74 443 /* Mirroring of Name Table */
charliex 4:53ef91c87d74 444 pNesX_Mirroring( ROM_Mirroring );
charliex 4:53ef91c87d74 445 }
charliex 4:53ef91c87d74 446
charliex 4:53ef91c87d74 447 /*===================================================================*/
charliex 4:53ef91c87d74 448 /* */
charliex 4:53ef91c87d74 449 /* pNesX_Mirroring() : Set up a Mirroring of Name Table */
charliex 4:53ef91c87d74 450 /* */
charliex 4:53ef91c87d74 451 /*===================================================================*/
charliex 4:53ef91c87d74 452 void pNesX_Mirroring( int nType )
charliex 4:53ef91c87d74 453 {
charliex 4:53ef91c87d74 454 /*
charliex 4:53ef91c87d74 455 * Set up a Mirroring of Name Table
charliex 4:53ef91c87d74 456 *
charliex 4:53ef91c87d74 457 * Parameters
charliex 4:53ef91c87d74 458 * int nType (Read)
charliex 4:53ef91c87d74 459 * Mirroring Type
charliex 4:53ef91c87d74 460 * 0 : Horizontal
charliex 4:53ef91c87d74 461 * 1 : Vertical
charliex 4:53ef91c87d74 462 * 2 : One Screen 0x2000
charliex 4:53ef91c87d74 463 * 3 : One Screen 0x2400
charliex 4:53ef91c87d74 464 */
charliex 4:53ef91c87d74 465
charliex 4:53ef91c87d74 466 PPUBANK[ NAME_TABLE0 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 0 ] * 0x400 ];
charliex 4:53ef91c87d74 467 PPUBANK[ NAME_TABLE1 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 1 ] * 0x400 ];
charliex 4:53ef91c87d74 468 PPUBANK[ NAME_TABLE2 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 2 ] * 0x400 ];
charliex 4:53ef91c87d74 469 PPUBANK[ NAME_TABLE3 ] = &PPURAM[ PPU_MirrorTable[ nType ][ 3 ] * 0x400 ];
charliex 4:53ef91c87d74 470 }
charliex 4:53ef91c87d74 471 extern DigitalOut back;
charliex 4:53ef91c87d74 472
charliex 4:53ef91c87d74 473 int backlight(float);
charliex 4:53ef91c87d74 474 /*===================================================================*/
charliex 4:53ef91c87d74 475 /* */
charliex 4:53ef91c87d74 476 /* pNesX_Main() : The main loop of pNesX */
charliex 4:53ef91c87d74 477 /* */
charliex 4:53ef91c87d74 478 /*===================================================================*/
charliex 4:53ef91c87d74 479 void pNesX_Main()
charliex 4:53ef91c87d74 480 {
charliex 4:53ef91c87d74 481
charliex 4:53ef91c87d74 482 /*
charliex 4:53ef91c87d74 483 * The main loop of pNesX
charliex 4:53ef91c87d74 484 *
charliex 4:53ef91c87d74 485 */
charliex 4:53ef91c87d74 486
charliex 4:53ef91c87d74 487 // Initialize pNesX
charliex 4:53ef91c87d74 488 pNesX_Init();
charliex 4:53ef91c87d74 489
charliex 4:53ef91c87d74 490 backlight(.8 );
charliex 4:53ef91c87d74 491
charliex 4:53ef91c87d74 492 // Main loop
charliex 4:53ef91c87d74 493 while ( 1 )
charliex 4:53ef91c87d74 494 {
charliex 4:53ef91c87d74 495
charliex 4:53ef91c87d74 496 back = !back;
charliex 4:53ef91c87d74 497
charliex 4:53ef91c87d74 498 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 499 /* To the menu screen */
charliex 4:53ef91c87d74 500 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 501 if ( pNesX_Menu() == -1 )
charliex 4:53ef91c87d74 502 {
charliex 4:53ef91c87d74 503 break; // Quit
charliex 4:53ef91c87d74 504 }
charliex 4:53ef91c87d74 505
charliex 4:53ef91c87d74 506 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 507 /* Start a NES emulation */
charliex 4:53ef91c87d74 508 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 509 pNesX_Cycle();
charliex 4:53ef91c87d74 510
charliex 4:53ef91c87d74 511
charliex 4:53ef91c87d74 512 }
charliex 4:53ef91c87d74 513
charliex 4:53ef91c87d74 514 // Completion treatment
charliex 4:53ef91c87d74 515 pNesX_Fin();
charliex 4:53ef91c87d74 516 }
charliex 4:53ef91c87d74 517
charliex 4:53ef91c87d74 518 /*===================================================================*/
charliex 4:53ef91c87d74 519 /* */
charliex 4:53ef91c87d74 520 /* pNesX_Cycle() : The loop of emulation */
charliex 4:53ef91c87d74 521 /* */
charliex 4:53ef91c87d74 522 /*===================================================================*/
charliex 4:53ef91c87d74 523 void pNesX_Cycle()
charliex 4:53ef91c87d74 524 {
charliex 4:53ef91c87d74 525 /*
charliex 4:53ef91c87d74 526 * The loop of emulation
charliex 4:53ef91c87d74 527 *
charliex 4:53ef91c87d74 528 */
charliex 4:53ef91c87d74 529
charliex 4:53ef91c87d74 530 // Emulation loop
charliex 4:53ef91c87d74 531 for (;;)
charliex 4:53ef91c87d74 532 {
charliex 4:53ef91c87d74 533 bLED2 = !bLED1;
charliex 4:53ef91c87d74 534
charliex 4:53ef91c87d74 535 // Execute instructions
charliex 4:53ef91c87d74 536 K6502_Step( 40 );
charliex 4:53ef91c87d74 537
charliex 4:53ef91c87d74 538 // Set a flag if a scanning line is a hit in the sprite #0
charliex 4:53ef91c87d74 539 if ( ( SPRRAM[ SPR_Y ] + SpriteHitPos ) == PPU_Scanline &&
charliex 4:53ef91c87d74 540 PPU_Scanline >= SCAN_ON_SCREEN_START && PPU_Scanline < SCAN_BOTTOM_OFF_SCREEN_START )
charliex 4:53ef91c87d74 541 //PPU_ScanTable[ PPU_Scanline ] == SCAN_ON_SCREEN )
charliex 4:53ef91c87d74 542 {
charliex 4:53ef91c87d74 543 // Set a sprite hit flag
charliex 4:53ef91c87d74 544 PPU_R2 |= R2_HIT_SP;
charliex 4:53ef91c87d74 545
charliex 4:53ef91c87d74 546 // NMI is required if there is necessity
charliex 4:53ef91c87d74 547 if ( ( PPU_R0 & R0_NMI_SP ) && ( PPU_R1 & R1_SHOW_SP ) )
charliex 4:53ef91c87d74 548 NMI_REQ;
charliex 4:53ef91c87d74 549 }
charliex 4:53ef91c87d74 550
charliex 4:53ef91c87d74 551 // Execute instructions
charliex 4:53ef91c87d74 552 K6502_Step( 75 );
charliex 4:53ef91c87d74 553
charliex 4:53ef91c87d74 554 // A mapper function in H-Sync
charliex 4:53ef91c87d74 555 MapperHSync();
charliex 4:53ef91c87d74 556
charliex 4:53ef91c87d74 557 // A function in H-Sync
charliex 4:53ef91c87d74 558 if ( pNesX_HSync() == -1 )
charliex 4:53ef91c87d74 559 return; // To the menu screen
charliex 4:53ef91c87d74 560 }
charliex 4:53ef91c87d74 561 }
charliex 4:53ef91c87d74 562
charliex 4:53ef91c87d74 563 /*===================================================================*/
charliex 4:53ef91c87d74 564 /* */
charliex 4:53ef91c87d74 565 /* pNesX_HSync() : A function in H-Sync */
charliex 4:53ef91c87d74 566 /* */
charliex 4:53ef91c87d74 567 /*===================================================================*/
charliex 4:53ef91c87d74 568 int pNesX_HSync()
charliex 4:53ef91c87d74 569
charliex 4:53ef91c87d74 570 {
charliex 4:53ef91c87d74 571 /*
charliex 4:53ef91c87d74 572 * A function in H-Sync
charliex 4:53ef91c87d74 573 *
charliex 4:53ef91c87d74 574 * Return values
charliex 4:53ef91c87d74 575 * 0 : Normally
charliex 4:53ef91c87d74 576 * -1 : Exit an emulation
charliex 4:53ef91c87d74 577 */
charliex 4:53ef91c87d74 578
charliex 4:53ef91c87d74 579 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 580 /* Render a scanline */
charliex 4:53ef91c87d74 581 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 582 if ( FrameDraw &&
charliex 4:53ef91c87d74 583 PPU_Scanline >= SCAN_ON_SCREEN_START && PPU_Scanline < SCAN_BOTTOM_OFF_SCREEN_START )
charliex 4:53ef91c87d74 584 {
charliex 4:53ef91c87d74 585 pNesX_DrawLine();
charliex 4:53ef91c87d74 586 pNesX_TransmitLinedata();
charliex 4:53ef91c87d74 587 }
charliex 4:53ef91c87d74 588
charliex 4:53ef91c87d74 589 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 590 /* Set new scroll values */
charliex 4:53ef91c87d74 591 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 592 PPU_Scr_V = PPU_Scr_V_Next;
charliex 4:53ef91c87d74 593 PPU_Scr_V_Byte = PPU_Scr_V_Byte_Next;
charliex 4:53ef91c87d74 594 PPU_Scr_V_Bit = PPU_Scr_V_Bit_Next;
charliex 4:53ef91c87d74 595
charliex 4:53ef91c87d74 596 PPU_Scr_H = PPU_Scr_H_Next;
charliex 4:53ef91c87d74 597 PPU_Scr_H_Byte = PPU_Scr_H_Byte_Next;
charliex 4:53ef91c87d74 598 PPU_Scr_H_Bit = PPU_Scr_H_Bit_Next;
charliex 4:53ef91c87d74 599
charliex 4:53ef91c87d74 600 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 601 /* Next Scanline */
charliex 4:53ef91c87d74 602 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 603 PPU_Scanline = ( PPU_Scanline == SCAN_VBLANK_END ) ? 0 : PPU_Scanline + 1;
charliex 4:53ef91c87d74 604
charliex 4:53ef91c87d74 605 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 606 /* Operation in the specific scanning line */
charliex 4:53ef91c87d74 607 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 608 switch ( PPU_Scanline )
charliex 4:53ef91c87d74 609 {
charliex 4:53ef91c87d74 610 case SCAN_ON_SCREEN_START:
charliex 4:53ef91c87d74 611 // Reset a PPU status
charliex 4:53ef91c87d74 612 PPU_R2 = 0;
charliex 4:53ef91c87d74 613
charliex 4:53ef91c87d74 614 // Set up a character data
charliex 4:53ef91c87d74 615 if ( NesHeader.byVRomSize == 0 && FrameDraw )
charliex 4:53ef91c87d74 616 pNesX_SetupChr();
charliex 4:53ef91c87d74 617
charliex 4:53ef91c87d74 618 // Get position of sprite #0
charliex 4:53ef91c87d74 619 pNesX_GetSprHitY();
charliex 4:53ef91c87d74 620 break;
charliex 4:53ef91c87d74 621
charliex 4:53ef91c87d74 622 case SCAN_VBLANK_START:
charliex 4:53ef91c87d74 623 // Frame skip
charliex 4:53ef91c87d74 624 FrameCnt = ++FrameCnt % 6;
charliex 4:53ef91c87d74 625 switch (FrameSkip)
charliex 4:53ef91c87d74 626 {
charliex 4:53ef91c87d74 627 case 0: // full
charliex 4:53ef91c87d74 628 FrameDraw = true;
charliex 4:53ef91c87d74 629 break;
charliex 4:53ef91c87d74 630
charliex 4:53ef91c87d74 631 case 1: // 1/2
charliex 4:53ef91c87d74 632 FrameDraw = FrameCnt & 1;
charliex 4:53ef91c87d74 633 break;
charliex 4:53ef91c87d74 634
charliex 4:53ef91c87d74 635 case 2: // 2/3
charliex 4:53ef91c87d74 636 FrameDraw = !(FrameCnt == 2 || FrameCnt == 5);
charliex 4:53ef91c87d74 637 break;
charliex 4:53ef91c87d74 638
charliex 4:53ef91c87d74 639 case 3: // 1/3
charliex 4:53ef91c87d74 640 FrameDraw = FrameCnt == 0 || FrameCnt == 3;
charliex 4:53ef91c87d74 641 }
charliex 4:53ef91c87d74 642
charliex 4:53ef91c87d74 643 pNesX_LoadFrame();
charliex 4:53ef91c87d74 644
charliex 4:53ef91c87d74 645 // Set a V-Blank flag
charliex 4:53ef91c87d74 646 PPU_R2 = R2_IN_VBLANK;
charliex 4:53ef91c87d74 647
charliex 4:53ef91c87d74 648 // Reset latch flag
charliex 4:53ef91c87d74 649 PPU_Latch_Flag = 0;
charliex 4:53ef91c87d74 650
charliex 4:53ef91c87d74 651 // A mapper function in V-Sync
charliex 4:53ef91c87d74 652 MapperVSync();
charliex 4:53ef91c87d74 653
charliex 4:53ef91c87d74 654 // Get the condition of the joypad
charliex 4:53ef91c87d74 655 pNesX_PadState( &PAD1_Latch, &PAD2_Latch, &PAD_System );
charliex 4:53ef91c87d74 656
charliex 4:53ef91c87d74 657 // NMI on V-Blank
charliex 4:53ef91c87d74 658 if ( PPU_R0 & R0_NMI_VB )
charliex 4:53ef91c87d74 659 NMI_REQ;
charliex 4:53ef91c87d74 660
charliex 4:53ef91c87d74 661 // Exit an emulation if a QUIT button is pushed
charliex 4:53ef91c87d74 662 static DWORD quitWait;
charliex 4:53ef91c87d74 663 if (PAD_PUSH( PAD_System, PAD_SYS_QUIT ))
charliex 4:53ef91c87d74 664 {
charliex 4:53ef91c87d74 665 quitWait++;
charliex 4:53ef91c87d74 666 }
charliex 4:53ef91c87d74 667 else
charliex 4:53ef91c87d74 668 {
charliex 4:53ef91c87d74 669 if (quitWait > 10)
charliex 4:53ef91c87d74 670 {
charliex 4:53ef91c87d74 671 quitWait = 0;
charliex 4:53ef91c87d74 672 return -1; // Exit an emulation
charliex 4:53ef91c87d74 673 }
charliex 4:53ef91c87d74 674 quitWait = 0;
charliex 4:53ef91c87d74 675 }
charliex 4:53ef91c87d74 676 break;
charliex 4:53ef91c87d74 677
charliex 4:53ef91c87d74 678 case SCAN_APU_CLK1: // 240Hz
charliex 4:53ef91c87d74 679 case SCAN_APU_CLK3: // 240Hz
charliex 4:53ef91c87d74 680 pNesX_ApuClk_240Hz();
charliex 4:53ef91c87d74 681 break;
charliex 4:53ef91c87d74 682
charliex 4:53ef91c87d74 683 case SCAN_APU_CLK2: // 240Hz 120Hz
charliex 4:53ef91c87d74 684 pNesX_ApuClk_240Hz();
charliex 4:53ef91c87d74 685 pNesX_ApuClk_120Hz();
charliex 4:53ef91c87d74 686 break;
charliex 4:53ef91c87d74 687
charliex 4:53ef91c87d74 688 case SCAN_APU_CLK4: // 240Hz 120Hz 60Hz
charliex 4:53ef91c87d74 689 pNesX_ApuClk_240Hz();
charliex 4:53ef91c87d74 690 pNesX_ApuClk_120Hz();
charliex 4:53ef91c87d74 691 pNesX_ApuClk_60Hz();
charliex 4:53ef91c87d74 692 break;
charliex 4:53ef91c87d74 693
charliex 4:53ef91c87d74 694 }
charliex 4:53ef91c87d74 695
charliex 4:53ef91c87d74 696 // Successful
charliex 4:53ef91c87d74 697 return 0;
charliex 4:53ef91c87d74 698 }
charliex 4:53ef91c87d74 699
charliex 4:53ef91c87d74 700 /*===================================================================*/
charliex 4:53ef91c87d74 701 /* */
charliex 4:53ef91c87d74 702 /* pNesX_DrawLine() : Render a scanline */
charliex 4:53ef91c87d74 703 /* */
charliex 4:53ef91c87d74 704 /*===================================================================*/
charliex 4:53ef91c87d74 705
charliex 4:53ef91c87d74 706
charliex 4:53ef91c87d74 707 void pNesX_DrawLine()
charliex 4:53ef91c87d74 708 {
charliex 4:53ef91c87d74 709 /*
charliex 4:53ef91c87d74 710 * Render a scanline
charliex 4:53ef91c87d74 711 *
charliex 4:53ef91c87d74 712 */
charliex 4:53ef91c87d74 713 int nX;
charliex 4:53ef91c87d74 714 int nY;
charliex 4:53ef91c87d74 715 int nY4;
charliex 4:53ef91c87d74 716 int nYBit;
charliex 4:53ef91c87d74 717 WORD *pPalTbl;
charliex 4:53ef91c87d74 718 BYTE *pAttrBase;
charliex 4:53ef91c87d74 719 WORD *pPoint;
charliex 4:53ef91c87d74 720 int nNameTable;
charliex 4:53ef91c87d74 721 BYTE *pbyNameTable;
charliex 4:53ef91c87d74 722 BYTE *pbyChrData;
charliex 4:53ef91c87d74 723 BYTE *pSPRRAM;
charliex 4:53ef91c87d74 724 int nAttr;
charliex 4:53ef91c87d74 725 int nSprCnt;
charliex 4:53ef91c87d74 726 int nIdx;
charliex 4:53ef91c87d74 727 BYTE bySprCol;
charliex 4:53ef91c87d74 728 bool bMask[ NES_DISP_WIDTH ];
charliex 4:53ef91c87d74 729 bool *pMask;
charliex 4:53ef91c87d74 730
charliex 4:53ef91c87d74 731 // Pointer to the render position
charliex 4:53ef91c87d74 732 pPoint = LineData[LineDataIdx];
charliex 4:53ef91c87d74 733 LineDataIdx = LineDataIdx == 0 ? 1 : 0;
charliex 4:53ef91c87d74 734 pDrawData = pPoint;
charliex 4:53ef91c87d74 735
charliex 4:53ef91c87d74 736 // Clear a scanline if screen is off
charliex 4:53ef91c87d74 737 if ( !( PPU_R1 & R1_SHOW_SCR ) )
charliex 4:53ef91c87d74 738 {
charliex 4:53ef91c87d74 739 pNesX_MemorySet( pPoint, 0, NES_DISP_WIDTH << 1 );
charliex 4:53ef91c87d74 740 return;
charliex 4:53ef91c87d74 741 }
charliex 4:53ef91c87d74 742
charliex 4:53ef91c87d74 743 nNameTable = PPU_NameTableBank;
charliex 4:53ef91c87d74 744
charliex 4:53ef91c87d74 745 nY = PPU_Scr_V_Byte + ( PPU_Scanline >> 3 );
charliex 4:53ef91c87d74 746
charliex 4:53ef91c87d74 747 nYBit = PPU_Scr_V_Bit + ( PPU_Scanline & 7 );
charliex 4:53ef91c87d74 748
charliex 4:53ef91c87d74 749 if ( nYBit > 7 )
charliex 4:53ef91c87d74 750 {
charliex 4:53ef91c87d74 751 ++nY;
charliex 4:53ef91c87d74 752 nYBit &= 7;
charliex 4:53ef91c87d74 753 }
charliex 4:53ef91c87d74 754 nYBit <<= 3;
charliex 4:53ef91c87d74 755
charliex 4:53ef91c87d74 756 if ( nY > 29 )
charliex 4:53ef91c87d74 757 {
charliex 4:53ef91c87d74 758 // Next NameTable (An up-down direction)
charliex 4:53ef91c87d74 759 nNameTable ^= NAME_TABLE_V_MASK;
charliex 4:53ef91c87d74 760 nY -= 30;
charliex 4:53ef91c87d74 761 }
charliex 4:53ef91c87d74 762
charliex 4:53ef91c87d74 763 nX = PPU_Scr_H_Byte;
charliex 4:53ef91c87d74 764
charliex 4:53ef91c87d74 765 nY4 = ( ( nY & 2 ) << 1 );
charliex 4:53ef91c87d74 766
charliex 4:53ef91c87d74 767 pMask = bMask;
charliex 4:53ef91c87d74 768
charliex 4:53ef91c87d74 769 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 770 /* Rendering of the block of the left end */
charliex 4:53ef91c87d74 771 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 772
charliex 4:53ef91c87d74 773 pbyNameTable = PPUBANK[ nNameTable ] + nY * 32 + nX;
charliex 4:53ef91c87d74 774 pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit;
charliex 4:53ef91c87d74 775 pAttrBase = PPUBANK[ nNameTable ] + 0x3c0 + ( nY / 4 ) * 8;
charliex 4:53ef91c87d74 776 pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ];
charliex 4:53ef91c87d74 777
charliex 4:53ef91c87d74 778 for ( nIdx = PPU_Scr_H_Bit; nIdx < 8; ++nIdx )
charliex 4:53ef91c87d74 779 {
charliex 4:53ef91c87d74 780 *( pPoint++ ) = pPalTbl[ pbyChrData[ nIdx ] ];
charliex 4:53ef91c87d74 781 *pMask++ = pbyChrData[ nIdx ] == 0;
charliex 4:53ef91c87d74 782 }
charliex 4:53ef91c87d74 783
charliex 4:53ef91c87d74 784 ++nX;
charliex 4:53ef91c87d74 785 ++pbyNameTable;
charliex 4:53ef91c87d74 786
charliex 4:53ef91c87d74 787 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 788 /* Rendering of the left table */
charliex 4:53ef91c87d74 789 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 790
charliex 4:53ef91c87d74 791 for ( ; nX < 32; ++nX )
charliex 4:53ef91c87d74 792 {
charliex 4:53ef91c87d74 793 pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit;
charliex 4:53ef91c87d74 794 pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ];
charliex 4:53ef91c87d74 795
charliex 4:53ef91c87d74 796 *pPoint++ = pPalTbl[ pbyChrData[ 0 ] ];
charliex 4:53ef91c87d74 797 *pPoint++ = pPalTbl[ pbyChrData[ 1 ] ];
charliex 4:53ef91c87d74 798 *pPoint++ = pPalTbl[ pbyChrData[ 2 ] ];
charliex 4:53ef91c87d74 799 *pPoint++ = pPalTbl[ pbyChrData[ 3 ] ];
charliex 4:53ef91c87d74 800 *pPoint++ = pPalTbl[ pbyChrData[ 4 ] ];
charliex 4:53ef91c87d74 801 *pPoint++ = pPalTbl[ pbyChrData[ 5 ] ];
charliex 4:53ef91c87d74 802 *pPoint++ = pPalTbl[ pbyChrData[ 6 ] ];
charliex 4:53ef91c87d74 803 *pPoint++ = pPalTbl[ pbyChrData[ 7 ] ];
charliex 4:53ef91c87d74 804
charliex 4:53ef91c87d74 805 *pMask++ = pbyChrData[ 0 ] == 0;
charliex 4:53ef91c87d74 806 *pMask++ = pbyChrData[ 1 ] == 0;
charliex 4:53ef91c87d74 807 *pMask++ = pbyChrData[ 2 ] == 0;
charliex 4:53ef91c87d74 808 *pMask++ = pbyChrData[ 3 ] == 0;
charliex 4:53ef91c87d74 809 *pMask++ = pbyChrData[ 4 ] == 0;
charliex 4:53ef91c87d74 810 *pMask++ = pbyChrData[ 5 ] == 0;
charliex 4:53ef91c87d74 811 *pMask++ = pbyChrData[ 6 ] == 0;
charliex 4:53ef91c87d74 812 *pMask++ = pbyChrData[ 7 ] == 0;
charliex 4:53ef91c87d74 813
charliex 4:53ef91c87d74 814 ++pbyNameTable;
charliex 4:53ef91c87d74 815 }
charliex 4:53ef91c87d74 816
charliex 4:53ef91c87d74 817 // Holizontal Mirror
charliex 4:53ef91c87d74 818 nNameTable ^= NAME_TABLE_H_MASK;
charliex 4:53ef91c87d74 819
charliex 4:53ef91c87d74 820 pbyNameTable = PPUBANK[ nNameTable ] + nY * 32;
charliex 4:53ef91c87d74 821 pAttrBase = PPUBANK[ nNameTable ] + 0x3c0 + ( nY / 4 ) * 8;
charliex 4:53ef91c87d74 822
charliex 4:53ef91c87d74 823 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 824 /* Rendering of the right table */
charliex 4:53ef91c87d74 825 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 826
charliex 4:53ef91c87d74 827 for ( nX = 0; nX < PPU_Scr_H_Byte; ++nX )
charliex 4:53ef91c87d74 828 {
charliex 4:53ef91c87d74 829 pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit;
charliex 4:53ef91c87d74 830 pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ];
charliex 4:53ef91c87d74 831
charliex 4:53ef91c87d74 832 *pPoint++ = pPalTbl[ pbyChrData[ 0 ] ];
charliex 4:53ef91c87d74 833 *pPoint++ = pPalTbl[ pbyChrData[ 1 ] ];
charliex 4:53ef91c87d74 834 *pPoint++ = pPalTbl[ pbyChrData[ 2 ] ];
charliex 4:53ef91c87d74 835 *pPoint++ = pPalTbl[ pbyChrData[ 3 ] ];
charliex 4:53ef91c87d74 836 *pPoint++ = pPalTbl[ pbyChrData[ 4 ] ];
charliex 4:53ef91c87d74 837 *pPoint++ = pPalTbl[ pbyChrData[ 5 ] ];
charliex 4:53ef91c87d74 838 *pPoint++ = pPalTbl[ pbyChrData[ 6 ] ];
charliex 4:53ef91c87d74 839 *pPoint++ = pPalTbl[ pbyChrData[ 7 ] ];
charliex 4:53ef91c87d74 840
charliex 4:53ef91c87d74 841 *pMask++ = pbyChrData[ 0 ] == 0;
charliex 4:53ef91c87d74 842 *pMask++ = pbyChrData[ 1 ] == 0;
charliex 4:53ef91c87d74 843 *pMask++ = pbyChrData[ 2 ] == 0;
charliex 4:53ef91c87d74 844 *pMask++ = pbyChrData[ 3 ] == 0;
charliex 4:53ef91c87d74 845 *pMask++ = pbyChrData[ 4 ] == 0;
charliex 4:53ef91c87d74 846 *pMask++ = pbyChrData[ 5 ] == 0;
charliex 4:53ef91c87d74 847 *pMask++ = pbyChrData[ 6 ] == 0;
charliex 4:53ef91c87d74 848 *pMask++ = pbyChrData[ 7 ] == 0;
charliex 4:53ef91c87d74 849
charliex 4:53ef91c87d74 850 ++pbyNameTable;
charliex 4:53ef91c87d74 851 }
charliex 4:53ef91c87d74 852
charliex 4:53ef91c87d74 853 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 854 /* Rendering of the block of the right end */
charliex 4:53ef91c87d74 855 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 856
charliex 4:53ef91c87d74 857 pbyChrData = PPU_BG_Base + ( *pbyNameTable << 6 ) + nYBit;
charliex 4:53ef91c87d74 858 pPalTbl = &PalTable[ ( ( ( pAttrBase[ nX >> 2 ] >> ( ( nX & 2 ) + nY4 ) ) & 3 ) << 2 ) ];
charliex 4:53ef91c87d74 859 for ( nIdx = 0; nIdx < PPU_Scr_H_Bit; ++nIdx )
charliex 4:53ef91c87d74 860 {
charliex 4:53ef91c87d74 861 pPoint[ nIdx ] = pPalTbl[ pbyChrData[ nIdx ] ];
charliex 4:53ef91c87d74 862 *pMask++ = pbyChrData[ nIdx ] == 0;
charliex 4:53ef91c87d74 863 }
charliex 4:53ef91c87d74 864
charliex 4:53ef91c87d74 865 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 866 /* Render a sprite */
charliex 4:53ef91c87d74 867 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 868
charliex 4:53ef91c87d74 869 if ( PPU_R1 & R1_SHOW_SP )
charliex 4:53ef91c87d74 870 {
charliex 4:53ef91c87d74 871 // Reset Scanline Sprite Count
charliex 4:53ef91c87d74 872 PPU_R2 &= ~R2_MAX_SP;
charliex 4:53ef91c87d74 873
charliex 4:53ef91c87d74 874 // Render a sprite to the sprite buffer
charliex 4:53ef91c87d74 875 pPoint = pDrawData;
charliex 4:53ef91c87d74 876 nSprCnt = 0;
charliex 4:53ef91c87d74 877 for ( pSPRRAM = SPRRAM + ( 63 << 2 ); pSPRRAM >= SPRRAM &&
charliex 4:53ef91c87d74 878 nSprCnt < 8; pSPRRAM -= 4 )
charliex 4:53ef91c87d74 879 {
charliex 4:53ef91c87d74 880 nY = pSPRRAM[ SPR_Y ] + 1;
charliex 4:53ef91c87d74 881 if ( nY > PPU_Scanline || nY + PPU_SP_Height <= PPU_Scanline )
charliex 4:53ef91c87d74 882 continue; // Next sprite
charliex 4:53ef91c87d74 883
charliex 4:53ef91c87d74 884 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 885 /* A sprite in scanning line */
charliex 4:53ef91c87d74 886 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 887
charliex 4:53ef91c87d74 888 // Holizontal Sprite Count +1
charliex 4:53ef91c87d74 889 ++nSprCnt;
charliex 4:53ef91c87d74 890
charliex 4:53ef91c87d74 891 nAttr = pSPRRAM[ SPR_ATTR ];
charliex 4:53ef91c87d74 892 nYBit = PPU_Scanline - nY;
charliex 4:53ef91c87d74 893 nYBit = ( nAttr & SPR_ATTR_V_FLIP ) ? ( PPU_SP_Height - nYBit - 1 ) << 3 : nYBit << 3;
charliex 4:53ef91c87d74 894
charliex 4:53ef91c87d74 895 if ( PPU_R0 & R0_SP_SIZE )
charliex 4:53ef91c87d74 896 {
charliex 4:53ef91c87d74 897 // Sprite size 8x16
charliex 4:53ef91c87d74 898 if ( pSPRRAM[ SPR_CHR ] & 1 )
charliex 4:53ef91c87d74 899 {
charliex 4:53ef91c87d74 900 pbyChrData = ChrBuf + 256 * 64 + ( ( pSPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit;
charliex 4:53ef91c87d74 901 }
charliex 4:53ef91c87d74 902 else
charliex 4:53ef91c87d74 903 {
charliex 4:53ef91c87d74 904 pbyChrData = ChrBuf + ( ( pSPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit;
charliex 4:53ef91c87d74 905 }
charliex 4:53ef91c87d74 906 }
charliex 4:53ef91c87d74 907 else
charliex 4:53ef91c87d74 908 {
charliex 4:53ef91c87d74 909 // Sprite size 8x8
charliex 4:53ef91c87d74 910 pbyChrData = PPU_SP_Base + ( pSPRRAM[ SPR_CHR ] << 6 ) + nYBit;
charliex 4:53ef91c87d74 911 }
charliex 4:53ef91c87d74 912
charliex 4:53ef91c87d74 913 bool bSprFront = !(nAttr & SPR_ATTR_PRI);
charliex 4:53ef91c87d74 914 bySprCol = (( nAttr & SPR_ATTR_COLOR ) << 2) + 0x10;
charliex 4:53ef91c87d74 915 nX = pSPRRAM[ SPR_X ];
charliex 4:53ef91c87d74 916
charliex 4:53ef91c87d74 917 if ( nAttr & SPR_ATTR_H_FLIP )
charliex 4:53ef91c87d74 918 {
charliex 4:53ef91c87d74 919 // Horizontal flip
charliex 4:53ef91c87d74 920 if ( pbyChrData[ 0 ] && nX < 249 && (bSprFront || bMask[nX + 7]) )
charliex 4:53ef91c87d74 921 pPoint[ nX + 7 ] = PalTable[ bySprCol | pbyChrData[ 0 ] ];
charliex 4:53ef91c87d74 922 if ( pbyChrData[ 1 ] && nX < 250 && (bSprFront || bMask[nX + 6]) )
charliex 4:53ef91c87d74 923 pPoint[ nX + 6 ] = PalTable[ bySprCol | pbyChrData[ 1 ] ];
charliex 4:53ef91c87d74 924 if ( pbyChrData[ 2 ] && nX < 251 && (bSprFront || bMask[nX + 5]) )
charliex 4:53ef91c87d74 925 pPoint[ nX + 5 ] = PalTable[ bySprCol | pbyChrData[ 2 ] ];
charliex 4:53ef91c87d74 926 if ( pbyChrData[ 3 ] && nX < 252 && (bSprFront || bMask[nX + 4]) )
charliex 4:53ef91c87d74 927 pPoint[ nX + 4 ] = PalTable[ bySprCol | pbyChrData[ 3 ] ];
charliex 4:53ef91c87d74 928 if ( pbyChrData[ 4 ] && nX < 253 && (bSprFront || bMask[nX + 3]) )
charliex 4:53ef91c87d74 929 pPoint[ nX + 3 ] = PalTable[ bySprCol | pbyChrData[ 4 ] ];
charliex 4:53ef91c87d74 930 if ( pbyChrData[ 5 ] && nX < 254 && (bSprFront || bMask[nX + 2]) )
charliex 4:53ef91c87d74 931 pPoint[ nX + 2 ] = PalTable[ bySprCol | pbyChrData[ 5 ] ];
charliex 4:53ef91c87d74 932 if ( pbyChrData[ 6 ] && nX < 255 && (bSprFront || bMask[nX + 1]) )
charliex 4:53ef91c87d74 933 pPoint[ nX + 1 ] = PalTable[ bySprCol | pbyChrData[ 6 ] ];
charliex 4:53ef91c87d74 934 if ( pbyChrData[ 7 ] && (bSprFront || bMask[nX]) )
charliex 4:53ef91c87d74 935 pPoint[ nX ] = PalTable[ bySprCol | pbyChrData[ 7 ] ];
charliex 4:53ef91c87d74 936 }
charliex 4:53ef91c87d74 937 else
charliex 4:53ef91c87d74 938 {
charliex 4:53ef91c87d74 939 // Non flip
charliex 4:53ef91c87d74 940 if ( pbyChrData[ 0 ] && (bSprFront || bMask[nX]) )
charliex 4:53ef91c87d74 941 pPoint[ nX ] = PalTable[ bySprCol | pbyChrData[ 0 ] ];
charliex 4:53ef91c87d74 942 if ( pbyChrData[ 1 ] && nX < 255 && (bSprFront || bMask[nX + 1]) )
charliex 4:53ef91c87d74 943 pPoint[ nX + 1 ] = PalTable[ bySprCol | pbyChrData[ 1 ] ];
charliex 4:53ef91c87d74 944 if ( pbyChrData[ 2 ] && nX < 254 && (bSprFront || bMask[nX + 2]) )
charliex 4:53ef91c87d74 945 pPoint[ nX + 2 ] = PalTable[ bySprCol | pbyChrData[ 2 ] ];
charliex 4:53ef91c87d74 946 if ( pbyChrData[ 3 ] && nX < 253 && (bSprFront || bMask[nX + 3]) )
charliex 4:53ef91c87d74 947 pPoint[ nX + 3 ] = PalTable[ bySprCol | pbyChrData[ 3 ] ];
charliex 4:53ef91c87d74 948 if ( pbyChrData[ 4 ] && nX < 252 && (bSprFront || bMask[nX + 4]) )
charliex 4:53ef91c87d74 949 pPoint[ nX + 4 ] = PalTable[ bySprCol | pbyChrData[ 4 ] ];
charliex 4:53ef91c87d74 950 if ( pbyChrData[ 5 ] && nX < 251 && (bSprFront || bMask[nX + 5]) )
charliex 4:53ef91c87d74 951 pPoint[ nX + 5 ] = PalTable[ bySprCol | pbyChrData[ 5 ] ];
charliex 4:53ef91c87d74 952 if ( pbyChrData[ 6 ] && nX < 250 && (bSprFront || bMask[nX + 6]) )
charliex 4:53ef91c87d74 953 pPoint[ nX + 6 ] = PalTable[ bySprCol | pbyChrData[ 6 ] ];
charliex 4:53ef91c87d74 954 if ( pbyChrData[ 7 ] && nX < 249 && (bSprFront || bMask[nX + 7]) )
charliex 4:53ef91c87d74 955 pPoint[ nX + 7 ] = PalTable[ bySprCol | pbyChrData[ 7 ] ];
charliex 4:53ef91c87d74 956 }
charliex 4:53ef91c87d74 957 }
charliex 4:53ef91c87d74 958
charliex 4:53ef91c87d74 959 if ( nSprCnt == 8 )
charliex 4:53ef91c87d74 960 PPU_R2 |= R2_MAX_SP; // Set a flag of maximum sprites on scanline
charliex 4:53ef91c87d74 961 }
charliex 4:53ef91c87d74 962 }
charliex 4:53ef91c87d74 963
charliex 4:53ef91c87d74 964 /*===================================================================*/
charliex 4:53ef91c87d74 965 /* */
charliex 4:53ef91c87d74 966 /* pNesX_GetSprHitY() : Get a position of scanline hits sprite #0 */
charliex 4:53ef91c87d74 967 /* */
charliex 4:53ef91c87d74 968 /*===================================================================*/
charliex 4:53ef91c87d74 969 void pNesX_GetSprHitY()
charliex 4:53ef91c87d74 970 {
charliex 4:53ef91c87d74 971 /*
charliex 4:53ef91c87d74 972 * Get a position of scanline hits sprite #0
charliex 4:53ef91c87d74 973 *
charliex 4:53ef91c87d74 974 */
charliex 4:53ef91c87d74 975
charliex 4:53ef91c87d74 976 int nYBit;
charliex 4:53ef91c87d74 977 DWORD *pdwChrData;
charliex 4:53ef91c87d74 978 int nOff;
charliex 4:53ef91c87d74 979
charliex 4:53ef91c87d74 980 if ( SPRRAM[ SPR_ATTR ] & SPR_ATTR_V_FLIP )
charliex 4:53ef91c87d74 981 {
charliex 4:53ef91c87d74 982 // Vertical flip
charliex 4:53ef91c87d74 983 nYBit = ( PPU_SP_Height - 1 ) << 3;
charliex 4:53ef91c87d74 984 nOff = -2;
charliex 4:53ef91c87d74 985 }
charliex 4:53ef91c87d74 986 else
charliex 4:53ef91c87d74 987 {
charliex 4:53ef91c87d74 988 // Non flip
charliex 4:53ef91c87d74 989 nYBit = 0;
charliex 4:53ef91c87d74 990 nOff = 2;
charliex 4:53ef91c87d74 991 }
charliex 4:53ef91c87d74 992
charliex 4:53ef91c87d74 993 if ( PPU_R0 & R0_SP_SIZE )
charliex 4:53ef91c87d74 994 {
charliex 4:53ef91c87d74 995 // Sprite size 8x16
charliex 4:53ef91c87d74 996 if ( SPRRAM[ SPR_CHR ] & 1 )
charliex 4:53ef91c87d74 997 {
charliex 4:53ef91c87d74 998 pdwChrData = (DWORD *)( ChrBuf + 256 * 64 + ( ( SPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit );
charliex 4:53ef91c87d74 999 }
charliex 4:53ef91c87d74 1000 else
charliex 4:53ef91c87d74 1001 {
charliex 4:53ef91c87d74 1002 pdwChrData = (DWORD * )( ChrBuf + ( ( SPRRAM[ SPR_CHR ] & 0xfe ) << 6 ) + nYBit );
charliex 4:53ef91c87d74 1003 }
charliex 4:53ef91c87d74 1004 }
charliex 4:53ef91c87d74 1005 else
charliex 4:53ef91c87d74 1006 {
charliex 4:53ef91c87d74 1007 // Sprite size 8x8
charliex 4:53ef91c87d74 1008 pdwChrData = (DWORD *)( PPU_SP_Base + ( SPRRAM[ SPR_CHR ] << 6 ) + nYBit );
charliex 4:53ef91c87d74 1009 }
charliex 4:53ef91c87d74 1010
charliex 4:53ef91c87d74 1011 for ( SpriteHitPos = 1; SpriteHitPos < PPU_SP_Height + 1; ++SpriteHitPos )
charliex 4:53ef91c87d74 1012 {
charliex 4:53ef91c87d74 1013 if ( pdwChrData[ 0 ] | pdwChrData[ 1 ] )
charliex 4:53ef91c87d74 1014 return; // Scanline hits sprite #0
charliex 4:53ef91c87d74 1015
charliex 4:53ef91c87d74 1016 pdwChrData += nOff;
charliex 4:53ef91c87d74 1017 }
charliex 4:53ef91c87d74 1018
charliex 4:53ef91c87d74 1019 // Scanline didn't hit sprite #0
charliex 4:53ef91c87d74 1020 SpriteHitPos = SCAN_VBLANK_END;
charliex 4:53ef91c87d74 1021 }
charliex 4:53ef91c87d74 1022
charliex 4:53ef91c87d74 1023 /*===================================================================*/
charliex 4:53ef91c87d74 1024 /* */
charliex 4:53ef91c87d74 1025 /* pNesX_SetupChr() : Develop character data */
charliex 4:53ef91c87d74 1026 /* */
charliex 4:53ef91c87d74 1027 /*===================================================================*/
charliex 4:53ef91c87d74 1028 void pNesX_SetupChr()
charliex 4:53ef91c87d74 1029 {
charliex 4:53ef91c87d74 1030 /*
charliex 4:53ef91c87d74 1031 * Develop character data
charliex 4:53ef91c87d74 1032 *
charliex 4:53ef91c87d74 1033 */
charliex 4:53ef91c87d74 1034
charliex 4:53ef91c87d74 1035 BYTE *pbyBGData;
charliex 4:53ef91c87d74 1036 BYTE byData1;
charliex 4:53ef91c87d74 1037 BYTE byData2;
charliex 4:53ef91c87d74 1038 int nIdx;
charliex 4:53ef91c87d74 1039 int nY;
charliex 4:53ef91c87d74 1040 int nOff;
charliex 4:53ef91c87d74 1041 static BYTE *pbyPrevBank[ 8 ];
charliex 4:53ef91c87d74 1042 int nBank;
charliex 4:53ef91c87d74 1043
charliex 4:53ef91c87d74 1044 for ( nBank = 0; nBank < 8; ++nBank )
charliex 4:53ef91c87d74 1045 {
charliex 4:53ef91c87d74 1046 if ( pbyPrevBank[ nBank ] == PPUBANK[ nBank ] && !( ( ChrBufUpdate >> nBank ) & 1 ) )
charliex 4:53ef91c87d74 1047 continue; // Next bank
charliex 4:53ef91c87d74 1048
charliex 4:53ef91c87d74 1049 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 1050 /* An address is different from the last time */
charliex 4:53ef91c87d74 1051 /* or */
charliex 4:53ef91c87d74 1052 /* An update flag is being set */
charliex 4:53ef91c87d74 1053 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 1054
charliex 4:53ef91c87d74 1055 for ( nIdx = 0; nIdx < 64; ++nIdx )
charliex 4:53ef91c87d74 1056 {
charliex 4:53ef91c87d74 1057 nOff = ( nBank << 12 ) + ( nIdx << 6 );
charliex 4:53ef91c87d74 1058
charliex 4:53ef91c87d74 1059 for ( nY = 0; nY < 8; ++nY )
charliex 4:53ef91c87d74 1060 {
charliex 4:53ef91c87d74 1061 pbyBGData = PPUBANK[ nBank ] + ( nIdx << 4 ) + nY;
charliex 4:53ef91c87d74 1062
charliex 4:53ef91c87d74 1063 byData1 = ( ( pbyBGData[ 0 ] >> 1 ) & 0x55 ) | ( pbyBGData[ 8 ] & 0xAA );
charliex 4:53ef91c87d74 1064 byData2 = ( pbyBGData[ 0 ] & 0x55 ) | ( ( pbyBGData[ 8 ] << 1 ) & 0xAA );
charliex 4:53ef91c87d74 1065
charliex 4:53ef91c87d74 1066 ChrBuf[ nOff++ ] = ( byData1 >> 6 ) & 3;
charliex 4:53ef91c87d74 1067 ChrBuf[ nOff++ ] = ( byData2 >> 6 ) & 3;
charliex 4:53ef91c87d74 1068 ChrBuf[ nOff++ ] = ( byData1 >> 4 ) & 3;
charliex 4:53ef91c87d74 1069 ChrBuf[ nOff++ ] = ( byData2 >> 4 ) & 3;
charliex 4:53ef91c87d74 1070 ChrBuf[ nOff++ ] = ( byData1 >> 2 ) & 3;
charliex 4:53ef91c87d74 1071 ChrBuf[ nOff++ ] = ( byData2 >> 2 ) & 3;
charliex 4:53ef91c87d74 1072 ChrBuf[ nOff++ ] = byData1 & 3;
charliex 4:53ef91c87d74 1073 ChrBuf[ nOff++ ] = byData2 & 3;
charliex 4:53ef91c87d74 1074 }
charliex 4:53ef91c87d74 1075 }
charliex 4:53ef91c87d74 1076 // Keep this address
charliex 4:53ef91c87d74 1077 pbyPrevBank[ nBank ] = PPUBANK[ nBank ];
charliex 4:53ef91c87d74 1078 }
charliex 4:53ef91c87d74 1079
charliex 4:53ef91c87d74 1080 // Reset update flag
charliex 4:53ef91c87d74 1081 ChrBufUpdate = 0;
charliex 4:53ef91c87d74 1082 }
charliex 4:53ef91c87d74 1083