2019-05-24 06:59:26 +08:00
/* FCEUmm - NES/Famicom Emulator
*
* Copyright ( C ) 2019 Libretro Team
*
* 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
*/
/* added 2019-5-23
* BMC - WS Used for Super 40 - in - 1 multicart
* https : //wiki.nesdev.com/w/index.php/NES_2.0_Mapper_332 */
# include "mapinc.h"
2021-04-07 18:45:37 +02:00
static uint8 preg , creg , latch , dipSwitch ;
2019-05-24 06:59:26 +08:00
static SFORMAT StateRegs [ ] =
{
{ & preg , 1 , " PREG " } ,
{ & creg , 1 , " CREG " } ,
2021-04-07 18:45:37 +02:00
{ & latch , 1 , " LATC " } ,
{ & dipSwitch , 1 , " DPSW " } ,
2019-05-24 06:59:26 +08:00
{ 0 }
} ;
static void Sync ( void ) {
2021-04-09 20:28:15 +08:00
int prg = ( preg & 7 ) | ( ( preg > > 3 ) & 0x08 ) ; /* There is a high bit 3 of the PRG register that applies both to PRG and CHR */
int chr = ( creg & 7 ) | ( ( preg > > 3 ) & 0x08 ) ; /* There is a high bit 3 of the PRG register that applies both to PRG and CHR */
int mask = ( creg & 0x10 ) ? 0 : ( creg & 0x20 ) ? 1 : 3 ; /* There is an CNROM mode that takes either two or four inner CHR banks from a CNROM-like latch register at $8000-$FFFF. */
2019-05-24 06:59:26 +08:00
if ( preg & 8 ) {
2021-04-07 18:45:37 +02:00
setprg16 ( 0x8000 , prg ) ;
setprg16 ( 0xc000 , prg ) ;
2019-05-24 06:59:26 +08:00
}
else
2021-04-07 18:45:37 +02:00
setprg32 ( 0x8000 , prg > > 1 ) ;
2021-04-09 20:28:15 +08:00
setchr8 ( ( chr & ~ mask ) | ( latch & mask ) ) ; /* This "inner CHR bank" substitutes the respective bit(s) of the creg register. */
2021-04-07 18:45:37 +02:00
2019-05-24 06:59:26 +08:00
setmirror ( ( ( preg > > 4 ) & 1 ) ^ 1 ) ;
}
2021-04-07 18:45:37 +02:00
static DECLFR ( BMCWSRead ) {
if ( ( creg > > 6 ) & ( dipSwitch & 3 ) )
return X . DB ;
2021-04-09 20:28:15 +08:00
return CartBR ( A ) ;
2021-04-07 18:45:37 +02:00
}
2019-05-24 06:59:26 +08:00
static DECLFW ( BMCWSWrite ) {
if ( preg & 0x20 )
return ;
switch ( A & 1 ) {
2021-04-07 18:45:37 +02:00
case 0 : preg = V ; Sync ( ) ; break ;
case 1 : creg = V ; Sync ( ) ; break ;
2019-05-24 06:59:26 +08:00
}
}
2021-04-07 18:45:37 +02:00
static DECLFW ( LatchWrite ) {
latch = V ;
Sync ( ) ;
}
2019-05-24 06:59:26 +08:00
static void MBMCWSPower ( void ) {
2021-04-07 18:45:37 +02:00
dipSwitch = 0 ;
2019-05-24 06:59:26 +08:00
Sync ( ) ;
2021-04-07 18:45:37 +02:00
SetReadHandler ( 0x8000 , 0xFFFF , BMCWSRead ) ;
SetWriteHandler ( 0x6000 , 0x7FFF , BMCWSWrite ) ;
SetWriteHandler ( 0x8000 , 0xFFFF , LatchWrite ) ;
2019-05-24 06:59:26 +08:00
}
static void BMCWSReset ( void ) {
2021-04-09 20:28:15 +08:00
dipSwitch + + ; /* Soft-resetting cycles through solder pad or DIP switch settings */
if ( dipSwitch = = 3 )
dipSwitch = 0 ; /* Only 00b, 01b and 10b settings are valid */
2021-04-07 18:45:37 +02:00
2021-04-09 20:28:15 +08:00
/* Always reset to menu */
2021-04-07 18:45:37 +02:00
preg = 0 ;
creg = 0 ;
latch = 0 ;
Sync ( ) ;
2019-05-24 06:59:26 +08:00
}
static void StateRestore ( int version ) {
Sync ( ) ;
}
void BMCWS_Init ( CartInfo * info ) {
info - > Reset = BMCWSReset ;
info - > Power = MBMCWSPower ;
GameStateRestore = StateRestore ;
AddExState ( & StateRegs , ~ 0 , 0 , 0 ) ;
}