games/nes: added dmc, fixed envelope, added cnrom

This commit is contained in:
aiju 2014-02-24 22:50:05 +01:00
parent 60c3c3b3db
commit 76b51dc816
6 changed files with 139 additions and 25 deletions

View file

@ -7,7 +7,17 @@
enum { MAXBUF = 2000 }; enum { MAXBUF = 2000 };
u8int apuseq, apuctr[10]; enum {
LEN = 0,
ENV = 4,
TRILIN = 6,
SWEEP = 8,
RELOAD = 10,
DMCCTR = 11,
DMCSHFT = 12,
};
u8int apuseq, apuctr[13];
u16int dmcaddr, dmccnt;
static int fd; static int fd;
static short sbuf[2*MAXBUF], *sbufp; static short sbuf[2*MAXBUF], *sbufp;
@ -41,10 +51,10 @@ declen(void)
m >>= 2; m >>= 2;
if((m & 0x20) != 0) if((m & 0x20) != 0)
continue; continue;
if(apuctr[i] != 0) if(apuctr[LEN + i] != 0)
apuctr[i]--; apuctr[LEN + i]--;
} }
for(i = 0, a = apuctr + 8; i < 2; i++, a++){ for(i = 0, a = apuctr + SWEEP; i < 2; i++, a++){
m = mem[0x4001 + i * 4]; m = mem[0x4001 + i * 4];
if((m & 0x80) != 0 && (m & 0x07) != 0 && (*a & 7) == 0){ if((m & 0x80) != 0 && (m & 0x07) != 0 && (*a & 7) == 0){
p = targperiod(i); p = targperiod(i);
@ -66,19 +76,23 @@ doenv(void)
int i, m; int i, m;
u8int *a; u8int *a;
for(i = 0, a = apuctr + 4; i < 4; i++, a++){ for(i = 0, a = apuctr + ENV; i < 4; i++, a++){
if(i == 2) if(i == 2)
continue; continue;
m = mem[0x4000 + 4 * i]; m = mem[0x4000 + 4 * i];
if((*a & 0x80) != 0) if((apuctr[RELOAD] & (1<<i)) != 0)
*a = *a & 0x70 | 0x0f; *a = 0xf0 | m & 0x0f;
else if(*a == 0){ else if((*a & 0x0f) == 0){
if((m & 0x20) != 0) *a |= m & 0x0f;
*a |= 0x0f; if((*a & 0xf0) == 0){
if((m & 0x20) != 0)
*a |= 0xf0;
}else
*a -= 0x10;
}else }else
(*a)--; (*a)--;
} }
a = apuctr + 6; a = apuctr + TRILIN;
if((*a & 0x80) != 0) if((*a & 0x80) != 0)
*a = mem[0x4008]; *a = mem[0x4008];
else if(*a != 0) else if(*a != 0)
@ -143,11 +157,10 @@ pulse(int i)
c[i]++; c[i]++;
m = mem[0x4000 + 4 * i]; m = mem[0x4000 + 4 * i];
if((m & 0x10) != 0) if((m & 0x10) != 0)
s = m; s = m & 0x0f;
else else
s = apuctr[i+4]; s = apuctr[ENV + i] >> 4;
s &= 0x0f; if(c[i] >= f/2 || apuctr[LEN + i] == 0)
if(c[i] >= f/2 || apuctr[i] == 0)
s = 0; s = 0;
return s; return s;
} }
@ -168,7 +181,7 @@ tri(void)
c++; c++;
i = 32 * c / f; i = 32 * c / f;
i ^= (i < 16) ? 0xf : 0x10; i ^= (i < 16) ? 0xf : 0x10;
if(apuctr[2] == 0 || (apuctr[6] & 0x7f) == 0) if(apuctr[LEN + 2] == 0 || (apuctr[TRILIN] & 0x7f) == 0)
return 0; return 0;
return i; return i;
} }
@ -191,18 +204,18 @@ noise(void)
r >>= 1; r >>= 1;
c -= f; c -= f;
} }
if(apuctr[3] == 0 || (r & 1) != 0) if(apuctr[LEN + 3] == 0 || (r & 1) != 0)
return 0; return 0;
m = mem[0x400C]; m = mem[0x400C];
if((m & 0x10) != 0) if((m & 0x10) != 0)
return m & 0xf; return m & 0xf;
return apuctr[7] & 0xf; return apuctr[ENV + 3] >> 4;
} }
static int static int
dmc(void) dmc(void)
{ {
return 0; return mem[DMCBUF];
} }
void void
@ -220,6 +233,40 @@ audiosample(void)
} }
} }
void
dmcstep(void)
{
if((apuctr[DMCCTR] & 7) == 0){
apuctr[DMCCTR] = 8;
if(dmccnt != 0){
apuctr[DMCSHFT] = memread(dmcaddr);
if(dmcaddr == 0xFFFF)
dmcaddr = 0x8000;
else
dmcaddr++;
if(--dmccnt == 0){
if((mem[DMCCTRL] & 0x40) != 0){
dmcaddr = mem[DMCADDR] * 0x40 + 0xC000;
dmccnt = mem[DMCLEN] * 0x10 + 1;
}else if((mem[DMCCTRL] & 0x80) != 0)
irq |= IRQDMC;
}
}else
apuctr[DMCCTR] |= 0x80;
}
if((apuctr[DMCCTR] & 0x80) == 0){
if((apuctr[DMCSHFT] & 1) != 0){
if(mem[DMCBUF] < 126)
mem[DMCBUF] += 2;
}else{
if(mem[DMCBUF] > 1)
mem[DMCBUF] -= 2;
}
}
apuctr[DMCSHFT] >>= 1;
apuctr[DMCCTR]--;
}
int int
audioout(void) audioout(void)
{ {
@ -252,3 +299,8 @@ u8int apulen[32] = {
0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16, 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E, 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E,
}; };
u16int dmclen[16] = {
0x1AC, 0x17C, 0x154, 0x140, 0x11E, 0x0FE, 0x0E2, 0x0D6,
0x0BE, 0x0A0, 0x08E, 0x080, 0x06A, 0x054, 0x048, 0x036,
};

View file

@ -10,9 +10,10 @@ extern int map, scale, mmc3hack, oflag;
extern uchar *prg, *chr; extern uchar *prg, *chr;
extern int nprg, nchr, map, chrram; extern int nprg, nchr, map, chrram;
extern u8int apuseq, apuctr[10]; extern u8int apuseq, apuctr[13];
extern u16int dmcaddr, dmccnt;
extern int keys, clock, ppuclock, apuclock, saveclock, paused; extern int keys, clock, ppuclock, apuclock, dmcclock, dmcfreq, saveclock, paused;
extern void (*mapper[])(int, u8int); extern void (*mapper[])(int, u8int);
@ -31,6 +32,10 @@ enum {
PPUMASK = 0x2001, PPUMASK = 0x2001,
PPUSTATUS = 0x2002, PPUSTATUS = 0x2002,
PPUSCROLL = 0x2005, PPUSCROLL = 0x2005,
DMCCTRL = 0x4010,
DMCBUF = 0x4011,
DMCADDR = 0x4012,
DMCLEN = 0x4013,
APUSTATUS = 0x4015, APUSTATUS = 0x4015,
APUFRAME = 0x4017, APUFRAME = 0x4017,

View file

@ -13,3 +13,4 @@ void apustep(void);
void initaudio(void); void initaudio(void);
void audiosample(void); void audiosample(void);
int audioout(void); int audioout(void);
void dmcstep(void);

View file

@ -167,6 +167,40 @@ uxrom(int p, u8int v)
prgb[0] = prg + b * 0x4000; prgb[0] = prg + b * 0x4000;
} }
static void
cnrom(int p, u8int v)
{
static u8int b;
if(p < 0)
switch(p){
case INIT:
prgsh = 14;
chrsh = 13;
prgb[0] = prg;
if(nprg == 1)
prgb[1] = prg;
else
prgb[1] = prg + 0x4000;
break;
case SAVE:
put8(b);
return;
case RSTR:
b = get8();
break;
case SCAN:
return;
default:
nope(p);
return;
}
else
b = v % nchr;
chrb[0] = chr + b * 0x2000;
}
static void static void
mmc3(int p, u8int v) mmc3(int p, u8int v)
{ {
@ -289,6 +323,7 @@ void (*mapper[256])(int, u8int) = {
[0] nrom, [0] nrom,
[1] mmc1, [1] mmc1,
[2] uxrom, [2] uxrom,
[3] cnrom,
[4] mmc3, [4] mmc3,
[7] axrom, [7] axrom,
}; };
@ -368,6 +403,7 @@ void
memwrite(u16int p, u8int v) memwrite(u16int p, u8int v)
{ {
extern u8int apulen[32]; extern u8int apulen[32];
extern u16int dmclen[16];
int i; int i;
if(p < 0x2000){ if(p < 0x2000){
@ -422,9 +458,17 @@ memwrite(u16int p, u8int v)
i = (p & 0xC) >> 2; i = (p & 0xC) >> 2;
if((mem[APUSTATUS] & (1<<i)) != 0){ if((mem[APUSTATUS] & (1<<i)) != 0){
apuctr[i] = apulen[v >> 3]; apuctr[i] = apulen[v >> 3];
apuctr[i+4] |= 0x80; apuctr[10] |= (1<<i);
} }
break; break;
case DMCCTRL:
if((v & 0x80) == 0)
irq &= ~IRQDMC;
dmcfreq = 12 * dmclen[v & 0xf];
break;
case DMCBUF:
v &= ~0x80;
break;
case 0x4014: case 0x4014:
memcpy(oam, mem + (v<<8), sizeof(oam)); memcpy(oam, mem + (v<<8), sizeof(oam));
return; return;
@ -432,6 +476,10 @@ memwrite(u16int p, u8int v)
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
if((v & (1<<i)) == 0) if((v & (1<<i)) == 0)
apuctr[i] = 0; apuctr[i] = 0;
if((v & 0x10) != 0 && dmccnt == 0){
dmcaddr = mem[DMCADDR] * 0x40 + 0xC000;
dmccnt = mem[DMCLEN] * 0x10 + 1;
}
irq &= ~IRQDMC; irq &= ~IRQDMC;
break; break;
case 0x4016: case 0x4016:

View file

@ -13,7 +13,7 @@ uchar *prg, *chr;
int scale; int scale;
Rectangle picr; Rectangle picr;
Image *tmp, *bg; Image *tmp, *bg;
int clock, ppuclock, apuclock, sampclock, msgclock, saveclock; int clock, ppuclock, apuclock, dmcclock, dmcfreq, sampclock, msgclock, saveclock;
Mousectl *mc; Mousectl *mc;
int keys, paused, savereq, loadreq, oflag, savefd = -1; int keys, paused, savereq, loadreq, oflag, savefd = -1;
int mirr; int mirr;
@ -230,6 +230,7 @@ threadmain(int argc, char **argv)
pc = memread(0xFFFC) | memread(0xFFFD) << 8; pc = memread(0xFFFC) | memread(0xFFFD) << 8;
rP = FLAGI; rP = FLAGI;
dmcfreq = 12 * 428;
for(;;){ for(;;){
if(savereq){ if(savereq){
savestate("nes.save"); savestate("nes.save");
@ -248,8 +249,7 @@ threadmain(int argc, char **argv)
ppuclock += t; ppuclock += t;
apuclock += t; apuclock += t;
sampclock += t; sampclock += t;
//syncclock += t; dmcclock += t;
//checkclock += t;
while(ppuclock >= 4){ while(ppuclock >= 4){
ppustep(); ppustep();
ppuclock -= 4; ppuclock -= 4;
@ -262,6 +262,10 @@ threadmain(int argc, char **argv)
audiosample(); audiosample();
sampclock -= SAMPDIV; sampclock -= SAMPDIV;
} }
if(dmcclock >= dmcfreq){
dmcstep();
dmcclock -= dmcfreq;
}
if(msgclock > 0){ if(msgclock > 0){
msgclock -= t; msgclock -= t;
if(msgclock <= 0){ if(msgclock <= 0){

View file

@ -94,6 +94,8 @@ loadstate(char *file)
ppuclock = get32(); ppuclock = get32();
apuclock = get32(); apuclock = get32();
apuseq = get8(); apuseq = get8();
dmcaddr = get16();
dmccnt = get16();
read(fd, apuctr, sizeof(apuctr)); read(fd, apuctr, sizeof(apuctr));
mapper[map](RSTR, 0); mapper[map](RSTR, 0);
close(fd); close(fd);
@ -133,6 +135,8 @@ savestate(char *file)
put32(ppuclock); put32(ppuclock);
put32(apuclock); put32(apuclock);
put8(apuseq); put8(apuseq);
put16(dmcaddr);
put16(dmccnt);
write(fd, apuctr, sizeof(apuctr)); write(fd, apuctr, sizeof(apuctr));
mapper[map](SAVE, 0); mapper[map](SAVE, 0);
close(fd); close(fd);