Update PPU to new version, correct a lot of bugs:

- Scanline counts was wrongPAL counts was wrong, correct some bugs in the plugins manager, remove a lot of warning
This commit is contained in:
godzil 2008-02-21 12:21:01 +00:00
parent bc118baac8
commit 5d3895f08a
33 changed files with 2674 additions and 2390 deletions

View File

@ -1,16 +1,17 @@
/** EMULib Emulation Library *********************************/
/** **/
/** SndUnix.c **/
/** **/
/** This file contains standard sound generation routines **/
/** for Unix using /dev/dsp and /dev/audio. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2002 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "Sound.h"
/*
* Allegro Sound Driver for EMULib Sound system - The TI-NESulator Project
* SndAlleg.C
*
* Created by Manoël Trapier
* Copyright 2003-2008 986 Corp. All rights reserved.
*
* $LastChangedDate: 2007-03-28 15:50:50 +0200 (mer, 28 mar 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/types.h $
* $Revision: 25 $
*
*/
#include <Sound.h>
#include <allegro.h>
@ -27,7 +28,6 @@
AUDIOSTREAM *stream;
static pthread_t ThreadID;
static int SoundFD;
static int SoundRate = 0;
static int MasterVolume = 64;
static int MasterSwitch = (1<<SND_CHANNELS)-1;
@ -41,7 +41,7 @@ static struct
int Freq; /* Channel frequency (Hz) */
int Volume; /* Channel volume (0..255) */
signed char *Data; /* Wave data (-128..127 each) */
const signed char *Data; /* Wave data (-128..127 each) */
int Length; /* Wave length in Data */
int Rate; /* Wave playback rate (or 0Hz) */
int Pos; /* Wave current position in Data */
@ -49,7 +49,7 @@ static struct
int Count; /* Phase counter */
} CH[SND_CHANNELS];
static void UnixSetWave(int Channel,signed char *Data,int Length,int Rate);
static void UnixSetWave(int Channel,const signed char *Data,int Length,int Rate);
static void UnixSetSound(int Channel,int NewType);
static void UnixDrum(int Type,int Force);
static void UnixSetChannels(int Volume,int Switch);
@ -89,6 +89,7 @@ static void *DSPLoop(void *Arg)
unsigned char *Buf;
register int J,I,K,L,M,N,L1,L2,A1,A2,V;
int FreqCount;
N = L = A2 = 0;
for(J=0;J<SND_CHANNELS;J++)
{
@ -252,7 +253,7 @@ static void *DSPLoop(void *Arg)
}
CH[J].Count=L1;
break;
case SND_TRIANGLE: /* Default Sound */
/* Do not allow frequencies that are too high */
if(CH[J].Freq>=SoundRate/3) break;
@ -262,7 +263,7 @@ static void *DSPLoop(void *Arg)
for(I=0;I<SND_BUFSIZE;I++)
{
L2=L1+K;
Wave[I]+= L1&0x2000?V:-V /*(L2&0x8000? V:0):(L2&0x8000? 0:-V)*/;
Wave[I]+= L1&0x8000?V:-V /*(L2&0x8000? V:0):(L2&0x8000? 0:-V)*/;
L1=L2;
}
CH[J].Count=L1;
@ -397,7 +398,7 @@ void UnixSetSound(int Channel,int NewType)
/** waveform to be an instrument or set it to the waveform **/
/** own playback rate. **/
/*************************************************************/
void UnixSetWave(int Channel,signed char *Data,int Length,int Rate)
void UnixSetWave(int Channel,const signed char *Data,int Length,int Rate)
{
if((Channel<0)||(Channel>=SND_CHANNELS)||(Length<=0)) return;

File diff suppressed because it is too large Load Diff

View File

@ -1,480 +1,482 @@
/** M6502: portable 6502 emulator ****************************/
/** **/
/** Debug.c **/
/** **/
/** This file contains the built-in debugging routine for **/
/** the 6502 emulator which is called on each 6502 step **/
/** when Trap!=0. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-1997 **/
/** Alex Krasivsky 1996 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
/*
* $LastChangedDate: 2007-04-19 18:18:57 +0200 (jeu, 19 avr 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/Debug.c $
* $Revision: 43 $
*/
#include "M6502.h"
#ifdef DEBUG
#include <allegro.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <ppu/ppu.h>
#include <Sound.h>
#define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
extern unsigned char *Memory;
void showlastop();
enum Addressing_Modes
{
Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
};
static byte *mn[] =
{
"adc ", "and ", "asl ", "bcc ", "bcs ", "beq ", "bit ", "bmi ",
"bne ", "bpl ", "brk", "bvc ", "bvs ", "clc", "cld", "cli",
"clv", "cmp ", "cpx ", "cpy ", "dec ", "dex", "dey", "inx",
"iny", "eor ", "inc ", "jmp ", "jsr ", "lda ", "nop ", "ldx ",
"ldy ", "lsr ", "ora ", "pha", "php", "pla", "plp", "rol ",
"ror ", "rti", "rts", "sbc ", "sta ", "stx ", "sty ", "sec ",
"sed", "sei", "tax", "tay", "txa", "tya", "tsx", "txs"
};
static byte ad[512] =
{
10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
};
/** DAsm() ****************************************************/
/** This function will disassemble a single command and **/
/** return the number of bytes disassembled. **/
/**************************************************************/
int DAsm(char *S, word A)
{
byte J;
word B, OP, TO;
B = A;
OP = Rd6502(B++) * 2;
switch (ad[OP + 1])
{
case Ac:
sprintf(S, "%s a", mn[ad[OP]]);
break;
case Il:
sprintf(S, "%s", mn[ad[OP]]);
break;
case Rl:
J = Rd6502(B++);
TO = A + 2 + ((J < 0x80) ? J : (J - 256));
sprintf(S, "%s $%04X", mn[ad[OP]], TO);
break;
case Im:
sprintf(S, "%s #$%02X", mn[ad[OP]], Rd6502(B++));
break;
case Zp:
sprintf(S, "%s $%02X", mn[ad[OP]], Rd6502(B++));
break;
case Zx:
sprintf(S, "%s $%02X,x", mn[ad[OP]], Rd6502(B++));
break;
case Zy:
sprintf(S, "%s $%02X,y", mn[ad[OP]], Rd6502(B++));
break;
case Ix:
sprintf(S, "%s ($%02X,x)", mn[ad[OP]], Rd6502(B++));
break;
case Iy:
sprintf(S, "%s ($%02X),y", mn[ad[OP]], Rd6502(B++));
break;
case Ab:
sprintf(S, "%s $%04X", mn[ad[OP]], RDWORD(B));
B += 2;
break;
case Ax:
sprintf(S, "%s $%04X,x", mn[ad[OP]], RDWORD(B));
B += 2;
break;
case Ay:
sprintf(S, "%s $%04X,y", mn[ad[OP]], RDWORD(B));
B += 2;
break;
case In:
sprintf(S, "%s ($%04X)", mn[ad[OP]], RDWORD(B));
B += 2;
break;
default:
sprintf(S, ".db $%02X; <Invalid OPcode>", OP / 2);
}
return (B - A);
}
/** Debug6502() **********************************************/
/** This function should exist if DEBUG is #defined. When **/
/** Trace!=0, it is called after each command executed by **/
/** the CPU, and given the 6502 registers. Emulation exits **/
/** if Debug6502() returns 0. **/
/*************************************************************/
byte Debug6502(M6502 * R)
{
static char FA[8] = "NVRBDIZC";
char S[128];
byte F;
int J, I;
DAsm(S, R->PC.W);
printf
(
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
);
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
printf("%c", F & 0x80 ? FA[J] : '.');
puts("]");
printf
(
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
Rd6502(R->PC.W), S,
Rd6502(0x0100 + (byte) (R->S + 1)),
Rd6502(0x0100 + (byte) (R->S + 2)),
Rd6502(0x0100 + (byte) (R->S + 3))
);
sprintf(S, "");
remove_keyboard();
#ifdef USE_SOUND
StopSound();
#endif
while (1)
{
printf("\n[Command,'?']-> ");
fflush(stdout);
fflush(stdin);
fgets(S, 50, stdin);
for (J = 0; S[J] >= ' '; J++)
S[J] = toupper(S[J]);
S[J] = '\0';
switch (S[0])
{
case 'H':
case '?':
puts("\n***** Built-in 6502 Debugger Commands *****");
puts("<CR> : Break at the next instruction");
puts("= <addr> : Break at addr");
puts("+ <offset> : Break at PC + offset");
puts("t <addr> : Set PC to addr");
puts("c : Continue without break");
puts("j <addr> : Continue from addr");
puts("m <addr> : Memory dump at addr");
puts("d <addr> : Disassembly at addr");
puts("v : Show ;interrupt vectors");
puts("?,h : Show this help text");
puts("r : Show Register Status");
puts("q : Exit 6502 emulation");
puts("----- TI-NES Specific -----");
puts("w : Dump Memory State");
puts("o : Show PPU registers");
puts("p <addr> : Dump PPU memory at addr");
puts("a : Dump all memory to memory.log");
puts("s : Dump sprite table to sprite.log");
puts("n <nb> : Dump name table <nb> to nt.log");
puts("z : Show lastest opcode executed");
puts("i : SpriteTable Dump");
puts("g <nb> : Get sprite <nb> info");
break;
case '\0':
return (1);
case 'Z':
showlastop();
break;
case 'W':
DumpMemoryState(stdout);
break;
case 'A':
{
FILE * fpDmpMem;
if ((fpDmpMem = fopen("memory.log", "wb")) != NULL)
{
// fwrite(Memory, 1, 0x8000, fpDmpMem);
//fwrite(mLBank, 1, 0x4000, fpDmpMem);
//fwrite(mUBank, 1, 0x4000, fpDmpMem);
fclose(fpDmpMem);
}
}
break;
case '=':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->Trap));
R->Trace = 0;
return (1);
}
break;
case '+':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->Trap));
R->Trap += R->PC.W;
R->Trace = 0;
return (1);
}
break;
case 'J':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->PC.W));
R->Trace = 0;
return (1);
}
break;
case 'T':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->PC.W));
R->Trace = 1;
}
break;
case 'C':
R->Trap = 0xFFFF;
R->Trace = 0;
install_keyboard();
//ResumeSound();
SetSound(0, SND_RECTANGLE);
SetSound(1, SND_RECTANGLE);
SetSound(2, SND_TRIANGLE);
SetSound(3, SND_NOISE);
return (1);
case 'Q':
return (0);
case 'V':
puts("\n6502 Interrupt Vectors:");
printf("[$FFFC] INIT: $%04X\n", Rd6502(0xFFFC) + 256 * Rd6502(0xFFFD));
printf("[$FFFE] IRQ: $%04X\n", Rd6502(0xFFFE) + 256 * Rd6502(0xFFFF));
printf("[$FFFA] NMI: $%04X\n", Rd6502(0xFFFA) + 256 * Rd6502(0xFFFB));
break;
case 'M':
{
word Addr;
if (strlen(S) > 1)
sscanf(S + 1, "%hX", &Addr);
else
Addr = R->PC.W;
puts("");
for (J = 0; J < 16; J++)
{
printf("%04X: ", Addr);
for (I = 0; I < 16; I++, Addr++)
printf("%02X ", Rd6502(Addr));
printf(" | ");
Addr -= 16;
for (I = 0; I < 16; I++, Addr++)
putchar(isprint(Rd6502(Addr)) ? Rd6502(Addr) : '.');
puts("");
}
}
break;
case 'R':
printf
(
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
);
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
printf("%c", F & 0x80 ? FA[J] : '.');
puts("]");
printf
(
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
Rd6502(R->PC.W), S,
Rd6502(0x0100 + (byte) (R->S + 1)),
Rd6502(0x0100 + (byte) (R->S + 2)),
Rd6502(0x0100 + (byte) (R->S + 3))
);
break;
case 'D':
{
word Addr;
if (strlen(S) > 1)
sscanf(S + 1, "%hX", &Addr);
else
Addr = R->PC.W;
puts("");
for (J = 0; J < 16; J++)
{
printf("%04X: ", Addr);
Addr += DAsm(S, Addr);
puts(S);
}
}
break;
}
}
/* Continue with emulation */
return (1);
}
#endif /* DEBUG */
/** M6502: portable 6502 emulator ****************************/
/** **/
/** Debug.c **/
/** **/
/** This file contains the built-in debugging routine for **/
/** the 6502 emulator which is called on each 6502 step **/
/** when Trap!=0. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-1997 **/
/** Alex Krasivsky 1996 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
/*
* $LastChangedDate: 2007-04-19 18:18:57 +0200 (jeu, 19 avr 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/Debug.c $
* $Revision: 43 $
*/
#include "M6502.h"
#ifdef DEBUG
#include <allegro.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <ppu/ppu.h>
#include <mappers/manager.h>
#include <memory/manager.h>
#include <Sound.h>
#define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
extern unsigned char *Memory;
void showlastop();
enum Addressing_Modes
{
Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
};
static char *mn[] =
{
"adc ", "and ", "asl ", "bcc ", "bcs ", "beq ", "bit ", "bmi ",
"bne ", "bpl ", "brk", "bvc ", "bvs ", "clc", "cld", "cli",
"clv", "cmp ", "cpx ", "cpy ", "dec ", "dex", "dey", "inx",
"iny", "eor ", "inc ", "jmp ", "jsr ", "lda ", "nop ", "ldx ",
"ldy ", "lsr ", "ora ", "pha", "php", "pla", "plp", "rol ",
"ror ", "rti", "rts", "sbc ", "sta ", "stx ", "sty ", "sec ",
"sed", "sei", "tax", "tay", "txa", "tya", "tsx", "txs"
};
static byte ad[512] =
{
10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
};
/** DAsm() ****************************************************/
/** This function will disassemble a single command and **/
/** return the number of bytes disassembled. **/
/**************************************************************/
int DAsm(char *S, word A)
{
byte J;
word B, OP, TO;
B = A;
OP = Rd6502(B++) * 2;
switch (ad[OP + 1])
{
case Ac:
sprintf(S, "%s a", mn[ad[OP]]);
break;
case Il:
sprintf(S, "%s", mn[ad[OP]]);
break;
case Rl:
J = Rd6502(B++);
TO = A + 2 + ((J < 0x80) ? J : (J - 256));
sprintf(S, "%s $%04X", mn[ad[OP]], TO);
break;
case Im:
sprintf(S, "%s #$%02X", mn[ad[OP]], Rd6502(B++));
break;
case Zp:
sprintf(S, "%s $%02X", mn[ad[OP]], Rd6502(B++));
break;
case Zx:
sprintf(S, "%s $%02X,x", mn[ad[OP]], Rd6502(B++));
break;
case Zy:
sprintf(S, "%s $%02X,y", mn[ad[OP]], Rd6502(B++));
break;
case Ix:
sprintf(S, "%s ($%02X,x)", mn[ad[OP]], Rd6502(B++));
break;
case Iy:
sprintf(S, "%s ($%02X),y", mn[ad[OP]], Rd6502(B++));
break;
case Ab:
sprintf(S, "%s $%04X", mn[ad[OP]], RDWORD(B));
B += 2;
break;
case Ax:
sprintf(S, "%s $%04X,x", mn[ad[OP]], RDWORD(B));
B += 2;
break;
case Ay:
sprintf(S, "%s $%04X,y", mn[ad[OP]], RDWORD(B));
B += 2;
break;
case In:
sprintf(S, "%s ($%04X)", mn[ad[OP]], RDWORD(B));
B += 2;
break;
default:
sprintf(S, ".db $%02X; <Invalid OPcode>", OP / 2);
}
return (B - A);
}
/** Debug6502() **********************************************/
/** This function should exist if DEBUG is #defined. When **/
/** Trace!=0, it is called after each command executed by **/
/** the CPU, and given the 6502 registers. Emulation exits **/
/** if Debug6502() returns 0. **/
/*************************************************************/
byte Debug6502(M6502 * R)
{
static char FA[8] = "NVRBDIZC";
char S[128];
byte F;
int J, I;
DAsm(S, R->PC.W);
printf
(
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
);
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
printf("%c", F & 0x80 ? FA[J] : '.');
puts("]");
printf
(
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
Rd6502(R->PC.W), S,
Rd6502(0x0100 + (byte) (R->S + 1)),
Rd6502(0x0100 + (byte) (R->S + 2)),
Rd6502(0x0100 + (byte) (R->S + 3))
);
S[0] = 0;
remove_keyboard();
#ifdef USE_SOUND
StopSound();
#endif
while (1)
{
printf("\n[Command,'?']-> ");
fflush(stdout);
fflush(stdin);
fgets(S, 50, stdin);
for (J = 0; S[J] >= ' '; J++)
S[J] = toupper(S[J]);
S[J] = '\0';
switch (S[0])
{
case 'H':
case '?':
puts("\n***** Built-in 6502 Debugger Commands *****");
puts("<CR> : Break at the next instruction");
puts("= <addr> : Break at addr");
puts("+ <offset> : Break at PC + offset");
puts("t <addr> : Set PC to addr");
puts("c : Continue without break");
puts("j <addr> : Continue from addr");
puts("m <addr> : Memory dump at addr");
puts("d <addr> : Disassembly at addr");
puts("v : Show ;interrupt vectors");
puts("?,h : Show this help text");
puts("r : Show Register Status");
puts("q : Exit 6502 emulation");
puts("----- TI-NES Specific -----");
puts("w : Dump Memory State");
puts("o : Show PPU registers");
puts("p <addr> : Dump PPU memory at addr");
puts("a : Dump all memory to memory.log");
puts("s : Dump sprite table to sprite.log");
puts("n <nb> : Dump name table <nb> to nt.log");
puts("z : Dump mapper status");
puts("i : SpriteTable Dump");
puts("g <nb> : Get sprite <nb> info");
break;
case '\0':
return (1);
case 'Z':
mapper_dump(stdout);
break;
case 'W':
DumpMemoryState(stdout);
break;
case 'A':
{
FILE * fpDmpMem;
if ((fpDmpMem = fopen("memory.log", "wb")) != NULL)
{
// fwrite(Memory, 1, 0x8000, fpDmpMem);
//fwrite(mLBank, 1, 0x4000, fpDmpMem);
//fwrite(mUBank, 1, 0x4000, fpDmpMem);
fclose(fpDmpMem);
}
}
break;
case '=':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->Trap));
R->Trace = 0;
return (1);
}
break;
case '+':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->Trap));
R->Trap += R->PC.W;
R->Trace = 0;
return (1);
}
break;
case 'J':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->PC.W));
R->Trace = 0;
return (1);
}
break;
case 'T':
if (strlen(S) >= 2)
{
sscanf(S + 1, "%hX", &(R->PC.W));
R->Trace = 1;
}
break;
case 'C':
R->Trap = 0xFFFF;
R->Trace = 0;
install_keyboard();
//ResumeSound();
SetSound(0, SND_RECTANGLE);
SetSound(1, SND_RECTANGLE);
SetSound(2, SND_TRIANGLE);
SetSound(3, SND_NOISE);
return (1);
case 'Q':
return (0);
case 'V':
puts("\n6502 Interrupt Vectors:");
printf("[$FFFC] INIT: $%04X\n", Rd6502(0xFFFC) + 256 * Rd6502(0xFFFD));
printf("[$FFFE] IRQ: $%04X\n", Rd6502(0xFFFE) + 256 * Rd6502(0xFFFF));
printf("[$FFFA] NMI: $%04X\n", Rd6502(0xFFFA) + 256 * Rd6502(0xFFFB));
break;
case 'M':
{
word Addr;
if (strlen(S) > 1)
sscanf(S + 1, "%hX", &Addr);
else
Addr = R->PC.W;
puts("");
for (J = 0; J < 16; J++)
{
printf("%04X: ", Addr);
for (I = 0; I < 16; I++, Addr++)
printf("%02X ", Rd6502(Addr));
printf(" | ");
Addr -= 16;
for (I = 0; I < 16; I++, Addr++)
putchar(isprint(Rd6502(Addr)) ? Rd6502(Addr) : '.');
puts("");
}
}
break;
case 'R':
printf
(
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
);
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
printf("%c", F & 0x80 ? FA[J] : '.');
puts("]");
printf
(
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
Rd6502(R->PC.W), S,
Rd6502(0x0100 + (byte) (R->S + 1)),
Rd6502(0x0100 + (byte) (R->S + 2)),
Rd6502(0x0100 + (byte) (R->S + 3))
);
break;
case 'D':
{
word Addr;
if (strlen(S) > 1)
sscanf(S + 1, "%hX", &Addr);
else
Addr = R->PC.W;
puts("");
for (J = 0; J < 16; J++)
{
printf("%04X: ", Addr);
Addr += DAsm(S, Addr);
puts(S);
}
}
break;
}
}
/* Continue with emulation */
return (1);
}
#endif /* DEBUG */

View File

@ -254,6 +254,155 @@ void Int6502(M6502 *R,byte Type)
}
}
#ifdef TRACE_EXECUTION
enum Addressing_Modes
{
Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
};
static char *mnCAP[] =
{
"ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI",
"BNE", "BPL", "BRK", "BVC", "BVS", "CLC", "CLD", "CLI",
"CLV", "CMP", "CPX", "CPY", "DEC", "DEX", "DEY", "INX",
"INY", "EOR", "INC", "JMP", "JSR", "LDA", "NOP", "LDX",
"LDY", "LSR", "ORA", "PHA", "PHP", "PLA", "PLP", "ROL",
"ROR", "RTI", "RTS", "SBC", "STA", "STX", "STY", "SEC",
"SED", "SEI", "TAX", "TAY", "TXA", "TYA", "TSX", "TXS"
};
#define DAsm DAsmCAP
static byte ad[512] =
{
10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
};
#define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
/** DAsm() ****************************************************/
/** This function will disassemble a single command and **/
/** return the number of bytes disassembled. **/
/**************************************************************/
int DAsmCAP(char *S, word A)
{
byte J;
word B, OP, TO;
B = A;
OP = Rd6502(B++) * 2;
switch (ad[OP + 1])
{
case Ac:
sprintf(S, "%s A", mnCAP[ad[OP]]);
break;
case Il:
sprintf(S, "%s", mnCAP[ad[OP]]);
break;
case Rl:
J = Rd6502(B++);
TO = A + 2 + ((J < 0x80) ? J : (J - 256));
sprintf(S, "%s $%04x", mnCAP[ad[OP]], TO);
break;
case Im:
sprintf(S, "%s #$%02x", mnCAP[ad[OP]], Rd6502(B++));
break;
case Zp:
sprintf(S, "%s $%02x", mnCAP[ad[OP]], Rd6502(B++));
break;
case Zx:
sprintf(S, "%s $%02x,X", mnCAP[ad[OP]], Rd6502(B++));
break;
case Zy:
sprintf(S, "%s $%02x,Y", mnCAP[ad[OP]], Rd6502(B++));
break;
case Ix:
sprintf(S, "%s ($%02x,X)", mnCAP[ad[OP]], Rd6502(B++));
break;
case Iy:
sprintf(S, "%s ($%02x),Y", mnCAP[ad[OP]], Rd6502(B++));
break;
case Ab:
sprintf(S, "%s $%04x", mnCAP[ad[OP]], RDWORD(B));
B += 2;
break;
case Ax:
sprintf(S, "%s $%04x,X", mnCAP[ad[OP]], RDWORD(B));
B += 2;
break;
case Ay:
sprintf(S, "%s $%04x,Y", mnCAP[ad[OP]], RDWORD(B));
B += 2;
break;
case In:
sprintf(S, "%s ($%04x)", mnCAP[ad[OP]], RDWORD(B));
B += 2;
break;
default:
sprintf(S, ".db $%02x; <Invalid OPcode>", OP / 2);
}
return (B - A);
}
#endif
/** Run6502() ************************************************/
/** This function will run 6502 code until Loop6502() call **/
@ -274,8 +423,29 @@ word Run6502(M6502 *R)
if(R->Trace)
if(!Debug6502(R)) return(R->PC.W);
#endif
#ifdef TRACE_EXECUTION
while(1)
{
I=Op6502(R->PC.W++);
static char FA[8] = "NV.BDIZC";
char S[128];
byte F;
int J, I;
DAsm(S, R->PC.W);
printf
(
"AT PC: [%02x - %s]\n",
Rd6502(R->PC.W), S
);
break;
}
#endif
I=Op6502(R->PC.W++);
R->ICount-=Cycles[I];
//#ifdef DEBUG
@ -289,6 +459,34 @@ word Run6502(M6502 *R)
#include "Codes.h"
}
#ifdef TRACE_EXECUTION
while(1)
{
static char FA[8] = "NV.BDIZC";
char S[128];
byte F;
int J, I;
printf
(
"A:%02x X:%02x Y:%02x S:%04x, PC:%04x Flags:[",
R->A, R->X, R->Y, R->S + 0x0100, R->PC.W
);
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
printf("%c", F & 0x80 ? FA[J] : '.');
printf("], Stack[%02x, %02x, %02x]\n",
Rd6502(0x0100 + (byte) (R->S + 1)),
Rd6502(0x0100 + (byte) (R->S + 2)),
Rd6502(0x0100 + (byte) (R->S + 3)));
break;
}
#endif
/* If cycle counter expired... */
if(R->ICount<=0)
{

View File

@ -18,24 +18,24 @@
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/Tables.h $
* $Revision: 52 $
*/
static byte Cycles[256] =
{
7, 6, 2, 1, 5, 3, 5, 5, 3, 2, 2, 1, 6, 4, 6, 2,
2, 5, 5, 1, 5, 4, 6, 5, 2, 4, 2, 1, 6, 4, 6, 2,
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 4, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 2, 1, 4, 4, 6, 2,
6, 6, 2, 1, 3, 3, 5, 5, 3, 2, 2, 1, 3, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 1, 8, 4, 6, 2,
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 6, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 5, 4, 4, 1, 6, 4, 6, 2,
3, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
2, 6, 5, 1, 4, 4, 4, 5, 2, 5, 2, 1, 4, 5, 5, 2,
2, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
2, 5, 5, 1, 4, 4, 4, 5, 2, 4, 2, 1, 4, 4, 4, 2,
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 2, 4, 4, 6, 2,
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 1, 4, 4, 6, 2,
static byte Cycles[256] =
{
7, 6, 2, 1, 5, 3, 5, 5, 3, 2, 2, 1, 6, 4, 6, 2,
2, 5, 5, 1, 5, 4, 6, 5, 2, 4, 2, 1, 6, 4, 6, 2,
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 4, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 2, 1, 4, 4, 6, 2,
6, 6, 2, 1, 3, 3, 5, 5, 3, 2, 2, 1, 3, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 1, 8, 4, 6, 2,
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 6, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 5, 4, 4, 1, 6, 4, 6, 2,
3, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
2, 6, 5, 1, 4, 4, 4, 5, 2, 5, 2, 1, 4, 5, 5, 2,
2, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
2, 5, 5, 1, 4, 4, 4, 5, 2, 4, 2, 1, 4, 4, 4, 2,
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 2, 4, 4, 6, 2,
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 1, 4, 4, 6, 2,
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 4, 1, 4, 4, 6, 2
};

View File

@ -137,7 +137,6 @@ void MIDITicks(int N);
/** skip initialization and be silent. Pass Verbose!=0 to **/
/** see initialization messages. **/
/*************************************************************/
#warning You Suck !
int InitSound(int Rate,int Verbose);
/** StopSound() **********************************************/

View File

@ -27,6 +27,9 @@ typedef void (*MapperDump) ();
#ifdef __TINES_MAPPERS__
#include <ppu/ppu.h>
#include <memory/manager.h>
extern NesCart *Cart;
/* Available functions for mappers */
@ -34,9 +37,6 @@ extern NesCart *Cart;
#define GETLAST16KBANK(c) ((c->PROMSize>>14)-1)
#define GETLAST32KBANK(c) ((c->PROMSize>>15)-1)
void map_sram(); /* Map SRAM */
void unmap_sram(); /* Unmap SRAM */
void set_vrom_bank_1k(unsigned short addr,int slot);
void set_vrom_bank_2k(unsigned short addr,int slot);
void set_vrom_bank_4k(unsigned short addr,int slot);
@ -57,4 +57,7 @@ extern void (*mapper_dump) (FILE *fp);
#endif /* __TINES_MAPPERS__ */
void map_sram(); /* Map SRAM */
void unmap_sram(); /* Unmap SRAM */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@ MapperWriteHook mapper_hook;
typedef struct Mapper_
{
byte id;
byte *name;
char *name;
MapperInit init;
MapperIRQ irq;

View File

@ -1,63 +1,65 @@
/*
* AOROM Mapper - The TI-NESulator Project
* aorom.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-04-26 18:47:34 +0200 (jeu, 26 avr 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/aorom.h $
* $Revision: 46 $
*
*/
unsigned char aorom_load_bank;
void aorom_MapperWriteHook(register byte Addr, register byte Value);
extern byte *ppu_mem_nameTables;
int aorom_InitMapper(NesCart * cart)
{
int i;
set_prom_bank_32k(0x8000,0);
ppu_setScreenMode(PPU_SCMODE_SINGLE);
aorom_load_bank = 0;
/* Register the write hook */
for (i = 0x80; i < 0x100; i++)
{
set_page_wr_hook(i, aorom_MapperWriteHook);
set_page_writeable(i, true);
}
return 0;
}
void aorom_MapperWriteHook(register byte Addr, register byte Value)
{
int BankNb;
if (Value & (1 << 4))
ppu_setSingleScreen(PPU_SCREEN_000);
else
ppu_setSingleScreen(PPU_SCREEN_400);
BankNb = Value & 0x0F;
aorom_load_bank = BankNb;
//printf("aorom: Asking bank %d (giving %d & %d) - mirror is %d\n",BankNb,BankNb,(Value<<1)+1,Value&0x0F);
set_prom_bank_32k(0x8000,BankNb);
}
void aorom_MapperDump(FILE *fp)
{
fprintf(fp,"aorom: bank:%d\n",aorom_load_bank);
}
/*
* AOROM Mapper - The TI-NESulator Project
* aorom.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-04-26 18:47:34 +0200 (jeu, 26 avr 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/aorom.h $
* $Revision: 46 $
*
*/
#include "aorom.h"
unsigned char aorom_load_bank;
void aorom_MapperWriteHook(register byte Addr, register byte Value);
extern byte *ppu_mem_nameTables;
int aorom_InitMapper(NesCart * cart)
{
int i;
set_prom_bank_32k(0x8000,0);
ppu_setScreenMode(PPU_SCMODE_SINGLE);
aorom_load_bank = 0;
/* Register the write hook */
for (i = 0x80; i < 0x100; i++)
{
set_page_wr_hook(i, aorom_MapperWriteHook);
set_page_writeable(i, true);
}
return 0;
}
void aorom_MapperWriteHook(register byte Addr, register byte Value)
{
int BankNb;
if (Value & (1 << 4))
ppu_setSingleScreen(PPU_SCREEN_000);
else
ppu_setSingleScreen(PPU_SCREEN_400);
BankNb = Value & 0x0F;
aorom_load_bank = BankNb;
//printf("aorom: Asking bank %d (giving %d & %d) - mirror is %d\n",BankNb,BankNb,(Value<<1)+1,Value&0x0F);
set_prom_bank_32k(0x8000,BankNb);
}
void aorom_MapperDump(FILE *fp)
{
fprintf(fp,"aorom: bank:%d\n",aorom_load_bank);
}

View File

@ -1,6 +1,6 @@
/*
* CNROM Mapper - The TI-NESulator Project
* cnrom.h
* cnrom.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
@ -12,6 +12,8 @@
*
*/
#include "cnrom.h"
unsigned char cnrom_load_bank;
void cnrom_MapperWriteHook(register byte Addr, register byte Value);

View File

@ -1,125 +1,127 @@
/*
* IREMH3001 Mapper - The TI-NESulator Project
* iremh3001.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
* $Author: godzil $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/iremh3001.h $
* $Revision: 39 $
*
*/
unsigned short iremh3001_prom_slot[3];
unsigned short iremh3001_vrom_slot[8];
int iremh3001_InitMapper(NesCart * cart)
{
set_prom_bank_16k(0x8000, 0);
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
iremh3001_prom_slot[0] = 0;
iremh3001_prom_slot[1] = 1;
iremh3001_prom_slot[2] = GETLAST16KBANK(cart);
set_vrom_bank_8k(0x0000,4);
iremh3001_vrom_slot[0] = 0;
iremh3001_vrom_slot[1] = 0;
iremh3001_vrom_slot[2] = 0;
iremh3001_vrom_slot[3] = 0;
iremh3001_vrom_slot[4] = 0;
iremh3001_vrom_slot[5] = 0;
iremh3001_vrom_slot[6] = 0;
iremh3001_vrom_slot[7] = 0;
return 0;
}
int iremh3001_MapperWriteHook(register word Addr, register byte Value)
{
switch(Addr)
{
case 0x8000: /* Set 8k PROM @ 8000 */
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
set_prom_bank_8k(0x8000, Value);
iremh3001_prom_slot[0] = Value;
break;
case 0x9003: /* Mirroring ??? */
printf("iremh3001: Mirroring[0x%X:%d] ?\n", Value, Value);
break;
case 0x9005: /* IRQ ??? */
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
break;
case 0x9006: /* IRQ ??? */
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
break;
case 0xA000: /* Set 8k PROM @ A000 */
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
set_prom_bank_8k(0xA000, Value);
iremh3001_prom_slot[1] = Value;
break;
case 0xB000: /* Set 1k VROM @ 0000 */
case 0xB001: /* Set 1k VROM @ 0400 */
case 0xB002: /* Set 1k VROM @ 0800 */
case 0xB003: /* Set 1k VROM @ 0C00 */
case 0xB004: /* Set 1k VROM @ 1000 */
case 0xB005: /* Set 1k VROM @ 1400 */
case 0xB006: /* Set 1k VROM @ 1800 */
case 0xB007: /* Set 1k VROM @ 1C00 */
printf("iremh3001: %X: change VROM to %d[%X]\n", (Addr&0x0F)<<10, Value, Value);
set_vrom_bank_1k((Addr&0xF)<<10, Value);
iremh3001_vrom_slot[Addr&0x0F] = Value;
break;
case 0xC000: /* Set 8k PROM @ C000 */
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
set_prom_bank_8k(0xC000, Value);
iremh3001_prom_slot[2] = Value;
break;
default:
printf("@:%X -- V:%X", Addr, Value);
return 0;
}
return 1;
}
void iremh3001_MapperDump(FILE *fp)
{
fprintf(fp,"iremh3001: prom: $8000:%d $A000:%d $C000:%d\n",
iremh3001_prom_slot[0],
iremh3001_prom_slot[1],
iremh3001_prom_slot[2]);
fprintf(fp,"iremh3001: vrom: $0000:%d $0400:%d $0800:%d $0C00:%d\n" \
" $1000:%d $1400:%d $1800:%d $1C00:%d\n",
iremh3001_vrom_slot[0],
iremh3001_vrom_slot[1],
iremh3001_vrom_slot[2],
iremh3001_vrom_slot[3],
iremh3001_vrom_slot[4],
iremh3001_vrom_slot[5],
iremh3001_vrom_slot[6],
iremh3001_prom_slot[7]);
}
int iremh3001_MapperIRQ(int cycledone)
{
return 0;
}
/*
* IREMH3001 Mapper - The TI-NESulator Project
* iremh3001.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
* $Author: godzil $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/iremh3001.h $
* $Revision: 39 $
*
*/
#include "iremh3001.h"
unsigned short iremh3001_prom_slot[3];
unsigned short iremh3001_vrom_slot[8];
int iremh3001_InitMapper(NesCart * cart)
{
set_prom_bank_16k(0x8000, 0);
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
iremh3001_prom_slot[0] = 0;
iremh3001_prom_slot[1] = 1;
iremh3001_prom_slot[2] = GETLAST16KBANK(cart);
set_vrom_bank_8k(0x0000,4);
iremh3001_vrom_slot[0] = 0;
iremh3001_vrom_slot[1] = 0;
iremh3001_vrom_slot[2] = 0;
iremh3001_vrom_slot[3] = 0;
iremh3001_vrom_slot[4] = 0;
iremh3001_vrom_slot[5] = 0;
iremh3001_vrom_slot[6] = 0;
iremh3001_vrom_slot[7] = 0;
return 0;
}
int iremh3001_MapperWriteHook(register byte Addr, register byte Value)
{
switch(Addr)
{
case 0x8000: /* Set 8k PROM @ 8000 */
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
set_prom_bank_8k(0x8000, Value);
iremh3001_prom_slot[0] = Value;
break;
case 0x9003: /* Mirroring ??? */
printf("iremh3001: Mirroring[0x%X:%d] ?\n", Value, Value);
break;
case 0x9005: /* IRQ ??? */
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
break;
case 0x9006: /* IRQ ??? */
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
break;
case 0xA000: /* Set 8k PROM @ A000 */
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
set_prom_bank_8k(0xA000, Value);
iremh3001_prom_slot[1] = Value;
break;
case 0xB000: /* Set 1k VROM @ 0000 */
case 0xB001: /* Set 1k VROM @ 0400 */
case 0xB002: /* Set 1k VROM @ 0800 */
case 0xB003: /* Set 1k VROM @ 0C00 */
case 0xB004: /* Set 1k VROM @ 1000 */
case 0xB005: /* Set 1k VROM @ 1400 */
case 0xB006: /* Set 1k VROM @ 1800 */
case 0xB007: /* Set 1k VROM @ 1C00 */
printf("iremh3001: %X: change VROM to %d[%X]\n", (Addr&0x0F)<<10, Value, Value);
set_vrom_bank_1k((Addr&0xF)<<10, Value);
iremh3001_vrom_slot[Addr&0x0F] = Value;
break;
case 0xC000: /* Set 8k PROM @ C000 */
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
set_prom_bank_8k(0xC000, Value);
iremh3001_prom_slot[2] = Value;
break;
default:
printf("@:%X -- V:%X", Addr, Value);
return 0;
}
return 1;
}
void iremh3001_MapperDump(FILE *fp)
{
fprintf(fp,"iremh3001: prom: $8000:%d $A000:%d $C000:%d\n",
iremh3001_prom_slot[0],
iremh3001_prom_slot[1],
iremh3001_prom_slot[2]);
fprintf(fp,"iremh3001: vrom: $0000:%d $0400:%d $0800:%d $0C00:%d\n" \
" $1000:%d $1400:%d $1800:%d $1C00:%d\n",
iremh3001_vrom_slot[0],
iremh3001_vrom_slot[1],
iremh3001_vrom_slot[2],
iremh3001_vrom_slot[3],
iremh3001_vrom_slot[4],
iremh3001_vrom_slot[5],
iremh3001_vrom_slot[6],
iremh3001_prom_slot[7]);
}
int iremh3001_MapperIRQ(int cycledone)
{
return 0;
}

View File

@ -16,6 +16,5 @@
#include <mappers/manager.h>
int iremh3001_InitMapper(NesCart * cart);
int iremh3001_MapperWriteHook(register word Addr, register byte Value);
void iremh3001_MapperDump(FILE *fp);
int iremh3001_MapperIRQ(int cycledone);

View File

@ -14,9 +14,6 @@
#include "norom.h"
#include <ppu/ppu.h>
#include <memory/manager.h>
unsigned char MMC1_reg0;
unsigned char MMC1_reg1;
@ -52,7 +49,6 @@ unsigned char mmc1_CurrentBank;
#define MMC1_REG2_DEFAULT 0
#define MMC1_REG3_DEFAULT 0
void mmc1_MapperWriteReg0(register byte Addr, register byte Value);
void mmc1_MapperWriteReg1(register byte Addr, register byte Value);
void mmc1_MapperWriteReg2(register byte Addr, register byte Value);

View File

@ -1,9 +1,14 @@
/*
* MMC1 Mapper - The TI-NESulator Project
* mmc1.h
* TI-NESulator.X
*
* Created by Manoël Trapier on 02/12/07.
* Copyright 2007 986 Corp. All rights reserved.
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc1.h $
* $Revision: 50 $
*
*/
@ -12,5 +17,4 @@
int mmc1_InitMapper (NesCart *cart);
int mmc1_MapperIRQ (int cycledone);
void mmc1_MapperDump ();
void mmc1_MapperWriteHook(register byte Addr, register byte Value);
void mmc1_MapperDump ();

View File

@ -12,6 +12,10 @@
*
*/
#include "mmc3.h"
extern unsigned short ScanLine;
unsigned short mmc3_command;
unsigned char mmc3_irq_counter;
@ -43,8 +47,6 @@ void mmc3_MapperDump(FILE *fp)
int mmc3_InitMapper(NesCart * cart)
{
int i;
set_prom_bank_16k(0x8000, 0);
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
@ -75,8 +77,6 @@ int mmc3_InitMapper(NesCart * cart)
mmc3_first_prom_page = 0x8000;
mmc3_second_prom_page = 0xA000;
//mmc3_first_prom_page = 0; // Set it to 0x8000
/* Register mapper write hook */
set_page_wr_hook(0x80, mmc3_MapperWrite80Hook);
@ -92,7 +92,6 @@ int mmc3_InitMapper(NesCart * cart)
set_page_writeable(0xE0, true);
return 0;
}
void mmc3_MapperWrite80Hook(byte addr, byte Value)
@ -250,8 +249,6 @@ void mmc3_MapperWriteA0Hook(byte addr, byte Value)
}
extern unsigned short ScanLine;
void mmc3_MapperWriteC0Hook(byte addr, byte Value)
{
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);

View File

@ -1,23 +1,25 @@
/*
* MMC4 Mapper - The TI-NESulator Project
* mmc4.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-05-31 18:00:41 +0200 (jeu, 31 mai 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc4.h $
* $Revision: 56 $
*
*/
/*
* MMC4 Mapper - The TI-NESulator Project
* mmc4.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-05-31 18:00:41 +0200 (jeu, 31 mai 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc4.h $
* $Revision: 56 $
*
*/
#include "mmc4.h"
byte mmc4_RegA;
byte mmc4_RegB;
byte mmc4_RegC;
byte mmc4_RegD;
byte mmc4_RegE;
byte mmc4_RegF;
byte mmc4_RegF;
#ifdef DEBUG
#define LOG
@ -25,8 +27,8 @@ byte mmc4_RegF;
#else
#define LOG
#endif
void mmc4_MapperWriteRegA(register byte Addr, register byte Value)
{
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
@ -75,51 +77,52 @@ void mmc4_MapperWriteRegF(register byte Addr, register byte Value)
ppu_setMirroring(PPU_MIRROR_VERTICAL);
}
void mmc4_MapperDump(FILE *fp)
{
}
int mmc4_InitMapper(NesCart * cart)
void mmc4_MapperDump(FILE *fp)
{
}
int mmc4_InitMapper(NesCart * cart)
{
int i;
set_prom_bank_16k(0x8000,0);
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
if (cart->VROMSize > 0) set_vrom_bank_8k(0x0000,0);
/* Mapper should register itself for write hook */
for (i = 0xA0; i < 0xB0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegA);
set_page_writeable(i, true);
}
for (i = 0xB0; i < 0xC0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegB);
set_page_writeable(i, true);
set_prom_bank_16k(0x8000,0);
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
if (cart->VROMSize > 0)
set_vrom_bank_8k(0x0000,0);
/* Mapper should register itself for write hook */
for (i = 0xA0; i < 0xB0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegA);
set_page_writeable(i, true);
}
for (i = 0xB0; i < 0xC0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegB);
set_page_writeable(i, true);
}
for (i = 0xC0; i < 0xD0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegC);
set_page_writeable(i, true);
}
for (i = 0xD0; i < 0xE0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegD);
set_page_writeable(i, true);
}
for (i = 0xE0; i < 0xF0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegE);
set_page_writeable(i, true);
}
for (i = 0xF0; i < 0x100 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegF);
set_page_writeable(i, true);
for (i = 0xC0; i < 0xD0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegC);
set_page_writeable(i, true);
}
for (i = 0xD0; i < 0xE0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegD);
set_page_writeable(i, true);
}
for (i = 0xE0; i < 0xF0 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegE);
set_page_writeable(i, true);
}
for (i = 0xF0; i < 0x100 ; i++)
{
set_page_wr_hook(i, mmc4_MapperWriteRegF);
set_page_writeable(i, true);
}
for (i = 0x60; i < 0x80 ; i++)
@ -130,8 +133,8 @@ int mmc4_InitMapper(NesCart * cart)
//ppu_setScreenMode(PPU_SCMODE_NORMAL);
//ppu_setMirroring(PPU_MIRROR_HORIZTAL);
return 0;
}
return 0;
}

View File

@ -1,9 +1,14 @@
/*
* NOROM Mapper - The TI-NESulator Project
* norom.c
* TI-NESulator.X
*
* Created by Manoël Trapier on 25/10/07.
* Copyright 2007 986 Corp. All rights reserved.
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
* $Author: godzil $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/unrom.h $
* $Revision: 39 $
*
*/
@ -11,8 +16,6 @@
int norom_InitMapper(NesCart *cart)
{
int i;
set_page_ptr_16k(0x80, cart->PROMBanks);
/* mUBank = 0xC000 */

View File

@ -1,9 +1,14 @@
/*
* norom.h
* TI-NESulator.X
* NOROM Mapper - The TI-NESulator Project
* norom.c
*
* Created by Manoël Trapier on 25/10/07.
* Copyright 2007 986 Corp. All rights reserved.
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
* $Author: godzil $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/unrom.h $
* $Revision: 39 $
*
*/
@ -12,5 +17,4 @@
int norom_InitMapper (NesCart *cart);
int norom_MapperIRQ (int cycledone);
void norom_MapperDump ();
void norom_MapperWriteHook(register byte Addr, register byte Value);
void norom_MapperDump ();

View File

@ -11,10 +11,12 @@
* $Revision: 39 $
*
*/
#include "unrom.h"
unsigned char unrom_load_vbank;
void unrom_MapperWriteHook(register byte Addr, register byte Value);
void unrom_MapperWriteHook(byte Addr, byte Value);
int unrom_InitMapper(NesCart * cart)
{
@ -39,7 +41,7 @@ int unrom_InitMapper(NesCart * cart)
}
void unrom_MapperWriteHook(register byte Addr, register byte Value)
void unrom_MapperWriteHook(byte Addr, byte Value)
{
set_vrom_bank_8k(0x0000,Value);
unrom_load_vbank = Value;

View File

@ -9,12 +9,28 @@
/* This file could be generated from the mappers directory... */
#include "mappers/norom.h"
#include "mappers/aorom.h"
#include "mappers/unrom.h"
#include "mappers/cnrom.h"
#include "mappers/iremh3001.h"
#include "mappers/mmc1.h"
#include "mappers/mmc3.h"
#include "mappers/mmc4.h"
Mapper Mappers[] = {
{ 0, "No Mapper", norom_InitMapper, norom_MapperIRQ, norom_MapperDump },
{ 1, "MMC1", mmc1_InitMapper, norom_MapperIRQ, mmc1_MapperDump },
{ 0 , "No Mapper", norom_InitMapper, norom_MapperIRQ, norom_MapperDump },
{ 7 , "AOROM", aorom_InitMapper, norom_MapperIRQ, aorom_MapperDump },
{ 2 , "CNROM", cnrom_InitMapper, norom_MapperIRQ, cnrom_MapperDump },
{ 3 , "UNROM", unrom_InitMapper, norom_MapperIRQ, unrom_MapperDump },
{ 1 , "MMC1", mmc1_InitMapper, norom_MapperIRQ, mmc1_MapperDump },
{ 4 , "MMC3", mmc3_InitMapper, mmc3_MapperIRQ, mmc3_MapperDump },
{ 10, "MMC4", mmc3_InitMapper, norom_MapperIRQ, mmc4_MapperDump },
{ 65, "Irem H3001", iremh3001_InitMapper, iremh3001_MapperIRQ, iremh3001_MapperDump },
/* EOL tag */
{ 0, NULL, NULL, NULL, NULL }
};

View File

@ -23,6 +23,10 @@
#include <mappers/manager.h>
#include <memory/manager.h>
#define __TINES_PPU_INTERNAL__
#include <ppu/ppu.memory.h>
#undef __TINES_PPU_INTERNAL__
extern NesCart *Cart;
extern char MapperWantIRQ;

View File

@ -19,7 +19,7 @@
typedef struct Plugin_
{
byte *name;
char *name;
PluginInit init;
PluginDeinit deinit;
@ -55,9 +55,15 @@ void plugin_list()
int plugin_load(int id)
{
Plugin *ptr = &(Plugins[0]);
int i = id;
for ( ; id == 0 && ptr != NULL; id -- )
ptr ++;
printf("%s(%d)", __func__, id);
for ( ; i > 1 && ptr->name != NULL; i -- )
{
printf("%d - %s\n", i, ptr->name);
ptr ++;
}
if (ptr == NULL)
return -1;

View File

@ -4,6 +4,7 @@
#define __TINES_PLUGINS__
#include <plugins/manager.h>
#undef __TINES_PLUGINS_
#include <memory/manager.h>
#include <types.h>
@ -53,7 +54,6 @@ byte gg_RdHookPatch##d(byte addr) \
}
#define GG_MAX_PATCH 10
/* Defines the rdhook patches */
GG_RDHOOKPATCH(0)
GG_RDHOOKPATCH(1)
@ -68,7 +68,7 @@ GG_RDHOOKPATCH(9)
void gg_SetPatch(int id, byte page, byte addr, byte value)
{
func_rdhook *fptr;
func_rdhook fptr;
if (id >= GG_MAX_PATCH)
return;
@ -418,7 +418,7 @@ byte gg_SelectPatch()
if (gg_PatchUsed[i] == 0x00)
sprintf(tmp, "Patch %d: Not used", i);
else
sprintf(tmp, "Patch %d: Put 0x%02X on address 0x%02X%02X (Code: %08X)",
sprintf(tmp, "Patch %d: Put 0x%02X on address 0x%02X%02X (Code: %08lX)",
i, gg_PatchedValue[i], gg_PatchedPage[i], gg_PatchedAddr[i],
gg_MakeCode((gg_PatchedPage[i]<<8) | gg_PatchedAddr[i], gg_PatchedValue[i]));

View File

@ -218,7 +218,7 @@ void ppu_dumpOneNameTable(unsigned short nametable, int xd, int yd)
void ppu_dumpOneAttributeTable(unsigned short nametable, int xd, int yd)
{
int x, y, x1, y1, Color, AttrByte;
int x, x1, y1, Color, AttrByte;
for (x = 0; x < 0x40; x++)
{
AttrByte = PPU_Rd(nametable + 0x23C0 + x);

View File

@ -1,9 +1,9 @@
/*
* PPU emulation - The TI-NESulator Project
* ppu.c
*
*
* Define and emulate the PPU (Picture Processing Unit) of the real NES
*
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
*
@ -23,6 +23,8 @@
#include <ppu/ppu.memory.h>
#include <ppu/ppu.debug.h>
#include <M6502.h>
#include <memory/manager.h>
#define __TINES_PLUGINS__
@ -185,43 +187,45 @@ byte ppu_screenMode;
int ppu_init()
{
int i;
/*byte defaultColors[] = { 0x09,0x01,0x00,0x01,0x00,0x02,0x02,0x0D,0x08,0x10,0x08,0x24,0x00,0x00,0x04,0x2C,
0x09,0x01,0x34,0x03,0x00,0x04,0x00,0x14,0x08,0x3A,0x00,0x02,0x00,0x20,0x2C,0x08 };*/
if (ppu_initMemory())
return -1;
/* Set ppu memory parameters */
/* First: Allocate each memory zone */
ppu_mem_patternTables = (byte*) malloc(PPU_MEM_PATTERNTABLES_SIZE);
if (!ppu_mem_patternTables)
return -1;
ppu_mem_nameTables = (byte*) malloc(PPU_MEM_NAMETABLE_SIZE);
if (!ppu_mem_nameTables)
return -1;
ppu_mem_paletteValues = (byte*) malloc(PPU_MEM_PALETTEVALUES_SIZE);
if (!ppu_mem_paletteValues)
return -1;
printf("ppu_mem_nameTables :%p\n"
"ppu_mem_patternTables:%p\n"
"ppu_mem_paletteValues:%p\n",
ppu_mem_nameTables,
ppu_mem_patternTables,
ppu_mem_paletteValues);
/* Second: make the ppu memory manager point on the memory zones */
ppu_setPagePtr8k(0x00, ppu_mem_patternTables);
ppu_setPagePtr4k(0x20, ppu_mem_nameTables);
ppu_setPagePtr (0x3F, ppu_mem_paletteValues);
ppu_setPagePtr (0x3F, ppu_mem_paletteValues);
for ( i = 0x00; i < 0x0F; i++ )
ppu_setPageGhost(0x30 + i, true, 0x20 + i);
/* Third: set registers to defaults */
/* Now test the memory ! */
/* Fille PPU memory with garbage */
@ -230,9 +234,10 @@ int ppu_init()
for (i = 0x0000; i < 0x1000 ; i++)
ppu_mem_nameTables[i] = rand()%0xFF;
for (i = 0x0000; i < 0x001F ; i++)
ppu_mem_paletteValues[i] = rand()%0xFF;
ppu_mem_paletteValues[i] = rand()%0xFF;
//memcpy(ppu_mem_paletteValues, defaultColors, 32);
/* Dump PPU memory state */
//ppu_memoryDumpState(stdout);
@ -241,8 +246,8 @@ int ppu_init()
ppu_addrIncrement = 1;
ppu_spritePatternTable = 0;
ppu_spriteSize = 8;
ppu_execNMIonVBlank = 0;
ppu_spriteSize = 8;
ppu_execNMIonVBlank = 0;
ppu_spriteVisibility = 0;
ppu_backgroundVisibility = 0;
@ -254,29 +259,29 @@ int ppu_init()
ppu_bgColor = 0;
/* Set PPU registers on CPU side */
set_page_rd_hook(0x20, ppu_readReg);
set_page_rd_hook(0x20, ppu_readReg);
set_page_wr_hook(0x20, ppu_writeReg);
set_page_readable(0x20, true);
set_page_writeable(0x20, true);
/* Set PPU Ghost Registers */
for(i = 0x21; i < 0x40; i++)
set_page_ghost(i, true, 0x20);
// plugin_install_keypressHandler('i', ppu_debugSprites);
// plugin_install_keypressHandler('I', ppu_debugSprites);
// plugin_install_keypressHandler('u', ppu_debugColor);
// plugin_install_keypressHandler('U', ppu_debugColor);
/* allocate the PPU Video memory */
VideoBuffer = create_bitmap(256, 240);
if (VideoBuffer == NULL)
return -1;
return 0;
}
@ -284,46 +289,45 @@ void ppu_updateSpriteScanlineTable()
{
int i, line, j, k;
volatile int sprite_x, sprite_y, sprite_idx, sprite_attr;
int curline;
for (line = 0; line < 241; line ++)
{
PPU_NbSpriteByScanLine[line] = 0;
PPU_NbSpriteByScanLineOverFlow[line] = 0;
for (i = 0; i < 9; i++)
PPU_SpriteByScanLine[line][i] = 0xFFFFFFFF;
}
for ( i = 0; i < 64; i ++)
{
/* Fill sprite_zzz variables */
sprite_y = ppu_mem_spritesTable[(i*4) + 0];
sprite_y = ppu_mem_spritesTable[(i*4) + 0] + 1;
sprite_idx = ppu_mem_spritesTable[(i*4) + 1];
sprite_attr = ppu_mem_spritesTable[(i*4) + 2] | ((i==0)?0x04:0); /* Add a flag for the sprite #0 */
sprite_x = ppu_mem_spritesTable[(i*4) + 3];
/* For each line covered by the sprite */
for (line = 0; line < ppu_spriteSize; line ++)
{
{
curline = line + sprite_y;
if ((curline < 0) || (curline > 240))
continue; /* Don't go beyond, this sprite go beyond the borders */
if (PPU_NbSpriteByScanLine[curline] < 7)
if (PPU_NbSpriteByScanLine[curline] < 8)
PPU_NbSpriteByScanLine[curline] ++;
else
{
PPU_NbSpriteByScanLineOverFlow[curline] = 1;
//printf("sprite of: %d - %d\n", curline, PPU_NbSpriteByScanLine[curline]);
//printf("sprite of: %u - %u\n", curline, PPU_NbSpriteByScanLine[curline]);
continue; /* We have 8 sprite in this line, don't continue */
}
if (((sprite_x+8) < 0) && ((sprite_x-8) > 256))
continue; /* this sprite isn't either displayable */
/* Now test if this sprite can be put in the sprite list */
/* Now test if this sprite can be put in the sprite list */
for (j = 0; j <= PPU_NbSpriteByScanLine[curline]; j++)
{
/* sprite are ordered by their y value, so, the first time that
@ -334,21 +338,21 @@ void ppu_updateSpriteScanlineTable()
if needed the rightest item. */
for (k = 7; k >= j; k--)
PPU_SpriteByScanLine[curline][k] = PPU_SpriteByScanLine[curline][k-1];
PPU_SpriteByScanLine[curline][j] = 0;
PPU_SCANLINESPRITE_SET_ATTRS (PPU_SpriteByScanLine[curline][j], sprite_attr);
//printf("new sprite [%02X:%02X:%02X:%02X] at sl:%d : 0x%08X ",
//sprite_attr, sprite_idx, curline - sprite_x, sprite_y,
//curline, PPU_SpriteByScanLine[curline][j]);
PPU_SCANLINESPRITE_SET_TILIDX(PPU_SpriteByScanLine[curline][j], sprite_idx);
//printf("- 0x%08X ", PPU_SpriteByScanLine[curline][j]);
PPU_SCANLINESPRITE_SET_RELY (PPU_SpriteByScanLine[curline][j], curline - sprite_y);
//printf("- 0x%08X ", PPU_SpriteByScanLine[curline][j]);
PPU_SCANLINESPRITE_SET_X (PPU_SpriteByScanLine[curline][j], sprite_x);
PPU_SCANLINESPRITE_SET_X (PPU_SpriteByScanLine[curline][j], sprite_x);
//printf("- 0x%08X\n", PPU_SpriteByScanLine[curline][j]);
break; /* Stop the for, we don't need to go further in the line list */
@ -371,7 +375,7 @@ void ppu_setMirroring(byte direction)
default:
direction = PPU_MIRROR_HORIZTAL;
ppu_mirrorMode = direction;
case PPU_MIRROR_HORIZTAL: /* Horizontal */
//printf("Set mirror to Hor\n");
ppu_setPagePtr1k(0x20, ppu_mem_nameTables + 0x000);
@ -396,13 +400,13 @@ void ppu_setSingleScreen(byte screen)
return;
if (ppu_singleScreenMode == screen)
return; /* Same value, no need to change! */
switch(screen)
{
default:
screen = PPU_SCREEN_000;
ppu_singleScreenMode = screen;
case PPU_SCREEN_000: /* 0x2000 */
//printf("Set screen to 0x000\n");
ppu_setPagePtr1k(0x20, ppu_mem_nameTables + 0x000);
@ -410,7 +414,7 @@ void ppu_setSingleScreen(byte screen)
ppu_setPagePtr1k(0x28, ppu_mem_nameTables + 0x000);
ppu_setPagePtr1k(0x2C, ppu_mem_nameTables + 0x000);
break;
case PPU_SCREEN_400: /* 0x2400 */
//printf("Set screen to 0x400\n");
ppu_setPagePtr1k(0x20, ppu_mem_nameTables + 0x400);
@ -418,7 +422,7 @@ void ppu_setSingleScreen(byte screen)
ppu_setPagePtr1k(0x28, ppu_mem_nameTables + 0x400);
ppu_setPagePtr1k(0x2C, ppu_mem_nameTables + 0x400);
break;
case PPU_SCREEN_800: /* 0x2800 */
//printf("Set screen to 0x800\n");
ppu_setPagePtr1k(0x20, ppu_mem_nameTables + 0x800);
@ -426,7 +430,7 @@ void ppu_setSingleScreen(byte screen)
ppu_setPagePtr1k(0x28, ppu_mem_nameTables + 0x800);
ppu_setPagePtr1k(0x2C, ppu_mem_nameTables + 0x800);
break;
case PPU_SCREEN_C00: /* 0x2C00 */
//printf("Set screen to 0xC00\n");
ppu_setPagePtr1k(0x20, ppu_mem_nameTables + 0xC00);
@ -458,7 +462,7 @@ void ppu_setScreenMode(byte mode)
default:
mode = PPU_SCMODE_NORMAL;
ppu_screenMode = mode;
ppu_screenMode = mode;
case PPU_SCMODE_NORMAL: /* Normal screen (2 NT with mirroring) */
//printf("Set Normal Screen\n");
@ -491,7 +495,7 @@ void ppu_updateCounters()
| |+===++=++=++=====++=====+ |
+---------------+-----------------------------------------------+
|2007 access | DC B A 98765 43210 |
+===============+===============================================+
+===============+===============================================+
8421 8421 8421 8421
-------------------
@ -505,120 +509,218 @@ _AAA BCDD DDDE EEEE
PPU_Reg_Counter |= PPU_Reg_H << 10;
PPU_Reg_Counter |= PPU_Reg_VT << 5;
PPU_Reg_Counter |= PPU_Reg_HT;
IF_N_KEY printf("Counter update to %04X\n",PPU_Reg_Counter);
}
extern M6502 MainCPU;
int ppu_hblank(int scanline)
{
{
int i, j;
byte pixelColor = 0x42;
byte Color = 0x42;
byte BgColor = 0x42;
byte SpriteColor = 0x42;
unsigned short addr;
byte value;
unsigned short tmp_HHT = 0;
unsigned short tmp_VVTFV = 0;
unsigned short tmp_VVTFV = 0;
unsigned long CurrentSprite;
byte SpriteVFlip;
/* If no plan activated, we have nothing to do ! */
if (scanline == 0)
{
ppu_bgColor = ppu_readMemory(0x3F,00);
clear_to_color(VideoBuffer, ppu_bgColor);
if ((ppu_spriteVisibility != 0) || (ppu_backgroundVisibility != 0))
ppu_updateCounters();
}
if (scanline < 240)
{
/* For each PPU pixel of this scanline */
for (i = 0; i < 256; i ++)
{
/* determine which from sprite bg, bg and sprite fg is in the front */
/* For each PPU pixel of this scanline */
for (i = 0; i < 256; i ++)
{
/* Set the current pixel color to the bg color */
pixelColor = ppu_readMemory(0x3F,00);
/* is there sprite(s) on this line ? */
/* */
/* Didn't display sprite for now, juste the BG */
/* Read NameTable */
/* Compute current pixel bg color if bg is visible */
if (ppu_backgroundVisibility == 1)
{
/*
xxxx AABB BxxC CCxx
xxxx AA11 11BB BCCC
*/
/*
s:32 i:235 cnt:089D addr:0BCF cba:0 addr:0000
0000 BBBB CCCC FFFF
0000 1100 1101 1111
AABB B C CC
BA98 7654 3210
xxxx 1111 1100 1111
FFFF CCCC FFFF
*/
addr = (PPU_Reg_Counter & 0x0C00);
addr = addr | 0x03C0;
addr |= (PPU_Reg_Counter >> 4 ) & 0x0038;
addr |= (PPU_Reg_Counter >> 2 ) & 0x0007;
addr |= (PPU_Reg_Counter >> 2 ) & 0x0007;
PPU_Reg_AR = ppu_readMemory(0x20 | ((addr>>8) & 0x0F), addr& 0xFF);
PPU_Reg_AR = PPU_Reg_AR >> (((PPU_Reg_Counter >> 4 ) & 0x04)|((PPU_Reg_Counter ) & 0x02));
PPU_Reg_AR = (PPU_Reg_AR<<2) & 0x0C;
PPU_Reg_PAR = ppu_readMemory(0x20 | ((PPU_Reg_Counter>>8) & 0x0F), PPU_Reg_Counter& 0xFF);
/* C BA98 7654 3210 */
/* 1 8421 8421 8421 */
addr = PPU_Reg_S;
addr |= ((PPU_Reg_PAR & 0xFF) << 4);
addr |= ((PPU_Reg_Counter >> 12) & 0x07);
value = ppu_readMemory((addr >> 8) , addr );
Color = (value & (1 << (7-(i + PPU_Reg_FH) % 8)))?0x01:0;
value = ppu_readMemory((addr >> 8) , addr | 0x08 );
Color |= (value & (1 << (7-(i + PPU_Reg_FH) % 8)))?0x02:0;
if (Color > 0x00)
{
Color |= PPU_Reg_AR;
Color &= 0x0F;
value = ppu_readMemory((addr >> 8) , addr );
BgColor = (value & (1 << (7-(i + PPU_Reg_FH) % 8)))?0x01:0;
pixelColor = ppu_readMemory(0x3F, Color);
value = ppu_readMemory((addr >> 8) , addr | 0x08 );
BgColor |= (value & (1 << (7-(i + PPU_Reg_FH) % 8)))?0x02:0;
if (BgColor > 0x00)
{
BgColor |= PPU_Reg_AR;
BgColor &= 0x0F;
pixelColor = ppu_readMemory(0x3F, BgColor);
}
if (((i + PPU_Reg_FH)%8) == 7)
{
tmp_HHT = ((PPU_Reg_Counter >> 5) & 0x0020) |
tmp_HHT = ((PPU_Reg_Counter >> 5) & 0x0020) |
(PPU_Reg_Counter & 0x001F);
tmp_HHT = (tmp_HHT + 1) & 0x003F;
/* Reassemble with HT & H */
PPU_Reg_Counter = (PPU_Reg_Counter & 0xFBE0) |
((tmp_HHT & 0x0020) << 5) |
(tmp_HHT & 0x001F);
}
/* Reassemble with HT & H */
PPU_Reg_Counter = (PPU_Reg_Counter & 0xFBE0) |
((tmp_HHT & 0x0020) << 5) |
(tmp_HHT & 0x001F);
}
}
/* draw the pixel */
_putpixel(VideoBuffer, i, scanline, pixelColor);
/* Now calculate if there is a sprite here and sprite visibility is on */
if ((ppu_spriteVisibility == 1) &&
(PPU_NbSpriteByScanLine[scanline] != 0))
{
/* scan each sprite on this line to find the one (or more) that is on this pixel */
for (j = 0; j < PPU_NbSpriteByScanLine[scanline]; j++)
{
/* they are orderer by X, so if this one is too far on the right
it's not need to go further */
CurrentSprite = PPU_SpriteByScanLine[scanline][j];
if (PPU_SCANLINESPRITE_GET_X(CurrentSprite) > i)
break; /* break the current for */
if ((PPU_SCANLINESPRITE_GET_X(CurrentSprite) + 8) < i)
continue; /* Not this one too (too far on the left) try next one*/
/* Ok if we arrive here, the current sprite is on the good position */
/* Does the sprite is a BG or FG sprite ? */
/* Ok we could now get the sprite current pixel color */
/* Read sprite scanline pattern */
SpriteVFlip = PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_VFLIP;
if (ppu_spriteSize == 8)
{
addr = (PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite) << 4) + ppu_spritePatternTable;
}
else
{
if (PPU_SCANLINESPRITE_GET_RELY(CurrentSprite) < 8)
addr = (((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0xFE) + (SpriteVFlip?1:0)) << 4) + ((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0x01)?0x1000:0x0000);
else
addr = (((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0xFE) + (SpriteVFlip?0:1)) << 4) + ((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0x01)?0x1000:0x0000);
}
//printf("sprite addr: %04X\n", addr);
if (SpriteVFlip)
{
addr += 7;
addr -= (PPU_SCANLINESPRITE_GET_RELY(CurrentSprite) % 8);
}
else
addr += (PPU_SCANLINESPRITE_GET_RELY(CurrentSprite) % 8);
if (PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_HFLIP)
{
value = ppu_readMemory((addr >> 8) , addr );
SpriteColor = (value & (1 << (i-PPU_SCANLINESPRITE_GET_X(CurrentSprite))))?0x01:0;
value = ppu_readMemory((addr >> 8) , addr | 0x08 );
SpriteColor |= (value & (1 << (i-PPU_SCANLINESPRITE_GET_X(CurrentSprite))))?0x02:0;
}
else
{
value = ppu_readMemory((addr >> 8) , addr );
SpriteColor = (value & (1 << (7-(i-PPU_SCANLINESPRITE_GET_X(CurrentSprite)))))?0x01:0;
value = ppu_readMemory((addr >> 8) , addr | 0x08 );
SpriteColor |= (value & (1 << (7-(i-PPU_SCANLINESPRITE_GET_X(CurrentSprite)))))?0x02:0;
}
if (SpriteColor > 0x00)
{
SpriteColor |= ((PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_UPPERCOLOR) << 2);
SpriteColor &= 0x0F;
}
if ((PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & 0x04) &&
(SpriteColor != 0x00) && (BgColor != 0x00))
{
ppu_spriteZeroHit = 1;
}
if ( ( (PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_BGPRIO) && (BgColor == 0x0000)) ||
(!(PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_BGPRIO)) )
{
if (SpriteColor != 0x00) pixelColor = ppu_readMemory(0x3F, (0x10 + SpriteColor));
}
}
}
/* draw the pixel */
/*if (ppu_displayType)
pixelColor &= 0x30;*/
_putpixel(VideoBuffer, i, scanline, pixelColor);
}
if (ppu_backgroundVisibility || ppu_spriteVisibility)
if (PPU_NbSpriteByScanLineOverFlow[scanline] == 1)
ppu_scanlineSpriteOverflow = 1;
//blit(VideoBuffer, screen, 0, scanline, 0, scanline, 256, 1);
if (ppu_backgroundVisibility == 1)
{
tmp_VVTFV = ((PPU_Reg_Counter >> 3 ) & 0x0100) | /* V */
((PPU_Reg_Counter >> 2 ) & 0x00F8) | /* VT */
((PPU_Reg_Counter >> 12) & 0x0007); /* FV */
//printf("counter:%04X vvtfv:%04X ", PPU_Reg_Counter, tmp_VVTFV);
tmp_VVTFV++;
//printf("__ vvtfv:0x%04X == 0x%04X ? ", tmp_VVTFV, 30<<3);
if ((tmp_VVTFV&0x0F8) == 0xF0)
{
tmp_VVTFV &= ~0x0F8;
tmp_VVTFV ^= 0x100;
//printf("YES _");
}
//printf("vvtfv:%04X ", tmp_VVTFV);
PPU_Reg_Counter = ( PPU_Reg_Counter & 0x041F) |
((tmp_VVTFV & 0x0100 ) << 3 ) | /* V */
((tmp_VVTFV & 0x00F8 ) << 2 ) | /* VT */
((tmp_VVTFV & 0x0007 ) << 12); /* FV */
//printf("counter:%04X ", PPU_Reg_Counter);
/* Update H & HT */
PPU_Reg_Counter = (PPU_Reg_Counter & ~0x041F) |
(PPU_Reg_H << 10) |
PPU_Reg_HT;
}
}
/* Increment only V & VT & FV*/
/*
8421 8421 8421 8421
@ -626,7 +728,7 @@ xxxx 1111 1100 1111
1111 1100 0000 0000
5432 1098 7654 3210
_AAA BCDD DDDE EEEE
xxx x xx xxx : vvtfv = 7BE0
x x xxxx : hht
@ -640,75 +742,13 @@ D = VT
E = HT
*/
if (ppu_backgroundVisibility == 1)
{
tmp_VVTFV = ((PPU_Reg_Counter >> 3 ) & 0x0100) | /* V */
((PPU_Reg_Counter >> 2 ) & 0x00F8) | /* VT */
((PPU_Reg_Counter >> 12) & 0x0007); /* FV */
//printf("counter:%04X vvtfv:%04X ", PPU_Reg_Counter, tmp_VVTFV);
tmp_VVTFV++;
//printf("__ vvtfv:0x%04X == 0x%04X ? ", tmp_VVTFV, 30<<3);
if ((tmp_VVTFV&0x0F8) == 0xF0)
{
tmp_VVTFV &= ~0x0F8;
tmp_VVTFV ^= 0x100;
//printf("YES _");
}
//printf("vvtfv:%04X ", tmp_VVTFV);
PPU_Reg_Counter = ( PPU_Reg_Counter & 0x041F) |
((tmp_VVTFV & 0x0100 ) << 3 ) | /* V */
((tmp_VVTFV & 0x00F8 ) << 2 ) | /* VT */
((tmp_VVTFV & 0x0007 ) << 12); /* FV */
//printf("counter:%04X ", PPU_Reg_Counter);
/* Update H & HT */
PPU_Reg_Counter = (PPU_Reg_Counter & ~0x041F) |
(PPU_Reg_H << 10) |
PPU_Reg_HT;
}
if (PPU_NbSpriteByScanLine[scanline] != 0)
{
for (j = 0; j < PPU_NbSpriteByScanLine[scanline]; j++)
{
static byte i = 0;
pixelColor = (i = (i+1)%4) | ((PPU_SCANLINESPRITE_GET_ATTRS(PPU_SpriteByScanLine[scanline][j]) << 2) & 0x0C);
pixelColor = ppu_readMemory(0x3F, 0x10 + pixelColor);
line(VideoBuffer,
PPU_SCANLINESPRITE_GET_X(PPU_SpriteByScanLine[scanline][j]),
scanline,
PPU_SCANLINESPRITE_GET_X(PPU_SpriteByScanLine[scanline][j]) + 8,
scanline, pixelColor
);
if (PPU_SCANLINESPRITE_GET_ATTRS(PPU_SpriteByScanLine[scanline][j]) & 0x04)
{
//printf("Hit!\n");
ppu_spriteZeroHit = 1;
}
}
}
ppu_scanlineSpriteOverflow = 0;
if (PPU_NbSpriteByScanLineOverFlow[scanline] == 1)
ppu_scanlineSpriteOverflow = 1;
}
/* if (scanline == 100)
ppu_spriteZeroHit = 1;*/
if (scanline == 243)
*/
if (scanline == 239)
{
ppu_inVBlankTime = 1;
IF_N_KEY printf("============= enter vblank =================\n");
return ppu_execNMIonVBlank;
}
}
if (key[KEY_B])
{
@ -717,26 +757,37 @@ E = HT
}
//if (scanline >= (241 + VBLANK_TIME))
if (scanline >= 262)
{
if (scanline >= (240 + VBLANK_TIME))
{
/*for ( i = 0; i < 256; i++)
for ( j = 0; j < 256; j++)
{
int i2 = i<<1, j2 = j<<1;
putpixel(Buffer, i2 , j2 , Op6502(i+j*256));
putpixel(Buffer, i2 , j2+1, Op6502(i+j*256));
putpixel(Buffer, i2+1, j2 , Op6502(i+j*256));
// putpixel(Buffer, i2+1, j2+1, Op6502(i+j*256));
}*/
//textprintf(Buffer, font, 5, 340, 4, "(SL:%d) FPS : %d IPS : %d", scanline, FPS, IPS);
textprintf(screen, font, 260, 3, 4, "FPS : %d (CPU@~%2.2fMhz : %d%%)", FPS, (float) (((float) IPS) / 1000000.0), (int) ((((float) IPS) / 1770000.0) * 100.0));
textprintf(Buffer, font, 260, 3, 4, "FPS : %d (CPU@~%2.2fMhz : %d%%)", FPS, (float) (((float) IPS) / 1000000.0), (int) ((((float) IPS) / 1770000.0) * 100.0));
//printf("(SL:%d) FPS : %d IPS : %d\n", scanline, FPS, IPS);
//ppu_dumpPalette(0, 241);
//ppu_dumpPattern(280, 150);
//ppu_dumpNameTable(256,0);
ppu_dumpPalette(0, 241);
ppu_dumpPattern(280, 150);
ppu_dumpNameTable(256,0);
//ppu_dumpAttributeTable(257, 0);
//blit(VideoBuffer, Buffer, 0, 0, 0, 0, 256, 240);
blit(VideoBuffer, screen, 0, 0, 0, 0, 256, 240);
//blit(Buffer, screen, 0, 0, 0, 0, 512 + 256, 480);
blit(VideoBuffer, Buffer, 0, 0, 0, 0, 256, 240);
blit(Buffer, screen, 0, 0, 0, 0, 512+256, 512);
//blit(VideoBuffer, screen, 0, 0, 0, 0, 256, 240);
IF_N_KEY printf("_____________ leave vblank _________________\n");
ppu_inVBlankTime = 0;
ppu_spriteZeroHit = 0;
//ppu_updateCounters();
ppu_scanlineSpriteOverflow = 0;
//ppu_updateCounters();
}
return 0;
}
@ -749,17 +800,17 @@ byte ppu_readReg(byte id)
static byte garbage;
static byte lastValue;
switch(id)
{
{
default:
garbage = PPU_RegValues[id];
printf("%s: try to read 0x20%02X\n", __func__, id);
break;
case 0x02: /* PPU Status Register */
/* Reset VRam 2005/2006 flipflop */
ppu_VramAccessFlipFlop = 0;
garbage = 0;
garbage |= (ppu_inVBlankTime!=0) ?PPU_FLAG_SR_VBLANK:0;
garbage |= (ppu_spriteZeroHit!=0) ?PPU_FLAG_SR_SPRT0:0;
garbage |= (ppu_scanlineSpriteOverflow!=0)?PPU_FLAG_SR_8SPRT:0;
@ -769,12 +820,12 @@ byte ppu_readReg(byte id)
ppu_inVBlankTime = 0;
break;
case 0x04: /* SPR-RAM I/O */
garbage = ppu_mem_spritesTable[ppu_mem_sptrTablePtr];
garbage = ppu_mem_spritesTable[ppu_mem_sptrTablePtr];
break;
case 0x07: /* VRAM I/O */
case 0x07: /* VRAM I/O */
if (PPU_Reg_Counter < 0x3F00)
{
garbage = lastValue;
@ -786,12 +837,12 @@ byte ppu_readReg(byte id)
lastValue = ppu_readMemory( 0x2F,
PPU_Reg_Counter & 0xFF);
garbage = ppu_readMemory( 0x3F,
PPU_Reg_Counter & 0xFF);
PPU_Reg_Counter & 0xFF);
}
PPU_Reg_Counter += ppu_addrIncrement;
PPU_Reg_Counter += ppu_addrIncrement;
break;
break;
}
//printf("ppuread %02X return: %02X\n", id, garbage);
return garbage;
@ -806,11 +857,11 @@ void ppu_writeReg(byte id, byte val)
switch(id)
{
default:
printf("%s: try to write 0x%02X @ 0x20%02X\n", __func__, val, id);
//printf("%s: try to write 0x%02X @ 0x20%02X\n", __func__, val, id);
break;
case 0x00: /* PPU Control Register #1 */
/*
+===============+===============================================+
|2000 | 1 0 4 |
@ -823,65 +874,64 @@ void ppu_writeReg(byte id, byte val)
*/
IF_N_KEY
printf("%s(%02X, %02X); /* 2000: "
"NMI:%c SPRTSIZE:%02d BGTA:%04X[0x%04X] SPTA:%04X INC:%02d NTA:%04X */\n"
, __func__, id, val,
(val & 0x80)?'E':'D',
(val & 0x20)?16:8,
(val & 0x10)?0x1000:0x0000, PPU_Reg_S,
(val & 0x08)?0x1000:0x0000,
(val & 0x04)?32:1,
(val & 0x03)<<10|0x2000
);
"NMI:%c SPRTSIZE:%02d BGTA:%04X[0x%04X] SPTA:%04X INC:%02d NTA:%04X */\n",
__func__, id, val,
(val & 0x80)?'E':'D',
(val & 0x20)?16:8,
(val & 0x10)?0x1000:0x0000, PPU_Reg_S,
(val & 0x08)?0x1000:0x0000,
(val & 0x04)?32:1,
(val & 0x03)<<10|0x2000
);
/* Set PPU internal registers */
PPU_Reg_V = (val & 0x02)?1:0;
PPU_Reg_V = (val & 0x02)?1:0;
PPU_Reg_H = (val & 0x01)?1:0;
PPU_Reg_S = (val & 0x10)?0x1000:0x0000;
/* Set Other parameters */
ppu_addrIncrement = (val & 0x04)?0x20:0x01;
ppu_spritePatternTable = (val & 0x08)?0x1000:0;
ppu_spriteSize = (val & 0x20)?16:8;
ppu_spriteSize = (val & 0x20)?16:8;
ppu_execNMIonVBlank = (val & 0x80)?1:0;
break;
case 0x01: /* PPU Control Register #2 */
ppu_spriteVisibility = (val & 0x10)?1:0;
ppu_backgroundVisibility = (val & 0x08)?1:0;
ppu_spriteClipping = (val & 0x04)?1:0;
ppu_backgroundClipping = (val & 0x02)?1:0;
ppu_displayType = (val & 0x01)?1:0;
ppu_backgroundVisibility = (val & 0x08)?1:0;
ppu_spriteClipping = (val & 0x04)?1:0;
ppu_backgroundClipping = (val & 0x02)?1:0;
ppu_displayType = (val & 0x01)?1:0;
ppu_updateSpriteScanlineTable();
IF_N_KEY
printf("%s(%02X, %02X); /* 2001 : "
"SprtV:%c BckgV:%c SprtC:%c BckgC:%c DispT:%c"
"SprtV:%c BckgV:%c SprtC:%c BckgC:%c DispT:%c"
" */\n", __func__, id, val,
ppu_spriteVisibility?'y':'n',
ppu_backgroundVisibility?'y':'n',
ppu_spriteClipping?'y':'n',
ppu_backgroundClipping?'y':'n',
ppu_displayType?'m':'c'
);
);
break;
case 0x03: /* SPR-RAM Address Register */
ppu_mem_sptrTablePtr = val;
break;
case 0x04: /* SPR-RAM I/O */
ppu_mem_spritesTable[ppu_mem_sptrTablePtr++] = val;
ppu_updateSpriteScanlineTable();
break;
case 0x05: /* 2005 VRAM Register */
/*
+===============+===============================================+
|2005/1 | 76543 210 |
|2005/2 | 210 76543 |
|2005/2 | 210 76543 |
+---------------+-----------------------------------------------+
| |+===++=++=++=====++=====++===++=++========++==+|
|PPU registers || FV||V||H|| VT|| HT|| FH||S|| PAR||AR||
@ -892,7 +942,7 @@ void ppu_writeReg(byte id, byte val)
if (ppu_VramAccessFlipFlop == 0)
{
ppu_VramAccessFlipFlop = ~0;
PPU_Reg_FH = val & 0x07;
PPU_Reg_HT = (val & 0xF8) >> 3;
IF_N_KEY
@ -901,15 +951,15 @@ void ppu_writeReg(byte id, byte val)
else
{
ppu_VramAccessFlipFlop = 0;
PPU_Reg_FV = val & 0x07;
PPU_Reg_VT = (val & 0xF8) >> 3;
IF_N_KEY
printf("2005/2[%04X]: fv:%01X v:%01X h:%01X vt:%01X ht:%01X fh:%01X\n",val,PPU_Reg_FV,PPU_Reg_V,PPU_Reg_H,PPU_Reg_VT,PPU_Reg_HT,PPU_Reg_FH);
}
break;
break;
case 0x06: /* 2006 VRAM Register */
/*
+===============+===============================================+
@ -926,10 +976,10 @@ void ppu_writeReg(byte id, byte val)
{
ppu_VramAccessFlipFlop = ~0;
PPU_Reg_FV = (val >> 4) & 0x03;
PPU_Reg_FV = (val >> 4) & 0x03;
PPU_Reg_V = (val >> 3) & 0x01;
PPU_Reg_H = (val >> 2) & 0x01;
PPU_Reg_VT = (PPU_Reg_VT & 0x07) | ((val & 0x03) << 3);
PPU_Reg_VT = (PPU_Reg_VT & 0x07) | ((val & 0x03) << 3);
IF_N_KEY
printf("2006/1[%04X]: fv:%01X v:%01X h:%01X vt:%01X ht:%01X fh:%01X\n",val,PPU_Reg_FV,PPU_Reg_V,PPU_Reg_H,PPU_Reg_VT,PPU_Reg_HT,PPU_Reg_FH);
}
@ -938,15 +988,15 @@ void ppu_writeReg(byte id, byte val)
ppu_VramAccessFlipFlop = 0;
PPU_Reg_VT = (PPU_Reg_VT & 0x18) | ((val >> 5) & 0x07);
PPU_Reg_HT = val & 0x1F;
IF_N_KEY
printf("2006/2[%04X]: fv:%01X v:%01X h:%01X vt:%01X ht:%01X fh:%01X\n",val,PPU_Reg_FV,PPU_Reg_V,PPU_Reg_H,PPU_Reg_VT,PPU_Reg_HT,PPU_Reg_FH);
ppu_updateCounters();
}
ppu_updateCounters();
}
break;
case 0x07: /* VRAM I/O */
/*
+---------------+-----------------------------------------------+
@ -956,10 +1006,10 @@ void ppu_writeReg(byte id, byte val)
| |+===++=++=++=====++=====+ |
+---------------+-----------------------------------------------+
|2007 access | DC B A 98765 43210 |
+===============+===============================================+
*/
+===============+===============================================+
*/
//if ( (PPU_Reg_Counter&0xFF00) == 0x3F00)
//{
@ -967,8 +1017,8 @@ void ppu_writeReg(byte id, byte val)
// printf("will write ppu: counter:%04X pa:%02X%02X v:%02X\n",
// PPU_Reg_Counter, (PPU_Reg_Counter>>8) & 0x3F, PPU_Reg_Counter & 0xFF, val);
// }
ppu_writeMemory((PPU_Reg_Counter>>8) & 0x3F, PPU_Reg_Counter & 0xFF, val);
ppu_writeMemory((PPU_Reg_Counter>>8) & 0x3F, PPU_Reg_Counter & 0xFF, val);
IF_N_KEY
{
@ -977,10 +1027,10 @@ void ppu_writeReg(byte id, byte val)
ppu_dumpNameTable(256,0);
blit(Buffer, screen, 0, 0, 0, 0, 512 + 256, 480);
}
PPU_Reg_Counter += ppu_addrIncrement;
break;
PPU_Reg_Counter += ppu_addrIncrement;
break;
}
}

View File

@ -12,15 +12,12 @@
*
*/
#ifndef PPU_MEMORY_H
#define PPU_MEMORY_H
#include <stdio.h>
#include <stdlib.h>
#define __TINES_PPU_INTERNAL__
#include <ppu/ppu.h>
#include <ppu.h>
#include <ppu/ppu.memory.h>
#include <types.h>
@ -39,7 +36,7 @@ byte ppu_SpriteRam[0x100];
/*
* Memory management functions
*
* Yes that true, PPU memory & CPU memory work in a nearly same fashion depite
* Yes that true, PPU memory & CPU memory work in a nearly same fashion despite
* the fact that we actually didn't have any Read/Write hook and ReadWrite
* protection. We even didn't need "attributes" for the page. One of the only
* need is the "powerful" ghost system
@ -159,17 +156,13 @@ void ppu_writeMemory(byte page, byte addr, byte value)
/* Here we will cheat with the palette miroring, since we didn't write
as often as we read the palette, we will mirror here */
//printf("%s palette: color %02X new value : %02d (0x%02X%02X)\n", ((addr&0x10)< 0x10) ? "Bgnd" : "Sprt", addr&0x1F, value & 0x3F, page, addr);
if ((addr & 0x10) == 0x00)
if ((addr & 0xEF) == 0x00)
{
ppu_memoryPages[0x3F][addr&0x1F] = value;
ppu_memoryPages[0x3F][(addr&0x1F) | 0x10] = value;
ppu_memoryPages[0x3F][0x00] = value;
ppu_memoryPages[0x3F][0x10] = value;
}
else
{
ppu_memoryPages[0x3F][addr&0x1F] = value;
if (( addr & 0x1F ) == 0x10 )
ppu_memoryPages[0x3F][(addr&0x1F) & 0xEF] = value;
}
}
else
{
@ -177,5 +170,3 @@ void ppu_writeMemory(byte page, byte addr, byte value)
ptr[addr] = value;
}
}
#endif