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:
parent
bc118baac8
commit
5d3895f08a
@ -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;
|
||||
|
||||
|
||||
1671
src/corecpu/Codes.h
1671
src/corecpu/Codes.h
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
||||
@ -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() **********************************************/
|
||||
|
||||
@ -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
|
||||
|
||||
937
src/main.c
937
src/main.c
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,7 @@ MapperWriteHook mapper_hook;
|
||||
typedef struct Mapper_
|
||||
{
|
||||
byte id;
|
||||
byte *name;
|
||||
char *name;
|
||||
|
||||
MapperInit init;
|
||||
MapperIRQ irq;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
||||
@ -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 ();
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 ();
|
||||
@ -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;
|
||||
@ -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 }
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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]));
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
566
src/ppu/ppu.c
566
src/ppu/ppu.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user