import { Bus } from '../api/bus' ; import { RAM } from '../api/ram' ; import { ROM , Mirror } from '../api/rom' ; import { uint16 , uint8 } from '../api/types' ; export class PPUBus implements Bus { public rom : ROM ; public ram : RAM ; public bgPalette : RAM ; public spPalette : RAM ; public readByte ( addr ) { addr &= 0x3FFF ; if ( addr < 0x2000 ) return this . rom . mapper . read ( addr ) ; if ( addr < 0x3000 ) return this . ram . read ( this . mirrored ( addr ) ) ; if ( addr < 0x3F00 ) return this . readByte ( addr - 0x1000 ) ; addr &= 0x3F1F ; if ( addr < 0x3F10 ) return this . bgPalette . read ( addr ) ; if ( ! ( addr & 0b11 ) ) return this . bgPalette . read ( addr - 0x10 ) ; return this . spPalette . read ( addr ) ; } public writeByte ( addr , data ) { addr &= 0x3FFF ; if ( addr < 0x2000 ) return this . rom . mapper . write ( addr , data ) ; if ( addr < 0x3000 ) return this . ram . write ( this . mirrored ( addr ) , data ) ; if ( addr < 0x3F00 ) return this . writeByte ( addr - 0x1000 , data ) ; addr &= 0x3F1F ; if ( addr < 0x3F10 ) return this . bgPalette . write ( addr , data ) ; if ( ! ( addr & 0b11 ) ) return this . bgPalette . write ( addr - 0x10 , data ) ; return this . spPalette . write ( addr , data ) ; } public readWord ( addr ) { return this . readByte ( addr + 1 ) << 8 | this . readByte ( addr ) ; } public writeWord ( addr , data ) { this . writeByte ( addr , data ) ; this . writeByte ( addr + 1 , data >> 8 ) ; } private mirrored ( addr ) { switch ( this . rom . header . mirror ) { case Mirror . HORIZONTAL : return ( addr & 9215 ) | ( addr & 2048 ? 1024 : 0 ) ; case Mirror . VERTICAL : return addr & 0x27FF ; case Mirror . FOUR_SCREEN : return addr ; case Mirror . SINGLE_SCREEN_LOWER_BANK : return addr & 0x23FF ; case Mirror . SINGLE_SCREEN_UPPER_BANK : return addr & 0x23FF + 0x0400 ; default : throw new Error ( `invalid mirror type: '${ this . rom . header . mirror }'` ) ; } } }