LayerOne / LayerOne2017_emu

Dependencies:   SDFileSystem mbed-dev

Fork of Nucleo_Ex06_EMU by woodstock .

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