2017-06-28 19:00:08 -04:00
# pragma once
# include "stdafx.h"
# include "PPU.h"
# include "HdNesPack.h"
# include "VideoDecoder.h"
# include "RewindManager.h"
# include "HdPackBuilder.h"
2018-09-13 20:58:35 -04:00
# include "HdPpu.h"
2017-06-28 19:00:08 -04:00
2017-11-19 23:08:23 -05:00
class ControlManager ;
2018-09-13 20:58:35 -04:00
class HdBuilderPpu : public HdPpu
2017-06-28 19:00:08 -04:00
{
private :
HdPackBuilder * _hdPackBuilder ;
bool _needChrHash = false ;
uint32_t _chrRamBankSize ;
uint32_t _chrRamIndexMask ;
vector < uint32_t > _bankHashes ;
2017-07-25 19:46:25 -04:00
HdPpuTileInfo sprite ;
HdPpuTileInfo tile ;
2017-06-28 19:00:08 -04:00
protected :
void DrawPixel ( )
{
if ( IsRenderingEnabled ( ) | | ( ( _state . VideoRamAddr & 0x3F00 ) ! = 0x3F00 ) ) {
2018-07-01 15:21:05 -04:00
bool isChrRam = ! _console - > GetMapper ( ) - > HasChrRom ( ) ;
BaseMapper * mapper = _console - > GetMapper ( ) ;
2017-06-28 19:00:08 -04:00
_lastSprite = nullptr ;
uint32_t color = GetPixelColor ( ) ;
_currentOutputBuffer [ ( _scanline < < 8 ) + _cycle - 1 ] = _paletteRAM [ color & 0x03 ? color : 0 ] ;
2017-08-15 19:18:00 -04:00
uint32_t backgroundColor = 0 ;
if ( _flags . BackgroundEnabled & & _cycle > _minimumDrawBgCycle ) {
backgroundColor = ( ( ( _state . LowBitShift < < _state . XScroll ) & 0x8000 ) > > 15 ) | ( ( ( _state . HighBitShift < < _state . XScroll ) & 0x8000 ) > > 14 ) ;
}
2017-06-28 19:00:08 -04:00
if ( _needChrHash ) {
uint16_t addr = 0 ;
_bankHashes . clear ( ) ;
while ( addr < 0x2000 ) {
uint32_t hash = 0 ;
for ( uint16_t i = 0 ; i < _chrRamBankSize ; i + + ) {
2018-07-01 15:21:05 -04:00
hash + = _console - > GetMapper ( ) - > DebugReadVRAM ( i + addr ) ;
2017-06-28 19:00:08 -04:00
hash = ( hash < < 1 ) | ( hash > > 31 ) ;
}
_bankHashes . push_back ( hash ) ;
addr + = _chrRamBankSize ;
}
_needChrHash = false ;
}
2017-08-15 19:18:00 -04:00
bool hasBgSprite = false ;
2017-06-28 19:00:08 -04:00
if ( _lastSprite & & _flags . SpritesEnabled ) {
2017-08-15 19:18:00 -04:00
if ( backgroundColor = = 0 ) {
for ( uint8_t i = 0 ; i < _spriteCount ; i + + ) {
if ( _spriteTiles [ i ] . BackgroundPriority ) {
hasBgSprite = true ;
break ;
}
}
}
2017-06-28 19:00:08 -04:00
if ( _lastSprite - > AbsoluteTileAddr > = 0 ) {
2018-07-01 15:21:05 -04:00
sprite . TileIndex = ( isChrRam ? ( _lastSprite - > TileAddr & _chrRamIndexMask ) : _lastSprite - > AbsoluteTileAddr ) / 16 ;
2017-07-25 19:46:25 -04:00
sprite . PaletteColors = ReadPaletteRAM ( _lastSprite - > PaletteOffset + 3 ) | ( ReadPaletteRAM ( _lastSprite - > PaletteOffset + 2 ) < < 8 ) | ( ReadPaletteRAM ( _lastSprite - > PaletteOffset + 1 ) < < 16 ) | 0xFF000000 ;
2018-07-01 15:21:05 -04:00
sprite . IsChrRamTile = isChrRam ;
2018-09-07 21:30:00 -04:00
_console - > GetMapper ( ) - > CopyChrTile ( _lastSprite - > AbsoluteTileAddr & 0xFFFFFFF0 , sprite . TileData ) ;
2017-06-28 19:00:08 -04:00
2018-07-01 15:21:05 -04:00
_hdPackBuilder - > ProcessTile ( _cycle - 1 , _scanline , _lastSprite - > AbsoluteTileAddr , sprite , mapper , false , _bankHashes [ _lastSprite - > TileAddr / _chrRamBankSize ] , false ) ;
2017-06-28 19:00:08 -04:00
}
}
if ( _flags . BackgroundEnabled ) {
TileInfo * lastTile = & ( ( _state . XScroll + ( ( _cycle - 1 ) & 0x07 ) < 8 ) ? _previousTile : _currentTile ) ;
if ( lastTile - > AbsoluteTileAddr > = 0 ) {
2018-07-01 15:21:05 -04:00
tile . TileIndex = ( isChrRam ? ( lastTile - > TileAddr & _chrRamIndexMask ) : lastTile - > AbsoluteTileAddr ) / 16 ;
2017-07-25 19:46:25 -04:00
tile . PaletteColors = ReadPaletteRAM ( lastTile - > PaletteOffset + 3 ) | ( ReadPaletteRAM ( lastTile - > PaletteOffset + 2 ) < < 8 ) | ( ReadPaletteRAM ( lastTile - > PaletteOffset + 1 ) < < 16 ) | ( ReadPaletteRAM ( 0 ) < < 24 ) ;
2018-07-01 15:21:05 -04:00
tile . IsChrRamTile = isChrRam ;
2018-09-07 21:30:00 -04:00
_console - > GetMapper ( ) - > CopyChrTile ( lastTile - > AbsoluteTileAddr & 0xFFFFFFF0 , tile . TileData ) ;
2017-06-28 19:00:08 -04:00
2018-07-01 15:21:05 -04:00
_hdPackBuilder - > ProcessTile ( _cycle - 1 , _scanline , lastTile - > AbsoluteTileAddr , tile , mapper , false , _bankHashes [ lastTile - > TileAddr / _chrRamBankSize ] , hasBgSprite ) ;
2017-06-28 19:00:08 -04:00
}
}
} else {
//"If the current VRAM address points in the range $3F00-$3FFF during forced blanking, the color indicated by this palette location will be shown on screen instead of the backdrop color."
_currentOutputBuffer [ ( _scanline < < 8 ) + _cycle - 1 ] = _paletteRAM [ _state . VideoRamAddr & 0x1F ] ;
}
2018-09-13 20:58:35 -04:00
if ( _hdData ) {
HdPpu : : DrawPixel ( ) ;
}
2017-06-28 19:00:08 -04:00
}
void WriteRAM ( uint16_t addr , uint8_t value )
{
2018-06-25 15:56:05 -04:00
if ( GetRegisterID ( addr ) = = PPURegisters : : VideoMemoryData ) {
if ( _state . VideoRamAddr < 0x2000 ) {
_needChrHash = true ;
}
2017-06-28 19:00:08 -04:00
}
PPU : : WriteRAM ( addr , value ) ;
}
void StreamState ( bool saving )
{
PPU : : StreamState ( saving ) ;
if ( ! saving ) {
_needChrHash = true ;
}
}
public :
2018-09-13 20:58:35 -04:00
HdBuilderPpu ( shared_ptr < Console > console , HdPackBuilder * hdPackBuilder , uint32_t chrRamBankSize , shared_ptr < HdPackData > hdData ) : HdPpu ( console , hdData . get ( ) )
2017-06-28 19:00:08 -04:00
{
_hdPackBuilder = hdPackBuilder ;
_chrRamBankSize = chrRamBankSize ;
_chrRamIndexMask = chrRamBankSize - 1 ;
_needChrHash = true ;
}
void SendFrame ( )
{
2018-09-13 20:58:35 -04:00
if ( _hdData ) {
HdPpu : : SendFrame ( ) ;
} else {
PPU : : SendFrame ( ) ;
}
2017-06-28 19:00:08 -04:00
}
} ;