f000 count = count & 0x00FF | data ^ 0xFF <<8lidnariq wrote:How did you implement the IRQ?zxbdragon wrote:emu....Failure
f008 enabled = data &0x01;
clock:
count=(count-1)&0xFFFF;
return count<enabled;
Moderator: Moderators
f000 count = count & 0x00FF | data ^ 0xFF <<8lidnariq wrote:How did you implement the IRQ?zxbdragon wrote:emu....Failure
not working!lidnariq wrote:Flipping around the direction it counts makes that more confusing...
I'm probably making mistakes, but at the very least, you'd need to add:
f008 enabled = data & 0x01; if (!enabled) { count |= 0xFF }
clock: if (enabled) {count--; }
and that's probably still missing something.
I'd personally do this with two unsigned 8-bit types instead of trying to stuff both into the same 16-bit integer:
WF000: count = data;
WF008: enabled = (data & 1); if (!enabled) { prescaler = 0; }
M2: if (enabled) { prescaler++; if (0x80 == (prescaler & 0xFF)) { count++ }}
IRQ: if (enabled && 0xFF == count && prescaler < 128) return ASSERTED;
If it helps, I tried to dump the game with mapper 22 option of TapeDump and got wrong CHR ROM.krzysiobal wrote:I wonder what would happen if the whole additional IRQ circuitry from the Gremlins2 would be removed and its DIL40 chip would be changed into AX5208C.
Code: Select all
#include "mapinc.h"
static int prg[2];
static int mirr;
static int chr[8];
static int counter;
static int counting_enabled;
static int m2_prescaler;
static int first_phase;
static int counterchanged;
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 int vrc_addr_mix(int A) {
//this game wires A0 to VRC_A0 and A1 to VRC_A1
return (A & 0xf000) | shi(A, 2, 0) | shi(A, 3, 1);
}
static void M273IRQHook(int a) {
if (counting_enabled) {
m2_prescaler += a;
if (m2_prescaler >= (first_phase ? 128 : 256)) {
first_phase = 0;
m2_prescaler -= (first_phase ? 128 : 256);
counter++;
counterchanged=1;
}
else {
counterchanged=0;
}
if (counterchanged) {
if (counter >= 256) {
counter -= 256;
X6502_IRQBegin(FCEU_IQEXT);
}
else {
X6502_IRQEnd(FCEU_IQEXT);
}
}
}
}
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 (mirr) {
case 0: setmirror(MI_V); break;
case 1: setmirror(MI_H); break;
}
}
static DECLFW(M273Write) {
//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;
}
switch (A & 0xf00c) {
case 0xf000: counter = V; X6502_IRQEnd(FCEU_IQEXT); break;
case 0xf008: if ((V & 1) == 0) {counting_enabled = 0; m2_prescaler = 0; first_phase = 1; X6502_IRQEnd(FCEU_IQEXT);}
else {counting_enabled = 1; }
break;
}
Sync();
}
static void M273Power(void) {
SetWriteHandler(0x8000, 0xFFFF, M273Write);
SetReadHandler(0x8000, 0xFFFF, CartBR);
Sync();
counter = 0;
}
static void M273Reset(void) {
counter = 0;
Sync();
}
void Mapper273_Init(CartInfo *info) {
info->Power = M273Power;
info->Reset = M273Reset;
MapIRQHook = M273IRQHook;
AddExState(&StateRegs, ~0, 0, 0);
}
O_okrzysiobal wrote:Lidnariq - could you explain why when writing 0 to $f00c, IRQ is deasserted?
(embarrassed) I'd made a UNIF image for testing and forgot to include a MIRR block.krzysiobal wrote:Maybe you have something wrong in iNES header in ROM, because this game does not even user IRQ at title screen and in game (first time it does is the shop screen).
Oh, right, duh. That's why my example didn't work; FCEUX doesn't give a callback on every M2 cycle, but instead a number of M2 cycles to advance. I need to do something silly like ((m2_prescaler + a)& 128 ) && !(m2_prescaler&128) to detect the edge.krzysiobal wrote: m2_prescaler += a;