How do we install the VRC6 Konami Sound Chip Software into other NES games?

Started by Thanatos-Zero, January 20, 2012, 06:36:03 PM

Previous topic - Next topic

Thanatos-Zero

How do we install the VRC6 Konami Chip Sound Software into other NES games? For example how do we install it in the very old Final Fantasy and Rockman games without to mess up the other data inside?

Just to let you know, I am not asking this for myself but on my own volition for Lugia2009 and other musicans with their respective knowledge about programming and hacking games. Since I know only binary with their values and such with the ability to change colours in GBA games, I won't be able to understand the complex structure behind these programs (I still would love to know how I could tell in binary the computer precise orders, but that will come later someday).

Bregalad

I don't think that what you want to do is possible.
Games were made with or without the chip. The chip can't be "installed" in a game.

Thanatos-Zero

So... There is no way to exchange the music engine with an different one? That is absurd.
I thought that programmers had only to adjust the order of executions in the data banks after the installation so that it works flawlessly.

Anyway, I have seen things with Rockman 4 Minus Infinity, which I thought to be impossible.

Guys, you are masters of your abilities. Show me and the others your best shot.

Gideon Zhi

It's not just a music engine, it's an entire mapper chip. NES games are built around their mappers, and while some mappers have similar hardware functions to others, the VRC6 is not one of them. It might be POSSIBLE but you're talking about basically reprogramming a lot of the game's core memory logic.

Thanatos-Zero

I see, but how about to expand and upgrade the mappers in the older games, so that they can do as much like the newer ones?
Example: Expand the ROM, add new databanks with scripts based on the newer mapper, make the approciate executions to connect the older mapper with the said databanks.

It is basically simple to understand how chains of orders are working, but to give the computer orders in binary is a different thing, because you have to know how to talk with it.

Gideon Zhi

What you're talking about is basically designing a new mapper, which would have to be implemented at the emulator level as well as at the rom level. Good luck getting the emulator authors to support your fictional hardware!

Thanatos-Zero

It was just a idea, also I didn't know that it would require an new emulator for this new mapper.

So.. How do we modify for example the FF7 nes ROM of Lugia2009 this way, that it produces sounds like Coatlesscarl's famitrack soundtracks? Rebuilt the game around the new mapper?

Bregalad

What you're trying to describe is a mapper hack, that is change a game to use a different mapper. This is sometimes possible but not always, depending on the bankswitching possibilities.

Even if you changed any random game to VRC6 mapper, the music won't magically use the extra VRC6 channels to expand itself ! I don't know if it's me but it sounds like it's what you're thinking.

Thanatos-Zero

Of course, the two additional sound channels won't be in use, because they were no orders assigned to them yet, if we were going the path to rebuilt the game around the VRC6.
The soundtrack must be expanded as well obviously, otherwise there won't be any additional sounds to hear.


It is too bad, that I am not able to do it for Lugia2009, but if you don't know how to give the computer orders via binary code, there is no chance to understand the system behind it, except that I can see values like 10010011 is equal to 147 or 93 in hex.

Bregalad

Yeah you pretty much got it.
Hacking some game to use VRC6 mapper is possible (depending on the old mapper it uses), you just need some free space in the ROM and override old mapper writes with new ones.

But there is no way you can easily hack the sound engine to add 2 or 3 extra channels (I think the VRC6 has 3 extra channels). In fact you might hack the game to use the VRC6 channels instead of the normal ones, this is very possible. But if you want to use all channels (both 2A03 and VRC6) then you'll have to do a major hack of the existing sound engine or to completely replace it with your own, and in both cases you'll need much more RAM because more channels imply more RAM. And also it'd take much more ROM to store sequence data for the extra channels ! So if by luck the game in question has a LOT of free RAM and ROM space then it's possible but not trivial to do.

Also you could use the extra SRAM in a game that didn't use it for extra RAM, and expand the ROM for extra ROM. So yeah this is possible to do, but definitely one of the most complex hack one could think of.

Jorpho

Of course, if you don't care that the hack would probably never, ever run on NES hardware, you could probably do something with Lua scripting in FCEUX that would play an alternative soundtrack.

(Someone should probably upload Rockman 4 Minus Infinity to this site.)
This signature is an illusion and is a trap devisut by Satan. Go ahead dauntlessly! Make rapid progres!

Sliver X

Disch converted Castlevania to VRC6 years ago, and yeah, he had to code his own sound engine to implement the extra channels. There were also various technical issues he had to work with due to using a new MMC.

I wish I still had a copy of that: I was using said new sound engine in conjunction with CV's standard one (They seemed to be two distinct engines running at the same time, though I'm not sure how it worked at the sound engine code level...) to compose music for a now dead hack that was going to be based on this particular ROM.

So yeah, it's possible, but it's a very advanced hack to pull off. Most certainly deep knowledge of the NES hardware and target mappers is needed: Disch wrote a rather good NES emulator, so he knows a lot about such things.

Thanatos-Zero

@Silver X
Do you know someone other than Disch, who can do the same like him? Disch is out of question, because he told me many months ago that he has problems to deal with in Real Life. I do not know, if he got over it by now.

optomon

I might actually have a copy of that said version Castlevania somewhere which happened to be in a large backup file I made some years ago. Or maybe it's just some random expansion of Castlevania, I can't remember.

Karatorian

If you're interested in mapper hacking specific games to VRC6, I could probably manage the technical end of things. If the game's existing mapper code isn't too complicated (or the mappers incompatible), it shouldn't be too much work. However, enhancing the music engine of a particular game is more work. I could probably transplant an existing music engine in, but writing one from scratch or extending the existing one isn't something I'd be interested in doing unless it was a project I was personally involved in.

So, do you have anything specific in mind? And what music playback engine where you looking to use?
Current ProjectsFinal Fantasy EngineSMB Special for NESStudio Karatorian
@loop: lda (src),y — sta (dst),y — iny — bne @loop — inc src+1 — inc dst+1 — dex — bne @loop

Lugia2009

It's for final fantasy VII famicom and it uses mapper 163, here's what I could find about the mapper.


//////////////////////////////////////////////////////////////////////////
//           Mapper163  NanJing Games (NES Chinese RPR game)            //
//////////////////////////////////////////////////////////////////////////

void   Mapper163::Reset()
{
   reg[1] = 0xFF;
   strobe = 1;
   security = trigger = reg[0] = 0x00;
   SetPROM_32K_Bank(15);
   SetCRAM_8K_Bank(0);
}

BYTE Mapper163::ReadLow( WORD addr )
{
   if((addr>=0x5000 && addr<0x6000))
   {
      switch (addr & 0x7700)
      {
         case 0x5100:
               return security;
               break;
         case 0x5500:
               if(trigger)
                  return security;
               else
                  return 0;
               break;
      }
      return 4;
   }
   else if( addr>=0x6000 ) {
      return   CPU_MEM_BANK[addr>>13][addr&0x1FFF];
   }
   return 0;
}

void Mapper163::WriteLow(WORD addr, BYTE data)
{
   if((addr>=0x4020 && addr<0x6000))
   {
      if(addr==0x5101){
         if(strobe && !data){
            trigger ^= 1;
         }
         strobe = data;
      }else if(addr==0x5100 && data==6){
         SetPROM_32K_Bank(3);
      }
      else{
         switch (addr & 0x7300)
         {
            case 0x5000:
                  reg[1]=data;
                  SetPROM_32K_Bank( (reg[1] & 0xF) | (reg[0] << 4) );
                  if(!(reg[1]&0x80)&&(nes->ppu->GetScanlineNo()<128))
                     SetCRAM_8K_Bank(0);
                  break;
            case 0x5200:
                  reg[0]=data;
                  SetPROM_32K_Bank( (reg[1] & 0xF) | (reg[0] << 4) );
                  break;
            case 0x5300:
                  security=data;
                  break;
         }
      }
   }
   else if( addr>=0x6000 ) {
      CPU_MEM_BANK[addr>>13][addr&0x1FFF] = data;
   }
}

void   Mapper163::HSync(int scanline)
{
   if( (reg[1]&0x80) && nes->ppu->IsDispON() ) {
      if(scanline==127){
         SetCRAM_4K_Bank(0, 1);
         SetCRAM_4K_Bank(4, 1);
      }
      if(scanline==239){
         SetCRAM_4K_Bank(0, 0);
         SetCRAM_4K_Bank(4, 0);
      }
   }
}

void   Mapper163::SaveState( LPBYTE p )
{
   p[0] = reg[0];
   p[1] = reg[1];
}

void   Mapper163::LoadState( LPBYTE p )
{

   reg[0] = p[0];
   reg[1] = p[1];
}


Code:

/*************************************************************

Bootleg Board by Nanjing

Games: A lot of pirate originals

iNES: mapper 163

In MESS: Unsupported.

*************************************************************/

static void nanjing_irq( device_t *device, int scanline, int vblank, int blanked )
{
   nes_state *state = device->machine().driver_data<nes_state>();

   if (BIT(state->m_mmc_reg[0], 7))
   {
      if (scanline == 127)
      {
         chr4_0(device->machine(), 1, CHRRAM);
         chr4_4(device->machine(), 1, CHRRAM);
      }

      if (scanline == 239)
      {
         chr4_0(device->machine(), 0, CHRRAM);
         chr4_4(device->machine(), 0, CHRRAM);
      }
   }

}

static WRITE8_HANDLER( nanjing_l_w )
{
   nes_state *state = space->machine().driver_data<nes_state>();
   LOG_MMC(("nanjing_l_w, offset: %04x, data: %02x\n", offset, data));

   offset += 0x100;

   if (offset < 0x1000)
      return;

   if (offset == 0x1100)   // 0x5100
   {
      if (data == 6)
         prg32(space->machine(), 3);
      return;
   }

   if (offset == 0x1101)   // 0x5101
   {
      UINT8 temp = state->m_mmc_count;
      state->m_mmc_count = data;

      if (temp & !data)
         state->m_mmc_latch2 ^= 0xff;
   }

   switch (offset & 0x300)
   {
      case 0x000:
      case 0x200:
         state->m_mmc_reg[BIT(offset, 9)] = data;
         if (!BIT(state->m_mmc_reg[0], 7) && ppu2c0x_get_current_scanline(state->m_ppu) <= 127)
            chr8(space->machine(), 0, CHRRAM);
         break;
      case 0x300:
         state->m_mmc_latch1 = data;
         break;
   }

   prg32(space->machine(), (state->m_mmc_reg[0] & 0x0f) | ((state->m_mmc_reg[1] & 0x0f) << 4));
}

static READ8_HANDLER( nanjing_l_r )
{
   nes_state *state = space->machine().driver_data<nes_state>();
   UINT8 value = 0;
   LOG_MMC(("nanjing_l_r, offset: %04x\n", offset));

   offset += 0x100;

   if (offset < 0x1000)
      return 0;

   switch (offset & 0x700)
   {
      case 0x100:
         value = state->m_mmc_latch1;
         break;
      case 0x500:
         value = state->m_mmc_latch2 & state->m_mmc_latch1;
         break;
      case 0x000:
      case 0x200:
      case 0x300:
      case 0x400:
      case 0x600:
      case 0x700:
         value = 4;
         break;
   }
   return value;


Not sure what it all means though...

Do you think it could be done?