2025-09-06 13:12:15 +02:00
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file :
* Copyright ( C ) 2023
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include "mapinc.h"
# include "asic_mmc3.h"
# include "asic_vrc2and4.h"
static uint8 reg ;
2025-09-07 00:32:28 +02:00
static uint8 init ; /* Games switch between ASICs expecting registers to keep their value, so initialize each ASIC only on the first switch and use this bitfield to track it */
2025-09-06 13:12:15 +02:00
static void applyMode ( uint8 ) ;
static SFORMAT StateRegs [ ] = {
{ & reg , 1 , " MODE " } ,
{ & init , 1 , " INIT " } ,
{ 0 } ,
} ;
static void sync ( void ) {
if ( reg & 0x02 ) {
MMC3_syncPRG ( 0x3F , 0x00 ) ;
MMC3_syncCHR ( 0x1FF , 0x00 ) ;
MMC3_syncMirror ( ) ;
} else {
VRC24_syncPRG ( 0x3F , 0x00 ) ;
VRC24_syncCHR ( 0x1FF , 0x00 ) ;
VRC24_syncMirror ( ) ;
}
}
int getCHRBank_MMC3 ( uint8 bank ) {
return MMC3_getCHRBank ( bank ) | reg < < ( ~ bank & 4 ? 5 : ~ bank & 2 ? 3 : 1 ) & 0x100 ;
}
int getCHRBank_VRC2 ( uint8 bank ) {
return VRC24_getCHRBank ( bank ) | reg < < ( ~ bank & 4 ? 5 : ~ bank & 2 ? 3 : 1 ) & 0x100 ;
}
2025-09-12 21:59:27 +02:00
static DECLFW ( writeReg ) {
2025-09-06 13:12:15 +02:00
uint8 previousReg = reg ;
reg = V ;
if ( ( previousReg ^ V ) & 2 )
applyMode ( 1 ) ;
else
sync ( ) ;
}
static void applyMode ( uint8 clear ) {
PPU_hook = NULL ;
MapIRQHook = NULL ;
GameHBIRQHook = NULL ;
if ( reg & 0x02 ) {
MMC3_activate ( clear & & init & 1 , sync , MMC3_TYPE_AX5202P , NULL , getCHRBank_MMC3 , NULL , NULL ) ;
init & = ~ 1 ;
} else {
VRC2_activate ( clear & & init & 2 , sync , 0x01 , 0x02 , NULL , getCHRBank_VRC2 , NULL , NULL ) ;
init & = ~ 2 ;
}
SetWriteHandler ( 0xA131 , 0xA131 , writeReg ) ;
}
static void reset ( void ) {
reg = 0 ;
init = 3 ;
applyMode ( 1 ) ;
}
static void power ( void ) {
reg = 0 ;
init = 3 ;
applyMode ( 1 ) ;
}
static void restore ( int version ) {
applyMode ( 0 ) ;
}
void UNLSL1632_Init ( CartInfo * info ) {
MMC3_addExState ( ) ;
VRC24_addExState ( ) ;
info - > Reset = reset ;
info - > Power = power ;
GameStateRestore = restore ;
AddExState ( StateRegs , ~ 0 , 0 , 0 ) ;
}