SUNSOFT-4 and SUNSOFT-6

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
lidnariq
Posts: 10677
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

SUNSOFT-4 and SUNSOFT-6

Post by lidnariq »

I would like to point to Naruko's post where he's given us a comprehensive description of the Sunsoft-4, and how it's used in all three games. Especially the game Nantettatte!! Baseball, which uses an external pluggable options ROM to update it with new season data (I think?)

His writeup survived machine translation surprisingly well, and I've done my best to incorporate the information into the wiki.

He ends with a plea to emulator authors to please fix support for loading these external ROMs with Nantettatte!! Baseball. He suggests a possible iNES layout for it, but it strikes me as roundabout. Dumps of the base game plus expansion are currently available as UNIF in GoodNES3.1.4:

Code: Select all

$ crc32 *PRG1
fdb61142	Nantettatte!! Baseball '91 Kaimaku Hen (J) [U][!].PRG1
dc0bd3c3	Nantettatte!! Baseball OB Allstar Hen (J) [U][!].PRG1
$ cat *91*PRG1 *91*PRG1 > doubled; crc32 doubled
d1d4a6a1
So he's verified the UNIF dump of one expansion.

If you have any questions, you can ask me or in his post.
etabeta
Posts: 109
Joined: Wed Nov 29, 2006 10:11 am
Location: Trieste, Italy

Re: SUNSOFT-4 and SUNSOFT-6

Post by etabeta »

a couple of minor comments about the wiki page. I think you have made a great job incorporating naruko's findings, but I think a couple of clarification could be made :)
Naruko implies that the game only reads the first 16KiB of the external ROM, and the known UNIF dumps of these external ROMs are also only 16KiB in size.
I might be wrong but I interpret both Naruko post and txt as the fact that the external ROM is 32K and it contains the 16K data repeated twice. This happened in a lot of cases if the manufacturer had e.g. a lot of spare 32K chips

The external ROM is only readable while the timer has not expired; once it has, reads should return open bus.
You put this part in the section of the $6000 register, which could make it sound as if the ROM is read through $6000 while the timer is on and open bus when it's expired.
but if I read it correctly you mean that once the timer has expired it is address range $8000-$bfff which should return open bus (until the game possibly writes bit4 at $8000). is this correct?

Also, the doc does not seem to say what reads from $6000 would return while the game is accessing Sunsoft-6 and hence WRAM is disabled, which I'd assume it's open bus...

Overall, thanks for the addition to the wiki: they made my life much easier when I came to implement the emulation in MESS! :)
lidnariq
Posts: 10677
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: SUNSOFT-4 and SUNSOFT-6

Post by lidnariq »

etabeta wrote:
nesdevwiki wrote:Naruko implies that the game only reads the first 16KiB of the external ROM, and the known UNIF dumps of these external ROMs are also only 16KiB in size.
I might be wrong but I interpret both Naruko post and txt as the fact that the external ROM is 32K and it contains the 16K data repeated twice. This happened in a lot of cases if the manufacturer had e.g. a lot of spare 32K chips
Right before that, I'd written:
nesdevwiki wrote:both seen subcartridges only use a 32KiB EPROM
I'm uncertain how to better phrase this, given the rapid string of numbers. If anything, the 32KiB point feels like a distraction: there's 16KiB of data, manually mirrored once to fill 32KiB, automatically mirrored four times to fill 128KiB.
etabeta wrote:
nesdevwiki wrote:The external ROM is only readable while the timer has not expired; once it has, reads should return open bus.
You put this part in the section of the $6000 register, which could make it sound as if the ROM is read through $6000 while the timer is on and open bus when it's expired.
but if I read it correctly you mean that once the timer has expired it is address range $8000-$bfff which should return open bus (until the game possibly writes bit4 at $8000). is this correct?

Also, the doc does not seem to say what reads from $6000 would return while the game is accessing Sunsoft-6 and hence WRAM is disabled, which I'd assume it's open bus...
You assumed correctly in both cases; I've updated the wiki to make those points clearer.
User avatar
naruko
Posts: 64
Joined: Mon Feb 09, 2009 9:10 am
Location: リムルダール Rimuldar
Contact:

Re: SUNSOFT-4 and SUNSOFT-6

Post by naruko »

It is difficult to explain for me. \(^o^)/
I write a pseudo (weird?) source code.

Code: Select all

static unknown_range sunsoft6_timer_value = 0; //It is disabled when the power is turned on
static uint1_t sunsoft4_workram_enable;
static uint4_t sunsoft4_cpubank0_page;

//I don't know detail behave for the timer 
void m2_clock_raise_or_fall(void)
{
	if(sunsoft6_timer_value != 0){
		sunsoft6_timer_value += 1;
	}
}

static uint8_t read_6000_7fff(uint13_t address)
{
	if(sunsoft4_workram_enable == 1){
		return workram[address];
	}else{
		return OPENBUS;
	}
}

//switchable bank
static uint8_t read_8000_bfff(uint14_t cpu_address)
{
	uint17_t rom_address = {sunsoft4_cpubank0_page[2:0], cpu_address};
	if(sunsoft4_cpubank_page[3] == 1){ //Main ROM is not effected by SUNSOFT-6
		return maincartrom[rom_address];
	}else if(sunsoft4_cpubank_page[3] == 0 && sunsoft6_timer_value != 0){
		return subcartrom[rom_address];
	}
	return OPENBUS;
}

//fixed bank
static uint8_t read_c000_ffff(uint14_t address)
{
	return maincartrom[{3'b111, address}];
}

uint8_t cpu_read_cartridge(uint16_t address)
{
	switch(address[15:12]){
	case 6: case 7:
		return read_6000_7fff(address[12:0]);
	case 8: case 9: case 0xa: case 0xb:
		return read_8000_bfff(address[13:0]);
	case 0xc: case 0xd: case 0xe: case 0xf:
		return read_c000_ffff(address[13:0]);
	}
	return OPENBUS;
}

static void write_6000_7fff(uint13_t address, uint8_t data)
{
	if(sunsoft4_workram_enable == 1){
		workram[address] = data;
	}else{
		sunsoft6_timer_value = TIMER_INTITIAL_VALUE;
	}
}

static void write_f000_ffff(uint8_t data)
{
	sunsoft4_workram_enable = data[4];
	sunsoft4_cpubank_page[3:0] = data[3:0];
}

void cpu_write_cartridge(uint16_t address, uint8_t data)
{
	switch(address[15:12]){
	case 6: case 7:
		write_6000_7fff(address[12:0], data);
		break;
	case 0xf:
		write_f000_ffff(data)
		break;
	case .... //snip
	}

}
etabeta
Posts: 109
Joined: Wed Nov 29, 2006 10:11 am
Location: Trieste, Italy

Re: SUNSOFT-4 and SUNSOFT-6

Post by etabeta »

thanks a lot. your reply explained all I needed to know :)
Post Reply