diff --git a/desmume/dsm.txt b/desmume/dsm.txt
new file mode 100644
index 000000000..b7ac03918
--- /dev/null
+++ b/desmume/dsm.txt
@@ -0,0 +1,63 @@
+DSM is ascii plain text. It is derived from the FCEUX FM2 format.
+It consists of several key-value pairs followed by an inputlog section.
+The inputlog section can be identified by its starting with a | (pipe).
+The inputlog section terminates at eof.
+Newlines may be \r\n or \n
+
+Key-value pairs consist of a key identifier, followed by a space separator, followed by the value text.
+Value text is always terminated by a newline, which the value text will not include.
+The value text is parsed differently depending on the type of the key.
+The key-value pairs may be in any order, except that the first key must be version.
+
+Integer keys (also used for booleans, with a 1 or 0) will have a value that is a simple integer not to exceed 32bits
+ - version (required) - the version of the movie file format; for now it is always 3
+ - emuVersion (required) - the version of the emulator used to produce the movie
+ - rerecordCount (optional) - the rerecord count
+
+String keys have values that consist of the remainder of the key-value pair line. As a consequence, string values cannot contain newlines.
+ - romFilename (required) - the name of the file used to record the movie
+ - comment (optional) - simply a memo. 
+     by convention, the first token in the comment value is the subject of the comment.
+     by convention, subsequent comments with the same subject will have their ordering preserved and may be used to approximate multiline comments.
+     by convention, the author of the movie should be stored in comment(s) with a subject of: author
+
+Hex string keys (used for binary blobs) will have a value that is like 0x0123456789ABCDEF...
+ - romChecksum (required) - this is currently unused.
+
+GUID keys have a value which is in the standard guid format: 452DE2C3-EF43-2FA9-77AC-0677FC51543B
+ - guid (required) a unique identifier for a movie, generated when the movie is created, which is used when loading a savestate to make sure it belongs to the current movie.
+
+The inputlog section consists of lines beginning and ending with a | (pipe).
+The fields are as follows, except as noted in note C.
+|c|.............XXX YYY Z|
+
+'R','L','D','U','T','S','B','A','Y','X','W','E','G'
+
+field c is a variable length decimal integer which is a bitfield corresponding to miscellaneous input states which are valid at the start of the frame.
+There are currently no valid values and so this should always be 0.
+
+the format of the main section is as follows:
+
+ the field begins with 13 characters which constitute a bitfield.
+ any character other than ' ' or '.' means that the button was pressed.
+ by convention, the following mnemonics will be used in a column to remind us of which button corresponds to which column:
+   RLDUTSBAYXWEG (Right,Left,Down,Up,sTart,Select,B,A,Y,X,lshoulder,rshoulder,debuG)
+ This ordering is based on FCEUX to a certain extent, and arbitrary after that.
+ W and E were chosen for shoulders to suggest West and East for Left and Right.
+ While the emulator supports a 'lid' button, and to some extent a 'blow' button, these are not supported in the movies.
+
+ XXX: %03d, the x position of the stylus (0,0 topleft, 255,191 bottomright)
+ YYY: %03d, the y position of the stylus
+ Z: %1d, 1 if the stylus is pressed pressed; 0 if not
+
+Additional fields after this main section may be added later without breaking the file format.
+
+* Notes *
+A. There is no key-value pair that indicates the length of the movie. This must be read by scanning the inputlog and counting the number of lines.
+
+B. All movies start from power-on.
+
+C. The emulator uses these framerate constants
+   arm7_cycles_per_frame = 560190
+   frames_per_second = 59.8261
+
diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp
index 179550ecb..564b140e6 100644
--- a/desmume/src/NDSSystem.cpp
+++ b/desmume/src/NDSSystem.cpp
@@ -881,6 +881,7 @@ void NDS_FreeROM(void)
 	MMU.bupmem.fp = NULL;
 }
 
+bool _HACK_DONT_STOPMOVIE = false;
 void NDS_Reset(BOOL resetBySavestate)
 {
 	unsigned int i;
@@ -889,7 +890,8 @@ void NDS_Reset(BOOL resetBySavestate)
 	FILE* inf = 0;
 	NDS_header * header = NDS_getROMHeader();
 
-	FCEUI_StopMovie();
+	if(!_HACK_DONT_STOPMOVIE)
+		FCEUI_StopMovie();
 
 	if (!header) return ;
 
diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp
index c0f42dce6..c286909f4 100644
--- a/desmume/src/gfx3d.cpp
+++ b/desmume/src/gfx3d.cpp
@@ -207,10 +207,10 @@ static CACHE_ALIGN float cacheHalfVector[4][4];
 
 
 //-------------poly and vertex lists and such things
-POLYLIST polylists[2];
-POLYLIST* polylist = &polylists[0];
-VERTLIST vertlists[2];
-VERTLIST* vertlist = &vertlists[0];
+POLYLIST* polylists = NULL;
+POLYLIST* polylist = NULL;
+VERTLIST* vertlists = NULL;
+VERTLIST* vertlist = NULL;
 
 int listTwiddle = 1;
 int triStripToggle;
@@ -278,6 +278,8 @@ static void makeTables() {
 
 void gfx3d_init()
 {
+	if(polylists == NULL) { polylists = new POLYLIST[2]; polylist = &polylists[0]; }
+	if(vertlists == NULL) { vertlists = new VERTLIST[2]; vertlist = &vertlists[0]; }
 	makeTables();
 	gfx3d_reset();
 }
@@ -2328,6 +2330,9 @@ SFORMAT SF_GFX3D[]={
 //-------------savestate
 void gfx3d_savestate(std::ostream* os)
 {
+	//version
+	write32le(1,os);
+
 	//dump the render lists
 	OSWRITE(vertlist->count);
 	for(int i=0;i<vertlist->count;i++)
@@ -2339,6 +2344,11 @@ void gfx3d_savestate(std::ostream* os)
 
 bool gfx3d_loadstate(std::istream* is, int size)
 {
+	int version;
+	if(read32le(&version,is) != 1) return false;
+	if(size==8) version = 0;
+
+
 	gfx3d_glPolygonAttrib_cache();
 	gfx3d_glTexImage_cache();
 	gfx3d_Control_cache();
@@ -2352,12 +2362,15 @@ bool gfx3d_loadstate(std::istream* is, int size)
 	polylist = &polylists[listTwiddle];
 	vertlist = &vertlists[listTwiddle];
 
-	OSREAD(vertlist->count);
-	for(int i=0;i<vertlist->count;i++)
-		vertlist->list[i].load(is);
-	OSREAD(polylist->count);
-	for(int i=0;i<polylist->count;i++)
-		polylist->list[i].load(is);
+	if(version==1)
+	{
+		OSREAD(vertlist->count);
+		for(int i=0;i<vertlist->count;i++)
+			vertlist->list[i].load(is);
+		OSREAD(polylist->count);
+		for(int i=0;i<polylist->count;i++)
+			polylist->list[i].load(is);
+	}
 
 	gfx3d.polylist = &polylists[listTwiddle^1];
 	gfx3d.vertlist = &vertlists[listTwiddle^1];
diff --git a/desmume/src/movie.cpp b/desmume/src/movie.cpp
index e4dd0ab88..5e2bd9c80 100644
--- a/desmume/src/movie.cpp
+++ b/desmume/src/movie.cpp
@@ -477,8 +477,12 @@ static void openRecordingMovie(const char* fname)
 	if(author != L"") currMovieData.comments.push_back(L"author " + author);
 	//currMovieData.romChecksum = GameInfo->MD5;
 	//currMovieData.romFilename = FileBase;
-
+	
+	extern bool _HACK_DONT_STOPMOVIE;
+	_HACK_DONT_STOPMOVIE = true;
 	NDS_Reset();
+	_HACK_DONT_STOPMOVIE = false;
+
 	//todo ?
 	//poweron(true);
 	//else
@@ -755,6 +759,7 @@ bool mov_loadstate(std::istream* is, int size)
 			currMovieData.rerecordCount = currRerecordCount;
 
 			openRecordingMovie(curMovieFilename);
+			//printf("DUMPING MOVIE: %d FRAMES\n",currMovieData.records.size());
 			currMovieData.dump(osRecordingMovie, false);
 			movieMode = MOVIEMODE_RECORD;
 		}
@@ -844,6 +849,7 @@ void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size)
 	int todo = std::min(size, flen);
 
 	int numRecords = todo/recordsize;
+	//printf("LOADED MOVIE: %d records; currFrameCounter: %d\n",numRecords,currFrameCounter);
 	movieData.records.resize(numRecords);
 	for(int i=0;i<numRecords;i++)
 	{
diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp
index 9312ab2be..c5ca33380 100644
--- a/desmume/src/rasterize.cpp
+++ b/desmume/src/rasterize.cpp
@@ -69,6 +69,17 @@ static u8 decal_table[32][32][32];
 static u8 index_lookup_table[65];
 static u8 index_start_table[8];
 
+static struct TClippedPoly
+{
+	int type;
+	POLY* poly;
+	VERT clipVerts[MAX_CLIPPED_VERTS];
+} *clippedPolys = NULL;
+static int clippedPolyCounter;
+
+TClippedPoly tempClippedPoly;
+TClippedPoly outClippedPoly;
+
 ////optimized float floor useful in limited cases
 ////from http://www.stereopsis.com/FPU.html#convert
 ////(unfortunately, it relies on certain FPU register settings)
@@ -895,6 +906,9 @@ static char SoftRastInit(void)
 	if(!tables_generated)
 	{
 		tables_generated = true;
+
+		clippedPolys = new TClippedPoly[POLYLIST_SIZE*2];
+
 		for(int i=0;i<32;i++)
 		{
 			for(int j=0;j<32;j++)
@@ -968,16 +982,6 @@ static void SoftRastConvertFramebuffer()
 	}
 }
 
-static struct TClippedPoly
-{
-	int type;
-	POLY* poly;
-	VERT clipVerts[MAX_CLIPPED_VERTS];
-} clippedPolys[POLYLIST_SIZE*2];
-static int clippedPolyCounter;
-
-TClippedPoly tempClippedPoly;
-TClippedPoly outClippedPoly;
 
 template<typename T>
 static T interpolate(const float ratio, const T& x0, const T& x1) {
diff --git a/desmume/src/rtc.cpp b/desmume/src/rtc.cpp
index ddac69bcb..43c7f977c 100644
--- a/desmume/src/rtc.cpp
+++ b/desmume/src/rtc.cpp
@@ -79,33 +79,30 @@ struct movietime {
 
 struct movietime movie;
 
-int oldframeCounter;
-u64 totalcycles=2904024960000ULL;//noon
-int totalseconds;
 bool moviemode=false;
 
-
-void InitMovieTime(void) {
-
-		movie.year=9;
-		movie.month=1;
-		movie.monthday=1;
-		movie.weekday=4;
-		oldframeCounter=0;
-
-}
+void InitMovieTime(void)
+{
+	movie.year=9;
+	movie.month=1;
+	movie.monthday=1;
+	movie.weekday=4;
+}	
 
 #ifdef WIN32
 static void MovieTime(void) {
 
-	if(currFrameCounter > oldframeCounter) {
-		int difference;
-		difference=currFrameCounter-oldframeCounter;
-		oldframeCounter=currFrameCounter;
-		totalcycles+=((560190<<1)*difference);
-	}
+	//now, you might think it is silly to go through all these conniptions
+	//when we could just assume that there are 60fps and base the seconds on frameCounter/60
+	//but, we were imagining that one day we might need more precision
 
-	totalseconds=totalcycles / 67222800; //one second
+	const u32 arm9rate_unitsperframe = 560190<<1;
+	const u32 arm9rate_unitspersecond = (u32)(arm9rate_unitsperframe * 59.8261);
+	const u64 noon = (u64)arm9rate_unitspersecond * 60 * 60 * 12;
+	           
+	u64 frameCycles = (u64)arm9rate_unitsperframe * currFrameCounter;
+	u64 totalcycles = frameCycles + noon;
+	u32 totalseconds=totalcycles/arm9rate_unitspersecond;
 
 	movie.sec=totalseconds % 60;
 	movie.minute=totalseconds/60;
diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp
index 9b6f5fff0..32d1a0ab5 100644
--- a/desmume/src/saves.cpp
+++ b/desmume/src/saves.cpp
@@ -862,7 +862,10 @@ static bool savestate_load(std::istream* is)
 	//while the series of resets below should work,
 	//we are testing the robustness of the savestate system with this full reset.
 	//the full reset wipes more things, so we can make sure that they are being restored correctly
-	NDS_Reset(TRUE);
+	extern bool _HACK_DONT_STOPMOVIE;
+	_HACK_DONT_STOPMOVIE = true;
+	NDS_Reset();
+	_HACK_DONT_STOPMOVIE = false;
 
 	//reset some options to their old defaults which werent saved
 	nds.debugConsole = FALSE;
diff --git a/desmume/src/texcache.cpp b/desmume/src/texcache.cpp
index 0adfac384..0accda6a5 100644
--- a/desmume/src/texcache.cpp
+++ b/desmume/src/texcache.cpp
@@ -132,10 +132,10 @@ static MemSpan MemSpan_TexPalette(u32 ofs, u32 len)
 	return ret;
 }
 
-TextureCache	texcache[MAX_TEXTURE+1];
-u32				texcache_start;
-u32				texcache_stop;
-u8 TexCache_texMAP[1024*2048*4]; 
+TextureCache *texcache;
+u32 texcache_start;
+u32 texcache_stop;
+u8 *TexCache_texMAP = NULL;
 
 
 #if defined (DEBUG_DUMP_TEXTURE) && defined (WIN32)
@@ -575,6 +575,9 @@ REJECT:
 
 void TexCache_Reset()
 {
+	if(TexCache_texMAP == NULL) TexCache_texMAP = new u8[1024*2048*4]; 
+	if(texcache == NULL) texcache = new TextureCache[MAX_TEXTURE+1];
+
 	memset(texcache,0,sizeof(texcache));
 
 	texcache_start=0;
diff --git a/desmume/src/texcache.h b/desmume/src/texcache.h
index c350a2fe4..3d6671871 100644
--- a/desmume/src/texcache.h
+++ b/desmume/src/texcache.h
@@ -36,7 +36,7 @@ struct ALIGN(8) TextureCache
 
 };
 
-extern TextureCache	texcache[MAX_TEXTURE+1];
+extern TextureCache	*texcache;
 
 extern void (*TexCache_BindTexture)(u32 texnum);
 extern void (*TexCache_BindTextureData)(u32 texnum, u8* data);
@@ -48,7 +48,7 @@ void TexCache_SetTexture(u32 format, u32 texpal);
 
 void TexCache_Invalidate();
 
-extern u8 TexCache_texMAP[1024*2048*4]; 
+extern u8 *TexCache_texMAP;
 TextureCache* TexCache_Curr();
 
 #endif
diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp
index 5b6c73cb1..21f7ecb54 100644
--- a/desmume/src/windows/main.cpp
+++ b/desmume/src/windows/main.cpp
@@ -114,6 +114,7 @@ void DRV_AviVideoUpdate(const u16* buffer);
 DWORD hKeyInputTimer;
 
 extern LRESULT CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+void InitRamSearch();
 
 
 CRITICAL_SECTION win_sync;
@@ -3139,6 +3140,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
 		case ID_RAM_SEARCH:
 					if(!RamSearchHWnd)
 					{
+						InitRamSearch();
 						RamSearchHWnd = CreateDialog(hAppInst, MAKEINTRESOURCE(IDD_RAMSEARCH), hwnd, (DLGPROC) RamSearchProc);
 					}
 					else
diff --git a/desmume/src/windows/ram_search.cpp b/desmume/src/windows/ram_search.cpp
index ad40237c6..0ed8f6f2f 100644
--- a/desmume/src/windows/ram_search.cpp
+++ b/desmume/src/windows/ram_search.cpp
@@ -63,10 +63,12 @@ struct MemoryRegion
 	unsigned int itemIndex; // index into listbox items, valid when s_itemIndicesInvalid is false
 };
 
-static unsigned char s_prevValues [MAX_RAM_SIZE+4] = {0}; // values at last search or reset
-static unsigned char s_curValues [MAX_RAM_SIZE+4] = {0}; // values at last frame update
-static unsigned short s_numChanges [MAX_RAM_SIZE+4] = {0}; // number of changes of the item starting at this virtual index address
-static MemoryRegion* s_itemIndexToRegionPointer [MAX_RAM_SIZE+4] = {0}; // used for random access into the memory list (trading memory size to get speed here, too bad it's so much memory), only valid when s_itemIndicesInvalid is false
+static struct Buffers {
+	unsigned char s_prevValues [MAX_RAM_SIZE+4]; // values at last search or reset
+	unsigned char s_curValues [MAX_RAM_SIZE+4]; // values at last frame update
+	unsigned short s_numChanges [MAX_RAM_SIZE+4]; // number of changes of the item starting at this virtual index address
+	MemoryRegion* s_itemIndexToRegionPointer [MAX_RAM_SIZE+4]; // used for random access into the memory list (trading memory size to get speed here, too bad it's so much memory), only valid when s_itemIndicesInvalid is false
+} *buffers = NULL;
 static BOOL s_itemIndicesInvalid = true; // if true, the link from listbox items to memory regions (s_itemIndexToRegionPointer) and the link from memory regions to list box items (MemoryRegion::itemIndex) both need to be recalculated
 static BOOL s_prevValuesNeedUpdate = true; // if true, the "prev" values should be updated using the "cur" values on the next frame update signaled
 static unsigned int s_maxItemIndex = 0; // max currently valid item index, the listbox sometimes tries to update things past the end of the list so we need to know this to ignore those attempts
@@ -92,6 +94,15 @@ static int s_undoType = 0; // 0 means can't undo, 1 means can undo, 2 means can
 void RamSearchSaveUndoStateIfNotTooBig(HWND hDlg);
 static const int tooManyRegionsForUndo = 10000;
 
+void InitRamSearch()
+{
+	if(buffers == NULL)
+	{
+		buffers = new Buffers;
+		memset(buffers,0,sizeof(Buffers));
+	}
+}
+
 void ResetMemoryRegions()
 {
 //	Clear_Sound_Buffer();
@@ -200,7 +211,7 @@ void CalculateItemIndices(int itemSize)
 		unsigned int start = startSkipSize;
 		unsigned int end = region.size;
 		for(unsigned int i = start; i < end; i += itemSize)
-			s_itemIndexToRegionPointer[itemIndex++] = &region;
+			buffers->s_itemIndexToRegionPointer[itemIndex++] = &region;
 	}
 	s_maxItemIndex = itemIndex;
 	s_itemIndicesInvalid = FALSE;
@@ -210,7 +221,7 @@ template<typename stepType, typename compareType, int swapXOR>
 void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr)
 {
 	if(s_prevValuesNeedUpdate)
-		memcpy(s_prevValues + region.virtualIndex, s_curValues + region.virtualIndex, region.size + sizeof(compareType) - sizeof(stepType));
+		memcpy(buffers->s_prevValues + region.virtualIndex, buffers->s_curValues + region.virtualIndex, region.size + sizeof(compareType) - sizeof(stepType));
 
 	unsigned int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType);
 
@@ -222,11 +233,11 @@ void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr
 	{
 		for(unsigned int i = indexStart; i < indexEnd; i++)
 		{
-			if(s_curValues[i] != sourceAddr[i^swapXOR]) // if value changed
+			if(buffers->s_curValues[i] != sourceAddr[i^swapXOR]) // if value changed
 			{
-				s_curValues[i] = sourceAddr[i^swapXOR]; // update value
+				buffers->s_curValues[i] = sourceAddr[i^swapXOR]; // update value
 				//if(s_numChanges[i] != 0xFFFF)
-					s_numChanges[i]++; // increase change count
+					buffers->s_numChanges[i]++; // increase change count
 			}
 		}
 	}
@@ -253,10 +264,10 @@ void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr
 
 		for(unsigned int i = indexStart, j = 0; i < lastIndexToRead; i++, j++)
 		{
-			if(s_curValues[i] != sourceAddr[i^swapXOR]) // if value of this byte changed
+			if(buffers->s_curValues[i] != sourceAddr[i^swapXOR]) // if value of this byte changed
 			{
 				if(i < lastIndexToCopy)
-					s_curValues[i] = sourceAddr[i^swapXOR]; // update value
+					buffers->s_curValues[i] = sourceAddr[i^swapXOR]; // update value
 				for(int k = 0; k < sizeof(compareType); k++) // loop through the previous entries that contain this byte
 				{
 					if(i >= indexEnd+k)
@@ -265,7 +276,7 @@ void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr
 					if(nextValidChange[m]+sizeof(compareType) <= i+sizeof(compareType)) // if we didn't already increase the change count for this entry
 					{
 						//if(s_numChanges[i-k] != 0xFFFF)
-							s_numChanges[i-k]++; // increase the change count for this entry
+							buffers->s_numChanges[i-k]++; // increase the change count for this entry
 						nextValidChange[m] = i+sizeof(compareType); // and remember not to increase it again
 					}
 				}
@@ -333,7 +344,7 @@ void ItemIndexToVirtualRegion(unsigned int itemIndex, MemoryRegion& virtualRegio
 		return;
 	}
 
-	const MemoryRegion* regionPtr = s_itemIndexToRegionPointer[itemIndex];
+	const MemoryRegion* regionPtr = buffers->s_itemIndexToRegionPointer[itemIndex];
 	const MemoryRegion& region = *regionPtr;
 
 	int bytesWithinRegion = (itemIndex - region.itemIndex) * sizeof(stepType);
@@ -375,19 +386,19 @@ template<> unsigned char ReadBigEndian(const unsigned char* data) { return *data
 template<typename stepType, typename compareType>
 compareType GetPrevValueFromVirtualIndex(unsigned int virtualIndex)
 {
-	return ReadBigEndian<compareType>(s_prevValues + virtualIndex);
+	return ReadBigEndian<compareType>(buffers->s_prevValues + virtualIndex);
 	//return *(compareType*)(s_prevValues+virtualIndex);
 }
 template<typename stepType, typename compareType>
 compareType GetCurValueFromVirtualIndex(unsigned int virtualIndex)
 {
-	return ReadBigEndian<compareType>(s_curValues + virtualIndex);
+	return ReadBigEndian<compareType>(buffers->s_curValues + virtualIndex);
 //	return *(compareType*)(s_curValues+virtualIndex);
 }
 template<typename stepType, typename compareType>
 unsigned short GetNumChangesFromVirtualIndex(unsigned int virtualIndex)
 {
-	unsigned short num = s_numChanges[virtualIndex];
+	unsigned short num = buffers->s_numChanges[virtualIndex];
 	//for(unsigned int i = 1; i < sizeof(stepType); i++)
 	//	if(num < s_numChanges[virtualIndex+i])
 	//		num = s_numChanges[virtualIndex+i];
@@ -970,14 +981,14 @@ void CompactAddrs()
 void soft_reset_address_info ()
 {
 	ResetMemoryRegions();
-	memset(s_numChanges, 0, sizeof(s_numChanges));
+	memset(buffers->s_numChanges, 0, sizeof(buffers->s_numChanges));
 	CompactAddrs();
 }
 void reset_address_info ()
 {
 	SetRamSearchUndoType(RamSearchHWnd, 0);
 	s_activeMemoryRegionsBackup.clear(); // not necessary, but we'll take the time hit here instead of at the next thing that sets up an undo
-	memcpy(s_prevValues, s_curValues, sizeof(s_prevValues));
+	memcpy(buffers->s_prevValues, buffers->s_curValues, sizeof(buffers->s_prevValues));
 	s_prevValuesNeedUpdate = false;
 	ResetMemoryRegions();
 	if(!RamSearchHWnd)
@@ -992,7 +1003,7 @@ void reset_address_info ()
 		s_prevValuesNeedUpdate = true;
 		signal_new_frame();
 	}
-	memset(s_numChanges, 0, sizeof(s_numChanges));
+	memset(buffers->s_numChanges, 0, sizeof(buffers->s_numChanges));
 	CompactAddrs();
 }
 
@@ -1663,7 +1674,7 @@ LRESULT CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
 					{rv = true; break;}
 				}
 				case IDC_C_RESET_CHANGES:
-					memset(s_numChanges, 0, sizeof(s_numChanges));
+					memset(buffers->s_numChanges, 0, sizeof(buffers->s_numChanges));
 					ListView_Update(GetDlgItem(hDlg,IDC_RAMLIST), -1);
 					//SetRamSearchUndoType(hDlg, 0);
 					{rv = true; break;}