games/nes: added dmc, fixed envelope, added cnrom
This commit is contained in:
parent
60c3c3b3db
commit
76b51dc816
6 changed files with 139 additions and 25 deletions
|
@ -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,
|
||||||
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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){
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue