metal combat chip question

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
fabrizio cabaleiro
Posts: 11
Joined: Thu Jul 03, 2008 11:52 pm
Location: chile

metal combat chip question

Post by fabrizio cabaleiro » Thu Sep 11, 2008 2:52 pm

HI

I have a METAL COMBAT cart, I read in the snes list that this cart has the FX chip, but, the chip that I see says:
4L01F1234
OBC1
NINTENDO
JAPAN 9204EAI

is this the FX chip?

thanks

User avatar
kyuusaku
Posts: 1665
Joined: Mon Sep 27, 2004 2:13 pm

Post by kyuusaku » Thu Sep 11, 2008 4:24 pm

Yes, it is the peripheral chip, but it is not a FX chip.

User avatar
MottZilla
Posts: 2832
Joined: Wed Dec 06, 2006 8:18 pm

Post by MottZilla » Thu Sep 11, 2008 5:30 pm

OBC-1 is a chip only used in Metal Combat. I've never heard specifically what it does but I imagine it helps with the very large and complex enemys you fight in the game compared to the first game, Battle Clash. Both are great games that I think are under appreciated since most people never played it with the Super Scope. I have and I think the games are fantastic.

byuu
Posts: 1539
Joined: Mon Mar 27, 2006 5:23 pm
Contact:

Post by byuu » Fri Sep 12, 2008 8:54 am

This is what the chip does:

Code: Select all

void OBC1::reset() {
  for(unsigned i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);

  status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
  status.address = (ram_read(0x1ff6) & 0x7f);
  status.shift   = (ram_read(0x1ff6) & 3) << 1;
}

uint8 OBC1::read(uint addr) {
  addr &= 0x1fff;
  if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);

  switch(addr) { default: //never used, avoids compiler warning
    case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
    case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
    case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
    case 0x1ff3: return ram_read(status.baseptr + (status.address << 2) + 3);
    case 0x1ff4: return ram_read(status.baseptr + (status.address >> 2) + 0x200);
    case 0x1ff5: case 0x1ff6: case 0x1ff7: return ram_read(addr);
  }
}

void OBC1::write(uint addr, uint8 data) {
  addr &= 0x1fff;
  if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);

  switch(addr) {
    case 0x1ff0: ram_write(status.baseptr + (status.address << 2) + 0, data); break;
    case 0x1ff1: ram_write(status.baseptr + (status.address << 2) + 1, data); break;
    case 0x1ff2: ram_write(status.baseptr + (status.address << 2) + 2, data); break;
    case 0x1ff3: ram_write(status.baseptr + (status.address << 2) + 3, data); break;
    case 0x1ff4: {
      uint8 temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
      temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
      ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
    } break;
    case 0x1ff5: {
      status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
      ram_write(addr, data);
    } break;
    case 0x1ff6: {
      status.address = (data & 0x7f);
      status.shift   = (data & 3) << 1;
      ram_write(addr, data);
    } break;
    case 0x1ff7: {
      ram_write(addr, data);
    } break;
  }
}
... and that's it. 100% bit-perfect emulation of the entire chip.

Mapping:

Code: Select all

void sBus::map_obc1() {
  map(MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, obc1);
  map(MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, obc1);
}
It's essentially a very, very simplistic save RAM mapper. It helps build OAM (sprite) tables in RAM (without the need for bit manipulation), that are then DMA'ed into OAM memory.

Honestly, it seems like a serious waste of an engineering effort. It should be a weekend project for an experienced programmer to remove the need for the chip entirely. That said, I'm not going to do it.

I think the biggest justification for it was the anti-piracy benefits.

fabrizio cabaleiro
Posts: 11
Joined: Thu Jul 03, 2008 11:52 pm
Location: chile

Post by fabrizio cabaleiro » Fri Sep 12, 2008 10:26 am

Thanks for the information
I have both games, battle clash and metal combat, but I don't have the Super Scope :(

User avatar
MottZilla
Posts: 2832
Joined: Wed Dec 06, 2006 8:18 pm

Post by MottZilla » Fri Sep 12, 2008 9:48 pm

Wow thanks byuu. Nice to know for sure what it does. Very interesting as well to hear that the chip is basically copy protection since it's not really doing anything that couldn't have been done standard.

If I actually understood what all what going on in that code I'd actually want to try to hack the game myself but I don't quite grasp what is going on. Personally I'd be more interested in knowing if it were feasible to hack the Cx4 games to run without the Cx4 chip. I know it is used for building OAM and some calculations and the wireframe business but I don't really think anything couldn't be done in software.

byuu
Posts: 1539
Joined: Mon Mar 27, 2006 5:23 pm
Contact:

Post by byuu » Sun Sep 14, 2008 7:16 am

The Cx4 is way more complicated. It does a bunch of 3D calculations and sprite sorting, some quite involved. Of course, given the SNES is turing complete, there's not really much you can't do on it. But implementing the full Cx4 in pure SNES ASM would prove much too slow, in my opinion.

The OBC-1 just makes writing sprite attributes easier. Probably helps because MC has some huge bosses, but I think with enough code optimization, you could avoid any visible slowdown and still remove the chip.

Post Reply