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++)
{
@ -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;

View File

@ -835,3 +835,4 @@ case 0x6A:
M_ROR(R->A);
break; /* ROR a ACC */

View File

@ -28,6 +28,8 @@
#include <ppu/ppu.h>
#include <mappers/manager.h>
#include <memory/manager.h>
#include <Sound.h>
#define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
@ -43,7 +45,7 @@ enum Addressing_Modes
static byte *mn[] =
static char *mn[] =
{
"adc ", "and ", "asl ", "bcc ", "bcs ", "beq ", "bit ", "bmi ",
"bne ", "bpl ", "brk", "bvc ", "bvs ", "clc", "cld", "cli",
@ -225,7 +227,7 @@ byte Debug6502(M6502 * R)
);
sprintf(S, "");
S[0] = 0;
remove_keyboard();
#ifdef USE_SOUND
@ -274,7 +276,7 @@ byte Debug6502(M6502 * R)
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("z : Dump mapper status");
puts("i : SpriteTable Dump");
puts("g <nb> : Get sprite <nb> info");
break;
@ -283,7 +285,7 @@ byte Debug6502(M6502 * R)
return (1);
case 'Z':
showlastop();
mapper_dump(stdout);
break;
case 'W':

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 **/
@ -275,6 +424,27 @@ word Run6502(M6502 *R)
if(!Debug6502(R)) return(R->PC.W);
#endif
#ifdef TRACE_EXECUTION
while(1)
{
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];
@ -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

@ -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

View File

@ -20,6 +20,7 @@
#include <sys/mman.h>
#include <sys/time.h>
#include <time.h>
#include <ctype.h>
#ifndef WIN32
@ -41,7 +42,7 @@ int HBLANK_TIME = 140;
double APU_BASEFREQ = 1.7734474;
#elif !ISPAL && ISNTSC
int VBLANK_TIME = 20;
int HBLANK_TIME = 119;
int HBLANK_TIME = 115; //119;
double APU_BASEFREQ = 1.7897725;
//#define VBLANK_TIME 20
//#define HBLANK_TIME 260
@ -69,7 +70,7 @@ double APU_BASEFREQ = 1.7897725;
#include <palette.h>
#define V_MAJOR 0
#define V_MINOR 29
#define V_MINOR 30
#define VS_ID "$Id: main.c 58 2007-05-31 16:02:16Z mtrapier $"
#define VS_REVISION "$Revision: 58 $"
@ -117,8 +118,6 @@ PALETTE pal;
short IRQScanHit = -1;
NesCart *Cart;
/* palette */
unsigned long ColorPalette[ 8 * 63 ];
@ -196,7 +195,7 @@ void LoadPalette(char *filename, PALETTE pal)
fread(&v, 1, 1, fp);
fread(&b, 1, 1, fp);
/* r = (r * 64) / 255;
/* r = (r * 64) / 255;
v = (v * 64) / 255;
b = (b * 64) / 255;*/
@ -279,6 +278,8 @@ void showlastop(FILE *fp)
#endif
}
NesCart *Cart;
void *signalhandler(int sig)
{
static int state=0;
@ -289,7 +290,7 @@ void *signalhandler(int sig)
char S[128];
char name[512];
static FILE *fp = NULL;
sprintf(name, "crashdump-%d.txt", time(NULL));
sprintf(name, "crashdump-%d.txt", (int)time(NULL));
if (state != 0)
{
fprintf(stderr, "\n\n\nCrashed within signal!\nEmergency exit\n");
@ -340,12 +341,12 @@ void *signalhandler(int sig)
Rd6502(0x0100 + (byte) (R->S + 2)),
Rd6502(0x0100 + (byte) (R->S + 3)));
showlastop(fp);
// fprintf(fp, "PPU: CR1: 0x%02X (NT:%d AI:%d SP:%d BP:%d SS:%d NMI:%d)\n",ppu.ControlRegister1.b, ppu.ControlRegister1.s.NameTblAddr, ppu.ControlRegister1.s.AddrIncrmt, ppu.ControlRegister1.s.SptPattern, ppu.ControlRegister1.s.BgPattern, ppu.ControlRegister1.s.SpriteSize, ppu.ControlRegister1.s.VBlank_NMI);
// fprintf(fp, "PPU: CR2: 0x%02X (FBC/CI:%d SV:%d BV:%d SC:%d BC:%d DT:%d)\n",ppu.ControlRegister2.b,ppu.ControlRegister2.s.Colour,ppu.ControlRegister2.s.SpriteVisibility,ppu.ControlRegister2.s.BgVisibility,ppu.ControlRegister2.s.SpriteClipping,ppu.ControlRegister2.s.BgClipping,ppu.ControlRegister2.s.DisplayType);
// fprintf(fp, "PPU: SR: 0x%02X (VB:%d S0:%d SSC:%d VWF:%d)\n", ppu.StatusRegister.b,ppu.StatusRegister.s.VBlankOccur,ppu.StatusRegister.s.Sprite0Occur,ppu.StatusRegister.s.SprtCount,ppu.StatusRegister.s.VRAMProtect);
// fprintf(fp, "PPU: M:%d ST:%d VRAMPtr:0x%04X T:0x%04X\n",ppu.MirrorDir,ppu.ScreenType,ppu.VRAMAddrReg2.W,ppu.TmpVRamPtr);
// fprintf(fp, "PPU: CR1: 0x%02X (NT:%d AI:%d SP:%d BP:%d SS:%d NMI:%d)\n",ppu.ControlRegister1.b, ppu.ControlRegister1.s.NameTblAddr, ppu.ControlRegister1.s.AddrIncrmt, ppu.ControlRegister1.s.SptPattern, ppu.ControlRegister1.s.BgPattern, ppu.ControlRegister1.s.SpriteSize, ppu.ControlRegister1.s.VBlank_NMI);
// fprintf(fp, "PPU: CR2: 0x%02X (FBC/CI:%d SV:%d BV:%d SC:%d BC:%d DT:%d)\n",ppu.ControlRegister2.b,ppu.ControlRegister2.s.Colour,ppu.ControlRegister2.s.SpriteVisibility,ppu.ControlRegister2.s.BgVisibility,ppu.ControlRegister2.s.SpriteClipping,ppu.ControlRegister2.s.BgClipping,ppu.ControlRegister2.s.DisplayType);
// fprintf(fp, "PPU: SR: 0x%02X (VB:%d S0:%d SSC:%d VWF:%d)\n", ppu.StatusRegister.b,ppu.StatusRegister.s.VBlankOccur,ppu.StatusRegister.s.Sprite0Occur,ppu.StatusRegister.s.SprtCount,ppu.StatusRegister.s.VRAMProtect);
// fprintf(fp, "PPU: M:%d ST:%d VRAMPtr:0x%04X T:0x%04X\n",ppu.MirrorDir,ppu.ScreenType,ppu.VRAMAddrReg2.W,ppu.TmpVRamPtr);
mapper_dump(fp);
//MapperDump(fp);
for(I = 0; I < 0xFFFF; I += 0x10)
fprintf(fp, "%04X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X | %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
@ -386,7 +387,6 @@ void WrHook4000Multiplexer(byte addr, byte value)
{
static byte SQ1V = 0;
static byte SQ2V = 0;
static byte TRIV = 0;
static byte NOIV = 0;
static unsigned short SQ1P = 0;
@ -404,7 +404,8 @@ void WrHook4000Multiplexer(byte addr, byte value)
static byte Sq2_reg2 = 0;
static byte Sq2_reg3 = 0;
double SQ;
double SQ = 0.0;
switch(addr)
{
#ifdef USE_SOUND
@ -445,12 +446,12 @@ void WrHook4000Multiplexer(byte addr, byte value)
//printf("SQ1V = %d - SQ = %f - SQ1P = %d\n", SQ1V, SQ, SQ1P);
// { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 0, SQ1P, SQ1V); fclose(fp); }
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 0, SQ1P, SQ1V); fclose(fp); }
#endif
Sound(0, (int) SQ/22, (0xFF/0x0F) * SQ1V);
// printf("40%02X: 0x%02X (SQ1P:%d SQ:%f (%d))\n", addr, value, SQ1P, SQ, (int) SQ);
// printf("40%02X: 0x%02X (SQ1P:%d SQ:%f (%d))\n", addr, value, SQ1P, SQ, (int) SQ);
Sq1_reg2 = value;
break;
@ -459,7 +460,9 @@ void WrHook4000Multiplexer(byte addr, byte value)
SQ1P = Sq1_reg2 | ((value&0x7) << 8);
SQ = APU_BASEFREQ * 1000 * 1000 / (SQ1P+1 /*+
(Sq1_reg1&0x80)?0:( (Sq1_reg1&0x08)?(SQ1P>>(Sq1_reg1&0x07)):(SQ1P<<(Sq1_reg1&0x07)) )*/);
// { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 0, SQ1P, SQ1V); fclose(fp); }
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 0, SQ1P, SQ1V); fclose(fp); }
#endif
Sound(0, (int) SQ/22, (0xFF/0x0F) * SQ1V);
break;
@ -505,8 +508,9 @@ void WrHook4000Multiplexer(byte addr, byte value)
printf("Sq2 reg2: 0x%02X\n", value);
printf("Sq2 reg3: 0x%02X\n", Sq2_reg3);
printf("SQ2V = %d - SQ = %f - SQ2P = %d\n", SQ2V, SQ, SQ2P);*/
// { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 1, SQ2P, SQ2V); fclose(fp); }
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 1, SQ2P, SQ2V); fclose(fp); }
#endif
Sound(1, (int) SQ/22, (0xFF/0x0F) * SQ2V);
break;
@ -517,43 +521,55 @@ void WrHook4000Multiplexer(byte addr, byte value)
//SQ2P = (SQ2P & 0x00FF) | ((value&0x7) << 8);
SQ = APU_BASEFREQ * 1000 * 1000 / (SQ2P+1 /*+
(Sq2_reg1&0x80)?0:( (Sq2_reg1&0x08)?(SQ2P>>(Sq2_reg1&0x07)):(SQ2P<<(Sq2_reg1&0x07)) )*/);
// { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 1, SQ2P, SQ2V); fclose(fp); }
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 1, SQ2P, SQ2V); fclose(fp); }
#endif
Sound(1, (int) SQ/22, (0xFF/0x0F) * SQ2V);
break;
case 0x0A:
TRIP = (TRIP & 0xFF00) | value;
SQ = APU_BASEFREQ * 1000 * 1000 / TRIP;
// { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 255); fclose(fp); }
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 127); fclose(fp); }
#endif
Sound(2, (int) SQ/22, 127);
break;
case 0x0B:
TRIP = (TRIP & 0x00FF) | ((value&0x7) << 8);;
SQ = APU_BASEFREQ * 1000 * 1000 / TRIP;
// { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 255); fclose(fp); }
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 127); fclose(fp); }
#endif
Sound(2, (int) SQ/22, 127);
break;
/* case 0x0C:
case 0x0C:
NOIV = value & 0x0F;
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 3, NOIP, NOIV); fclose(fp); }
#endif
SetSound(3, SND_NOISE);
Sound(3, (int) SQ/22, (0xFF/0x0F) * NOIV);
break;
case 0x0E:
NOIP = value & 0x0F;
SQ = APU_BASEFREQ * 1000 * 1000 / NOIP;
// { FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 2, TRIP, 255); fclose(fp); }
#ifdef SOUND_LOG
{ FILE *fp = fopen("sound.log", "at"); fprintf(fp, "%d %d %d\n", 3, NOIP, NOIV); fclose(fp); }
#endif
SetSound(3, SND_NOISE);
Sound(3, (int) SQ/22, (0xFF/0x0F) * NOIV);
Sound(3, (int) SQ/22, NOIV);
break;
case 0x0F:
break;*/
break;
case 0x15:
/* DMC, Noise, Triangle, Sq 2, Sq 1 */
//SetChannels(0, (value&0x01)?0x01:0);
/* printf("40%02X: 0x%02X [%c%c%c%c%c]\n", addr, value,
/* printf("40%02X: 0x%02X [%c%c%c%c%c]\n", addr, value,
(value&0x10)?'d':'.',
(value&0x08)?'n':'.',
(value&0x04)?'t':'.',
@ -561,7 +577,7 @@ void WrHook4000Multiplexer(byte addr, byte value)
(value&0x01)?'1':'.');*/
break;
#endif
#endif
case 0x14:
ppu_fillSprRamDMA(value);
break;
@ -572,13 +588,15 @@ void WrHook4000Multiplexer(byte addr, byte value)
break;
case 0x17:
// printf("40%02X: 0x%02X\n", addr, value);
// printf("40%02X: 0x%02X\n", addr, value);
if (value == 0x00)
Int6502(&MainCPU,INT_IRQ);
break;
// default:
// default:
//Page40[addr] = value;
// printf("40%02X: 0x%02X\n", addr, value);
// printf("pAPU: 0x%X @ 0x40%X\n", value, addr);
// printf("pAPU: 0x%X @ 0x40%X\n", value, addr);
}
}
@ -828,7 +846,7 @@ int main(int argc, char *argv[])
}
printf("Reseting main RAM...\t\t");
//Force the stack to be empty of zero
/* Force the stack to be full of zero */
for( i = 0x100 ; i < 0x200 ; i++ ) {
Wr6502(i, 0x00);
}
@ -904,7 +922,7 @@ int main(int argc, char *argv[])
if (ppu_init() != 0)
fatal("PPU Initialisation error..\n");
//DumpMemoryState();
/* DumpMemoryState(); */
if (Cart->Flags & iNES_4SCREEN)
{
ppu_setScreenMode(PPU_SCMODE_FOURSC);
@ -996,25 +1014,6 @@ int main(int argc, char *argv[])
}
exit(0);*/
/* int K, L1, V = 127, L2, I;
if(440>=48000/3) printf("Pwet\n");
K=48000/440;
L1=0;
V<<=7;
for(I=0;I<SND_BUFSIZE;I++)
{
L2=L1+K;
printf("L1:%d L2:%d K:%d V:%d\n", L1, L2, K, V);
//L1&0x8000?(L2&0x8000? V:0):(L2&0x8000? 0:-V)
//printf("Wave[%d] = %d\n", I, L1&0x8000?(L2&0x8000? V:0):(L2&0x8000? 0:-V));
L1=L2;
}
printf("Phaser: %d\n", L1);
exit(0);*/
printf("Press ESC to pause emulation and jump to debugguer\n");
@ -1023,7 +1022,6 @@ int main(int argc, char *argv[])
//Do a loop every HBlank
MainCPU.IPeriod = HBLANK_TIME;
//MainCPU.IPeriod = 260;
Reset6502(&MainCPU);
@ -1066,7 +1064,7 @@ extern byte *memory_pages[0xFF];
byte Op6502(register word Addr)
{ /* Read OpCodes */
byte *ptr;
return (ptr = memory_pages[(Addr&0xFF00)>>8])>1?ptr[Addr&0x00FF]:0;
return ((ptr = memory_pages[(Addr&0xFF00)>>8])>(byte*)1)?ptr[Addr&0x00FF]:0;
//return ReadMemory((Addr&0xFF00)>>8,Addr&0x00FF);
}
@ -1082,7 +1080,6 @@ byte Loop6502(register M6502 * R)
{
byte ret;
short skey;
printf("pouic\n");
long WaitTime;
static long delta=0;
@ -1110,19 +1107,21 @@ byte Loop6502(register M6502 * R)
if (ScanLine == 241)
frame++;
//if (ScanLine >= (241 + VBLANK_TIME))
if (ScanLine >= 262)
if (ScanLine >= 240 + VBLANK_TIME)
{ /* End of VBlank Time */
/* Sync at 60FPS */
/* Get current time in microseconds */
gettimeofday(&timeEnd, NULL);
/* Calculate the waiting time, 16666 is the time of one frame in microseconds at a 60Hz rate) */
WaitTime = (timeEnd.tv_sec) - (timeStart.tv_sec);
WaitTime *= 1000000;
WaitTime += (timeEnd.tv_usec - timeStart.tv_usec);
#if !ISPAL && ISNTSC
/* Calculate the waiting time, 16666 is the time of one frame in microseconds at a 60Hz rate) */
WaitTime = 16666 - WaitTime + delta;
#elif ISPAL && !ISNTSC
WaitTime = 20000 - WaitTime + delta;
#endif
/* If we press Page Up, we dont we to accelerate "time" */
if (!key[KEY_PGUP])

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,6 +1,6 @@
/*
* AOROM Mapper - The TI-NESulator Project
* aorom.h
* aorom.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
@ -12,6 +12,8 @@
*
*/
#include "aorom.h"
unsigned char aorom_load_bank;
void aorom_MapperWriteHook(register byte Addr, register byte Value);

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,6 +1,6 @@
/*
* IREMH3001 Mapper - The TI-NESulator Project
* iremh3001.h
* iremh3001.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2007 986Corp. All rights reserved.
@ -12,6 +12,8 @@
*
*/
#include "iremh3001.h"
unsigned short iremh3001_prom_slot[3];
unsigned short iremh3001_vrom_slot[8];
@ -41,7 +43,7 @@ int iremh3001_InitMapper(NesCart * cart)
}
int iremh3001_MapperWriteHook(register word Addr, register byte Value)
int iremh3001_MapperWriteHook(register byte Addr, register byte Value)
{
switch(Addr)

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 $
*
*/
@ -13,4 +18,3 @@
int mmc1_InitMapper (NesCart *cart);
int mmc1_MapperIRQ (int cycledone);
void mmc1_MapperDump ();
void mmc1_MapperWriteHook(register byte Addr, register byte Value);

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

@ -12,6 +12,8 @@
*
*/
#include "mmc4.h"
byte mmc4_RegA;
byte mmc4_RegB;
byte mmc4_RegC;
@ -88,7 +90,8 @@ int mmc4_InitMapper(NesCart * cart)
set_prom_bank_16k(0x8000,0);
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
if (cart->VROMSize > 0) set_vrom_bank_8k(0x0000,0);
if (cart->VROMSize > 0)
set_vrom_bank_8k(0x0000,0);
/* Mapper should register itself for write hook */
for (i = 0xA0; i < 0xB0 ; i++)

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 $
*
*/
@ -13,4 +18,3 @@
int norom_InitMapper (NesCart *cart);
int norom_MapperIRQ (int cycledone);
void norom_MapperDump ();
void norom_MapperWriteHook(register byte Addr, register byte Value);

View File

@ -12,9 +12,11 @@
*
*/
#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,11 +9,27 @@
/* 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 -- )
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

@ -23,6 +23,8 @@
#include <ppu/ppu.memory.h>
#include <ppu/ppu.debug.h>
#include <M6502.h>
#include <memory/manager.h>
#define __TINES_PLUGINS__
@ -186,6 +188,9 @@ 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;
@ -221,7 +226,6 @@ int ppu_init()
/* Third: set registers to defaults */
/* Now test the memory ! */
/* Fille PPU memory with garbage */
@ -232,6 +236,7 @@ int ppu_init()
for (i = 0x0000; i < 0x001F ; i++)
ppu_mem_paletteValues[i] = rand()%0xFF;
//memcpy(ppu_mem_paletteValues, defaultColors, 32);
/* Dump PPU memory state */
//ppu_memoryDumpState(stdout);
@ -299,7 +304,7 @@ void ppu_updateSpriteScanlineTable()
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];
@ -312,15 +317,14 @@ void ppu_updateSpriteScanlineTable()
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 */
@ -509,15 +513,20 @@ _AAA BCDD DDDE EEEE
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 long CurrentSprite;
byte SpriteVFlip;
/* If no plan activated, we have nothing to do ! */
@ -536,37 +545,12 @@ int ppu_hblank(int scanline)
/* 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 */
/* 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;
@ -574,31 +558,27 @@ xxxx 1111 1100 1111
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;
BgColor = (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;
BgColor |= (value & (1 << (7-(i + PPU_Reg_FH) % 8)))?0x02:0;
if (Color > 0x00)
if (BgColor > 0x00)
{
BgColor |= PPU_Reg_AR;
BgColor &= 0x0F;
Color |= PPU_Reg_AR;
Color &= 0x0F;
pixelColor = ppu_readMemory(0x3F, Color);
pixelColor = ppu_readMemory(0x3F, BgColor);
}
if (((i + PPU_Reg_FH)%8) == 7)
@ -612,35 +592,103 @@ xxxx 1111 1100 1111
((tmp_HHT & 0x0020) << 5) |
(tmp_HHT & 0x001F);
}
}
/* 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);
}
/* Increment only V & VT & FV*/
/*
if (ppu_backgroundVisibility || ppu_spriteVisibility)
if (PPU_NbSpriteByScanLineOverFlow[scanline] == 1)
ppu_scanlineSpriteOverflow = 1;
8421 8421 8421 8421
-------------------
1111 1100 0000 0000
5432 1098 7654 3210
_AAA BCDD DDDE EEEE
xxx x xx xxx : vvtfv = 7BE0
x x xxxx : hht
B DDDD DAAA : vvtfv
CE EEEE : hht
A = FV
B = V
C = H
D = VT
E = HT
//blit(VideoBuffer, screen, 0, scanline, 0, scanline, 256, 1);
*/
if (ppu_backgroundVisibility == 1)
{
@ -670,40 +718,32 @@ E = HT
(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;
}
/* Increment only V & VT & FV*/
}
}
ppu_scanlineSpriteOverflow = 0;
if (PPU_NbSpriteByScanLineOverFlow[scanline] == 1)
ppu_scanlineSpriteOverflow = 1;
/*
}
8421 8421 8421 8421
-------------------
1111 1100 0000 0000
5432 1098 7654 3210
_AAA BCDD DDDE EEEE
/* if (scanline == 100)
ppu_spriteZeroHit = 1;*/
xxx x xx xxx : vvtfv = 7BE0
x x xxxx : hht
if (scanline == 243)
B DDDD DAAA : vvtfv
CE EEEE : hht
A = FV
B = V
C = H
D = VT
E = HT
*/
if (scanline == 239)
{
ppu_inVBlankTime = 1;
IF_N_KEY printf("============= enter vblank =================\n");
@ -717,25 +757,36 @@ 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_scanlineSpriteOverflow = 0;
//ppu_updateCounters();
}
return 0;
@ -806,7 +857,7 @@ 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 */
@ -823,8 +874,8 @@ 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,
"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,
@ -853,6 +904,8 @@ void ppu_writeReg(byte id, byte val)
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"
@ -863,7 +916,6 @@ void ppu_writeReg(byte id, byte val)
ppu_backgroundClipping?'y':'n',
ppu_displayType?'m':'c'
);
break;
case 0x03: /* SPR-RAM Address Register */
@ -872,9 +924,7 @@ void ppu_writeReg(byte id, byte val)
case 0x04: /* SPR-RAM I/O */
ppu_mem_spritesTable[ppu_mem_sptrTablePtr++] = val;
ppu_updateSpriteScanlineTable();
break;
case 0x05: /* 2005 VRAM Register */

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