* base DMA time accounting on MMU_timing infrastructure for slightly better estimate, and add system to lock ARM9 bus while DMA occurs. still not completely realistic, but fixes a number of freezes

* fix multithreading bug in rasterizer exposed by some OSX builds a few weeks ago
* remove --dsimode and --debug-console and replace with --console-type={fat,lite,ique,debug,dsi}
* add a zany hack to jitter the stylus position for frames which read it more than once; no human can hold his hands that still, and CSI polled for and demanded sub-frame touch motion for swipe gestures, it seems. this is a bit fishy.. it is still open for discussion.
* track raw ADC coords for NDS and screen coords for DSI independently.
This commit is contained in:
zeromus 2011-11-23 10:32:27 +00:00
parent ffcca74387
commit e101b54d21
13 changed files with 223 additions and 171 deletions

View File

@ -1,5 +1,6 @@
/* Copyright (C) 2006 yopyop /*
Copyright (C) 2006-2010 DeSmuME team Copyright (C) 2006 yopyop
Copyright (C) 2006-2011 DeSmuME team
This file is free software: you can redistribute it and/or modify This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -297,8 +298,8 @@ static void drawPad(double x, double y, double ratio) {
// touch pad // touch pad
{ {
BOOL gameTouchOn = nds.isTouch; BOOL gameTouchOn = nds.isTouch;
double gameTouchX = screenLeft+1 + (nds.touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0; double gameTouchX = screenLeft+1 + (nds.scr_touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0;
double gameTouchY = screenTop+1 + (nds.touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0; double gameTouchY = screenTop+1 + (nds.scr_touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0;
bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch; bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch;
double physicalTouchX = screenLeft+1 + (NDS_getRawUserInput().touch.touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0; double physicalTouchX = screenLeft+1 + (NDS_getRawUserInput().touch.touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0;
double physicalTouchY = screenTop+1 + (NDS_getRawUserInput().touch.touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0; double physicalTouchY = screenTop+1 + (NDS_getRawUserInput().touch.touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0;
@ -373,8 +374,8 @@ static void TextualInputDisplay() {
{ {
char str [32]; char str [32];
BOOL gameTouchOn = nds.isTouch; BOOL gameTouchOn = nds.isTouch;
int gameTouchX = nds.touchX >> 4; int gameTouchX = nds.adc_touchX >> 4;
int gameTouchY = nds.touchY >> 4; int gameTouchY = nds.adc_touchY >> 4;
bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch; bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch;
int physicalTouchX = NDS_getRawUserInput().touch.touchX >> 4; int physicalTouchX = NDS_getRawUserInput().touch.touchX >> 4;
int physicalTouchY = NDS_getRawUserInput().touch.touchY >> 4; int physicalTouchY = NDS_getRawUserInput().touch.touchY >> 4;
@ -433,8 +434,8 @@ static void TouchDisplay() {
} }
if(nds.isTouch) { if(nds.isTouch) {
temptouch.X = nds.touchX >> 4; temptouch.X = nds.scr_touchX;
temptouch.Y = nds.touchY >> 4; temptouch.Y = nds.scr_touchY;
aggDraw.hud->lineColor(255, 0, 0, 128); aggDraw.hud->lineColor(255, 0, 0, 128);
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert

View File

@ -1102,7 +1102,7 @@ u16 DSI_TSC::write16(u16 val)
{ } { }
else else
{ {
registers[reg_selection] = val; registers[reg_selection] = (u8)val;
} }
ret = read16(); ret = read16();
reg_selection++; reg_selection++;
@ -1137,19 +1137,19 @@ u16 DSI_TSC::read16()
{ {
//high byte of X: //high byte of X:
case 1: case 3: case 5: case 7: case 9: case 1: case 3: case 5: case 7: case 9:
return (nds.touchX>>8)&0xFF; return (nds.scr_touchX>>8)&0xFF;
//low byte of X: //low byte of X:
case 2: case 4: case 6: case 8: case 10: case 2: case 4: case 6: case 8: case 10:
return nds.touchX&0xFF; return nds.scr_touchX&0xFF;
//high byte of Y: //high byte of Y:
case 11: case 13: case 15: case 17: case 19: case 11: case 13: case 15: case 17: case 19:
return (nds.touchY>>8)&0xFF; return (nds.scr_touchY>>8)&0xFF;
//low byte of Y: //low byte of Y:
case 12: case 14: case 16: case 18: case 20: case 12: case 14: case 16: case 18: case 20:
return nds.touchY&0xFF; return nds.scr_touchY&0xFF;
default: default:
return 0xFF; return 0xFF;
@ -1886,8 +1886,13 @@ if(_startmode==0 && wordcount==1) {
void DmaController::exec() void DmaController::exec()
{ {
//this function runs when the DMA ends. the dma start actually queues this event after some kind of guess as to how long the DMA should take
//we'll need to unfreeze the arm9 bus now
if(procnum==ARMCPU_ARM9) nds.freezeBus &= ~(1<<(chan+1));
dmaCheck = FALSE; dmaCheck = FALSE;
if(running) if(running)
{ {
switch(startmode) { switch(startmode) {
@ -1944,7 +1949,8 @@ void DmaController::exec()
} }
running = TRUE; running = TRUE;
paused = FALSE; paused = FALSE;
doCopy(); if(procnum == ARMCPU_ARM9) doCopy<ARMCPU_ARM9>();
else doCopy<ARMCPU_ARM7>();
//printf(";%d\n",gxFIFO.size); //printf(";%d\n",gxFIFO.size);
} }
} }
@ -1952,6 +1958,7 @@ void DmaController::exec()
driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA); driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA);
} }
template<int PROCNUM>
void DmaController::doCopy() void DmaController::doCopy()
{ {
//generate a copy count depending on various copy mode's behavior //generate a copy count depending on various copy mode's behavior
@ -2004,13 +2011,13 @@ void DmaController::doCopy()
//TODO - these might be losing out a lot by not going through the templated version anymore. //TODO - these might be losing out a lot by not going through the templated version anymore.
//we might make another function to do just the raw copy op which can use them with checks //we might make another function to do just the raw copy op which can use them with checks
//outside the loop //outside the loop
int time_elapsed = 0;
if(sz==4) { if(sz==4) {
for(s32 i=(s32)todo; i>0; i--) for(s32 i=(s32)todo; i>0; i--)
{ {
time_elapsed += _MMU_accesstime<PROCNUM,MMU_AT_DMA,32,MMU_AD_READ,TRUE>(src,true);
time_elapsed += _MMU_accesstime<PROCNUM,MMU_AT_DMA,32,MMU_AD_WRITE,TRUE>(dst,true);
u32 temp = _MMU_read32(procnum,MMU_AT_DMA,src); u32 temp = _MMU_read32(procnum,MMU_AT_DMA,src);
if(startmode == EDMAMode_GXFifo) {
//printf("GXFIFO DMA OF %08X FROM %08X WHILE GXFIFO.SIZE=%d\n",temp,src,gxFIFO.size);
}
_MMU_write32(procnum,MMU_AT_DMA,dst, temp); _MMU_write32(procnum,MMU_AT_DMA,dst, temp);
dst += dstinc; dst += dstinc;
src += srcinc; src += srcinc;
@ -2018,23 +2025,25 @@ void DmaController::doCopy()
} else { } else {
for(s32 i=(s32)todo; i>0; i--) for(s32 i=(s32)todo; i>0; i--)
{ {
_MMU_write16(procnum,MMU_AT_DMA,dst, _MMU_read16(procnum,MMU_AT_DMA,src)); time_elapsed += _MMU_accesstime<PROCNUM,MMU_AT_DMA,16,MMU_AD_READ,TRUE>(src,true);
time_elapsed += _MMU_accesstime<PROCNUM,MMU_AT_DMA,16,MMU_AD_WRITE,TRUE>(dst,true);
u16 temp = _MMU_read16(procnum,MMU_AT_DMA,src);
_MMU_write16(procnum,MMU_AT_DMA,dst, temp);
dst += dstinc; dst += dstinc;
src += srcinc; src += srcinc;
} }
} }
//printf("dma of size %d took %d cycles\n",todo*sz,time_elapsed);
//reschedule an event for the end of this dma, and figure out how much it cost us //reschedule an event for the end of this dma, and figure out how much it cost us
doSchedule(); doSchedule();
nextEvent += time_elapsed;
// zeromus, check it //freeze the ARM9 bus for the duration of this DMA
if (wordcount > todo) //thats not entirely accurate
nextEvent += todo/4; //TODO - surely this is a gross simplification if(procnum==ARMCPU_ARM9)
//<zeromus> nextEvent must [always] be advanced to schedule the completion IRQ to fire, even if the timing is pretty much completely imaginary. nds.freezeBus |= (1<<(chan+1));
//<crazymax> but it fixes contra 4 bonus menu, #2867258
//apparently moon has very, very tight timing (i didnt spy it using waitbyloop swi...)
//so lets bump this down a bit for now,
//(i think this code is in nintendo libraries)
//write back the addresses //write back the addresses
saddr = src; saddr = src;
@ -2192,7 +2201,7 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 WRITE\n"); return; case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 WRITE\n"); return;
case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 WRITE\n"); return; case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 WRITE\n"); return;
#if 0 #if 1
case REG_DIVCNT: printf("ERROR 8bit DIVCNT WRITE\n"); return; case REG_DIVCNT: printf("ERROR 8bit DIVCNT WRITE\n"); return;
case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT1 WRITE\n"); return; case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT1 WRITE\n"); return;
case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT2 WRITE\n"); return; case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT2 WRITE\n"); return;
@ -2543,7 +2552,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
MMU_new.div.write16(val); MMU_new.div.write16(val);
execdiv(); execdiv();
return; return;
#if 0 #if 1
case REG_DIVNUMER: case REG_DIVNUMER:
case REG_DIVNUMER+2: case REG_DIVNUMER+2:
case REG_DIVNUMER+4: case REG_DIVNUMER+4:
@ -2975,7 +2984,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
case 0x40005B: case 0x40005B:
case 0x40005C: // Individual Commands case 0x40005C: // Individual Commands
if (gxFIFO.size > 254) if (gxFIFO.size > 254)
nds.freezeBus = TRUE; nds.freezeBus |= 1;
((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val;
gfx3d_sendCommand(adr, val); gfx3d_sendCommand(adr, val);
@ -3354,7 +3363,7 @@ u8 FASTCALL _MMU_ARM9_read08(u32 adr)
#endif #endif
case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 READ\n"); return 0; case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 READ\n"); return 0;
case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 READ\n"); return 0; case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 READ\n"); return 0;
#if 0 #if 1
case REG_DIVCNT: printf("ERROR 8bit DIVCNT READ\n"); return 0; case REG_DIVCNT: printf("ERROR 8bit DIVCNT READ\n"); return 0;
case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT1 READ\n"); return 0; case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT1 READ\n"); return 0;
#else #else
@ -3527,10 +3536,10 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr)
switch(adr) switch(adr)
{ {
case REG_DSIMODE: case REG_DSIMODE:
if(!CommonSettings.DSI) break; if(!CommonSettings.Is_DSI()) break;
return 1; return 1;
case 0x04004008: case 0x04004008:
if(!CommonSettings.DSI) break; if(!CommonSettings.Is_DSI()) break;
return 0x8000; return 0x8000;
case REG_DISPA_DISPSTAT: case REG_DISPA_DISPSTAT:
@ -3739,8 +3748,8 @@ static void CalculateTouchPressure(int pressurePercent, u16 &z1, u16& z2)
z1 = z2 = 0; z1 = z2 = 0;
return; return;
} }
int y = nds.touchY/16; int y = nds.scr_touchY;
int x = nds.touchX/16; int x = nds.scr_touchX;
float u = (x/256.0f); float u = (x/256.0f);
float v = (y/192.0f); float v = (y/192.0f);
@ -3938,7 +3947,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
case 2: case 2:
{ {
if(CommonSettings.DSI) if(CommonSettings.Is_DSI())
{ {
//pass data to TSC //pass data to TSC
val = MMU_new.dsi_tsc.write16(val); val = MMU_new.dsi_tsc.write16(val);
@ -3988,23 +3997,32 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
break; break;
case TSC_MEASURE_Y: case TSC_MEASURE_Y:
//emu_halt();
if(MMU.SPI_CNT&(1<<11))
{ {
if(partie) //counter the number of adc touch coord reads and jitter it after a while to simulate a shaky human hand or multiple reads
nds.adc_jitterctr++;
if(nds.adc_jitterctr == 25)
{ {
val = ((nds.touchY<<3)&0x7FF); nds.adc_jitterctr = 0;
partie = 0; nds.adc_touchY ^= 16;
//emu_halt(); nds.adc_touchX ^= 16;
}
if(MMU.SPI_CNT&(1<<11))
{
if(partie)
{
val = (nds.adc_touchY<<3) & 0xFF;
partie = 0;
break;
}
val = (nds.adc_touchY>>5) & 0xFF;
partie = 1;
break; break;
} }
val = (nds.touchY>>5); val = (nds.adc_touchY<<3)&0xFF;
partie = 1; partie = 1;
break; break;
} }
val = ((nds.touchY<<3)&0x7FF);
partie = 1;
break;
case TSC_MEASURE_Z1: //Z1 case TSC_MEASURE_Z1: //Z1
//used for pressure calculation - must be nonzero or else some softwares will think the stylus is up. //used for pressure calculation - must be nonzero or else some softwares will think the stylus is up.
//something is wrong in here and some of these LSB dont make it back to libnds... whatever. //something is wrong in here and some of these LSB dont make it back to libnds... whatever.
@ -4054,15 +4072,15 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
{ {
if(partie) if(partie)
{ {
val = ((nds.touchX<<3)&0x7FF); val = (nds.adc_touchX << 3) & 0xFF;
partie = 0; partie = 0;
break; break;
} }
val = (nds.touchX>>5); val = (nds.adc_touchX>>5) & 0xFF;
partie = 1; partie = 1;
break; break;
} }
val = ((nds.touchX<<3)&0x7FF); val = (nds.adc_touchX<<3) & 0xFF;
partie = 1; partie = 1;
break; break;
case TSC_MEASURE_AUX: case TSC_MEASURE_AUX:
@ -4390,7 +4408,8 @@ u16 FASTCALL _MMU_ARM7_read16(u32 adr)
{ {
//this is gross. we should generate this whole reg instead of poking it in ndssystem //this is gross. we should generate this whole reg instead of poking it in ndssystem
u16 ret = MMU.ARM7_REG[0x136]; u16 ret = MMU.ARM7_REG[0x136];
if(nds.isTouch) ret &= ~64; if(nds.isTouch)
ret &= ~64;
else ret |= 64; else ret |= 64;
return ret; return ret;
} }

View File

@ -222,7 +222,7 @@ public:
bool loadstate(EMUFILE *f); bool loadstate(EMUFILE *f);
void exec(); void exec();
void doCopy(); template<int PROCNUM> void doCopy();
void doPause(); void doPause();
void doStop(); void doStop();
void doSchedule(); void doSchedule();

View File

@ -1,23 +1,20 @@
/* Copyright (C) 2006 yopyop /*
Copyright (C) 2006 yopyop
Copyright (C) 2007 shash Copyright (C) 2007 shash
Copyright (C) 2007-2010 DeSmuME team Copyright (C) 2007-2011 DeSmuME team
This file is part of DeSmuME This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
DeSmuME is free software; you can redistribute it and/or modify This file is distributed in the hope that it will be useful,
it under the terms of the GNU General Public License as published by but WITHOUT ANY WARRANTY; without even the implied warranty of
the Free Software Foundation; either version 2 of the License, or MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(at your option) any later version. GNU General Public License for more details.
DeSmuME is distributed in the hope that it will be useful, You should have received a copy of the GNU General Public License
but WITHOUT ANY WARRANTY; without even the implied warranty of along with the this software. If not, see <http://www.gnu.org/licenses/>.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
// this file is split from MMU.h for the purpose of avoiding ridiculous recompile times // this file is split from MMU.h for the purpose of avoiding ridiculous recompile times
@ -296,7 +293,7 @@ FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential)
#endif #endif
// for now, assume the cache is always enabled for all of main memory // for now, assume the cache is always enabled for all of main memory
if(TIMING && PROCNUM==ARMCPU_ARM9 && (addr & 0x0F000000) == 0x02000000) if(AT != MMU_AT_DMA && TIMING && PROCNUM==ARMCPU_ARM9 && (addr & 0x0F000000) == 0x02000000)
{ {
#ifdef ENABLE_CACHE_CONTROLLER_EMULATION #ifdef ENABLE_CACHE_CONTROLLER_EMULATION
bool cached = false; bool cached = false;

View File

@ -46,7 +46,7 @@
//int xxctr=0; //int xxctr=0;
//#define LOG_ARM9 //#define LOG_ARM9
//#define LOG_ARM7 //#define LOG_ARM7
//bool dolog = false; //#define dolog (currFrameCounter>15)
//#define LOG_TO_FILE //#define LOG_TO_FILE
//#define LOG_TO_FILE_REGS //#define LOG_TO_FILE_REGS
@ -1861,7 +1861,7 @@ static /*donotinline*/ std::pair<s32,s32> armInnerLoop(
s32 temp = arm9; s32 temp = arm9;
arm9 = min(s32next, arm9 + kIrqWait); arm9 = min(s32next, arm9 + kIrqWait);
nds.idleCycles[0] += arm9-temp; nds.idleCycles[0] += arm9-temp;
if (gxFIFO.size < 255) nds.freezeBus = FALSE; if (gxFIFO.size < 255) nds.freezeBus &= ~1;
} }
} }
if(doarm7 && (!doarm9 || arm7 <= timer)) if(doarm7 && (!doarm9 || arm7 <= timer))
@ -2084,7 +2084,7 @@ void NDS_Reset()
nds.sleeping = FALSE; nds.sleeping = FALSE;
nds.cardEjected = FALSE; nds.cardEjected = FALSE;
nds.freezeBus = FALSE; nds.freezeBus = 0;
nds.power1.lcd = nds.power1.gpuMain = nds.power1.gfx3d_render = nds.power1.gfx3d_geometry = nds.power1.gpuSub = nds.power1.dispswap = 1; nds.power1.lcd = nds.power1.gpuMain = nds.power1.gfx3d_render = nds.power1.gfx3d_geometry = nds.power1.gpuSub = nds.power1.dispswap = 1;
nds.power2.speakers = 1; nds.power2.speakers = 1;
nds.power2.wifi = 0; nds.power2.wifi = 0;
@ -2382,7 +2382,7 @@ void NDS_Reset()
nds.wifiCycle = 0; nds.wifiCycle = 0;
memset(nds.timerCycle, 0, sizeof(u64) * 2 * 4); memset(nds.timerCycle, 0, sizeof(u64) * 2 * 4);
nds.old = 0; nds.old = 0;
nds.touchX = nds.touchY = 0; nds.scr_touchX = nds.scr_touchY = nds.adc_touchX = nds.adc_touchY = 0;
nds.isTouch = 0; nds.isTouch = 0;
nds.paddle = 0; nds.paddle = 0;
nds.debugConsole = CommonSettings.DebugConsole; nds.debugConsole = CommonSettings.DebugConsole;
@ -2528,22 +2528,22 @@ void ClearAutoHold(void) {
} }
} }
//convert a 12.4 screen coordinate to an ADC value.
INLINE u16 NDS_getADCTouchPosX(u16 scrX) //the desmume host system will track the screen coordinate, but the hardware should be receiving the raw ADC values.
//so we'll need to use this to simulate the ADC values corresponding to the desired screen coords, based on the current TSC calibrations
u16 NDS_getADCTouchPosX(int scrX_lsl4)
{ {
// this is a little iffy, scrX_lsl4 >>= 4;
// we're basically adjusting the ADC results to int rv = ((scrX_lsl4 - TSCal.scr.x1 + 1) * TSCal.adc.width) / TSCal.scr.width + TSCal.adc.x1;
// compensate for how they will be interpreted.
// the actual system doesn't do this transformation.
int rv = (scrX - TSCal.scr.x1 + 1) * TSCal.adc.width / TSCal.scr.width + TSCal.adc.x1;
rv = min(0xFFF, max(0, rv)); rv = min(0xFFF, max(0, rv));
return (u16)rv; return (u16)(rv);
} }
INLINE u16 NDS_getADCTouchPosY(u16 scrY) u16 NDS_getADCTouchPosY(int scrY_lsl4)
{ {
int rv = (scrY - TSCal.scr.y1 + 1) * TSCal.adc.height / TSCal.scr.height + TSCal.adc.y1; scrY_lsl4 >>= 4;
int rv = ((scrY_lsl4 - TSCal.scr.y1 + 1) * TSCal.adc.height) / TSCal.scr.height + TSCal.adc.y1;
rv = min(0xFFF, max(0, rv)); rv = min(0xFFF, max(0, rv));
return (u16)rv; return (u16)(rv);
} }
static UserInput rawUserInput = {}; // requested input, generally what the user is physically pressing static UserInput rawUserInput = {}; // requested input, generally what the user is physically pressing
@ -2645,8 +2645,8 @@ void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,b
void NDS_setTouchPos(u16 x, u16 y) void NDS_setTouchPos(u16 x, u16 y)
{ {
gotInputRequest(); gotInputRequest();
rawUserInput.touch.touchX = NDS_getADCTouchPosX(x); rawUserInput.touch.touchX = x<<4;
rawUserInput.touch.touchY = NDS_getADCTouchPosY(y); rawUserInput.touch.touchY = y<<4;
rawUserInput.touch.isTouch = true; rawUserInput.touch.isTouch = true;
if(movieMode != MOVIEMODE_INACTIVE && movieMode != MOVIEMODE_FINISHED) if(movieMode != MOVIEMODE_INACTIVE && movieMode != MOVIEMODE_FINISHED)
@ -2759,33 +2759,32 @@ static void NDS_applyFinalInput()
if(input.touch.isTouch) if(input.touch.isTouch)
{ {
nds.touchX = input.touch.touchX; u16 adc_x = NDS_getADCTouchPosX(input.touch.touchX);
nds.touchY = input.touch.touchY; u16 adc_y = NDS_getADCTouchPosY(input.touch.touchY);
nds.isTouch = 1; nds.adc_touchX = adc_x;
nds.adc_touchY = adc_y;
nds.adc_jitterctr = 0;
MMU.ARM7_REG[0x136] &= 0xBF; nds.scr_touchX = input.touch.touchX;
nds.scr_touchY = input.touch.touchY;
nds.isTouch = 1;
} }
else else
{ {
nds.touchX = 0; nds.adc_touchX = 0;
nds.touchY = 0; nds.adc_touchY = 0;
nds.scr_touchX = 0;
nds.scr_touchY = 0;
nds.isTouch = 0; nds.isTouch = 0;
MMU.ARM7_REG[0x136] |= 0x40;
} }
if (input.buttons.F && !countLid) if (input.buttons.F && !countLid)
{ {
LidClosed = (!LidClosed) & 0x01; LidClosed = (!LidClosed) & 0x01;
if (!LidClosed) if (!LidClosed)
{ {
// SPU_Pause(FALSE);
NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_FOLD); NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_FOLD);
} }
//else
//SPU_Pause(TRUE);
countLid = 30; countLid = 30;
} }

View File

@ -1,5 +1,6 @@
/* Copyright (C) 2006 yopyop /*
Copyright (C) 2008-2010 DeSmuME team Copyright (C) 2006 yopyop
Copyright (C) 2008-2011 DeSmuME team
This file is free software: you can redistribute it and/or modify This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -164,8 +165,15 @@ struct NDSSystem
u32 VCount; u32 VCount;
u32 old; u32 old;
u16 touchX; //raw adc touch coords for old NDS
u16 touchY; u16 adc_touchX;
u16 adc_touchY;
s32 adc_jitterctr;
//the DSI returns calibrated touch coords from its TSC (?), so we need to save these separately
u16 scr_touchX;
u16 scr_touchY;
BOOL isTouch; BOOL isTouch;
u16 pad; u16 pad;
@ -180,7 +188,7 @@ struct NDSSystem
BOOL sleeping; BOOL sleeping;
BOOL cardEjected; BOOL cardEjected;
BOOL freezeBus; u32 freezeBus;
//this is not essential NDS runtime state. //this is not essential NDS runtime state.
//it was perhaps a mistake to put it here. //it was perhaps a mistake to put it here.
@ -225,19 +233,20 @@ struct NDS_fw_touchscreen_cal {
u8 screen_y; u8 screen_y;
}; };
/** /brief The type of DS enum NDS_CONSOLE_TYPE
*/ {
enum nds_fw_ds_type { NDS_CONSOLE_TYPE_FAT,
NDS_FW_DS_TYPE_FAT, NDS_CONSOLE_TYPE_LITE,
NDS_FW_DS_TYPE_LITE, NDS_CONSOLE_TYPE_IQUE,
NDS_FW_DS_TYPE_iQue NDS_CONSOLE_TYPE_DSI
}; };
#define MAX_FW_NICKNAME_LENGTH 10 #define MAX_FW_NICKNAME_LENGTH 10
#define MAX_FW_MESSAGE_LENGTH 26 #define MAX_FW_MESSAGE_LENGTH 26
struct NDS_fw_config_data { struct NDS_fw_config_data
enum nds_fw_ds_type ds_type; {
NDS_CONSOLE_TYPE ds_type;
u8 fav_colour; u8 fav_colour;
u8 birth_month; u8 birth_month;
@ -251,8 +260,8 @@ struct NDS_fw_config_data {
u8 language; u8 language;
/* touchscreen calibration */ //touchscreen calibration
struct NDS_fw_touchscreen_cal touch_cal[2]; NDS_fw_touchscreen_cal touch_cal[2];
}; };
extern NDSSystem nds; extern NDSSystem nds;
@ -352,7 +361,7 @@ struct GameInfo
typedef struct TSCalInfo typedef struct TSCalInfo
{ {
struct adc struct
{ {
u16 x1, x2; u16 x1, x2;
u16 y1, y2; u16 y1, y2;
@ -360,7 +369,7 @@ typedef struct TSCalInfo
u16 height; u16 height;
} adc; } adc;
struct scr struct
{ {
u8 x1, x2; u8 x1, x2;
u8 y1, y2; u8 y1, y2;
@ -493,7 +502,7 @@ extern struct TCommonSettings {
, spu_captureMuted(false) , spu_captureMuted(false)
, spu_advanced(false) , spu_advanced(false)
, StylusPressure(50) , StylusPressure(50)
, DSI(false) , ConsoleType(NDS_CONSOLE_TYPE_FAT)
{ {
strcpy(ARM9BIOS, "biosnds9.bin"); strcpy(ARM9BIOS, "biosnds9.bin");
strcpy(ARM7BIOS, "biosnds7.bin"); strcpy(ARM7BIOS, "biosnds7.bin");
@ -529,7 +538,8 @@ extern struct TCommonSettings {
bool BootFromFirmware; bool BootFromFirmware;
struct NDS_fw_config_data InternalFirmConf; struct NDS_fw_config_data InternalFirmConf;
bool DSI; NDS_CONSOLE_TYPE ConsoleType;
bool Is_DSI() { return ConsoleType == NDS_CONSOLE_TYPE_DSI; }
bool DebugConsole; bool DebugConsole;
bool EnsataEmulation; bool EnsataEmulation;

View File

@ -18,7 +18,7 @@
//windows note: make sure this file gets compiled with _cdecl //windows note: make sure this file gets compiled with _cdecl
#include <glib.h> #include <glib.h>
#include <algorithm>
#include <stdio.h> #include <stdio.h>
#include "commandline.h" #include "commandline.h"
#include "types.h" #include "types.h"
@ -49,9 +49,8 @@ CommandLine::CommandLine()
, _advanced_timing(-1) , _advanced_timing(-1)
, _slot1(NULL) , _slot1(NULL)
, _slot1_fat_dir(NULL) , _slot1_fat_dir(NULL)
, _console_type(NULL)
, depth_threshold(-1) , depth_threshold(-1)
, debug_console(-1)
, dsi_mode(-1)
, load_slot(-1) , load_slot(-1)
, arm9_gdb_port(0) , arm9_gdb_port(0)
, arm7_gdb_port(0) , arm7_gdb_port(0)
@ -96,8 +95,7 @@ void CommandLine::loadCommonOptions()
{ "slot1", 0, 0, G_OPTION_ARG_STRING, &_slot1, "Device to load in slot 1 (default retail)", "SLOT1"}, { "slot1", 0, 0, G_OPTION_ARG_STRING, &_slot1, "Device to load in slot 1 (default retail)", "SLOT1"},
{ "slot1-fat-dir", 0, 0, G_OPTION_ARG_STRING, &_slot1_fat_dir, "Directory to scan for slot 1", "SLOT1_DIR"}, { "slot1-fat-dir", 0, 0, G_OPTION_ARG_STRING, &_slot1_fat_dir, "Directory to scan for slot 1", "SLOT1_DIR"},
{ "depth-threshold", 0, 0, G_OPTION_ARG_INT, &depth_threshold, "Depth comparison threshold (default 0)", "DEPTHTHRESHOLD"}, { "depth-threshold", 0, 0, G_OPTION_ARG_INT, &depth_threshold, "Depth comparison threshold (default 0)", "DEPTHTHRESHOLD"},
{ "debug-console", 0, 0, G_OPTION_ARG_INT, &debug_console, "Behave as 8MB debug console (default 0)", "DEBUGCONSOLE"}, { "console-type", 0, 0, G_OPTION_ARG_STRING, &_console_type, "Select console type: {fat,lite,ique,debug,dsi}", "CONSOLETYPE" },
{ "dsi-mode", 0, 0, G_OPTION_ARG_INT, &dsi_mode, "Behave as a DSi", "DSIMODE"},
#ifndef _MSC_VER #ifndef _MSC_VER
{ "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL}, { "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL},
{ "disable-limiter", 0, 0, G_OPTION_ARG_NONE, &disable_limiter, "Disables the 60fps limiter", NULL}, { "disable-limiter", 0, 0, G_OPTION_ARG_NONE, &disable_limiter, "Disables the 60fps limiter", NULL},
@ -114,6 +112,8 @@ void CommandLine::loadCommonOptions()
g_option_context_add_main_entries (ctx, options, "options"); g_option_context_add_main_entries (ctx, options, "options");
} }
char mytoupper(char c) { return ::toupper(c); }
bool CommandLine::parse(int argc,char **argv) bool CommandLine::parse(int argc,char **argv)
{ {
g_option_context_parse (ctx, &argc, &argv, &error); g_option_context_parse (ctx, &argc, &argv, &error);
@ -125,6 +125,7 @@ bool CommandLine::parse(int argc,char **argv)
if(_slot1_fat_dir) slot1_fat_dir = _slot1_fat_dir; if(_slot1_fat_dir) slot1_fat_dir = _slot1_fat_dir;
if(_slot1) slot1 = _slot1; if(_slot1) slot1 = _slot1;
if(_console_type) console_type = _console_type;
if(slot1.size() != 0) str_lcase((char*)&slot1[0]); if(slot1.size() != 0) str_lcase((char*)&slot1[0]);
if(_play_movie_file) play_movie_file = _play_movie_file; if(_play_movie_file) play_movie_file = _play_movie_file;
if(_record_movie_file) record_movie_file = _record_movie_file; if(_record_movie_file) record_movie_file = _record_movie_file;
@ -137,14 +138,26 @@ bool CommandLine::parse(int argc,char **argv)
if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1; if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1;
if(depth_threshold != -1) if(depth_threshold != -1)
CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = depth_threshold; CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = depth_threshold;
if(debug_console != -1)
CommonSettings.DebugConsole = (debug_console==1);
if(dsi_mode != -1) //process console type
CommonSettings.DSI = (dsi_mode==1); CommonSettings.DebugConsole = false;
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
std::transform(console_type.begin(), console_type.end(), console_type.begin(), ::mytoupper);
if(console_type == "") {}
else if(console_type == "FAT") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
else if(console_type == "LITE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_LITE;
else if(console_type == "IQUE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_IQUE;
else if(console_type == "DSI") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_DSI;
else if(console_type == "DEBUG")
{
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
CommonSettings.DebugConsole = true;
}
CommonSettings.autodetectBackupMethod = autodetect_method; CommonSettings.autodetectBackupMethod = autodetect_method;
//TODO MAX PRIORITY! change ARM9BIOS etc to be a std::string //TODO NOT MAX PRIORITY! change ARM9BIOS etc to be a std::string
if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); } if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); }
if(_bios_arm7) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM7BIOS,_bios_arm7); } if(_bios_arm7) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM7BIOS,_bios_arm7); }
if(_bios_swi) CommonSettings.SWIFromBIOS = true; if(_bios_swi) CommonSettings.SWIFromBIOS = true;
@ -160,6 +173,8 @@ bool CommandLine::parse(int argc,char **argv)
bool CommandLine::validate() bool CommandLine::validate()
{ {
if(slot1 != "") if(slot1 != "")
{ {
if(slot1 != "r4" && slot1 != "retail" && slot1 != "none") { if(slot1 != "r4" && slot1 != "retail" && slot1 != "none") {

View File

@ -37,8 +37,6 @@ public:
//actual options: these may move to another sturct //actual options: these may move to another sturct
int load_slot; int load_slot;
int depth_threshold; int depth_threshold;
int debug_console;
int dsi_mode;
int autodetect_method; int autodetect_method;
std::string nds_file; std::string nds_file;
std::string play_movie_file; std::string play_movie_file;
@ -49,6 +47,7 @@ public:
std::string cflash_path; std::string cflash_path;
std::string gbaslot_rom; std::string gbaslot_rom;
std::string slot1; std::string slot1;
std::string console_type;
std::string slot1_fat_dir; std::string slot1_fat_dir;
#ifndef _MSC_VER #ifndef _MSC_VER
int disable_sound; int disable_sound;
@ -92,6 +91,7 @@ private:
int _advanced_timing; int _advanced_timing;
char* _slot1; char* _slot1;
char *_slot1_fat_dir; char *_slot1_fat_dir;
char* _console_type;
}; };
#endif #endif

View File

@ -1,20 +1,18 @@
/* Copyright (C) 2009-2011 DeSmuME Team /*
Copyright (C) 2009-2011 DeSmuME Team
This file is part of DeSmuME This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
DeSmuME is free software; you can redistribute it and/or modify This file is distributed in the hope that it will be useful,
it under the terms of the GNU General Public License as published by but WITHOUT ANY WARRANTY; without even the implied warranty of
the Free Software Foundation; either version 2 of the License, or MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(at your option) any later version. GNU General Public License for more details.
DeSmuME is distributed in the hope that it will be useful, You should have received a copy of the GNU General Public License
but WITHOUT ANY WARRANTY; without even the implied warranty of along with the this software. If not, see <http://www.gnu.org/licenses/>.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "firmware.h" #include "firmware.h"
@ -798,7 +796,7 @@ int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings)
MMU.fw.data[0x8 + 3] = 'P'; MMU.fw.data[0x8 + 3] = 'P';
// DS type // DS type
if ( user_settings->ds_type == NDS_FW_DS_TYPE_LITE) if ( user_settings->ds_type == NDS_CONSOLE_TYPE_LITE)
MMU.fw.data[0x1d] = 0x20; MMU.fw.data[0x1d] = 0x20;
else else
MMU.fw.data[0x1d] = 0xff; MMU.fw.data[0x1d] = 0xff;
@ -881,7 +879,7 @@ void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config) {
int str_length; int str_length;
memset( fw_config, 0, sizeof( struct NDS_fw_config_data)); memset( fw_config, 0, sizeof( struct NDS_fw_config_data));
fw_config->ds_type = NDS_FW_DS_TYPE_FAT; fw_config->ds_type = NDS_CONSOLE_TYPE_FAT;
fw_config->fav_colour = 7; fw_config->fav_colour = 7;
@ -900,19 +898,32 @@ void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config) {
} }
fw_config->message_len = str_length; fw_config->message_len = str_length;
/* default to English */ //default to English
fw_config->language = 1; fw_config->language = 1;
/* default touchscreen calibration */ // default touchscreen calibration
//ANCIENT DESMUME VALUES
fw_config->touch_cal[0].adc_x = 0x200; fw_config->touch_cal[0].adc_x = 0x200;
fw_config->touch_cal[0].adc_y = 0x200; fw_config->touch_cal[0].adc_y = 0x200;
fw_config->touch_cal[0].screen_x = 0x20 + 1; // calibration screen coords are 1-based, fw_config->touch_cal[0].screen_x = 0x20 + 1; // calibration screen coords are 1-based,
fw_config->touch_cal[0].screen_y = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong. fw_config->touch_cal[0].screen_y = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong.
//VALUES FROM NOCASH
//fw_config->touch_cal[0].adc_x = 0x02DF;
//fw_config->touch_cal[0].adc_y = 0x032C;
//fw_config->touch_cal[0].screen_x = 0x20;
//fw_config->touch_cal[0].screen_y = 0x20;
//ANCIENT DESMUME VALUES
fw_config->touch_cal[1].adc_x = 0xe00; fw_config->touch_cal[1].adc_x = 0xe00;
fw_config->touch_cal[1].adc_y = 0x800; fw_config->touch_cal[1].adc_y = 0x800;
fw_config->touch_cal[1].screen_x = 0xe0 + 1; fw_config->touch_cal[1].screen_x = 0xe0 + 1;
fw_config->touch_cal[1].screen_y = 0x80 + 1; fw_config->touch_cal[1].screen_y = 0x80 + 1;
//VALUES FROM NOCASH
//fw_config->touch_cal[1].adc_x = 0x0D3B;
//fw_config->touch_cal[1].adc_y = 0x0CE7;
//fw_config->touch_cal[1].screen_x = 0xE0;
//fw_config->touch_cal[1].screen_y = 0xA0;
} }
void NDS_PatchFirmwareMAC() void NDS_PatchFirmwareMAC()

View File

@ -4408,9 +4408,9 @@ static int stylus_read(lua_State *L){
lua_newtable(L); lua_newtable(L);
lua_pushinteger(L, nds.touchX >> 4); lua_pushinteger(L, nds.scr_touchX >> 4);
lua_setfield(L, -2, "x"); lua_setfield(L, -2, "x");
lua_pushinteger(L, nds.touchY >> 4); lua_pushinteger(L, nds.scr_touchY >> 4);
lua_setfield(L, -2, "y"); lua_setfield(L, -2, "y");
lua_pushboolean(L, nds.isTouch); lua_pushboolean(L, nds.isTouch);
lua_setfield(L, -2, "touch"); lua_setfield(L, -2, "touch");

View File

@ -1,4 +1,5 @@
/* Copyright 2008-2010 DeSmuME team /*
Copyright 2008-2011 DeSmuME team
This file is free software: you can redistribute it and/or modify This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -814,8 +815,8 @@ void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::stri
mr.touch.y = input.touch.isTouch ? input.touch.touchY >> 4 : 0; mr.touch.y = input.touch.isTouch ? input.touch.touchY >> 4 : 0;
assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y)); assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y));
assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY); //assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY);
assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY); //assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY);
mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size()); mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size());
currMovieData.records.push_back(mr); currMovieData.records.push_back(mr);

View File

@ -1,20 +1,18 @@
/* Copyright 2009-2010 DeSmuME team /*
Copyright (C) 2009-2011 DeSmuME team
This file is part of DeSmuME This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
DeSmuME is free software; you can redistribute it and/or modify This file is distributed in the hope that it will be useful,
it under the terms of the GNU General Public License as published by but WITHOUT ANY WARRANTY; without even the implied warranty of
the Free Software Foundation; either version 2 of the License, or MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(at your option) any later version. GNU General Public License for more details.
DeSmuME is distributed in the hope that it will be useful, You should have received a copy of the GNU General Public License
but WITHOUT ANY WARRANTY; without even the implied warranty of along with the this software. If not, see <http://www.gnu.org/licenses/>.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
//nothing in this file should be assumed to be accurate //nothing in this file should be assumed to be accurate
@ -455,7 +453,7 @@ public:
FORCEINLINE FragmentColor sample(float u, float v) FORCEINLINE FragmentColor sample(float u, float v)
{ {
static FragmentColor white = MakeFragmentColor(63,63,63,31); static const FragmentColor white = MakeFragmentColor(63,63,63,31);
if(!sampler.enabled) return white; if(!sampler.enabled) return white;
//finally, we can use floor here. but, it is slower than we want. //finally, we can use floor here. but, it is slower than we want.
@ -814,8 +812,6 @@ public:
//do not overstep either of the edges //do not overstep either of the edges
int Height = min(left->Height,right->Height); int Height = min(left->Height,right->Height);
bool first=true; bool first=true;
static int runctr=0;
runctr++;
//HACK: special handling for horizontal line poly //HACK: special handling for horizontal line poly
if (lineHack && left->Height == 0 && right->Height == 0 && left->Y<192 && left->Y>=0) if (lineHack && left->Height == 0 && right->Height == 0 && left->Y<192 && left->Y>=0)

View File

@ -162,8 +162,11 @@ SFORMAT SF_NDS[]={
{ "_TCY", 8, 8, nds.timerCycle}, { "_TCY", 8, 8, nds.timerCycle},
{ "_VCT", 4, 1, &nds.VCount}, { "_VCT", 4, 1, &nds.VCount},
{ "_OLD", 4, 1, &nds.old}, { "_OLD", 4, 1, &nds.old},
{ "_TPX", 2, 1, &nds.touchX}, { "_TPX", 2, 1, &nds.adc_touchX},
{ "_TPY", 2, 1, &nds.touchY}, { "_TPY", 2, 1, &nds.adc_touchY},
{ "_TPC", 2, 1, &nds.adc_jitterctr},
{ "_STX", 2, 1, &nds.scr_touchX},
{ "_STY", 2, 1, &nds.scr_touchY},
{ "_TPB", 4, 1, &nds.isTouch}, { "_TPB", 4, 1, &nds.isTouch},
{ "_DBG", 4, 1, &nds.debugConsole}, { "_DBG", 4, 1, &nds.debugConsole},
{ "_ENS", 4, 1, &nds.ensataEmulation}, { "_ENS", 4, 1, &nds.ensataEmulation},