It is currently Sun Dec 10, 2017 5:29 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5
Author Message
PostPosted: Thu Jan 19, 2017 2:46 pm 
Offline
User avatar

Joined: Fri Feb 27, 2009 2:35 pm
Posts: 215
Location: Fort Wayne, Indiana
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.


Top
 Profile  
 
PostPosted: Sun Oct 08, 2017 6:00 pm 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 254
Location: Poland
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


Top
 Profile  
 
PostPosted: Sun Oct 08, 2017 6:12 pm 
Offline
User avatar

Joined: Sat Jul 04, 2015 9:58 am
Posts: 583
Location: -29.794229 -55.795374
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.


Top
 Profile  
 
PostPosted: Wed Oct 11, 2017 10:17 am 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 254
Location: Poland
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)


Top
 Profile  
 
PostPosted: Wed Oct 11, 2017 3:48 pm 
Offline
User avatar

Joined: Sat Jul 04, 2015 9:58 am
Posts: 583
Location: -29.794229 -55.795374
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?


Top
 Profile  
 
PostPosted: Wed Oct 11, 2017 4:32 pm 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 254
Location: Poland
Quote:
Do your ROMs have the same content as mine?

Yes


Top
 Profile  
 
PostPosted: Wed Oct 11, 2017 6:30 pm 
Offline

Joined: Mon Dec 12, 2011 8:15 pm
Posts: 361
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信息,我会尝试。


Top
 Profile  
 
PostPosted: Thu Oct 12, 2017 4:25 pm 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 254
Location: Poland
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);
}



Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5

All times are UTC - 7 hours


Who is online

Users browsing this forum: Bing [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group