rewrite dma, gxfifo, gxstat, command unpacking; old gxfifo removed; many games fixed, gta and dq4 broken; dma still not finished; your savestates will be broken; have coded 40 hours without checking performance, beware; add dma regs to ioregview, fix cpu selector in < vista;
This commit is contained in:
parent
8c6e56e679
commit
523d2713f9
|
@ -144,6 +144,10 @@ void IPC_FIFOcnt(u8 proc, u16 val)
|
|||
GFX_PIPE gxPIPE;
|
||||
GFX_FIFO gxFIFO;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void GFX_PIPEclear()
|
||||
{
|
||||
gxPIPE.head = 0;
|
||||
|
@ -153,192 +157,122 @@ void GFX_PIPEclear()
|
|||
|
||||
void GFX_FIFOclear()
|
||||
{
|
||||
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
|
||||
gxstat &= 0x0000FFFF;
|
||||
|
||||
gxFIFO.head = 0;
|
||||
gxFIFO.tail = 0;
|
||||
gxFIFO.size = 0;
|
||||
gxstat |= 0x06000000;
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
|
||||
}
|
||||
|
||||
static void GXF_FIFO_handleEvents()
|
||||
{
|
||||
if(gxFIFO.size <= 127)
|
||||
{
|
||||
//TODO - should this always happen, over and over, until the dma is disabled?
|
||||
//or only when we change to this state?
|
||||
if(MMU_new.gxstat.gxfifo_irq == 1)
|
||||
setIF(0, (1<<21)); //the half gxfifo irq
|
||||
|
||||
//might need to trigger a gxfifo dma
|
||||
triggerDma(EDMAMode_GXFifo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(gxFIFO.size == 0) {
|
||||
//we just went to empty
|
||||
if(MMU_new.gxstat.gxfifo_irq == 2)
|
||||
setIF(0, (1<<21)); //the empty gxfifo irq
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GFX_FIFOsend(u8 cmd, u32 param)
|
||||
{
|
||||
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
|
||||
if(cmd==0x41) {
|
||||
int zzz=9;
|
||||
}
|
||||
|
||||
//INFO("gxFIFO: send 0x%02X = 0x%08X (size %03i/0x%02X) gxstat 0x%08X\n", cmd, param, gxFIFO.size, gxFIFO.size, gxstat);
|
||||
//printf("fifo recv: %02X: %08X upto:%d\n",cmd,param,gxFIFO.size+1);
|
||||
|
||||
gxstat &= 0xF000FFFF;
|
||||
//TODO - WOAH ! NOT HANDLING A TOO-BIG FIFO RIGHT NOW!
|
||||
//if (gxFIFO.size > 255)
|
||||
//{
|
||||
// GXF_FIFO_handleEvents();
|
||||
// //NEED TO HANDLE THIS!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
if (gxFIFO.size == 0) // FIFO empty
|
||||
{
|
||||
gxstat |= 0x06000000;
|
||||
if (gxPIPE.size < 4) // pipe not full
|
||||
{
|
||||
gxPIPE.cmd[gxPIPE.tail] = cmd;
|
||||
gxPIPE.param[gxPIPE.tail] = param;
|
||||
gxPIPE.tail++;
|
||||
gxPIPE.size++;
|
||||
if (gxPIPE.tail > 3) gxPIPE.tail = 0;
|
||||
// //gxstat |= 0x08000000; // busy
|
||||
// NDS_RescheduleGXFIFO(1);
|
||||
// //INFO("ERROR: gxFIFO is full (cmd 0x%02X = 0x%08X) (prev cmd 0x%02X = 0x%08X)\n", cmd, param, gxFIFO.cmd[255], gxFIFO.param[255]);
|
||||
// return;
|
||||
//}
|
||||
|
||||
#ifdef USE_GEOMETRY_FIFO_EMULATION
|
||||
gxstat |= 0x08000000; // set busy flag
|
||||
#endif
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
|
||||
NDS_RescheduleGXFIFO();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (gxFIFO.size > 255)
|
||||
{
|
||||
#ifdef USE_GEOMETRY_FIFO_EMULATION
|
||||
gxstat |= 0x01000000; // full
|
||||
gxstat |= 0x08000000; // busy
|
||||
#else
|
||||
gxstat |= 0x02000000; // this is hack (must be removed later)
|
||||
#endif
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
|
||||
NDS_RescheduleGXFIFO();
|
||||
//INFO("ERROR: gxFIFO is full (cmd 0x%02X = 0x%08X) (prev cmd 0x%02X = 0x%08X)\n", cmd, param, gxFIFO.cmd[255], gxFIFO.param[255]);
|
||||
return;
|
||||
}
|
||||
|
||||
gxFIFO.cmd[gxFIFO.tail] = cmd;
|
||||
gxFIFO.param[gxFIFO.tail] = param;
|
||||
gxFIFO.tail++;
|
||||
gxFIFO.size++;
|
||||
if (gxFIFO.tail > 255) gxFIFO.tail = 0;
|
||||
if (gxFIFO.tail > HACK_GXIFO_SIZE-1) gxFIFO.tail = 0;
|
||||
|
||||
#ifdef USE_GEOMETRY_FIFO_EMULATION
|
||||
gxstat |= 0x08000000; // set busy flag
|
||||
#endif
|
||||
|
||||
gxstat |= ((gxFIFO.size & 0x1FF) << 16);
|
||||
|
||||
if (gxFIFO.size < 128) // less half
|
||||
{
|
||||
gxstat |= 0x02000000;
|
||||
if(gxFIFO.size>=HACK_GXIFO_SIZE) {
|
||||
printf("--FIFO FULL-- : %d\n",gxFIFO.size);
|
||||
}
|
||||
|
||||
#ifndef USE_GEOMETRY_FIFO_EMULATION
|
||||
gxstat |= 0x02000000; // this is hack (must be removed later)
|
||||
#endif
|
||||
//gxstat |= 0x08000000; // set busy flag
|
||||
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
|
||||
GXF_FIFO_handleEvents();
|
||||
|
||||
NDS_RescheduleGXFIFO();
|
||||
NDS_RescheduleGXFIFO(1);
|
||||
}
|
||||
|
||||
// this function used ONLY in gxFIFO
|
||||
BOOL GFX_PIPErecv(u8 *cmd, u32 *param)
|
||||
{
|
||||
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
|
||||
gxstat &= 0xF7FFFFFF; // clear busy flag
|
||||
//gxstat &= 0xF7FFFFFF; // clear busy flag
|
||||
|
||||
if (gxPIPE.size > 0)
|
||||
if (gxFIFO.size == 0)
|
||||
{
|
||||
*cmd = gxPIPE.cmd[gxPIPE.head];
|
||||
*param = gxPIPE.param[gxPIPE.head];
|
||||
gxPIPE.head++;
|
||||
gxPIPE.size--;
|
||||
if (gxPIPE.head > 3) gxPIPE.head = 0;
|
||||
|
||||
if (gxPIPE.size < 3)
|
||||
{
|
||||
if (gxFIFO.size > 0)
|
||||
{
|
||||
gxstat &= 0xF000FFFF;
|
||||
|
||||
gxPIPE.cmd[gxPIPE.tail] = gxFIFO.cmd[gxFIFO.head];
|
||||
gxPIPE.param[gxPIPE.tail] = gxFIFO.param[gxFIFO.head];
|
||||
gxPIPE.tail++;
|
||||
gxPIPE.size++;
|
||||
if (gxPIPE.tail > 3) gxPIPE.tail = 0;
|
||||
|
||||
gxFIFO.head++;
|
||||
gxFIFO.size--;
|
||||
if (gxFIFO.head > 255) gxFIFO.head = 0;
|
||||
|
||||
if (gxFIFO.size > 0)
|
||||
{
|
||||
gxPIPE.cmd[gxPIPE.tail] = gxFIFO.cmd[gxFIFO.head];
|
||||
gxPIPE.param[gxPIPE.tail] = gxFIFO.param[gxFIFO.head];
|
||||
gxPIPE.tail++;
|
||||
gxPIPE.size++;
|
||||
if (gxPIPE.tail > 3) gxPIPE.tail = 0;
|
||||
|
||||
gxFIFO.head++;
|
||||
gxFIFO.size--;
|
||||
if (gxFIFO.head > 255) gxFIFO.head = 0;
|
||||
}
|
||||
|
||||
gxstat |= ((gxFIFO.size & 0x1FF) << 16);
|
||||
|
||||
if (gxFIFO.size < 128)
|
||||
{
|
||||
gxstat |= 0x02000000;
|
||||
if (gxstat & 0x40000000) // IRQ: less half
|
||||
{
|
||||
setIF(0, (1<<21));
|
||||
}
|
||||
execHardware_doAllDma(EDMAMode_GXFifo);
|
||||
}
|
||||
|
||||
if (gxFIFO.size == 0) // empty
|
||||
{
|
||||
gxstat |= 0x04000000;
|
||||
if (gxstat & 0x80000000) // IRQ: empty
|
||||
setIF(0, (1<<21));
|
||||
}
|
||||
}
|
||||
else // FIFO empty
|
||||
{
|
||||
gxstat &= 0xF000FFFF;
|
||||
gxstat |= 0x06000000;
|
||||
if (gxstat & 0x80000000) // IRQ: empty
|
||||
setIF(0, (1<<21));
|
||||
}
|
||||
}
|
||||
|
||||
if (gxPIPE.size > 0)
|
||||
gxstat |= 0x08000000; // set busy flag
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
if (gxstat & 0x80000000) // IRQ: empty
|
||||
setIF(0, (1<<21));
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
|
||||
GXF_FIFO_handleEvents();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*cmd = gxFIFO.cmd[gxFIFO.head];
|
||||
*param = gxFIFO.param[gxFIFO.head];
|
||||
|
||||
gxFIFO.head++;
|
||||
gxFIFO.size--;
|
||||
if (gxFIFO.head > HACK_GXIFO_SIZE-1) gxFIFO.head = 0;
|
||||
|
||||
GXF_FIFO_handleEvents();
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
void GFX_FIFOcnt(u32 val)
|
||||
{
|
||||
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
|
||||
//INFO("gxFIFO: write cnt 0x%08X (prev 0x%08X) FIFO size %03i PIPE size %03i\n", val, gxstat, gxFIFO.size, gxPIPE.size);
|
||||
//zeromus: i dont like any of this.
|
||||
|
||||
if (val & (1<<29)) // clear? (only in homebrew?)
|
||||
{
|
||||
GFX_PIPEclear();
|
||||
GFX_FIFOclear();
|
||||
return;
|
||||
}
|
||||
////INFO("gxFIFO: write cnt 0x%08X (prev 0x%08X) FIFO size %03i PIPE size %03i\n", val, gxstat, gxFIFO.size, gxPIPE.size);
|
||||
|
||||
if (val & (1<<15)) // projection stack pointer reset
|
||||
{
|
||||
gfx3d_ClearStack();
|
||||
val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13)
|
||||
}
|
||||
//if (val & (1<<29)) // clear? (only in homebrew?)
|
||||
//{
|
||||
// GFX_PIPEclear();
|
||||
// GFX_FIFOclear();
|
||||
// return;
|
||||
//}
|
||||
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, val);
|
||||
//if (val & (1<<15)) // projection stack pointer reset
|
||||
//{
|
||||
// gfx3d_ClearStack();
|
||||
// val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13)
|
||||
//}
|
||||
|
||||
if (gxFIFO.size == 0) // empty
|
||||
{
|
||||
if (val & 0x80000000) // IRQ: empty
|
||||
setIF(0, (1<<21));
|
||||
}
|
||||
//T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, val);
|
||||
|
||||
//if (gxFIFO.size == 0) // empty
|
||||
//{
|
||||
// if (val & 0x80000000) // IRQ: empty
|
||||
// setIF(0, (1<<21));
|
||||
//}
|
||||
}
|
||||
|
||||
// ========================================================= DISP FIFO
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#ifndef FIFO_H
|
||||
#define FIFO_H
|
||||
|
||||
//#define USE_GEOMETRY_FIFO_EMULATION //enable gxFIFO emulation
|
||||
|
||||
#include "types.h"
|
||||
|
||||
//=================================================== IPC FIFO
|
||||
|
@ -47,14 +45,20 @@ extern u32 IPC_FIFOrecv(u8 proc);
|
|||
extern void IPC_FIFOcnt(u8 proc, u16 val);
|
||||
|
||||
//=================================================== GFX FIFO
|
||||
|
||||
//yeah, its oversize for now. thats a simpler solution
|
||||
//moon seems to overdrive the fifo with immediate dmas
|
||||
//i think this might be nintendo code too
|
||||
#define HACK_GXIFO_SIZE 200000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 cmd[256];
|
||||
u32 param[256];
|
||||
u8 cmd[HACK_GXIFO_SIZE];
|
||||
u32 param[HACK_GXIFO_SIZE];
|
||||
|
||||
u16 head; // start position
|
||||
u16 tail; // tail
|
||||
u16 size; // size FIFO buffer
|
||||
u32 head; // start position
|
||||
u32 tail; // tail
|
||||
u32 size; // size FIFO buffer
|
||||
} GFX_FIFO;
|
||||
|
||||
typedef struct
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,8 +27,9 @@
|
|||
|
||||
#include "FIFO.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include "registers.h"
|
||||
#include "mc.h"
|
||||
#include "bits.h"
|
||||
|
||||
#define ARMCPU_ARM7 1
|
||||
#define ARMCPU_ARM9 0
|
||||
|
@ -36,6 +37,195 @@
|
|||
|
||||
typedef const u8 TWaitState;
|
||||
|
||||
|
||||
enum EDMAMode : u8
|
||||
{
|
||||
EDMAMode_Immediate = 0,
|
||||
EDMAMode_VBlank = 1,
|
||||
EDMAMode_HBlank = 2,
|
||||
EDMAMode_HStart = 3,
|
||||
EDMAMode_MemDisplay = 4,
|
||||
EDMAMode_Card = 5,
|
||||
EDMAMode_GBASlot = 6,
|
||||
EDMAMode_GXFifo = 7,
|
||||
EDMAMode7_Wifi = 8,
|
||||
EDMAMode7_GBASlot = 9,
|
||||
};
|
||||
|
||||
enum EDMABitWidth : u8
|
||||
{
|
||||
EDMABitWidth_16 = 0,
|
||||
EDMABitWidth_32 = 1
|
||||
};
|
||||
|
||||
enum EDMASourceUpdate : u8
|
||||
{
|
||||
EDMASourceUpdate_Increment = 0,
|
||||
EDMASourceUpdate_Decrement = 1,
|
||||
EDMASourceUpdate_Fixed = 2,
|
||||
EDMASourceUpdate_Invalid = 3,
|
||||
};
|
||||
|
||||
enum EDMADestinationUpdate : u8
|
||||
{
|
||||
EDMADestinationUpdate_Increment = 0,
|
||||
EDMADestinationUpdate_Decrement = 1,
|
||||
EDMADestinationUpdate_Fixed = 2,
|
||||
EDMADestinationUpdate_IncrementReload = 3,
|
||||
};
|
||||
|
||||
|
||||
class TRegister_32
|
||||
{
|
||||
public:
|
||||
virtual u32 read32() = 0;
|
||||
virtual void write32(const u32 val) = 0;
|
||||
void write(const int size, const u32 adr, const u32 val) {
|
||||
if(size==32) write32(val);
|
||||
else {
|
||||
const u32 offset = adr&3;
|
||||
const u32 baseaddr = adr&~offset;
|
||||
if(size==8) {
|
||||
printf("WARNING! 8BIT DMA ACCESS\n");
|
||||
u32 mask = 0xFF<<(offset<<3);
|
||||
write32((read32()&~mask)|(val<<(offset<<3)));
|
||||
}
|
||||
else if(size==16) {
|
||||
u32 mask = 0xFFFF<<(offset<<3);
|
||||
write32((read32()&~mask)|(val<<(offset<<3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 read(const int size, const u32 adr)
|
||||
{
|
||||
if(size==32) return read32();
|
||||
else {
|
||||
const u32 offset = adr&3;
|
||||
const u32 baseaddr = adr&~offset;
|
||||
if(size==8) { printf("WARNING! 8BIT DMA ACCESS\n"); return (read32()>>(offset<<3))&0xFF; }
|
||||
else return (read32()>>(offset<<3))&0xFFFF;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct TGXSTAT : public TRegister_32
|
||||
{
|
||||
TGXSTAT() {
|
||||
gxfifo_irq = se = tr = tb = 0;
|
||||
}
|
||||
u8 tb; //test busy
|
||||
u8 tr; //test result
|
||||
u8 se; //stack error
|
||||
u8 gxfifo_irq; //irq configuration
|
||||
|
||||
|
||||
virtual u32 read32();
|
||||
virtual void write32(const u32 val);
|
||||
|
||||
void savestate(EMUFILE *f);
|
||||
bool loadstate(EMUFILE *f);
|
||||
};
|
||||
|
||||
void triggerDma(EDMAMode mode);
|
||||
|
||||
class DmaController
|
||||
{
|
||||
public:
|
||||
u8 enable, irq, repeatMode, _startmode;
|
||||
u8 userEnable;
|
||||
u32 wordcount;
|
||||
EDMAMode startmode;
|
||||
EDMABitWidth bitWidth;
|
||||
EDMASourceUpdate sar;
|
||||
EDMADestinationUpdate dar;
|
||||
u32 saddr, daddr;
|
||||
|
||||
//indicates whether the dma needs to be checked for triggering
|
||||
BOOL check;
|
||||
|
||||
//indicates whether the dma right now is logically running
|
||||
//(though for now we copy all the data when it triggers)
|
||||
BOOL running;
|
||||
|
||||
BOOL paused;
|
||||
|
||||
//this flag will sometimes be set when a start condition is triggered
|
||||
//other conditions may be automatically triggered based on scanning conditions
|
||||
BOOL triggered;
|
||||
|
||||
u64 nextEvent;
|
||||
|
||||
int procnum, chan;
|
||||
|
||||
void savestate(EMUFILE *f);
|
||||
bool loadstate(EMUFILE *f);
|
||||
|
||||
void exec();
|
||||
void doCopy();
|
||||
void doPause();
|
||||
void doStop();
|
||||
void doSchedule();
|
||||
void tryTrigger(EDMAMode mode);
|
||||
|
||||
DmaController() :
|
||||
enable(0), irq(0), bitWidth(EDMABitWidth_16), repeatMode(0), _startmode(0),
|
||||
sar(EDMASourceUpdate_Increment), dar(EDMADestinationUpdate_Increment),
|
||||
wordcount(0), startmode(EDMAMode_Immediate),
|
||||
sad(&saddr),
|
||||
dad(&daddr),
|
||||
check(FALSE),
|
||||
running(FALSE),
|
||||
paused(FALSE),
|
||||
triggered(FALSE),
|
||||
nextEvent(0)
|
||||
{
|
||||
sad.controller = this;
|
||||
dad.controller = this;
|
||||
ctrl.controller = this;
|
||||
regs[0] = &sad;
|
||||
regs[1] = &dad;
|
||||
regs[2] = &ctrl;
|
||||
}
|
||||
|
||||
class AddressRegister : public TRegister_32 {
|
||||
public:
|
||||
//we pass in a pointer to the controller here so we can alert it if anything changes
|
||||
DmaController* controller;
|
||||
u32 * const ptr;
|
||||
AddressRegister(u32* _ptr)
|
||||
: ptr(_ptr)
|
||||
{}
|
||||
virtual u32 read32() {
|
||||
return *ptr;
|
||||
}
|
||||
virtual void write32(const u32 val) {
|
||||
*ptr = val;
|
||||
}
|
||||
};
|
||||
|
||||
class ControlRegister : public TRegister_32 {
|
||||
public:
|
||||
//we pass in a pointer to the controller here so we can alert it if anything changes
|
||||
DmaController* controller;
|
||||
ControlRegister() {}
|
||||
virtual u32 read32() {
|
||||
return controller->read32();
|
||||
}
|
||||
virtual void write32(const u32 val) {
|
||||
return controller->write32(val);
|
||||
}
|
||||
};
|
||||
|
||||
AddressRegister sad, dad;
|
||||
ControlRegister ctrl;
|
||||
TRegister_32* regs[3];
|
||||
|
||||
void write32(const u32 val);
|
||||
u32 read32();
|
||||
|
||||
};
|
||||
|
||||
enum ECardMode
|
||||
{
|
||||
CardMode_Normal = 0,
|
||||
|
@ -168,9 +358,17 @@ struct MMU_struct
|
|||
u32 CheckDMAs;
|
||||
};
|
||||
|
||||
//this contains things which can't be memzeroed because they are smarter classes
|
||||
struct MMU_struct_new
|
||||
{
|
||||
MMU_struct_new() ;
|
||||
BackupDevice backupDevice;
|
||||
DmaController dma[2][4];
|
||||
TGXSTAT gxstat;
|
||||
|
||||
void write_dma(const int proc, const int size, const u32 adr, const u32 val);
|
||||
u32 read_dma(const int proc, const int size, const u32 adr);
|
||||
bool is_dma(const u32 adr) { return adr >= _REG_DMA_CONTROL_MIN && adr <= _REG_DMA_CONTROL_MAX; }
|
||||
};
|
||||
|
||||
extern MMU_struct MMU;
|
||||
|
@ -220,7 +418,7 @@ void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val);
|
|||
void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val);
|
||||
void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val);
|
||||
|
||||
template<int PROCNUM> void FASTCALL MMU_doDMA(u32 num);
|
||||
//template<int PROCNUM> void FASTCALL MMU_doDMA(u32 num);
|
||||
|
||||
//The base ARM memory interfaces
|
||||
extern struct armcpu_memory_iface arm9_base_memory_iface;
|
||||
|
@ -343,20 +541,6 @@ inline void SetupMMU(BOOL debugConsole) {
|
|||
//T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
|
||||
// adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]);
|
||||
|
||||
enum EDMAMode
|
||||
{
|
||||
EDMAMode_Immediate = 0,
|
||||
EDMAMode_VBlank = 1,
|
||||
EDMAMode_HBlank = 2,
|
||||
EDMAMode_HStart = 3,
|
||||
EDMAMode_MemDisplay = 4,
|
||||
EDMAMode_Card = 5,
|
||||
EDMAMode_GBASlot = 6,
|
||||
EDMAMode_GXFifo = 7,
|
||||
EDMAMode7_Wifi = 8,
|
||||
EDMAMode7_GBASlot = 9,
|
||||
};
|
||||
|
||||
FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr)
|
||||
{
|
||||
//special handling for DMA: read 0 from TCM
|
||||
|
|
|
@ -1492,22 +1492,6 @@ void NDS_SkipNextFrame() {
|
|||
|
||||
#define INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
||||
|
||||
static void execHardware_doDma(int procnum, int chan, EDMAMode modeNum)
|
||||
{
|
||||
if(MMU.DMAStartTime[procnum][chan] == modeNum)
|
||||
{
|
||||
if(procnum == ARMCPU_ARM9) MMU_doDMA<ARMCPU_ARM9>(chan);
|
||||
else MMU_doDMA<ARMCPU_ARM7>(chan);
|
||||
//MMU.DMAStartTime[procnum][chan] = 0; //this was here for main mem dma
|
||||
}
|
||||
}
|
||||
|
||||
void execHardware_doAllDma(EDMAMode modeNum)
|
||||
{
|
||||
for(int i=0;i<2;i++)
|
||||
for(int j=0;j<4;j++)
|
||||
execHardware_doDma(i,j,modeNum);
|
||||
}
|
||||
|
||||
enum ESI_DISPCNT
|
||||
{
|
||||
|
@ -1555,22 +1539,15 @@ struct TSequenceItem_GXFIFO : public TSequenceItem
|
|||
{
|
||||
FORCEINLINE bool isTriggered()
|
||||
{
|
||||
#ifndef USE_GEOMETRY_FIFO_EMULATION
|
||||
return false;
|
||||
#else
|
||||
return enabled && nds_timer >= MMU.gfx3dCycles;
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void exec()
|
||||
{
|
||||
#ifdef USE_GEOMETRY_FIFO_EMULATION
|
||||
enabled = false; //do this first, because gfx3d_execute3D() will cause more scheduled events if necessary
|
||||
while(isTriggered()) {
|
||||
enabled = false;
|
||||
gfx3d_execute3D();
|
||||
MMU.gfx3dCycles = max(MMU.gfx3dCycles,nds_timer); //uhh i dont entirely understand why this was necessary
|
||||
//i need to learn more about how the new gxfifo works, but I am leaving that to you for now crazymax ^_^
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE u64 next()
|
||||
|
@ -1651,30 +1628,57 @@ template<int procnum, int num> struct TSequenceItem_Timer : public TSequenceItem
|
|||
|
||||
template<int procnum, int chan> struct TSequenceItem_DMA : public TSequenceItem
|
||||
{
|
||||
DmaController* controller;
|
||||
|
||||
FORCEINLINE bool isTriggered()
|
||||
{
|
||||
return (MMU.DMAing[procnum][chan])&&nds_timer>=(MMU.DMACycle[procnum][chan]);
|
||||
return (controller->check && nds_timer>= controller->nextEvent);
|
||||
}
|
||||
|
||||
FORCEINLINE bool isEnabled() { return MMU.DMAing[procnum][chan]!=0; }
|
||||
FORCEINLINE bool isEnabled() {
|
||||
return controller->check?TRUE:FALSE;
|
||||
}
|
||||
|
||||
FORCEINLINE u64 next()
|
||||
{
|
||||
return MMU.DMACycle[procnum][chan];
|
||||
return controller->nextEvent;
|
||||
}
|
||||
|
||||
FORCEINLINE void exec()
|
||||
{
|
||||
if (MMU.DMACompleted[procnum][chan])
|
||||
{
|
||||
u8* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG;
|
||||
T1WriteLong(regs, 0xB8 + (0xC*chan), T1ReadLong(regs, 0xB8 + (0xC*chan)) & 0x7FFFFFFF);
|
||||
if((MMU.DMACrt[procnum][chan])&(1<<30)) {
|
||||
if(procnum==0) NDS_makeARM9Int(8+chan);
|
||||
else NDS_makeARM7Int(8+chan);
|
||||
}
|
||||
MMU.DMAing[procnum][chan] = FALSE;
|
||||
}
|
||||
//printf("exec from TSequenceItem_DMA: %d %d\n",procnum,chan);
|
||||
controller->exec();
|
||||
// //give gxfifo dmas a chance to re-trigger
|
||||
// if(MMU.DMAStartTime[procnum][chan] == EDMAMode_GXFifo) {
|
||||
// MMU.DMAing[procnum][chan] = FALSE;
|
||||
// if (gxFIFO.size <= 127)
|
||||
// {
|
||||
// execHardware_doDma(procnum,chan,EDMAMode_GXFifo);
|
||||
// if (MMU.DMACompleted[procnum][chan])
|
||||
// goto docomplete;
|
||||
// else return;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//docomplete:
|
||||
// if (MMU.DMACompleted[procnum][chan])
|
||||
// {
|
||||
// u8* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG;
|
||||
//
|
||||
// //disable the channel
|
||||
// if(MMU.DMAStartTime[procnum][chan] != EDMAMode_GXFifo) {
|
||||
// T1WriteLong(regs, 0xB8 + (0xC*chan), T1ReadLong(regs, 0xB8 + (0xC*chan)) & 0x7FFFFFFF);
|
||||
// MMU.DMACrt[procnum][chan] &= 0x7FFFFFFF; //blehhh i hate this shit being mirrored in memory
|
||||
// }
|
||||
//
|
||||
// if((MMU.DMACrt[procnum][chan])&(1<<30)) {
|
||||
// if(procnum==0) NDS_makeARM9Int(8+chan);
|
||||
// else NDS_makeARM7Int(8+chan);
|
||||
// }
|
||||
//
|
||||
// MMU.DMAing[procnum][chan] = FALSE;
|
||||
// }
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1790,12 +1794,14 @@ struct Sequencer
|
|||
|
||||
} sequencer;
|
||||
|
||||
void NDS_RescheduleGXFIFO()
|
||||
void NDS_RescheduleGXFIFO(u32 cost)
|
||||
{
|
||||
#ifdef USE_GEOMETRY_FIFO_EMULATION
|
||||
if(!sequencer.gxfifo.enabled) {
|
||||
MMU.gfx3dCycles = nds_timer;
|
||||
sequencer.gxfifo.enabled = true;
|
||||
}
|
||||
MMU.gfx3dCycles += cost;
|
||||
NDS_Reschedule();
|
||||
#endif
|
||||
}
|
||||
|
||||
void NDS_RescheduleTimers()
|
||||
|
@ -1812,6 +1818,7 @@ void NDS_RescheduleDMA()
|
|||
{
|
||||
//TBD
|
||||
NDS_Reschedule();
|
||||
|
||||
}
|
||||
|
||||
static void initSchedule()
|
||||
|
@ -1850,6 +1857,15 @@ void Sequencer::init()
|
|||
|
||||
gxfifo.enabled = false;
|
||||
|
||||
dma_0_0.controller = &MMU_new.dma[0][0];
|
||||
dma_0_1.controller = &MMU_new.dma[0][1];
|
||||
dma_0_2.controller = &MMU_new.dma[0][2];
|
||||
dma_0_3.controller = &MMU_new.dma[0][3];
|
||||
dma_1_0.controller = &MMU_new.dma[1][0];
|
||||
dma_1_1.controller = &MMU_new.dma[1][1];
|
||||
dma_1_2.controller = &MMU_new.dma[1][2];
|
||||
dma_1_3.controller = &MMU_new.dma[1][3];
|
||||
|
||||
|
||||
#ifdef EXPERIMENTAL_WIFI
|
||||
wifi.enabled = true;
|
||||
|
@ -1891,7 +1907,7 @@ static void execHardware_hblank()
|
|||
//trigger hblank dmas
|
||||
//but notice, we do that just after we finished drawing the line
|
||||
//(values copied by this hdma should not be used until the next scanline)
|
||||
execHardware_doAllDma(EDMAMode_HBlank);
|
||||
triggerDma(EDMAMode_HBlank);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1908,6 +1924,8 @@ static void execHardware_hstart_vblankEnd()
|
|||
|
||||
static void execHardware_hstart_vblankStart()
|
||||
{
|
||||
//printf("--------VBLANK!!!--------\n");
|
||||
|
||||
//turn on vblank status bit
|
||||
T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 1);
|
||||
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
|
||||
|
@ -1927,7 +1945,7 @@ static void execHardware_hstart_vblankStart()
|
|||
SkipCur2DFrame = false;
|
||||
|
||||
//trigger vblank dmas
|
||||
execHardware_doAllDma(EDMAMode_VBlank);
|
||||
triggerDma(EDMAMode_VBlank);
|
||||
}
|
||||
|
||||
static void execHardware_hstart_vcount()
|
||||
|
@ -1979,7 +1997,7 @@ static void execHardware_hstart()
|
|||
execHardware_hstart_vcount();
|
||||
|
||||
//trigger hstart dmas
|
||||
execHardware_doAllDma(EDMAMode_HStart);
|
||||
triggerDma(EDMAMode_HStart);
|
||||
|
||||
if(nds.VCount<192)
|
||||
{
|
||||
|
@ -1988,7 +2006,7 @@ static void execHardware_hstart()
|
|||
//it should be driven by a fifo (and generate just in time as the scanline is displayed)
|
||||
//but that isnt even possible until we have some sort of sub-scanline timing.
|
||||
//it may not be necessary.
|
||||
execHardware_doAllDma(EDMAMode_MemDisplay);
|
||||
triggerDma(EDMAMode_MemDisplay);
|
||||
}
|
||||
|
||||
//end of 3d vblank
|
||||
|
@ -2321,12 +2339,6 @@ void NDS_exec(s32 nb)
|
|||
|
||||
void execHardware_interrupts()
|
||||
{
|
||||
//THIS IS A HACK but it is necessary until we have gxfifo emulation
|
||||
#ifndef USE_GEOMETRY_FIFO_EMULATION
|
||||
if(MMU.reg_IE[ARMCPU_ARM9]&(1<<21))
|
||||
NDS_makeARM9Int(21); // GX geometry
|
||||
#endif
|
||||
|
||||
if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0]))
|
||||
{
|
||||
#ifdef GDB_STUB
|
||||
|
|
|
@ -146,7 +146,7 @@ void emu_halt();
|
|||
|
||||
extern u64 nds_timer;
|
||||
void NDS_Reschedule();
|
||||
void NDS_RescheduleGXFIFO();
|
||||
void NDS_RescheduleGXFIFO(u32 cost);
|
||||
void NDS_RescheduleDMA();
|
||||
void NDS_RescheduleTimers();
|
||||
|
||||
|
|
|
@ -855,12 +855,12 @@ static void OGLRender()
|
|||
glBegin(GL_TRIANGLES);
|
||||
|
||||
VERT *vert0 = &gfx3d.vertlist->list[poly->vertIndexes[0]];
|
||||
float alpha = poly->getAlpha()/31.0;
|
||||
float alpha = poly->getAlpha()/31.0f;
|
||||
if(wireframe) alpha = 1.0;
|
||||
float color0[4] = {
|
||||
(vert0->color[0]<<2)/255.0,
|
||||
(vert0->color[1]<<2)/255.0,
|
||||
(vert0->color[2]<<2)/255.0,
|
||||
(vert0->color[0]<<2)/255.0f,
|
||||
(vert0->color[1]<<2)/255.0f,
|
||||
(vert0->color[2]<<2)/255.0f,
|
||||
alpha
|
||||
};
|
||||
|
||||
|
@ -873,15 +873,15 @@ static void OGLRender()
|
|||
VERT *vert2 = &gfx3d.vertlist->list[poly->vertIndexes[j+1]];
|
||||
|
||||
float color1[4] = {
|
||||
(vert1->color[0]<<2)/255.0,
|
||||
(vert1->color[1]<<2)/255.0,
|
||||
(vert1->color[2]<<2)/255.0,
|
||||
(vert1->color[0]<<2)/255.0f,
|
||||
(vert1->color[1]<<2)/255.0f,
|
||||
(vert1->color[2]<<2)/255.0f,
|
||||
alpha
|
||||
};
|
||||
float color2[4] = {
|
||||
(vert2->color[0]<<2)/255.0,
|
||||
(vert2->color[1]<<2)/255.0,
|
||||
(vert2->color[2]<<2)/255.0,
|
||||
(vert2->color[0]<<2)/255.0f,
|
||||
(vert2->color[1]<<2)/255.0f,
|
||||
(vert2->color[2]<<2)/255.0f,
|
||||
alpha
|
||||
};
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ static void gbaWriteFlash(u32 adr, u8 val)
|
|||
{
|
||||
u32 ofs = (adr & 0x0000F000);
|
||||
//INFO("GBAgame: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000);
|
||||
for (int i = ofs; i < (ofs + 0x1000); i++)
|
||||
for (u32 i = ofs; i < (ofs + 0x1000); i++)
|
||||
saveData[i] = 0xFF;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
|
@ -223,7 +223,7 @@ static u8 getSaveTypeGBA(const u8 *data, const u32 size)
|
|||
u8 type = 0;
|
||||
u8 *dat = (u8 *)data;
|
||||
|
||||
for (int i = 0; i < (size / 4); i++)
|
||||
for (u32 i = 0; i < (size / 4); i++)
|
||||
{
|
||||
u32 tmp = T1ReadLong(dat, i);
|
||||
|
||||
|
|
|
@ -24,12 +24,11 @@
|
|||
#include "MMU.h"
|
||||
#include "SPU.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
|
||||
#define cpu (&ARMPROC)
|
||||
#define TEMPLATE template<int PROCNUM>
|
||||
|
||||
extern BOOL execute;
|
||||
|
||||
static const u16 getsinetbl[] = {
|
||||
0x0000, 0x0324, 0x0648, 0x096A, 0x0C8C, 0x0FAB, 0x12C8, 0x15E2,
|
||||
0x18F9, 0x1C0B, 0x1F1A, 0x2223, 0x2528, 0x2826, 0x2B1F, 0x2E11,
|
||||
|
@ -198,6 +197,7 @@ TEMPLATE static u32 bios_nop()
|
|||
|
||||
TEMPLATE static u32 WaitByLoop()
|
||||
{
|
||||
//printf("%lld waitbyloop\n",nds_timer);
|
||||
//INFO("ARM%c: SWI 0x03 (WaitByLoop)\n", PROCNUM?'7':'9');
|
||||
if (PROCNUM == ARMCPU_ARM9)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,6 +31,47 @@
|
|||
#include "emufile.h"
|
||||
|
||||
|
||||
//geometry engine command numbers
|
||||
#define GFX3D_NOP 0x00
|
||||
#define GFX3D_MTX_MODE 0x10
|
||||
#define GFX3D_MTX_PUSH 0x11
|
||||
#define GFX3D_MTX_POP 0x12
|
||||
#define GFX3D_MTX_STORE 0x13
|
||||
#define GFX3D_MTX_RESTORE 0x14
|
||||
#define GFX3D_MTX_IDENTITY 0x15
|
||||
#define GFX3D_MTX_LOAD_4x4 0x16
|
||||
#define GFX3D_MTX_LOAD_4x3 0x17
|
||||
#define GFX3D_MTX_MULT_4x4 0x18
|
||||
#define GFX3D_MTX_MULT_4x3 0x19
|
||||
#define GFX3D_MTX_MULT_3x3 0x1A
|
||||
#define GFX3D_MTX_SCALE 0x1B
|
||||
#define GFX3D_MTX_TRANS 0x1C
|
||||
#define GFX3D_COLOR 0x20
|
||||
#define GFX3D_NORMAL 0x21
|
||||
#define GFX3D_TEXCOORD 0x22
|
||||
#define GFX3D_VTX_16 0x23
|
||||
#define GFX3D_VTX_10 0x24
|
||||
#define GFX3D_XY 0x25
|
||||
#define GFX3D_XZ 0x26
|
||||
#define GFX3D_YZ 0x27
|
||||
#define GFX3D_DIFF 0x28
|
||||
#define GFX3D_POLYGON_ATTR 0x29
|
||||
#define GFX3D_TEXIMAGE_PARAM 0x2A
|
||||
#define GFX3D_PLTT_BASE 0x2B
|
||||
#define GFX3D_DIF_AMB 0x30
|
||||
#define GFX3D_SPE_EMI 0x31
|
||||
#define GFX3D_LIGHT_VECTOR 0x32
|
||||
#define GFX3D_LIGHT_COLOR 0x33
|
||||
#define GFX3D_SHININESS 0x34
|
||||
#define GFX3D_BEGIN_VTXS 0x40
|
||||
#define GFX3D_END_VTXS 0x41
|
||||
#define GFX3D_SWAP_BUFFERS 0x50
|
||||
#define GFX3D_VIEWPORT 0x60
|
||||
#define GFX3D_BOX_TEST 0x70
|
||||
#define GFX3D_POS_TEST 0x71
|
||||
#define GFX3D_VEC_TEST 0x72
|
||||
#define GFX3D_NOP_NOARG_HACK 0xDD
|
||||
|
||||
//produce a 32bpp color from a DS RGB16
|
||||
#define RGB16TO32(col,alpha) (((alpha)<<24) | ((((col) & 0x7C00)>>7)<<16) | ((((col) & 0x3E0)>>2)<<8) | (((col) & 0x1F)<<3))
|
||||
|
||||
|
@ -274,44 +315,8 @@ extern CACHE_ALIGN const u8 material_3bit_to_8bit[8];
|
|||
extern CACHE_ALIGN u8 gfx3d_convertedScreen[256*192*4];
|
||||
extern CACHE_ALIGN u8 gfx3d_convertedAlpha[256*192*2]; //see cpp for explanation of illogical *2
|
||||
|
||||
//GE commands:
|
||||
#ifndef USE_GEOMETRY_FIFO_EMULATION
|
||||
void gfx3d_glMatrixMode(u32 v);
|
||||
void gfx3d_glPushMatrix(void);
|
||||
void gfx3d_glPopMatrix(s32 i);
|
||||
void gfx3d_glStoreMatrix(u32 v);
|
||||
void gfx3d_glRestoreMatrix(u32 v);
|
||||
void gfx3d_glLoadIdentity();
|
||||
BOOL gfx3d_glLoadMatrix4x4(s32 v);
|
||||
BOOL gfx3d_glLoadMatrix4x3(s32 v);
|
||||
BOOL gfx3d_glMultMatrix4x4(s32 v);
|
||||
BOOL gfx3d_glMultMatrix3x3(s32 v);
|
||||
BOOL gfx3d_glMultMatrix4x3(s32 v);
|
||||
BOOL gfx3d_glScale(s32 v);
|
||||
BOOL gfx3d_glTranslate(s32 v);
|
||||
void gfx3d_glColor3b(u32 v);
|
||||
void gfx3d_glNormal(u32 v);
|
||||
void gfx3d_glTexCoord(u32 val);
|
||||
BOOL gfx3d_glVertex16b(u32 v);
|
||||
void gfx3d_glVertex10b(u32 v);
|
||||
void gfx3d_glVertex3_cord(u32 one, u32 two, u32 v);
|
||||
void gfx3d_glVertex_rel(u32 v);
|
||||
void gfx3d_glPolygonAttrib (u32 val);
|
||||
void gfx3d_glTexImage(u32 val);
|
||||
void gfx3d_glTexPalette(u32 val);
|
||||
void gfx3d_glMaterial0(u32 val);
|
||||
void gfx3d_glMaterial1(u32 val);
|
||||
void gfx3d_glLightDirection (u32 v);
|
||||
void gfx3d_glLightColor (u32 v);
|
||||
BOOL gfx3d_glShininess (u32 val);
|
||||
void gfx3d_glBegin(u32 v);
|
||||
void gfx3d_glEnd(void);
|
||||
// SwapBuffers see follow
|
||||
void gfx3d_glViewPort(u32 v);
|
||||
BOOL gfx3d_glBoxTest(u32 v);
|
||||
BOOL gfx3d_glPosTest(u32 v);
|
||||
void gfx3d_glVecTest(u32 v);
|
||||
#endif
|
||||
extern BOOL isSwapBuffers;
|
||||
|
||||
void gfx3d_glFlush(u32 v);
|
||||
// end GE commands
|
||||
|
||||
|
@ -332,9 +337,7 @@ u16 gfx3d_glGetVecRes(u32 index);
|
|||
void gfx3d_VBlankSignal();
|
||||
void gfx3d_VBlankEndSignal(bool skipFrame);
|
||||
void gfx3d_Control(u32 v);
|
||||
#ifdef USE_GEOMETRY_FIFO_EMULATION
|
||||
void gfx3d_execute3D();
|
||||
#endif
|
||||
void gfx3d_sendCommandToFIFO(u32 val);
|
||||
void gfx3d_sendCommand(u32 cmd, u32 param);
|
||||
|
||||
|
@ -352,4 +355,5 @@ void gfx3d_savestate(EMUFILE* os);
|
|||
bool gfx3d_loadstate(EMUFILE* is, int size);
|
||||
|
||||
void gfx3d_ClearStack();
|
||||
#endif
|
||||
|
||||
#endif //_GFX3D_H_
|
||||
|
|
|
@ -1353,6 +1353,7 @@ static void SoftRastRender()
|
|||
}
|
||||
|
||||
//printf("%d %d %d %d\n",gfx3d.viewport.x,gfx3d.viewport.y,gfx3d.viewport.width,gfx3d.viewport.height);
|
||||
// printf("%f\n",vert.coord[0]);
|
||||
|
||||
//viewport transforms
|
||||
for(int i=0;i<clippedPolyCounter;i++)
|
||||
|
|
|
@ -32,6 +32,21 @@ int write16le(u16 b, EMUFILE* os);
|
|||
int write32le(u32 b, EMUFILE* os);
|
||||
int write64le(u64 b, EMUFILE* os);
|
||||
|
||||
template<typename T>
|
||||
int readle(T *Bufo, EMUFILE*is)
|
||||
{
|
||||
CTASSERT(sizeof(T)==1||sizeof(T)==2||sizeof(T)==4||sizeof(T)==8);
|
||||
switch(sizeof(T)) {
|
||||
case 1: return read8le((u8*)Bufo,is);
|
||||
case 2: return read16le((u16*)Bufo,is);
|
||||
case 4: return read32le((u32*)Bufo,is);
|
||||
case 8: return read64le((u64*)Bufo,is);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int read8le(u8 *Bufo, EMUFILE*is);
|
||||
int read16le(u16 *Bufo, EMUFILE*is);
|
||||
inline int read16le(s16 *Bufo, EMUFILE*is) { return read16le((u16*)Bufo,is); }
|
||||
|
|
|
@ -78,22 +78,40 @@
|
|||
#define REG_DISPA_MASTERBRIGHT 0x0400006C
|
||||
|
||||
// DMA
|
||||
#define _REG_DMA_CONTROL_MIN 0x040000B0
|
||||
#define REG_DMA0SAD 0x040000B0
|
||||
#define REG_DMA0SADL 0x040000B0
|
||||
#define REG_DMA0SADH 0x040000B2
|
||||
#define REG_DMA0DAD 0x040000B4
|
||||
#define REG_DMA0DADL 0x040000B4
|
||||
#define REG_DMA0DADH 0x040000B6
|
||||
#define REG_DMA0CNTL 0x040000B8
|
||||
#define REG_DMA0CNTH 0x040000BA
|
||||
#define REG_DMA1SAD 0x040000BC
|
||||
#define REG_DMA1SADL 0x040000BC
|
||||
#define REG_DMA1SADH 0x040000BE
|
||||
#define REG_DMA1DAD 0x040000C0
|
||||
#define REG_DMA1DADL 0x040000C0
|
||||
#define REG_DMA1DADH 0x040000C2
|
||||
#define REG_DMA1CNTL 0x040000C4
|
||||
#define REG_DMA1CNTH 0x040000C6
|
||||
#define REG_DMA2SAD 0x040000C8
|
||||
#define REG_DMA2SADL 0x040000C8
|
||||
#define REG_DMA2SADH 0x040000CA
|
||||
#define REG_DMA2DAD 0x040000CC
|
||||
#define REG_DMA2DADL 0x040000CC
|
||||
#define REG_DMA2DADH 0x040000CE
|
||||
#define REG_DMA2CNTL 0x040000D0
|
||||
#define REG_DMA2CNTH 0x040000D2
|
||||
#define REG_DMA3SAD 0x040000D4
|
||||
#define REG_DMA3SADL 0x040000D4
|
||||
#define REG_DMA3SADH 0x040000D6
|
||||
#define REG_DMA3DAD 0x040000D8
|
||||
#define REG_DMA3DADL 0x040000D8
|
||||
#define REG_DMA3DADH 0x040000DA
|
||||
#define REG_DMA3CNTL 0x040000DC
|
||||
#define REG_DMA3CNTH 0x040000DE
|
||||
#define _REG_DMA_CONTROL_MAX 0x040000DF
|
||||
#define REG_DMA0FILL 0x040000E0
|
||||
#define REG_DMA1FILL 0x040000E4
|
||||
#define REG_DMA2FILL 0x040000E8
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <zlib.h>
|
||||
#endif
|
||||
#include <stack>
|
||||
#include <set>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -269,9 +270,15 @@ static void mmu_savestate(EMUFILE* os)
|
|||
u32 version = 3;
|
||||
write32le(version,os);
|
||||
|
||||
//newer savefile system:
|
||||
//version 2:
|
||||
MMU_new.backupDevice.save_state(os);
|
||||
|
||||
//version 3:
|
||||
MMU_new.gxstat.savestate(os);
|
||||
for(int i=0;i<2;i++)
|
||||
for(int j=0;j<4;j++)
|
||||
MMU_new.dma[i][j].savestate(os);
|
||||
|
||||
MMU_timing.arm9codeFetch.savestate(os, version);
|
||||
MMU_timing.arm9dataFetch.savestate(os, version);
|
||||
MMU_timing.arm7codeFetch.savestate(os, version);
|
||||
|
@ -423,11 +430,16 @@ static bool mmu_loadstate(EMUFILE* is, int size)
|
|||
if(version < 2)
|
||||
return true;
|
||||
|
||||
//newer savefile system:
|
||||
bool ok = MMU_new.backupDevice.load_state(is);
|
||||
|
||||
if(version < 3)
|
||||
return ok;
|
||||
return true;
|
||||
|
||||
ok &= MMU_new.gxstat.loadstate(is);
|
||||
|
||||
for(int i=0;i<2;i++)
|
||||
for(int j=0;j<4;j++)
|
||||
ok &= MMU_new.dma[i][j].loadstate(is);
|
||||
|
||||
ok &= MMU_timing.arm9codeFetch.loadstate(is, version);
|
||||
ok &= MMU_timing.arm9dataFetch.loadstate(is, version);
|
||||
|
@ -800,6 +812,10 @@ static int SubWrite(EMUFILE* os, const SFORMAT *sf)
|
|||
{
|
||||
uint32 acc=0;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::set<std::string> keyset;
|
||||
#endif
|
||||
|
||||
const SFORMAT* temp = sf;
|
||||
while(temp->v) {
|
||||
const SFORMAT* seek = sf;
|
||||
|
@ -839,6 +855,16 @@ static int SubWrite(EMUFILE* os, const SFORMAT *sf)
|
|||
write32le(sf->size,os);
|
||||
write32le(sf->count,os);
|
||||
|
||||
#ifdef DEBUG
|
||||
//make sure we dont dup any keys
|
||||
if(keyset.find(sf->desc) != keyset.end())
|
||||
{
|
||||
printf("duplicate save key!\n");
|
||||
assert(false);
|
||||
}
|
||||
keyset.insert(sf->desc);
|
||||
#endif
|
||||
|
||||
#ifdef LOCAL_LE
|
||||
// no need to ever loop one at a time if not flipping byte order
|
||||
os->fwrite((char *)sf->v,size*count);
|
||||
|
|
|
@ -186,6 +186,29 @@ IOReg IORegs9[] = {
|
|||
{"Mtx stack busy",14,1},{"Mtx stack over/under-flow",15,1},{"GX FIFO level",16,9},{"GX FIFO full",24,1},
|
||||
{"GX FIFO less than half full",25,1},{"GX FIFO empty",26,1},{"GX busy",27,1},{"GX FIFO IRQ condition",30,2}}},
|
||||
|
||||
{CatBegin, "DMA registers", 0, 4, 0, {{0}}},
|
||||
{MMIOReg, "DMA0SAD", REG_DMA0SAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA0DAD", REG_DMA0DAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA0CNT", REG_DMA0CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",27,3}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
{MMIOReg, "DMA1SAD", REG_DMA1SAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA1DAD", REG_DMA1DAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA1CNT", REG_DMA1CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",27,3}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
{MMIOReg, "DMA2SAD", REG_DMA2SAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA2DAD", REG_DMA2DAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA2CNT", REG_DMA2CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",27,3}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
{MMIOReg, "DMA3SAD", REG_DMA3SAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA3DAD", REG_DMA3DAD, 4, 1, {{"Value",0,28}}},
|
||||
{MMIOReg, "DMA3CNT", REG_DMA3CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",27,3}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
|
||||
|
||||
/*{CatBegin, "Video engine B registers", 0, 36, 0, {{0}}},
|
||||
{MMIOReg, "[B]DISPCNT", 0x04001000, 4, 18, {{"BG mode",0,3},{"Tile OBJ mapping",4,1},{"Bitmap OBJ 2D size",5,1},{"Bitmap OBJ mapping",6,1},
|
||||
{"Forced blank",7,1},{"Display BG0",8,1},{"Display BG1",9,1},{"Display BG2",10,1},
|
||||
{"Display BG3",11,1},{"Display OBJ",12,1},{"Display window 0",13,1},{"Display window 1",14,1},
|
||||
{"Display OBJ window",15,1},{"Display mode",16,2},{"Tile OBJ 1D boundary",20,2},{"Process OBJs during HBlank",23,1},
|
||||
{"Enable BG ext. palettes",30,1},{"Enable OBJ ext. palettes",31,1}}},
|
||||
{MMIOReg, "[B]BG0CNT", 0x04001008, 2, 7, {{"Priority",0,2},{"Character base",2,4},{"Mosaic",6,1},{"Palette mode",7,1},
|
||||
*/
|
||||
|
||||
{CatBegin, "IPC registers", 0, 2, 0, {{0}}},
|
||||
{MMIOReg, "IPCSYNC", 0x04000180, 2, 3, {{"Data input from remote",0,4},{"Data output to remote",8,4},{"Enable IRQ from remote",14,1}}},
|
||||
|
@ -234,6 +257,21 @@ IOReg IORegs7[] = {
|
|||
{"IPC recv FIFO not empty",18,1},{"Gamecard transfer",19,1},{"Gamecard IREQ_MC",20,1},{"Lid opened",22,1},
|
||||
{"SPI bus",23,1},{"Wifi",24,1}}},
|
||||
|
||||
{CatBegin, "DMA registers", 0, 4, 0, {{0}}},
|
||||
{MMIOReg, "DMA0SAD", REG_DMA0SAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA0DAD", REG_DMA0DAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA0CNT", REG_DMA0CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",28,2}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
{MMIOReg, "DMA1SAD", REG_DMA1SAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA1DAD", REG_DMA1DAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA1CNT", REG_DMA1CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",28,2}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
{MMIOReg, "DMA2SAD", REG_DMA2SAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA2DAD", REG_DMA2DAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA2CNT", REG_DMA2CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",28,2}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
{MMIOReg, "DMA3SAD", REG_DMA3SAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA3DAD", REG_DMA3DAD, 4, 1, {{"Value",0,27}}},
|
||||
{MMIOReg, "DMA3CNT", REG_DMA3CNTL, 4, 8, {{"Word Count",0,21}, {"Dest update method",21,2}, {"Src update method",23,2}, {"Repeat Flag",25,1}, {"32bit Width Enable",26,1},{"Start Mode",28,2}, {"IRQ Enable",30,1}, {"Enabled",31,1}}},
|
||||
|
||||
|
||||
{ListEnd, 0, 0, 0, 0, {{0}}}
|
||||
};
|
||||
|
||||
|
@ -242,6 +280,20 @@ IOReg* IORegs[2] = {IORegs9, IORegs7};
|
|||
static const int kXMargin = 5;
|
||||
static const int kYMargin = 1;
|
||||
|
||||
typedef std::vector<CIORegView*> TIORegViewList;
|
||||
static TIORegViewList liveIORegViews;
|
||||
|
||||
void RefreshAllIORegViews()
|
||||
{
|
||||
//TODO - this is a placeholder for a more robust system for signalling changes to the IORegView for immediate display.
|
||||
//individual windows should subscribe to this service (so it doesnt always waste time)
|
||||
for(TIORegViewList::iterator it(liveIORegViews.begin()); it != liveIORegViews.end(); ++it)
|
||||
{
|
||||
(*it)->Refresh();
|
||||
UpdateWindow((*it)->hWnd); //TODO - base class should have this functionality
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
CIORegView::CIORegView()
|
||||
|
@ -250,12 +302,15 @@ CIORegView::CIORegView()
|
|||
, Reg(0)
|
||||
, yoff(0)
|
||||
{
|
||||
liveIORegViews.push_back(this);
|
||||
}
|
||||
|
||||
CIORegView::~CIORegView()
|
||||
{
|
||||
DestroyWindow(hWnd);
|
||||
UnregWndClass("DeSmuME_IORegView");
|
||||
//TODO - is this thread safe? which thread do these calls come from
|
||||
liveIORegViews.erase(std::find(liveIORegViews.begin(),liveIORegViews.end(),this));
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -609,6 +664,7 @@ LRESULT CALLBACK IORegView_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
rbBand.hwndChild = wnd->hCPUCombo;
|
||||
rbBand.cxMinChild = 0;
|
||||
rbBand.cyMinChild = rc.bottom - rc.top;
|
||||
rbBand.cx = 100;
|
||||
SendMessage(wnd->hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
|
||||
|
||||
GetWindowRect(wnd->hRegCombo, &rc);
|
||||
|
@ -642,7 +698,7 @@ LRESULT CALLBACK IORegView_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
SetWindowPos(wnd->hScrollbar, NULL, rc.right-wnd->vsbWidth, wnd->rebarHeight, wnd->vsbWidth, rc.bottom-wnd->rebarHeight, SWP_NOZORDER);
|
||||
|
||||
// Keep the first rebar band width to a reasonable value
|
||||
SendMessage(wnd->hRebar, RB_SETBANDWIDTH, 0, 60);
|
||||
SendMessage(wnd->hRebar, RB_SETBANDWIDTH, 0, 100);
|
||||
|
||||
GetClientRect(hWnd, &rc);
|
||||
wnd->maxlines = (rc.bottom - wnd->rebarHeight) / wnd->lineheight;
|
||||
|
|
|
@ -23,9 +23,12 @@
|
|||
#define IO_REG_H
|
||||
|
||||
#include "../common.h"
|
||||
#include "CWindow.h"
|
||||
|
||||
LRESULT CALLBACK IORegView_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void RefreshAllIORegViews();
|
||||
|
||||
class CIORegView : public CToolWindow
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1267,7 +1267,7 @@ static void StepRunLoop_Paused()
|
|||
|
||||
static void StepRunLoop_User()
|
||||
{
|
||||
const int kFramesPerToolUpdate = 6;
|
||||
const int kFramesPerToolUpdate = 1;
|
||||
|
||||
Hud.fps = mainLoopData.fps;
|
||||
Hud.fps3d = mainLoopData.fps3d;
|
||||
|
|
Loading…
Reference in New Issue