nesdev.com
http://forums.nesdev.com/

Pirate Kid Dracula reverse engineering
http://forums.nesdev.com/viewtopic.php?f=9&t=15302
Page 5 of 5

Author:  NovaSquirrel [ Thu Jan 19, 2017 2:46 pm ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

lidnariq wrote:
This should be titled "How the MMC5's scanline timer works"

Wasn't it confirmed in this thread that the MMC5 watches for multiple reads from the same address in a row? That's way different from this description.

Author:  krzysiobal [ Sun Oct 08, 2017 6:00 pm ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

I am in possesion of the famicom bootleg version:
Image Image Image Image

PAL must be quite different at least in pinout. I am in process of creating my own utility for dumping pals (it will autodetect input/outputs, if pal is combinatory or not, all inputs will be fed not in natural binary code but using gray code to minimize hazards and there will be option for manually toggling pins in order to discover new features)
Image Image Image Image Image Image

Author:  Fisher [ Sun Oct 08, 2017 6:12 pm ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

krzysiobal wrote:
I am in process of creating my own utility for dumping pals

That's great!!
Would that be able to dump the N64 GameShark GAL? It's quite different from normal PAL ICs...
Maybe the SNES GameGenie could, since it seems more standard.

Author:  krzysiobal [ Wed Oct 11, 2017 10:17 am ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

I performed deep analysis of the PAL from my Kid Dracula version (for Famicom)
Image

Generally it agrees with what lidnariq said except one additional discovered register:
$800c - writing any value forces interrupt to be triggered

Here are equations for the chip:


Code:
O6 <= D0 when CPU-!ROMSEL=0 and R/!W=0 and A14=0 and A3=0 and A2=1; --latch

O5 <= D1 when CPU-!ROMSEL=0 and R/!W=0 and A14=0 and A3=0 and A2=1; --latch

02 <= 0 when CPU-!ROMSEL=0 and R/!W=0 and A14=1 and A3=1 and A2=1 else --latch
      1 when CPU-!ROMSEL=0 and R/!W=0 and A14=1 and A3=1 and A2=0;

!IRQ! <= 1 when CPU-!ROMSEL=0 and R/!W=0 and A14=1 and A3=0 and A2=1 else  --latch
         1 when CPU-!ROMSEL=0 and R/!W=0 and A14=1 and A3=1 and A2=1 else
         0 when (CPU-!ROMSEL!=1 or R/!W=1) and IRQ_PEN = 1 else
       0 when CPU-!ROMSEL=0 and R/!W=0 and A14=0 and A3=1 and A2=1
    
CLR <= not O2 or IRQ_PEN

CIRAM <= 0 when O6=0 and O5=1  else
       1 when 06=1 and 05=1  else
       VRC-CIRAM
         
      a a a  dddd dddd
      1 3 2  7654 3210
      4
     -----------------
$8004 0 0 1 [.... ..mm] mm - mirroring (source of ciram) (0/1: VRC-CIRAM, 2:GND, 3: VCC)
$800c 0 1 1 [.... ....] writing any value forces interrupt to be triggered
$c004 1 0 1 [.... ....] writing any value acknowledges pending interrupt
$c008 1 1 0 [.... ....] writing any value resets counter from clear
$c00c 1 1 1 [.... ....] writing any value holds counter in clear & acknowledges pending interrupt

* counter is automatically cleared when interrupt becomes pending
* interrupt is triggered when IRQ_PEN=1 and (CPU-!ROMSEL! = 1 or R/!W=1)

Author:  Fisher [ Wed Oct 11, 2017 3:48 pm ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

Great findings Krzysiobal!
Do your ROMs have the same content as mine?
CRC32
PRG: 6a50b553
CHR: c5d1196e (same as original)

Maybe this was the part of the puzzle that ZxbDragon was needing to finish it's implementation?

Author:  krzysiobal [ Wed Oct 11, 2017 4:32 pm ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

Quote:
Do your ROMs have the same content as mine?

Yes

Author:  zxbdragon [ Wed Oct 11, 2017 6:30 pm ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

Fisher wrote:
Great findings Krzysiobal!
Do your ROMs have the same content as mine?
CRC32
PRG: 6a50b553
CHR: c5d1196e (same as original)

Maybe this was the part of the puzzle that ZxbDragon was needing to finish it's implementation?


no finish,Krzysiobal info,I try.
没有成功,Krzysiobal信息,我会尝试。

Author:  krzysiobal [ Thu Oct 12, 2017 4:25 pm ]
Post subject:  Re: Pirate Kid Dracula reverse engineering

Of course FCEU has ability to track PPU bus, otherwise mappers like MMC2 would not be implemented.

I did my own mapper implementation for Pirate Kid Dracula and it works fine (just there is one quirk - when implementing counter at 86, status bar is switched too late, implementing at 84 seems to be most accurate (should be 83.5 because it is fired in middle of scanline, while in real hardware - almost at end)

Maybe you do it wrong because u assume that when counter reaches 86, it's clocking is stopped?
Analyzing the PAL - reaching 86 makes IRQ_PEN = 1 which makes
CLR <= not O2 or IRQ_PEN
equal to 1 and thus resets counter, but if counter is now reset, AND gate returns 0 (so IRQ_PEN=0) and then CLR=0 so counter is no longer being cleared, so it starts counting from beginning.

https://youtu.be/5hQucuRMnRQ

Code:
#include "mapinc.h"

static int prg[2];
static int mirr;
static int chr[8];
static int last_pa13;
static int counter;

static int pal_mirr;
static int counter_canclock;

static SFORMAT StateRegs[] =
{
   { 0 }
};


//shifts bit from position `bit` into position `pos` of expression `exp`
#define shi(exp, bit, pos) \
   ((((exp) & (1 << (bit))) >> (bit)) << (pos))

static void M272Hook(uint32 A) {
   int pa13 = (A >> 13) & 1;
   if ((last_pa13 == 1) && (pa13 == 0)) {
      if (counter_canclock) {
         counter++;
         if (counter == 84) {
            counter = 0;
            X6502_IRQBegin(FCEU_IQEXT);
         }
      }
   }
   last_pa13 = pa13;
}

static int vrc_addr_mix(int A) {
   //this game wires A0 to VRC_A0 and A1 to VRC_A1
   return (A & 0xf000) | shi(A, 0, 0) | shi(A, 1, 1);
}

static void Sync(void) {
   setprg8(0x8000, prg[0]);
   setprg8(0xa000, prg[1]);
   setprg16(0xc000, -1);   
   for (int i = 0; i < 8; ++i) {
      setchr1(0x400 * i, chr[i]);
   }
   
   switch (pal_mirr) {
   case 2: setmirror(MI_0); break;
   case 3: setmirror(MI_1); break;
   default:
      switch (mirr) {
      case 0: setmirror(MI_V); break;
      case 1: setmirror(MI_H); break;
      }
   }
}

static DECLFW(M272Write) {
   //writes to VRC chip
   switch (vrc_addr_mix(A)) {
   case 0x8000:
   case 0x8001:
   case 0x8002:
   case 0x8003:
      prg[0] = V;
      break;
   case 0xA000:
   case 0xA001:
   case 0xA002:
   case 0xA003:
      prg[1] = V;
      break;
   case 0x9000:
   case 0x9001:
   case 0x9002:
   case 0x9003:
      mirr = V & 1;
      break;
   case 0xb000: chr[0] = (chr[0] & 0xF0) | (V & 0xF); break;
   case 0xb001: chr[0] = (chr[0] & 0xF) | ((V & 0xF) << 4); break;
   case 0xb002: chr[1] = (chr[1] & 0xF0) | (V & 0xF); break;
   case 0xb003: chr[1] = (chr[1] & 0xF) | ((V & 0xF) << 4); break;
   case 0xc000: chr[2] = (chr[2] & 0xF0) | (V & 0xF); break;
   case 0xc001: chr[2] = (chr[2] & 0xF) | ((V & 0xF) << 4); break;
   case 0xc002: chr[3] = (chr[3] & 0xF0) | (V & 0xF); break;
   case 0xc003: chr[3] = (chr[3] & 0xF) | ((V & 0xF) << 4); break;
   case 0xd000: chr[4] = (chr[4] & 0xF0) | (V & 0xF); break;
   case 0xd001: chr[4] = (chr[4] & 0xF) | ((V & 0xF) << 4); break;
   case 0xd002: chr[5] = (chr[5] & 0xF0) | (V & 0xF); break;
   case 0xd003: chr[5] = (chr[5] & 0xF) | ((V & 0xF) << 4); break;
   case 0xe000: chr[6] = (chr[6] & 0xF0) | (V & 0xF); break;
   case 0xe001: chr[6] = (chr[6] & 0xF) | ((V & 0xF) << 4); break;
   case 0xe002: chr[7] = (chr[7] & 0xF0) | (V & 0xF); break;
   case 0xe003: chr[7] = (chr[7] & 0xF) | ((V & 0xF) << 4); break;
      
   default:
      break;
   }

   //writes to PAL chip
   switch (A & 0xC00C) {
   case 0x8004: pal_mirr = V & 3; break;
   case 0x800c: X6502_IRQBegin(FCEU_IQEXT); break;
   case 0xc004: X6502_IRQEnd(FCEU_IQEXT); break;
   case 0xc008: counter_canclock = 1; break;
   case 0xc00c: counter_canclock = 0; counter = 0; X6502_IRQEnd(FCEU_IQEXT); break;
   }

   Sync();
}

static void M272Power(void) {
   SetWriteHandler(0x8000, 0xFFFF, M272Write);
   SetReadHandler(0x8000, 0xFFFF, CartBR);
   Sync();
   
   last_pa13 = 0;
   counter = 0;
}

static void M272Reset(void) {
   last_pa13 = 0;
   counter = 0;
   Sync();
}

void Mapper272_Init(CartInfo *info) {
   info->Power = M272Power;
   info->Reset = M272Reset;
   PPU_hook = M272Hook;

   AddExState(&StateRegs, ~0, 0, 0);
}


Page 5 of 5 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/