[Scummvm-cvs-logs] SF.net SVN: scummvm: [24596] scummvm/trunk/backends/platform/ds

agent-q at users.sourceforge.net agent-q at users.sourceforge.net
Sat Nov 4 00:17:12 CET 2006


Revision: 24596
          http://svn.sourceforge.net/scummvm/?rev=24596&view=rev
Author:   agent-q
Date:     2006-11-03 15:16:29 -0800 (Fri, 03 Nov 2006)

Log Message:
-----------
Merging in changes made in branch for 0.9.1 release into trunk

Modified Paths:
--------------
    scummvm/trunk/backends/platform/ds/arm7/Makefile
    scummvm/trunk/backends/platform/ds/arm7/source/main.cpp
    scummvm/trunk/backends/platform/ds/arm9/makefile
    scummvm/trunk/backends/platform/ds/arm9/source/cdaudio.cpp
    scummvm/trunk/backends/platform/ds/arm9/source/dsmain.cpp
    scummvm/trunk/backends/platform/ds/arm9/source/dsmain.h
    scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.cpp
    scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.h
    scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.h
    scummvm/trunk/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.h
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd_asm.s
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mpcf.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_scsd_asm.s
    scummvm/trunk/backends/platform/ds/arm9/source/osystem_ds.cpp
    scummvm/trunk/backends/platform/ds/arm9/source/osystem_ds.h
    scummvm/trunk/backends/platform/ds/arm9/source/portdefs.h
    scummvm/trunk/backends/platform/ds/arm9/source/ramsave.cpp
    scummvm/trunk/backends/platform/ds/arm9/source/ramsave.h
    scummvm/trunk/backends/platform/ds/arm9/source/scummhelp.cpp
    scummvm/trunk/backends/platform/ds/arm9/source/zipreader.cpp

Added Paths:
-----------
    scummvm/trunk/backends/platform/ds/arm9/ndsloader.bin
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3_common.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.h
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_njsd.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_njsd.h
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_sd_common.c
    scummvm/trunk/backends/platform/ds/arm9/source/fat/io_sd_common.h
    scummvm/trunk/backends/platform/ds/logoa.bmp
    scummvm/trunk/backends/platform/ds/logob.bmp
    scummvm/trunk/backends/platform/ds/logoc.bmp

Modified: scummvm/trunk/backends/platform/ds/arm7/Makefile
===================================================================
--- scummvm/trunk/backends/platform/ds/arm7/Makefile	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm7/Makefile	2006-11-03 23:16:29 UTC (rev 24596)
@@ -12,6 +12,9 @@
 BUILD		:=	build
 SOURCES	:=	gfx source data  
 INCLUDES	:=	include build
+
+# Enable support for debugger (must be the same as in the arm9 makefile)
+USE_DEBUGGER = 1
  
 #---------------------------------------------------------------------------------
 # options for code generation
@@ -27,6 +30,11 @@
 
 CFLAGS	+=	$(INCLUDE) -DARM7
 
+ifdef USE_DEBUGGER
+	CFLAGS += -DUSE_DEBUGGER
+endif
+	
+
 CXXFLAGS	:=	$(CFLAGS) -fno-exceptions -fno-rtti
 ASFLAGS	:=	-g $(ARCH)
 LDFLAGS	:=	-g $(ARCH) -mno-fpu
@@ -49,6 +57,10 @@
 # any extra libraries we wish to link with the project
 #---------------------------------------------------------------------------------
 LIBS	:= -lnds7
+
+ifdef USE_DEBUGGER
+	LIBS += -ldswifi7
+endif
  
  
 #---------------------------------------------------------------------------------

Modified: scummvm/trunk/backends/platform/ds/arm7/source/main.cpp
===================================================================
--- scummvm/trunk/backends/platform/ds/arm7/source/main.cpp	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm7/source/main.cpp	2006-11-03 23:16:29 UTC (rev 24596)
@@ -34,9 +34,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <registers_alt.h>
-
 #include <NDS/scummvm_ipc.h>
 //////////////////////////////////////////////////////////////////////
+#ifdef USE_DEBUGGER
+#include <dswifi7.h>
+#endif
 
 
 #define TOUCH_CAL_X1 (*(vs16*)0x027FFCD8)
@@ -99,7 +101,7 @@
 }
 
 void startSound(int sampleRate, const void* data, uint32 bytes, u8 channel=0, u8 vol=0x7F,  u8 pan=63, u8 format=0) {
-  REG_IME = IME_DISABLE;
+//  REG_IME = IME_DISABLE;
 
   channel = getFreeSoundChannel();
 /*  if (format == 2) {
@@ -216,7 +218,7 @@
 //  IPC->fillSoundSecondHalf = true;
 //  soundFirstHalf = true;
   
-  REG_IME = IME_ENABLE;
+//  REG_IME = IME_ENABLE;
 }
 
 void stopSound(int chan) {
@@ -310,9 +312,8 @@
   
   powerManagerWrite(0, 0x30, false);
 }
+
 */
-
-
 void performSleep() {
   powerManagerWrite(0, 0x30, true);
 
@@ -345,11 +346,9 @@
 
 //////////////////////////////////////////////////////////////////////
 
-
-void InterruptHandler(void) {
-  static int heartbeat = 0;
-
-  if (REG_IF & IRQ_TIMER1) {
+  
+  	
+void InterruptTimer1() {
 	
 	IPC->fillNeeded[playingSection] = true;
 	soundFilled[playingSection] = false;
@@ -385,13 +384,9 @@
 			soundFilled[r] = true;
 		//}
 	}*/
-	
-
-    REG_IF = IRQ_TIMER1;
-  }
+}	
   
-
-  if (REG_IF & IRQ_TIMER3) {
+void InterruptTimer3() {
 	while (IPC->adpcm.semaphore);		// Wait for buffer to become free if needed
 	IPC->adpcm.semaphore = true;		// Lock the buffer structure to prevent clashing with the ARM7
 		
@@ -403,12 +398,10 @@
 		IPC->streamPlayingSection++;
 	}
 	
-    REG_IF = IRQ_TIMER3;
 	
 	IPC->adpcm.semaphore = false;
-  }
+}
 
-
 //  IPC->performArm9SleepMode = false;
 
 	// precalculate some values
@@ -420,13 +413,12 @@
   
   
  
- 
-  if (REG_IF & IRQ_VBLANK) {
+ void InterruptVBlank() {
     uint16 but=0, x=0, y=0, xpx=0, ypx=0, z1=0, z2=0, batt=0, aux=0;
     int t1=0, t2=0;
     uint32 temp=0;
     uint8 ct[sizeof(IPC->curtime)];
-
+	static int heartbeat = 0;
     
     // Update the heartbeat
     heartbeat++;
@@ -472,6 +464,7 @@
     // Read the temperature
     temp = touchReadTemperature(&t1, &t2);
  
+ 
     // Update the IPC struct
     IPC->heartbeat = heartbeat;
     IPC->buttons   = but;
@@ -508,18 +501,69 @@
 			stopSound(-snd->data[i].rate);
 		}
       }
-    } 
+    }
+    
+   
+ #ifdef USE_DEBUGGER
+    Wifi_Update(); // update wireless in vblank
+ #endif
+ }
+ 
 
-    REG_IF = IRQ_VBLANK;
-  }
- 
+//////////////////////////////////////////////////////////////////////
+
+
+#ifdef USE_DEBUGGER
+
+// callback to allow wifi library to notify arm9
+void arm7_synctoarm9() { // send fifo message
+   REG_IPC_FIFO_TX = 0x87654321;
 }
- 
+// interrupt handler to allow incoming notifications from arm9
+void arm7_fifo() { // check incoming fifo messages
+   u32 msg = REG_IPC_FIFO_RX;
+   if(msg==0x87654321) Wifi_Sync();
+}
 
-//////////////////////////////////////////////////////////////////////
  
 
+void initDebugger() {
+	
+	// set up the wifi irq
+	irqSet(IRQ_WIFI, Wifi_Interrupt); // set up wifi interrupt
+	irqEnable(IRQ_WIFI);
+
+    //get them talking together
+
+	// sync with arm9 and init wifi
+	u32 fifo_temp;
+
+	while(1) { // wait for magic number
+		while(REG_IPC_FIFO_CR&IPC_FIFO_RECV_EMPTY) swiWaitForVBlank();
+		fifo_temp=REG_IPC_FIFO_RX;
+		if(fifo_temp==0x12345678) break;
+   	}
+
+   	while(REG_IPC_FIFO_CR&IPC_FIFO_RECV_EMPTY) swiWaitForVBlank();
+   	fifo_temp=REG_IPC_FIFO_RX; // give next value to wifi_init
+   	Wifi_Init(fifo_temp);
+
+   	irqSet(IRQ_FIFO_NOT_EMPTY,arm7_fifo); // set up fifo irq
+   	irqEnable(IRQ_FIFO_NOT_EMPTY);
+   	REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_RECV_IRQ;
+
+   	Wifi_SetSyncHandler(arm7_synctoarm9); // allow wifi lib to notify arm9
+	// arm7 wifi init complete	
+
+}
+#endif
+
 int main(int argc, char ** argv) {
+	
+#ifdef USE_DEBUGGER
+  REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR;
+#endif
+  
   // Reset the clock if needed
   rtcReset();
 
@@ -528,8 +572,10 @@
   SOUND_CR = SOUND_ENABLE | SOUND_VOL(0x7F);
   IPC->soundData = 0;
   IPC->reset = false;
+
+
+ 
   
-  
   for (int r = 0; r < 8; r++) {
 	IPC->adpcm.arm7Buffer[r] = (u8 *) malloc(512);
   }
@@ -540,14 +586,29 @@
 
  
   // Set up the interrupt handler
-  REG_IME = 0;
+  
+  irqInit();
+
+  irqSet(IRQ_VBLANK, InterruptVBlank);
+  irqEnable(IRQ_VBLANK);
+
+  irqSet(IRQ_TIMER1, InterruptTimer1);
+  irqEnable(IRQ_TIMER1);
+
+  irqSet(IRQ_TIMER3, InterruptTimer3);
+  irqEnable(IRQ_TIMER3);
+  
+/*  REG_IME = 0;
   IRQ_HANDLER = &InterruptHandler;
   REG_IE = IRQ_VBLANK | IRQ_TIMER1 | IRQ_TIMER3;
   REG_IF = ~0;
   DISP_SR = DISP_VBLANK_IRQ;
   REG_IME = 1;
-  
-  
+  */
+ 
+#ifdef USE_DEBUGGER  
+  initDebugger();
+#endif  
 
   // Keep the ARM7 out of main RAM
   while (1) {

Modified: scummvm/trunk/backends/platform/ds/arm9/makefile
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/makefile	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/makefile	2006-11-03 23:16:29 UTC (rev 24596)
@@ -1,15 +1,23 @@
 #BUILD_PLUGINS = 1
 libndsdir = $(DEVKITPRO)/libnds
 
-#DS_BUILD_A = 1
+# Select the build you want by uncommenting one of the following lines:
+
+DS_BUILD_A = 1
 #DS_BUILD_B = 1
-DS_BUILD_C = 1
+#DS_BUILD_C = 1
 
-#DS_SCUMM_BUILD = 1
-#DS_NON_SCUMM_BUILD = 1
 
-#USE_MAD = 1
+# Uncomment the following line to build in support for MP3 audio
+# using libmad:
+USE_MAD = 1
 
+# Uncomment the following line to enable support for the
+# ace DS Debugger (remembering to make the same change in the arm7 makefile):
+#USE_DEBUGGER = 1
+# NOTE: The header and libs for the debugger is assumed to be in the libnds
+# folder.
+
 VPATH = $(srcdir)
 
 # Command to build libmad is:
@@ -17,7 +25,8 @@
 
 
 ifdef DS_BUILD_A
-	DEFINES = -DDS_SCUMM_BUILD
+	DEFINES = -DDS_SCUMM_BUILD -DDS_BUILD_A
+	LOGO = logoa.bmp
 	DISABLE_HE = 1
 	#DISABLE_SCUMM = 1
 	DISABLE_SCUMM_7_8 = 1
@@ -36,37 +45,39 @@
 endif
 
 ifdef DS_BUILD_B
-	DEFINES = -DDS_NON_SCUMM_BUILD
+	DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_B
+	LOGO = logob.bmp
 	DISABLE_HE = 1
 	DISABLE_SCUMM = 1
 	DISABLE_SCUMM_7_8 = 1
-	#DISABLE_AGOS = 1
-	DISABLE_SKY = 1
+	DISABLE_AGOS = 1
+	#DISABLE_SKY = 1
 	DISABLE_SWORD1 = 1
 	DISABLE_SWORD2 = 1
 	#DISABLE_QUEEN = 1
 	DISABLE_SAGA = 1
 	DISABLE_KYRA = 1
-	#DISABLE_GOB = 1
+	DISABLE_GOB = 1
 	DISABLE_LURE = 1
 	DISABLE_CINE = 1
 	DISABLE_AGI = 1
 	BUILD=scummvm-B
 endif
 
-ifdef DS_BUILD_C
-	DEFINES = -DDS_NON_SCUMM_BUILD
+ifdef DS_BUILD_C	
+	DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_C
+	LOGO = logoc.bmp
 	DISABLE_HE = 1
 	DISABLE_SCUMM = 1
 	DISABLE_SCUMM_7_8 = 1
-	DISABLE_AGOS = 1
+	#DISABLE_AGOS = 1
 	DISABLE_SKY = 1
 	DISABLE_SWORD1 = 1
 	DISABLE_SWORD2 = 1
 	DISABLE_QUEEN = 1
-	#DISABLE_SAGA = 1
-	DISABLE_KYRA = 1
-	DISABLE_GOB = 1
+	DISABLE_SAGA = 1
+	#DISABLE_KYRA = 1
+	#DISABLE_GOB = 1
 	DISABLE_LURE = 1
 	DISABLE_CINE = 1
 	DISABLE_AGI = 1
@@ -84,6 +95,11 @@
 		-Wno-multichar -mcpu=arm9tdmi -mtune=arm9tdmi \
  		-mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
 		-ffast-math -mthumb-interwork
+
+ifdef USE_DEBUGGER
+	DEFINES += -DUSE_DEBUGGER
+	CFLAGS += -g
+endif
 		
 CXXFLAGS=	$(CFLAGS) -Wno-non-virtual-dtor	 -Wno-non-virtual-dtor \
 		-fno-exceptions -fno-rtti
@@ -94,6 +110,7 @@
 	DEFINES += -DUSE_MAD
 endif
 
+
 LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -mno-fpu -Wl,-Map,map.txt
 
 INCLUDES= -I./ -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/common -I$(portdir)/source -I$(portdir)/source/compressor -I$(portdir)/source/fat \
@@ -105,6 +122,9 @@
 ifdef USE_MAD
 	LIBS += -lmad
 endif
+ifdef USE_DEBUGGER
+	LIBS += -ldsdebugger -ldswifi9
+endif
 
 #-Lscumm -lscumm -Lbase -lbase -Lcommon -lcommon -Lgraphics -lgraphics -Lgui -lgui -Lsound -lsound
 EXECUTABLE = scummvm.elf
@@ -144,7 +164,18 @@
 			$(portdir)/source/fat/io_mpcf.o $(portdir)/source/fat/io_sccf.o\
 			$(portdir)/source/fat/io_m3sd.o\
 			$(portdir)/source/fat/io_nmmc.o $(portdir)/source/fat/io_scsd.o \
-			$(portdir)/source/fat/io_m3sd_asm.o $(portdir)/source/fat/io_scsd_asm.o 
+			$(portdir)/source/fat/io_m3sd_asm.o $(portdir)/source/fat/io_scsd_asm.o \
+			$(portdir)/source/fat/io_njsd.o \
+			$(portdir)/source/fat/io_mmcf.o \
+			$(portdir)/source/fat/io_sd_common.o \
+			$(portdir)/source/fat/io_m3_common.o 
+
+
+
+#			$(portdir)/source/fat/io_cf_common.o $(portdir)/source/fat/io_m3_common.o\
+#			$(portdir)/source/fat/io_sd_common.o $(portdir)/source/fat/io_scsd_s.o \
+#			$(portdir)/source/fat/io_sc_common.o $(portdir)/source/fat/io_sd_common.o 
+
 			
 			
 			
@@ -230,6 +261,7 @@
 endif
 
 
+#---------------------------------------------------------------------------------
  
 #---------------------------------------------------------------------------------
 %.o	:	%.pcx
@@ -269,9 +301,10 @@
 
 #---------------------------------------------------------------------------------
 %.nds: %.bin
-	@echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../logo.bmp "$(shell basename $@);ScummVM 0.9.0;Port v0.6"
-	ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../logo.bmp "$(shell basename $@);ScummVM 0.9.0;Port v0.6"
-	dsbuild $@
+	@echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.9.0;DS Port"
+	ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.9.1;DS Port"
+	dsbuild $@ -l ../ndsloader.bin
+
 	padbin 16 $(basename $@).ds.gba
 
 #---------------------------------------------------------------------------------

Added: scummvm/trunk/backends/platform/ds/arm9/ndsloader.bin
===================================================================
(Binary files differ)


Property changes on: scummvm/trunk/backends/platform/ds/arm9/ndsloader.bin
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: scummvm/trunk/backends/platform/ds/arm9/source/cdaudio.cpp
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/cdaudio.cpp	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/cdaudio.cpp	2006-11-03 23:16:29 UTC (rev 24596)
@@ -133,8 +133,14 @@
 	
 	
 	char str[100];
-	sprintf(str, "/track%d.wav", track);
-	path = path + str;
+
+	if (path[strlen(path.c_str()) - 1] == '/') {
+		sprintf(str, "track%d.wav", track);
+		path = path + str;
+	} else {
+		sprintf(str, "/track%d.wav", track);
+		path = path + str;
+	}
 	
 	
 	//1820160
@@ -459,10 +465,14 @@
 	consolePrintf("Attempted to open cd drive\n");
 
 	Common::String path = ConfMan.get("path");
-	path = path + "/track2.wav";
 	// 6577 153 154
+	if (path[strlen(path.c_str()) - 1] == '/') {
+		path = path + "track2.wav";
+	} else {
+		path = path + "/track2.wav";
+	}
 	consolePrintf("Looking for %s...", path.c_str());
-	
+
 	FILE* file;
 	if ((file = DS::std_fopen(path.c_str(), "r"))) {
 		consolePrintf("Success!\n");

Modified: scummvm/trunk/backends/platform/ds/arm9/source/dsmain.cpp
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/dsmain.cpp	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/dsmain.cpp	2006-11-03 23:16:29 UTC (rev 24596)
@@ -19,6 +19,21 @@
  */
  
 
+// - Turn off when quit - Done
+// - Simon and Kyrandia - Done
+// - 200% scale option - Done
+// - Change zoom range - Done
+// - Speed increase! - Done
+// - Fixed bugs in Sky - Done
+// - Change name of ini file and intro screen for build c - Done
+// - Check for existance of zip file in batch file - Done
+// - Add new support - Done
+// - Fix help screen
+
+// - Remove scummconsole.c
+// - Delete files
+// - Fatlib conversion
+
 #include <nds.h>
 
 #include <ARM9/console.h> //basic print funcionality
@@ -40,6 +55,9 @@
 #include "registers_alt.h"
 //#include "compact_flash.h"
 #include "dsoptions.h"
+#include "user_debugger.h"
+#include "ramsave.h"
+#include "disc_io.h"
 #include "blitters.h"
 
 namespace DS {
@@ -58,7 +76,7 @@
 // Defines
 #define FRAME_TIME 17
 #define SCUMM_GAME_HEIGHT 142
-#define SCUMM_GAME_WIDTH 232
+#define SCUMM_GAME_WIDTH 227
 
 int textureID;
 u16* texture;
@@ -93,6 +111,7 @@
 int bufferRate;
 int bufferSamples;
 bool soundHiPart;
+int soundFrequency;
 
 // Events
 int lastEventFrame;
@@ -116,12 +135,8 @@
 bool consoleEnable = true;
 bool gameScreenSwap = false;
 bool cpuScaler = false;
-bool isCpuScalerEnabled()
-{
-	return cpuScaler;	
-}
+bool isCpuScalerEnabled();
 
-
 MouseMode mouseMode;
 
 // Sprites
@@ -152,6 +167,9 @@
 int gameWidth = 320;
 int gameHeight = 200;
 
+// Scale
+bool twoHundredPercentFixedScale = false;
+
 enum controlType {
 	CONT_SCUMM_ORIGINAL,
 	CONT_SCUMM_SAMNMAX,
@@ -216,6 +234,10 @@
 
 TransferSound soundControl;
 
+bool isCpuScalerEnabled() {
+	return cpuScaler;	
+}
+
 //plays an 8 bit mono sample at 11025Hz
 void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate)
 {
@@ -313,11 +335,49 @@
 }
 
 
+void startSound(int freq, int buffer) {
+	bufferRate = freq * 2;
+	bufferFrame = 0;
+	bufferSamples = 4096;
+
+	bufferFirstHalf = false;
+	bufferSecondHalf = true;
+	
+	int bytes = (2 * (bufferSamples)) + 100;
+	
+	soundBuffer = (s16 *) malloc(bytes * 2);
+
+
+	soundHiPart = true;
+	
+	for (int r = 0; r < bytes; r++) {
+		soundBuffer[r] = 0;
+	}
+
+	soundFrequency = freq;
+	
+
+	swiWaitForVBlank();
+	swiWaitForVBlank();
+	playSound(soundBuffer, (bufferSamples * 2), true, false, freq * 2);
+	swiWaitForVBlank();
+	swiWaitForVBlank();
+	swiWaitForVBlank();
+}
+
+int getSoundFrequency() {
+	return soundFrequency;
+}
+
+
 void initGame() {
 	// This is a good time to check for left handed mode since the mode change is done as the game starts.
 	// There's probably a better way, but hey.
 //	consolePrintf("initing game\n");
 
+	static bool firstTime = true;
+
+
 	setOptions();
 
 	//strcpy(gameName, ConfMan.getActiveDomain().c_str());
@@ -332,8 +392,18 @@
 //			consolePrintf("Game list num: %d\n", currentGame);
 		}
 	}
-	
+		
+	if (firstTime) {
+		firstTime = false;
 
+		if (ConfMan.hasKey("22khzaudio", "ds") && ConfMan.getBool("22khzaudio", "ds")) {
+			startSound(22050, 8192);
+		} else {
+			startSound(11025, 4096);
+		}
+
+	}
+
 }
 
 void setLeftHanded(bool enable) {
@@ -348,6 +418,10 @@
 	touchYOffset = y;
 }
 
+void set200PercentFixedScale(bool on) {
+	twoHundredPercentFixedScale = on;
+}
+
 void setUnscaledMode(bool enable) {
 	scaledMode = !enable;
 }
@@ -991,7 +1065,7 @@
 					// Extra controls for Benieth a Steel Sky
 					if ((getKeysDown() & KEY_DOWN)) {
 						penY = 0;
-						penX = 0;		// Show inventory by moving mouse onto top line
+						penX = 160;		// Show inventory by moving mouse onto top line
 					}
 				}
 
@@ -1244,7 +1318,16 @@
 
 //	consolePri ntf("X:%d Y:%d\n", getPenX(), getPenY());
 
+	static bool firstTime = true;
 
+	// This is to ensure that the ARM7 vblank handler runs before this one.
+	// Fixes the problem with the MMD when the screens swap over on load.
+	if (firstTime) {
+		firstTime = false;
+		return;
+	}
+
+
 	IPC->tweak = tweak;
 	soundUpdate();
 
@@ -1327,36 +1410,46 @@
     SUB_BG3_XDY = 0;
     SUB_BG3_YDX = 0;
     SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256);*/
+
+	static int ratio = ( 320 << 8) / SCUMM_GAME_WIDTH;
 	
 	
 	if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) {
-		if ((getKeysHeld() & KEY_A) && (subScreenScale < 256)) {
-			subScreenScale += 3;
+		if ((getKeysHeld() & KEY_A) && (subScreenScale < ratio)) {
+			subScreenScale += 2;
 		}
 		
 		if ((getKeysHeld() & KEY_B) && (subScreenScale > 128)) {
-			subScreenScale -=3;
+			subScreenScale -=2;
 		}
-		
-		int xCenter = subScTargetX + ((subScreenWidth >> 1) << 8);
-		int yCenter = subScTargetY + ((subScreenHeight >> 1) << 8);
-		
-		subScreenWidth = SCUMM_GAME_WIDTH * subScreenScale >> 8;
-		subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8;
-		
-		subScTargetX = xCenter - ((subScreenWidth >> 1) << 8);
-		subScTargetY = yCenter - ((subScreenHeight >> 1) << 8);
-		
+	}
 
-		
 
-		if (subScTargetX < 0) subScTargetX = 0;
-		if (subScTargetX > (gameWidth - subScreenWidth) << 8) subScTargetX = (gameWidth - subScreenWidth) << 8;
+	int xCenter = subScTargetX + ((subScreenWidth >> 1) << 8);
+	int yCenter = subScTargetY + ((subScreenHeight >> 1) << 8);
 	
-		if (subScTargetY < 0) subScTargetY = 0;
-		if (subScTargetY > (gameHeight - subScreenHeight) << 8) subScTargetY = (gameHeight - subScreenHeight) << 8;
+	if (twoHundredPercentFixedScale) {
+		subScreenWidth = 256 >> 1;
+		subScreenHeight = 192 >> 1;
+	} else {
+		subScreenWidth = SCUMM_GAME_WIDTH * subScreenScale >> 8;
+		subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8;
 	}
+	
+	subScTargetX = xCenter - ((subScreenWidth >> 1) << 8);
+	subScTargetY = yCenter - ((subScreenHeight >> 1) << 8);
+	
 
+	
+
+	if (subScTargetX < 0) subScTargetX = 0;
+	if (subScTargetX > (gameWidth - subScreenWidth) << 8) subScTargetX = (gameWidth - subScreenWidth) << 8;
+
+	if (subScTargetY < 0) subScTargetY = 0;
+	if (subScTargetY > (gameHeight - subScreenHeight) << 8) subScTargetY = (gameHeight - subScreenHeight) << 8;
+
+
+
 	subScX += (subScTargetX - subScX) >> 2;
 	subScY += (subScTargetY - subScY) >> 2;
 	
@@ -1526,9 +1619,19 @@
 */
 
 
+	for (int r = 0; r < 255; r++) {
+		PALETTE[r] = 0;
+	}
 
 	PALETTE[255] = RGB15(0,31,0);
 
+
+	for (int r = 0; r < 255; r++) {
+		PALETTE_SUB[r] = 0;
+	}
+
+	PALETTE_SUB[255] = RGB15(0,31,0);
+
 	// Allocate save buffer for game screen
 //	savedBuffer = new u8[320 * 200];
 	displayMode16Bit();
@@ -1797,9 +1900,11 @@
 
 bool GBAMPAvail = false;
 
-void initGBAMP() {	
-	FAT_InitFiles();
-	if (disc_IsInserted()) {
+void initGBAMP(int mode) {	
+	if (FAT_InitFiles()) {
+		if (mode == 2)	{
+			disc_IsInserted();
+		}
 		GBAMPAvail = true;
 		consolePrintf("Found flash card reader!\n");
 	} else {
@@ -1813,14 +1918,52 @@
 }
 
 
+#ifdef USE_DEBUGGER
+void initDebugger() {
+	set_verbosity(VERBOSE_INFO | VERBOSE_ERROR);
+	wireless_init(0);
+	wireless_connect();
+	
+	// This is where the address of the computer running the Java
+	// stub goes.
+	debugger_connect_tcp(192, 168, 0, 1);
+	debugger_init();	
+	
+	// Update function - should really call every frame
+	user_debugger_update();	
+}
 
+
+// Ensure the function is processed with C linkage
+extern "C" void debug_print_stub(char* string);
+
+void debug_print_stub(char *string) {
+	consolePrintf(string);
+}
+#endif
+
+void powerOff() {
+	while (keysHeld() != 0) {		// Wait for all keys to be released.
+		swiWaitForVBlank();			// Allow you to read error before the power
+	}								// is turned off.
+
+	for (int r = 0; r < 60; r++) {
+		swiWaitForVBlank();
+	}
+
+	if (ConfMan.hasKey("disablepoweroff", "ds") && ConfMan.getBool("disablepoweroff", "ds")) {
+		while (true);
+	} else {
+		IPC->reset = true;				// Send message to ARM7 to turn power off
+		while (true);		// Stop the program continuing beyond this point
+	}
+}
+
 /////////////////
 // Main
 /////////////////
 
 
-
-
 int main(void)
 {
 	soundCallback = NULL;
@@ -1828,6 +1971,13 @@
 
 	initHardware();
 	
+#ifdef USE_DEBUGGER
+	swiWaitForVBlank();
+	if (!(keysHeld() & KEY_Y)) {
+		initDebugger();
+	}
+#endif
+	
 	// Let arm9 read cartridge
 	*((u16 *) (0x04000204)) &= ~0x0080;
 	
@@ -1844,26 +1994,40 @@
 //	playSound(twang, 11010, true);   // 18640
 
 //	bufferSize = 10;
-	bufferRate = 22050;
+
+	
+	/*bufferRate = 44100;
 	bufferFrame = 0;
-//	bufferSamples = (bufferRate * bufferSize) / 60;
-	bufferSamples = 4096;
-	
+	bufferSamples = 8192;
+
 	bufferFirstHalf = false;
 	bufferSecondHalf = true;
 	
-	lastEventFrame = 0;
-	mouseMode = MOUSE_LEFT;
+	int bytes = (2 * (bufferSamples)) + 100;
+	
+	soundBuffer = (s16 *) malloc(bytes * 2);
 
+
+	soundHiPart = true;
 	
+	for (int r = 0; r < bytes; r++) {
+		soundBuffer[r] = 0;
+	}
+	
 
+	swiWaitForVBlank();
+	swiWaitForVBlank();
+	playSound(soundBuffer, (bufferSamples * 2), true);
+	swiWaitForVBlank();
+	swiWaitForVBlank();
+	swiWaitForVBlank();
+*/
 	
-	int bytes = (2 * (bufferSamples)) + 100;
+
+	lastEventFrame = 0;
+	mouseMode = MOUSE_LEFT;
 	
-	soundBuffer = (s16 *) malloc(bytes * 2);
 
-
-	soundHiPart = true;
 /*
 	TIMER1_CR = 0;
 	TIMER1_DATA = TIMER_FREQ(bufferRate);
@@ -1883,50 +2047,110 @@
 	
 
 	
-	consolePrintf("------------------------\n");
+	consolePrintf("---------------------------\n");
 	consolePrintf("ScummVM DS\n");
 	consolePrintf("Ported by Neil Millstone\n");
-#ifdef DS_SCUMM_BUILD
-	consolePrintf("Version 0.61 build A\n");
-#else
-	consolePrintf("Version 0.61 build B\n");
+	consolePrintf("Version 0.10.0SVN ");
+#if defined(DS_BUILD_A)
+	consolePrintf("build A\n");
+	consolePrintf("Supports: Lucasarts SCUMM\n");
+	consolePrintf("---------------------------\n");
+#elif defined(DS_BUILD_B)
+	consolePrintf("build B\n");
+	consolePrintf("Supports: BASS, QUEEN\n");
+	consolePrintf("---------------------------\n");
+#elif defined(DS_BUILD_C)
+	consolePrintf("build C\n");
+	consolePrintf("---------------------------\n");
+	consolePrintf("Supports: SIMON, KYRA, GOB\n");
 #endif
-	consolePrintf("------------------------\n");
 	consolePrintf("L/R + D-pad/pen: Scroll view\n");
 	consolePrintf("D-pad left:  Left mouse button\n");
 	consolePrintf("D-pad right: Right mouse button\n");
 	consolePrintf("D-pad up:    Hover mouse\n");
-	consolePrintf("D-pad down:  Skip dialog line\n");
 	consolePrintf("B button:    Skip cutscenes\n");
 	consolePrintf("Select:		DS Options menu\n");
 	consolePrintf("Start:       Game menu\n");
 	consolePrintf("Y (in game): Toggle console\n");
 	consolePrintf("X:           Toggle keyboard\n");
 	consolePrintf("A:			Swap screens\n");
-	consolePrintf("L + R on bootup: Clear SRAM\n\n");
-	consolePrintf("For a complete poo list see the\n");
+	consolePrintf("L+R (on start): Clear SRAM\n");
+
+#if defined(DS_BUILD_A)
+	consolePrintf("For a complete key list see the\n");
 	consolePrintf("help screen.\n\n");
+#else
+	consolePrintf("\n");
+#endif
 
+	
+	// Do M3 detection selectioon
+	int extraData = DSSaveFileManager::getExtraData();
+	bool present = DSSaveFileManager::isExtraDataPresent();
 
-	for (int r = 0; r < bytes; r++) {
-		soundBuffer[r] = 0;
+	for (int r = 0; r < 30; r++) {
+		swiWaitForVBlank();
 	}
-	
 
-	swiWaitForVBlank();
-	swiWaitForVBlank();
-	playSound(soundBuffer, (bufferSamples * 2), true);
-	swiWaitForVBlank();
-	swiWaitForVBlank();
-	swiWaitForVBlank();
-	
+	int mode = extraData & 0x03;
 
+	if (mode == 0) {
+		if ((keysHeld() & KEY_L) && !(keysHeld() & KEY_R)) {
+			mode = 1;
+		} else if (!(keysHeld() & KEY_L) && (keysHeld() & KEY_R)) {
+			mode = 2;
+		}
+	} else {
+		if ((keysHeld() & KEY_L) && !(keysHeld() & KEY_R)) {
+			mode = 0;
+		}
+	}
 
+
+	if (mode == 0) {
+		consolePrintf("On startup hold L if you have\n");
+		consolePrintf("an M3 SD or R for an SC SD\n");
+	} else if (mode == 1) {
+		consolePrintf("Using M3 SD Mode.\n");
+		consolePrintf("Hold L on startup to disable.\n");
+	} else if (mode == 2) {
+		consolePrintf("Using SC SD Mode.\n");
+		consolePrintf("Hold L on startup to disable.\n");
+	}
+
+	disc_setEnable(mode);
+	DSSaveFileManager::setExtraData(mode);
+
+
+/*
+	if ((present) && (extraData & 0x00000001)) {
+
+		if (keysHeld() & KEY_L) {
+			extraData &= ~0x00000001;
+			consolePrintf("M3 SD Detection: OFF\n");
+			DSSaveFileManager::setExtraData(extraData);
+		} else {
+			consolePrintf("M3 SD Detection: ON\n");
+			consolePrintf("Hold L on startup to disable.\n");
+		}
+
+	} else if (keysHeld() & KEY_L) {
+		consolePrintf("M3 SD Detection: ON\n");
+		extraData |= 0x00000001;
+		DSSaveFileManager::setExtraData(extraData);
+	} else {
+		consolePrintf("M3 SD Detection: OFF\n");
+		consolePrintf("Hold L on startup to enable.\n");
+	}
+
+	disc_setM3SDEnable(extraData & 0x00000001);
+*/
 	// Create a file system node to force search for a zip file in GBA rom space
+
 	DSFileSystemNode* node = new DSFileSystemNode();
 	if (!node->getZip() || (!node->getZip()->isReady())) {
 		// If not found, init CF/SD driver
-		initGBAMP();
+		initGBAMP(mode);
 	}
 	delete node;
 
@@ -1936,6 +2160,7 @@
 	
 	
 //	OSystem_DS::instance();
+
 	g_system = new OSystem_DS();
 	assert(g_system);
 
@@ -1945,20 +2170,28 @@
 
 //	printf("'%s'", Common::ConfigManager::kTransientDomain.c_str());
 	//printf("'%s'", Common::ConfigManager::kApplicationDomain.c_str());
-	
 
+#if defined(DS_BUILD_A)
+	char* argv[2] = {"/scummvmds", "--config=scummvm.ini"};
+#elif defined(DS_BUILD_B)
 	char* argv[2] = {"/scummvmds", "--config=scummvmb.ini"};
+#elif defined(DS_BUILD_C)
+	char* argv[2] = {"/scummvmds", "--config=scummvmc.ini"};
+#endif
+
+
 #ifdef DS_NON_SCUMM_BUILD	
 
 	while (1) {
 		scummvm_main(2, (char **) &argv);
+		powerOff();
 	}
 #else
 	while (1) {
 		scummvm_main(1, (char **) &argv);
+		powerOff();
 	}
 #endif
-	
 
 	return 0;
 }
@@ -1968,3 +2201,4 @@
 int main() {
 	DS::main();
 }
+

Modified: scummvm/trunk/backends/platform/ds/arm9/source/dsmain.h
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/dsmain.h	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/dsmain.h	2006-11-03 23:16:29 UTC (rev 24596)
@@ -61,6 +61,7 @@
 
 void 	setTalkPos(int x, int y);
 void 	setTopScreenTarget(int x, int y);
+void	set200PercentFixedScale(bool on);
 
 // Timers
 void 	setTimerCallback(OSystem_DS::TimerProc proc, int interval);		// Setup a callback function at a regular interval
@@ -72,6 +73,7 @@
 void 	doSoundCallback();												// Call function if sound buffers need more data
 void 	playSound(const void* data, u32 length, bool loop, bool adpcm = false, int rate = 22050);		// Start a sound
 void 	stopSound(int channel);
+int		getSoundFrequency();
 
 // Event queue
 void 	addEventsToQueue();
@@ -108,7 +110,6 @@
 bool 	getIndyFightState();
 bool    isCpuScalerEnabled();
 
-
 // Display
 bool 	getIsDisplayMode8Bit();
 void 	setGameSize(int width, int height);

Modified: scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.cpp
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.cpp	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.cpp	2006-11-03 23:16:29 UTC (rev 24596)
@@ -36,8 +36,8 @@
 
 namespace DS {
 
-DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 20, 320 - 40, 200 - 40) {
-	addButton(this, 10, 140, "Close", GUI::kCloseCmd, 'C');
+DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) {
+	addButton(this, 10, 160, "Close", GUI::kCloseCmd, 'C');
 	
 #ifdef DS_SCUMM_BUILD
 	if (!DS::isGBAMPAvailable()) {
@@ -45,29 +45,32 @@
 	}
 #endif
 
-	new GUI::StaticTextWidget(this, 0, 10, 280, 20, "ScummVM DS Options", GUI::kTextAlignCenter);
+	new GUI::StaticTextWidget(this, 80, 10, 130, 15, "ScummVM DS Options", GUI::kTextAlignCenter);
 
-	_leftHandedCheckbox = new GUI::CheckboxWidget(this, 20, 30, 280, 20, "Left handed mode", 0, 'L');
-	_indyFightCheckbox = new GUI::CheckboxWidget(this, 20, 50, 280, 20, "Indy fighting controls", 0, 'I');
-	_unscaledCheckbox = new GUI::CheckboxWidget(this, 20, 70, 280, 20, "Unscaled lower screen", 0, 'S');
+	_leftHandedCheckbox = new GUI::CheckboxWidget(this, 20, 25, 200, 20, "Left handed mode", 0, 'L');
+	_indyFightCheckbox = new GUI::CheckboxWidget(this, 20, 40, 200, 20, "Indy fighting controls", 0, 'I');
+	_unscaledCheckbox = new GUI::CheckboxWidget(this, 20, 55, 200, 20, "Unscaled main screen", 0, 'S');
+	_twoHundredPercentCheckbox = new GUI::CheckboxWidget(this, 20, 70, 230, 20, "Zoomed screen at fixed 200% zoom", 0, 'T');
+	_highQualityAudioCheckbox = new GUI::CheckboxWidget(this, 20, 85, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
+	_disablePowerOff = new GUI::CheckboxWidget(this, 20, 100, 250, 20, "Disable power off on quit", 0, 'T');
 
-	new GUI::StaticTextWidget(this, 20, 90, 110, 20, "Touch X Offset", GUI::kTextAlignLeft);
-	_touchX = new GUI::SliderWidget(this, 130, 90, 130, 12, 1);
+	new GUI::StaticTextWidget(this, 20, 130, 110, 15, "Touch X Offset", GUI::kTextAlignLeft);
+	_touchX = new GUI::SliderWidget(this, 130, 130, 130, 12, 1);
 	_touchX->setMinValue(-8);
 	_touchX->setMaxValue(+8);
 	_touchX->setValue(0);
 	_touchX->setFlags(GUI::WIDGET_CLEARBG);
 
-	new GUI::StaticTextWidget(this, 20, 110, 110, 20, "Touch Y Offset", GUI::kTextAlignLeft);
-	_touchY = new GUI::SliderWidget(this, 130, 110, 130, 12, 2);
+	new GUI::StaticTextWidget(this, 20, 145, 110, 15, "Touch Y Offset", GUI::kTextAlignLeft);
+	_touchY = new GUI::SliderWidget(this, 130, 145, 130, 12, 2);
 	_touchY->setMinValue(-8);
 	_touchY->setMaxValue(+8);
 	_touchY->setValue(0);
 	_touchY->setFlags(GUI::WIDGET_CLEARBG);
 
-	new GUI::StaticTextWidget(this, 130 + 65 - 10, 130, 20, 20, "0", GUI::kTextAlignCenter);
-	new GUI::StaticTextWidget(this, 130 + 130 - 10, 130, 20, 20, "8", GUI::kTextAlignCenter);
-	new GUI::StaticTextWidget(this, 130 - 10, 130, 20, 20, "-8", GUI::kTextAlignCenter);
+	new GUI::StaticTextWidget(this, 130 + 65 - 10, 160, 20, 15, "0", GUI::kTextAlignCenter);
+	new GUI::StaticTextWidget(this, 130 + 130 - 10, 160, 20, 15, "8", GUI::kTextAlignCenter);
+	new GUI::StaticTextWidget(this, 130 - 10, 160, 20, 15, "-8", GUI::kTextAlignCenter);
 
 #ifdef DS_SCUMM_BUILD
 	_delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm);
@@ -84,7 +87,25 @@
 	} else {
 		_unscaledCheckbox->setState(false);
 	}
-	
+
+	if (ConfMan.hasKey("twohundredpercent", "ds")) {
+		_twoHundredPercentCheckbox->setState(ConfMan.getBool("twohundredpercent", "ds"));
+	} else {
+		_twoHundredPercentCheckbox->setState(false);
+	}
+
+	if (ConfMan.hasKey("22khzaudio", "ds")) {
+		_highQualityAudioCheckbox->setState(ConfMan.getBool("22khzaudio", "ds"));
+	} else {
+		_highQualityAudioCheckbox->setState(false);
+	}
+
+	if (ConfMan.hasKey("disablepoweroff", "ds")) {
+		_disablePowerOff->setState(ConfMan.getBool("disablepoweroff", "ds"));
+	} else {
+		_disablePowerOff->setState(false);
+	}
+
 	_indyFightCheckbox->setState(DS::getIndyFightState());
 
 	if (ConfMan.hasKey("xoffset", "ds")) {
@@ -104,6 +125,9 @@
 DSOptionsDialog::~DSOptionsDialog() {
 	ConfMan.setBool("lefthanded", _leftHandedCheckbox->getState(), "ds");
 	ConfMan.setBool("unscaled", _unscaledCheckbox->getState(), "ds");
+	ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
+	ConfMan.setBool("22khzaudio", _highQualityAudioCheckbox->getState(), "ds");
+	ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds");
 	ConfMan.setInt("xoffset", _touchX->getValue(), "ds");
 	ConfMan.setInt("yoffset", _touchY->getValue(), "ds");
 	DS::setOptions();
@@ -189,6 +213,12 @@
 		DS::setUnscaledMode(false);
 	}
 
+	if (ConfMan.hasKey("twohundredpercent", "ds")) {
+		DS::set200PercentFixedScale(ConfMan.getBool("twohundredpercent", "ds"));
+	} else {
+		DS::set200PercentFixedScale(false);
+	}
+
 	if (ConfMan.hasKey("xoffset", "ds")) {
 		DS::setTouchXOffset(ConfMan.getInt("xoffset", "ds"));
 	} else {

Modified: scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.h
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.h	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/dsoptions.h	2006-11-03 23:16:29 UTC (rev 24596)
@@ -47,7 +47,10 @@
 	GUI::SliderWidget* _touchY;
 	GUI::CheckboxWidget* _leftHandedCheckbox;
 	GUI::CheckboxWidget* _unscaledCheckbox;
+	GUI::CheckboxWidget* _twoHundredPercentCheckbox;
 	GUI::CheckboxWidget* _indyFightCheckbox;
+	GUI::CheckboxWidget* _highQualityAudioCheckbox;
+	GUI::CheckboxWidget* _disablePowerOff;
 #ifdef DS_SCUMM_BUILD
 	Scumm::SaveLoadChooser* _delDialog;
 #endif

Modified: scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.c
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.c	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.c	2006-11-03 23:16:29 UTC (rev 24596)
@@ -29,6 +29,7 @@
 */
 
 #include "disc_io.h"
+#include "scummconsole.h"
 
 #ifdef NDS
 	#include <nds.h>
@@ -68,6 +69,14 @@
  #include "io_efa2.h"
 #endif
 
+#ifdef SUPPORT_NJSD
+ #include "io_njsd.h"
+#endif
+
+#ifdef SUPPORT_MMCF
+ #include "io_mmcf.h"
+#endif
+
 // Keep a pointer to the active interface
 LPIO_INTERFACE active_interface = 0;
 
@@ -79,6 +88,7 @@
 		Added by www.neoflash.com 
 
 */
+int discDetect = 0;
 
 #ifdef DISC_CACHE
 
@@ -122,16 +132,16 @@
 			i = j;
 		}
 	}
-	
+	/*
 	if( cache[ i ].sector != CACHE_FREE && cache[i].dirty != 0 ) {
 
 		active_interface->fn_WriteSectors( cache[ i ].sector, 1, &cacheBuffer[ i * 512 ] );
-		/* todo: handle write error here */
+		/* todo: handle write error here 
 
 		cache[ i ].sector = CACHE_FREE;
 		cache[ i ].dirty = 0;
 		cache[ i ].count = 0;
-	}
+	}*/
 
 	return i;
 }
@@ -210,6 +220,10 @@
 
 */
 
+void disc_setEnable(int disc) {
+	discDetect = disc;
+}
+
 bool disc_setGbaSlotInterface (void)
 {
 	// If running on an NDS, make sure the correct CPU can access
@@ -223,26 +237,45 @@
  #endif
 #endif
 
-#ifdef SUPPORT_M3CF
-	// check if we have a M3 perfect CF plugged in
-	active_interface = M3CF_GetInterface() ;
+
+#ifdef SUPPORT_M3SD
+	if (discDetect == 1)	{
+		// check if we have a M3 perfect SD plugged in
+		active_interface = M3SD_GetInterface() ;
+		if (active_interface->fn_StartUp())
+		{
+			// set M3 SD as default IO
+			return true ;
+		} ;
+	}
+#endif
+
+
+
+
+#ifdef SUPPORT_MMCF
+	// check if we have a GBA Flash Cart plugged in
+	active_interface = MMCF_GetInterface() ;
 	if (active_interface->fn_StartUp())
 	{
-		// set M3 CF as default IO
+		// set MMCF as default IO
 		return true ;
 	} ;
 #endif
 
-#ifdef SUPPORT_M3SD
-	// check if we have a M3 perfect SD plugged in
-	active_interface = M3SD_GetInterface() ;
+
+
+#ifdef SUPPORT_M3CF
+	// check if we have a M3 perfect CF plugged in
+	active_interface = M3CF_GetInterface() ;
 	if (active_interface->fn_StartUp())
 	{
-		// set M3 SD as default IO
+		// set M3 CF as default IO
 		return true ;
 	} ;
 #endif
 
+
 #ifdef SUPPORT_MPCF
 	// check if we have a GBA Movie Player plugged in
 	active_interface = MPCF_GetInterface() ;
@@ -253,6 +286,7 @@
 	} ;
 #endif
 
+
 #ifdef SUPPORT_SCCF
 	// check if we have a SuperCard CF plugged in
 	active_interface = SCCF_GetInterface() ;
@@ -263,15 +297,6 @@
 	} ;
 #endif
 
-#ifdef SUPPORT_SCSD
-	// check if we have a SuperCard SD plugged in
-	active_interface = SCSD_GetInterface() ;
-	if (active_interface->fn_StartUp())
-	{
-		// set SC SD as default IO
-		return true ;
-	} ;
-#endif
 
 
 #ifdef SUPPORT_EFA2
@@ -283,6 +308,7 @@
 	} ;
 #endif
 
+
 #ifdef SUPPORT_FCSR
 	// check if we have a GBA Flash Cart plugged in
 	active_interface = FCSR_GetInterface() ;
@@ -293,6 +319,9 @@
 	} ;
 #endif
 
+
+
+
 	return false;
 }
 
@@ -310,6 +339,29 @@
 	WAIT_CR |= (1<<11);
 #endif
 
+#ifdef SUPPORT_SCSD
+	// check if we have a SuperCard SD plugged in
+	if (discDetect == 2) {
+		active_interface = SCSD_GetInterface() ;
+		consolePrintf("SCSD!");
+		if (active_interface->fn_StartUp())
+		{
+			// set SC SD as default IO
+			return true ;
+		} ;
+	}
+#endif
+
+#ifdef SUPPORT_NJSD
+	// check if we have a GBA Flash Cart plugged in
+	active_interface = NJSD_GetInterface() ;
+	if (active_interface->fn_StartUp())
+	{
+		// set NJSD as default IO
+		return true ;
+	} ;
+#endif
+
 #ifdef SUPPORT_NMMC
 	// check if we have a Neoflash MK2 / MK3 plugged in
 	active_interface = NMMC_GetInterface() ;
@@ -320,6 +372,9 @@
 	} ;
 #endif
 
+
+
+
 	return false;
 }
 #endif
@@ -378,7 +433,7 @@
 
 bool disc_WriteSectors(u32 sector, u8 numSecs, void* buffer) 
 {
-#ifdef DISC_CACHE
+/*#ifdef DISC_CACHE
 	u8 *p=(u8*)buffer;
 	u32 i;
 	u32 inumSecs=numSecs;
@@ -389,10 +444,13 @@
 			return false;
 	}
 	return true;
-#else
+#else*/
+#ifdef DISC_CACHE
+	disc_CacheInit();
+#endif
 	if (active_interface) return active_interface->fn_WriteSectors(sector,numSecs,buffer) ;
 	return false ;
-#endif
+//#endif
 } 
 
 bool disc_ClearStatus(void) 

Modified: scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.h
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.h	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/disc_io.h	2006-11-03 23:16:29 UTC (rev 24596)
@@ -10,7 +10,8 @@
 // Allow buffers not aligned to 16 bits when reading files. 
 // Note that this will slow down access speed, so only use if you have to.
 // It is also incompatible with DMA
-//#define _CF_ALLOW_UNALIGNED
+#define _CF_ALLOW_UNALIGNED
+#define _IO_ALLOW_UNALIGNED
 
 // Device support options, added by www.neoflash.com
 
@@ -22,13 +23,15 @@
 #define SUPPORT_SCSD		// comment out this line to remove Supercard SD support
 //#define SUPPORT_EFA2		// comment out this line to remove EFA2 linker support
 #define SUPPORT_FCSR		// comment out this line to remove GBA Flash Cart support
+#define SUPPORT_NJSD
+#define SUPPORT_MMCF
 
 // Disk caching options, added by www.neoflash.com
 // Each additional sector cache uses 512 bytes of memory
 // Disk caching is disabled on GBA to conserve memory
 
 #define DISC_CACHE				// uncomment this line to enable disc caching
-#define DISC_CACHE_COUNT	16	// maximum number of sectors to cache (512 bytes per sector)
+#define DISC_CACHE_COUNT	32	// maximum number of sectors to cache (512 bytes per sector)
 //#define DISK_CACHE_DMA		// use DMA for cache copies. If this is enabled, the data buffers must be word aligned
 
 
@@ -83,189 +86,9 @@
 -----------------------------------------------------------------*/
 extern bool disc_IsInserted(void) ;
 
-/*-----------------------------------------------------------------
-disc_ReadSectors
-Read 512 byte sector numbered "sector" into "buffer"
-u32 sector IN: address of first 512 byte sector on disc to read
-u8 numSecs IN: number of 512 byte sectors to read,
- 1 to 256 sectors can be read, 0 = 256
-void* buffer OUT: pointer to 512 byte buffer to store data in
-bool return OUT: true if successful
------------------------------------------------------------------*/
-extern bool disc_ReadSectors(u32 sector, u8 numSecs, void* buffer) ;
-#define disc_ReadSector(sector,buffer)	disc_ReadSectors(sector,1,buffer)
 
+extern void disc_setEnable(int en);
 /*-----------------------------------------------------------------
-disc_WriteSectors
-Write 512 byte sector numbered "sector" from "buffer"
-u32 sector IN: address of 512 byte sector on disc to write
-u8 numSecs IN: number of 512 byte sectors to write	,
- 1 to 256 sectors can be read, 0 = 256
-void* buffer IN: pointer to 512 byte buffer to read data from
-bool return OUT: true if successful
------------------------------------------------------------------*/
-extern bool disc_WriteSectors(u32 sector, u8 numSecs, void* buffer) ;
-#define disc_WriteSector(sector,buffer)	disc_WriteSectors(sector,1,buffer)
-
-/*-----------------------------------------------------------------
-disc_ClearStatus
-Tries to make the disc go back to idle mode
-bool return OUT:  true if the disc is idle
------------------------------------------------------------------*/
-extern bool disc_ClearStatus(void) ;
-
-/*-----------------------------------------------------------------
-disc_Shutdown
-unload the disc interface
-bool return OUT: true if successful
------------------------------------------------------------------*/
-extern bool disc_Shutdown(void) ;
-
-/*-----------------------------------------------------------------
-disc_HostType
-Returns a unique u32 number identifying the host type
-u32 return OUT: 0 if no host initialised, else the identifier of
-	the host
------------------------------------------------------------------*/
-extern u32 disc_HostType(void);
-
-/*-----------------------------------------------------------------
-disc_CacheFlush
-Flushes any cache writes to disc
-bool return OUT: true if successful, false if an error occurs
-Added by www.neoflash.com
------------------------------------------------------------------*/
-#ifdef DISC_CACHE
-extern bool disc_CacheFlush(void);
-#else
-static inline bool disc_CacheFlush(void)
-{
-	return true;
-}
-#endif // DISC_CACHE
-
-
-/*
-
-	Interface for IO libs
-
-*/
-
-#define FEATURE_MEDIUM_CANREAD		0x00000001
-#define FEATURE_MEDIUM_CANWRITE		0x00000002
-#define FEATURE_SLOT_GBA			0x00000010
-#define FEATURE_SLOT_NDS			0x00000020
-
-typedef bool (* FN_MEDIUM_STARTUP)(void) ;
-typedef bool (* FN_MEDIUM_ISINSERTED)(void) ;
-typedef bool (* FN_MEDIUM_READSECTORS)(u32 sector, u8 numSecs, void* buffer) ;
-typedef bool (* FN_MEDIUM_WRITESECTORS)(u32 sector, u8 numSecs, void* buffer) ;
-typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ;
-typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ;
-
-
-typedef struct {
-	unsigned long			ul_ioType ;
-	unsigned long			ul_Features ;
-	FN_MEDIUM_STARTUP		fn_StartUp ;
-	FN_MEDIUM_ISINSERTED	fn_IsInserted ;
-	FN_MEDIUM_READSECTORS	fn_ReadSectors ;
-	FN_MEDIUM_WRITESECTORS	fn_WriteSectors ;
-	FN_MEDIUM_CLEARSTATUS	fn_ClearStatus ;
-	FN_MEDIUM_SHUTDOWN		fn_Shutdown ;
-} IO_INTERFACE, *LPIO_INTERFACE ;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	// define DISC_IO_H
-#ifndef DISC_IO_H
-#define DISC_IO_H
-
-//----------------------------------------------------------------------
-// Customisable features
-
-// Use DMA to read the card, remove this line to use normal reads/writes
-// #define _CF_USE_DMA
-
-// Allow buffers not aligned to 16 bits when reading files. 
-// Note that this will slow down access speed, so only use if you have to.
-// It is also incompatible with DMA
-//#define _CF_ALLOW_UNALIGNED
-
-// Device support options, added by www.neoflash.com
-
-#define SUPPORT_NMMC		// comment out this line to remove Neoflash MK2 MMC Card support
-#define SUPPORT_MPCF		// comment out this line to remove GBA Movie Player support
-#define SUPPORT_M3CF		// comment out this line to remove M3 Perfect CF support
-#define SUPPORT_M3SD		// comment out this line to remove M3 Perfect SD support
-#define SUPPORT_SCCF		// comment out this line to remove Supercard CF support
-#define SUPPORT_SCSD		// comment out this line to remove Supercard SD support
-//#define SUPPORT_EFA2		// comment out this line to remove EFA2 linker support
-#define SUPPORT_FCSR		// comment out this line to remove GBA Flash Cart support
-
-// Disk caching options, added by www.neoflash.com
-// Each additional sector cache uses 512 bytes of memory
-// Disk caching is disabled on GBA to conserve memory
-
-#define DISC_CACHE				// uncomment this line to enable disc caching
-#define DISC_CACHE_COUNT	16	// maximum number of sectors to cache (512 bytes per sector)
-//#define DISK_CACHE_DMA		// use DMA for cache copies. If this is enabled, the data buffers must be word aligned
-
-
-//----------------------------------------------------------------------
-
-#if defined _CF_USE_DMA && defined _CF_ALLOW_UNALIGNED
- #error You can't use both DMA and unaligned memory
-#endif
-
-// When compiling for NDS, make sure NDS is defined
-#ifndef NDS
- #if defined ARM9 || defined ARM7
-  #define NDS
- #endif
-#endif
-
-#ifdef NDS
- #include <nds/jtypes.h>
-#else
- #include "gba_types.h"
-#endif
-
-// Disable NDS specific hardware and features if running on a GBA
-#ifndef NDS 
- #undef SUPPORT_NMMC
- #undef DISC_CACHE
-#endif
-
-/*
-
-	Interface for host program
-
-*/
-
-#define BYTE_PER_READ 512
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*-----------------------------------------------------------------
-disc_Init
-Detects the inserted hardware and initialises it if necessary
-bool return OUT:  true if a suitable device was found
------------------------------------------------------------------*/
-extern bool disc_Init(void) ;
-
-/*-----------------------------------------------------------------
-disc_IsInserted
-Is a usable disc inserted?
-bool return OUT:  true if a disc is inserted
------------------------------------------------------------------*/
-extern bool disc_IsInserted(void) ;
-
-/*-----------------------------------------------------------------
 disc_ReadSectors
 Read 512 byte sector numbered "sector" into "buffer"
 u32 sector IN: address of first 512 byte sector on disc to read
@@ -362,3 +185,4 @@
 #endif
 
 #endif	// define DISC_IO_H
+

Modified: scummvm/trunk/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/gba_nds_fat.c	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/gba_nds_fat.c	2006-11-03 23:16:29 UTC (rev 24596)
@@ -818,17 +818,19 @@
 	{
 		return (false);
 	}
-	
 	// Read first sector of CF card
 	if ( !disc_ReadSector(0, globalBuffer)) {
 		return false;
 	}
 
+
 	// Make sure it is a valid MBR or boot sector
 	if ( (globalBuffer[0x1FE] != 0x55) || (globalBuffer[0x1FF] != 0xAA)) {
 		return false;
 	}
 
+	
+
 	// Check if there is a FAT string, which indicates this is a boot sector
 	if ((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T'))
 	{

Added: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3_common.c
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3_common.c	                        (rev 0)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3_common.c	2006-11-03 23:16:29 UTC (rev 24596)
@@ -0,0 +1,60 @@
+/*
+	io_m3_common.c 
+
+	Routines common to all version of the M3
+	
+	Some code based on M3 SD drivers supplied by M3Adapter.
+	Some code written by SaTa may have been unknowingly used.
+
+ Copyright (c) 2006 Michael "Chishm" Chisholm
+	
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation and/or
+     other materials provided with the distribution.
+  3. The name of the author may not be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "io_m3_common.h"
+
+static u16 _M3_readHalfword (u32 addr) {
+	return *((vu16*)addr);
+}
+
+void _M3_changeMode (u32 mode) {
+	_M3_readHalfword (0x08e00002);
+	_M3_readHalfword (0x0800000e);
+	_M3_readHalfword (0x08801ffc);
+	_M3_readHalfword (0x0800104a);
+	_M3_readHalfword (0x08800612);
+	_M3_readHalfword (0x08000000);
+	_M3_readHalfword (0x08801b66);
+	_M3_readHalfword (0x08000000 + (mode << 1));
+	_M3_readHalfword (0x0800080e);
+	_M3_readHalfword (0x08000000);
+	
+	if ((mode & 0x0f) != 4) {
+		_M3_readHalfword (0x09000000);
+	} else {
+		_M3_readHalfword (0x080001e4);
+		_M3_readHalfword (0x080001e4);
+		_M3_readHalfword (0x08000188);
+		_M3_readHalfword (0x08000188);
+	}
+}	
+


Property changes on: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3_common.c
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + LF

Modified: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.c
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.c	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.c	2006-11-03 23:16:29 UTC (rev 24596)
@@ -1,375 +1,526 @@
 /*
-	io_m3sd.c based on io_m3cf.c by SaTa.
+	io_m3sd.c 
 
-	io_m3cf.c based on
+	Hardware Routines for reading a Secure Digital card
+	using the M3 SD
+	
+	Some code based on M3 SD drivers supplied by M3Adapter.
+	Some code written by SaTa may have been unknowingly used.
 
-	compact_flash.c
-	By chishm (Michael Chisholm)
+ Copyright (c) 2006 Michael "Chishm" Chisholm
+	 
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
 
-	Hardware Routines for reading a compact flash card
-	using the M3 Perfect CF Adapter
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation and/or
+     other materials provided with the distribution.
+  3. The name of the author may not be used to endorse or promote products derived
+     from this software without specific prior written permission.
 
-	CF routines modified with help from Darkfader
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ 
+	2006-07-25 - Chishm
+		* Improved startup function that doesn't delay hundreds of seconds
+		  before reporting no card inserted.
+		* Fixed writeData function to timeout on error
+		* writeSectors function now wait until the card is ready before continuing with a transfer
 
-	This software is completely free. No warranty is provided.
-	If you use it, please give me credit and email me about your
-	project at chishm at hotmail.com
-
-	See gba_nds_fat.txt for help and license details.
+	2006-08-05 - Chishm
+		* Tries multiple times to get a Relative Card Address at startup
+		
+	2006-08-07 - Chishm
+		* Moved the SD initialization to a common function
 */
 
-
 #include "io_m3sd.h"
+#include "io_sd_common.h"
+#include "io_m3_common.h"
+//#include "common.h"
+#include "disc_io.h"
+#include <stdio.h>
 
-#ifdef SUPPORT_M3SD
+#define BYTES_PER_READ 512
 
-//SD dir control bit cmddir=bit0 clken=bit1
-//output
-#define SDDIR			(*(volatile u16*)0x8800000)
+//---------------------------------------------------------------
+// M3SD register addresses
 
-//SD send get control bit send=bit0 get=bit1
-//output
-#define SDCON			(*(volatile u16*)0x9800000)
+#define REG_M3SD_DIR	(*(vu16*)0x08800000)	// direction control register
+#define REG_M3SD_DAT	(*(vu16*)0x09000000)	// SD data line, 8 bits at a time
+#define REG_M3SD_CMD	(*(vu16*)0x09200000)	// SD command byte
+#define REG_M3SD_ARGH	(*(vu16*)0x09400000)	// SD command argument, high halfword
+#define REG_M3SD_ARGL	(*(vu16*)0x09600000)	// SD command argument, low halfword
+#define REG_M3SD_STS	(*(vu16*)0x09800000)	// command and status register
 
-//SD output data obyte[7:0]=AD[7:0]
-//output
-#define SDODA			(*(volatile u16*)0x9000000)
+//---------------------------------------------------------------
+// Send / receive timeouts, to stop infinite wait loops
+#define NUM_STARTUP_CLOCKS 100	// Number of empty (0xFF when sending) bytes to send/receive to/from the card
+#define TRANSMIT_TIMEOUT 20000	// Time to wait for the M3 to respond to transmit or receive requests
+#define RESPONSE_TIMEOUT 256	// Number of clocks sent to the SD card before giving up
+#define WRITE_TIMEOUT	3000	// Time to wait for the card to finish writing
 
-//SD input data AD[7:0]=ibyte[7:0]
-//input
-#define SDIDA			(*(volatile u16*)0x9000000)
+//---------------------------------------------------------------
+// Variables required for tracking SD state
+static u32 _M3SD_relativeCardAddress = 0;	// Preshifted Relative Card Address
 
-//readsector data1
-#define SDIDA1			(*(volatile u16*)0x9200000)
+//---------------------------------------------------------------
+// Internal M3 SD functions
 
-//readsector data2
-#define SDIDA2			(*(volatile u16*)0x9400000)
+static inline void _M3SD_unlock (void) {
+	_M3_changeMode (M3_MODE_MEDIA);
+}
 
-//readsector data3
-#define SDIDA3			(*(volatile u16*)0x9600000)
+static inline bool _M3SD_waitOnBusy (void) {
+	int i = 0;
+	while ( (REG_M3SD_STS & 0x01) == 0x00) {
+		i++;
+		if (i >= TRANSMIT_TIMEOUT) {
+			return false;
+		}
+	}
+	return true;
+}
 
-//SD stutas cmdneg=bit0 cmdpos=bit1 issend=bit2 isget=bit3
-//input
-#define SDSTA			(*(volatile u16*)0x9800000)
+static inline bool _M3SD_waitForDataReady (void) {
+	int i = 0;
+	while ( (REG_M3SD_STS & 0x40) == 0x00) {
+		i++;
+		if (i >= TRANSMIT_TIMEOUT) {
+			return false;
+		}
+	}
+	return true;
+}
 
-//#define CARD_TIMEOUT	10000000		// Updated due to suggestion from SaTa, otherwise card will timeout sometimes on a write
-#define CARD_TIMEOUT	(500*100)		// M3SD timeout nomal:500
 
-//======================================================
-bool M3SD_read1sector(u32 sectorn,u32 TAddr)
-{
-	u32 i;
-	int w;
+static bool _M3SD_sendCommand (u16 command, u32 argument) {
+	REG_M3SD_STS = 0x8;
+	REG_M3SD_CMD = 0x40 + command;		// Include the start bit
+	REG_M3SD_ARGH = argument >> 16;
+	REG_M3SD_ARGL = argument;
+	// The CRC7 of the command is calculated by the M3
 	
-	SDCON=0x8;		//	bit3:\x83R\x83}\x83\x93\x83h\x83\x82\x81[\x83h\x81H
-	SDIDA1=0x40+17;		//	\x83R\x83}\x83\x93\x83h CMD17
-	SDIDA2=(sectorn>>7);//	\x83Z\x83N\x83^H 9\x83r\x83b\x83g=\x83A\x83h\x83\x8C\x83XH \x82P\x82U\x83r\x83b\x83g
-	SDIDA3=(sectorn<<9);//	\x83Z\x83N\x83^L 7\x83r\x83b\x83g=\x83A\x83h\x83\x8C\x83XL \x82P\x82U\x83r\x83b\x83g
-	SDDIR=0x29;		//	\x83R\x83}\x83\x93\x83h\x91\x97\x90M\x81H
-	i=0;
+	REG_M3SD_DIR=0x29;
+	if (!_M3SD_waitOnBusy()) {
+		REG_M3SD_DIR=0x09;
+		return false;
+	}
+	REG_M3SD_DIR=0x09;
+	return true;
+}
 
-	while ( ((SDSTA&0x01) != 0x01)&&(i < CARD_TIMEOUT) )
-	{
+static bool _M3SD_sendByte (u8 byte) {
+	int i = 0;
+	REG_M3SD_DAT = byte;
+	REG_M3SD_DIR = 0x03;
+	REG_M3SD_STS = 0x01;
+	while ((REG_M3SD_STS & 0x04) == 0) {
 		i++;
+		if (i >= TRANSMIT_TIMEOUT) {
+			return false;
+		}
 	}
-	SDDIR=0x09;
-	i=0;
-	SDDIR=0x49;
-	while ( ((SDSTA&0x40) != 0x40)&&(i < CARD_TIMEOUT) )
-	{
+	return true;
+}
+
+static u8 _M3SD_getByte (void) {
+	int i;
+	// Request 8 bits of data from the SD's CMD pin
+	REG_M3SD_DIR = 0x02;
+	REG_M3SD_STS = 0x02;
+	// Wait for the data to be ready
+	i = 0;
+	while ((REG_M3SD_STS & 0x08) == 0) {
 		i++;
+		if (i >= TRANSMIT_TIMEOUT) {
+			// Return an empty byte if a timeout occurs
+			return 0xFF;
+		}
 	}
-	SDDIR=0x09;
-		
-	SDDIR=0x8;//cmd input clken=0 datadir input clock=0
-	SDCON=0x4;//send=0 get=0 en25=1 cmd1=0
+	i = 0;
+	while ((REG_M3SD_STS & 0x08) != 0) {
+		i++;
+		if (i >= TRANSMIT_TIMEOUT) {
+			// Return an empty byte if a timeout occurs
+			return 0xFF;
+		}
+	}
+	// Return the data
+	return (REG_M3SD_DAT & 0xff);
+}
 
-	w = SDDIR;
-	for(w=0;w<0x100;w++)
-	{
-		u16 d16;
-		u8 *d8=(u8 *)&d16;
-//		*(u16*)(TAddr+w*2) = SDDIR;	//	16bit
-		d16 = SDDIR;	//	16bit
-		*(u8 *)(TAddr+w*2) =d8[0];
-		*(u8 *)(TAddr+w*2+1) =d8[1];
-		
+// Returns the response from the SD card to a previous command.
+static bool _M3SD_getResponse (u8* dest, u32 length) {
+	u32 i;	
+	u8 dataByte;
+	int shiftAmount;
+	
+	// Wait for the card to be non-busy
+	for (i = 0; i < RESPONSE_TIMEOUT; i++) {
+		dataByte = _M3SD_getByte();
+		if (dataByte != SD_CARD_BUSY) {
+			break;
+		}
 	}
-	w = SDDIR;
-	w = SDDIR;
 	
-	if (i >= CARD_TIMEOUT)
+	if (dest == NULL) {
+		return true;
+	}
+	
+	// Still busy after the timeout has passed
+	if (dataByte == 0xff) {
 		return false;
+	}
+	
+	// Read response into buffer
+	for ( i = 0; i < length; i++) {
+		dest[i] = dataByte;
+		dataByte = _M3SD_getByte();
+	}
+	// dataByte will contain the last piece of the response
+	
+	// Send 16 more clocks, 8 more than the delay required between a response and the next command
+	i = _M3SD_getByte();
+	i = _M3SD_getByte();
+	
+	// Shift response so that the bytes are correctly aligned
+	// The register may not contain properly aligned data
+	for (shiftAmount = 0; ((dest[0] << shiftAmount) & 0x80) != 0x00; shiftAmount++) {
+		if (shiftAmount >= 7) {
+			return false;
+		}
+	}
+	
+	for (i = 0; i < length - 1; i++) {
+		dest[i] = (dest[i] << shiftAmount) | (dest[i+1] >> (8-shiftAmount));
+	}
+	// Get the last piece of the response from dataByte
+	dest[i] = (dest[i] << shiftAmount) | (dataByte >> (8-shiftAmount));
 
 	return true;
-	
-} 
-//==================================================
+}
 
 
-//======================================================
-void SD_crc16(u16* buff,u16 num,u16* crc16buff);
-void SD_data_write(u16 *buff,u16* crc16buff);
+static inline bool _M3SD_getResponse_R1 (u8* dest) {
+	return _M3SD_getResponse (dest, 6);
+}
 
-u16  Hal4ATA_StatusByte;
+static inline bool _M3SD_getResponse_R1b (u8* dest) {
+	return _M3SD_getResponse (dest, 6);
+}
 
-void Hal4ATA_GetStatus(void)
-{
-	Hal4ATA_StatusByte = SDSTA;
+static inline bool _M3SD_getResponse_R2 (u8* dest) {
+	return _M3SD_getResponse (dest, 17);
 }
 
-bool Hal4ATA_WaitOnBusy(void)
-{
-	Hal4ATA_GetStatus();
-	while ( (Hal4ATA_StatusByte & 0x01) != 0x1)
-	{
-		Hal4ATA_GetStatus();
+static inline bool _M3SD_getResponse_R3 (u8* dest) {
+	return _M3SD_getResponse (dest, 6);
+}
+
+static inline bool _M3SD_getResponse_R6 (u8* dest) {
+	return _M3SD_getResponse (dest, 6);
+}
+
+static void _M3SD_sendClocks (u32 numClocks) {
+	while (numClocks--) {
+		_M3SD_sendByte(0xff);
 	}
-	return TRUE;
 }
 
-bool Hal4ATA_WaitOnBusyNDrdy(void)
-{
-	Hal4ATA_GetStatus();
-	while ( (Hal4ATA_StatusByte&0x40) !=0x40)
-	{
-		Hal4ATA_GetStatus();
+static void _M3SD_getClocks (u32 numClocks) {
+	while (numClocks--) {
+		_M3SD_getByte();
 	}
-	return TRUE;
 }
 
-
-void SendCommand(u16 command, u32 sectorn)
-{
-	SDCON=0x8;
-	SDIDA1=0x40+command;
-	SDIDA2=(sectorn>>7);
-	SDIDA3=(sectorn<<9);
-
-	SDDIR=0x29;
-	Hal4ATA_WaitOnBusy();
-	SDDIR=0x09;
+bool _M3SD_cmd_6byte_response (u8* responseBuffer, u8 command, u32 data) {
+	_M3SD_sendCommand (command, data);
+	return _M3SD_getResponse (responseBuffer, 6);
 }
 
-
-#define DMA3SAD      *(u32*)0x040000D4
-#define DMA3DAD      *(u32*)0x040000D8
-#define DMA3CNT      *(u32*)0x040000DC
-
-void DMA3(u32 src, u32 dst, u32 cnt)
-{
-	DMA3SAD=src;
-	DMA3DAD=dst;
-	DMA3CNT=cnt;
+bool _M3SD_cmd_17byte_response (u8* responseBuffer, u8 command, u32 data) {
+	_M3SD_sendCommand (command, data);
+	return _M3SD_getResponse (responseBuffer, 17);
 }
 
+static bool _M3SD_initCard (void) {
+	// Give the card time to stabilise
+	_M3SD_sendClocks (NUM_STARTUP_CLOCKS);
+	
+	// Reset the card
+	if (!_M3SD_sendCommand (GO_IDLE_STATE, 0)) {
+		return false;
+	}
 
+	_M3SD_getClocks (NUM_STARTUP_CLOCKS);
 
-void PassRespond(u32 num)
-{
-	u32 i,dmanum;
+	// Card is now reset, including it's address
+	_M3SD_relativeCardAddress = 0;
 	
-	dmanum=(64+(num<<3))>>2;
-	SDDIR=0x8;
-	SDCON=0x4;
-	DMA3(0x8800000,(u32)&i,0x80400000+dmanum);
+	// Init the card
+	return _SD_InitCard (_M3SD_cmd_6byte_response, 
+				_M3SD_cmd_17byte_response,
+				true,
+				&_M3SD_relativeCardAddress);
 }
 
-//bool M3SD_write1sector(u32 sectorn,u16 * p)
-bool M3SD_write1sector(u32 sectorn,u32 p)
-{
-	u16 crc[4];
+static bool _M3SD_readData (void* buffer) {
+	u32 i;
+	u8* buff_u8 = (u8*)buffer;
+	u16* buff = (u16*)buffer;
+	u16 temp;
 
-	SendCommand(24,sectorn);
-	PassRespond(6);
-
-	SDDIR=0x4;
-	SDCON=0x0;
-
-	SD_crc16((u16 *)p,512,crc);
-	SD_data_write((u16 *)p,crc);
+	REG_M3SD_DIR = 0x49;
+	if (!_M3SD_waitForDataReady()) {
+		REG_M3SD_DIR = 0x09;
+		return false;
+	}
+	REG_M3SD_DIR = 0x09;
+	
+	REG_M3SD_DIR =  0x8;
+	REG_M3SD_STS = 0x4;
+	
+	i = REG_M3SD_DIR;
+	// Read data
+	i=256;
+	if ((u32)buff_u8 & 0x01) {
+		while(i--)
+		{
+			temp = REG_M3SD_DIR;
+			*buff_u8++ = temp & 0xFF;
+			*buff_u8++ = temp >> 8;
+		}
+	} else {
+		while(i--)
+			*buff++ = REG_M3SD_DIR; 
+	}
+	// Read end checksum
+	i = REG_M3SD_DIR + REG_M3SD_DIR + REG_M3SD_DIR + REG_M3SD_DIR;
+	
 	return true;
-} 
-//==================================================
+}
 
+static void _M3SD_clkout (void) {
+	REG_M3SD_DIR = 0x4;
+	REG_M3SD_DIR = 0xc;
+/*	__asm volatile (
+	"ldr 	r1, =0x08800000		\n"	
+	"mov 	r0, #0x04			\n"
+	"strh	r0, [r1]			\n"
+	"mov	r0, r0				\n"
+	"mov	r0, r0				\n"
+	"mov    r0, #0x0c			\n"
+	"strh	r0, [r1]			\n"
+	:					// Outputs
+	:					// Inputs
+	: "r0", "r1"		// Clobber list
+	);*/
+}
 
-// GBAMP CF Addresses
+static void _M3SD_clkin (void) {
+	REG_M3SD_DIR = 0x0;
+	REG_M3SD_DIR = 0x8;
+/*	__asm volatile (
+	"ldr 	r1, =0x08800000		\n"	
+	"mov 	r0, #0x00			\n"
+	"strh	r0, [r1]			\n"
+	"mov	r0, r0				\n"
+	"mov	r0, r0				\n"
+	"mov    r0, #0x08			\n"
+	"strh	r0, [r1]			\n"
+	:					// Outputs
+	:					// Inputs
+	: "r0", "r1"		// Clobber list
+	);*/
+}
 
-#define M3_REG_STS		*(vu16*)(0x09800000)	// Status of the CF Card / Device control
-
-#define M3_DATA			(vu16*)(0x08800000)		// Pointer to buffer of CF data transered from card
-
-// CF Card status
-#define CF_STS_INSERTED1		0x20
-#define CF_STS_INSERTED2		0x30
-
-/*-----------------------------------------------------------------
-M3SD_IsInserted
-Is a compact flash card inserted?
-bool return OUT:  true if a CF card is inserted
------------------------------------------------------------------*/
-bool M3SD_IsInserted (void) 
-{
+static bool _M3SD_writeData (u8* data, u8* crc) {
 	int i;
-	u16 sta;
-	// Change register, then check if value did change
-	M3_REG_STS = CF_STS_INSERTED1;
+	u8 temp;
 
-	for(i=0;i<CARD_TIMEOUT;i++)
-	{
-		sta=M3_REG_STS;
-		if((sta == CF_STS_INSERTED1)||(sta == CF_STS_INSERTED2))
-		{
-			return true;
-			//break;
+	do {
+		_M3SD_clkin();
+	} while ((REG_M3SD_DAT & 0x100) == 0);
+	
+	REG_M3SD_DAT = 0;	// Start bit
+	
+	_M3SD_clkout();
+	
+	for (i = 0; i < BYTES_PER_READ; i++) {
+		temp = (*data++);
+		REG_M3SD_DAT = temp >> 4;
+		_M3SD_clkout();
+		REG_M3SD_DAT = temp;
+		_M3SD_clkout();
+	}
+	
+	if (crc != NULL) {
+		for (i = 0; i < 8; i++) {
+			temp = (*crc++);
+			REG_M3SD_DAT = temp >> 4;
+			_M3SD_clkout();
+			REG_M3SD_DAT = temp;
+			_M3SD_clkout();
 		}
 	}
-	return false;
 
-//	return ( (sta == CF_STS_INSERTED1)||(sta == CF_STS_INSERTED2) );
-//	return true;
+	i = 32;
+	while (i--) {
+		temp += 2;		// a NOP to stop the compiler optimising out the loop
+	}
+	
+	for (i = 0; i  < 32; i++) {
+		REG_M3SD_DAT = 0xff;
+		_M3SD_clkout();
+	}
+	
+	do {
+		_M3SD_clkin();
+	} while ((REG_M3SD_DAT & 0x100) == 0);
+	
+	return true;
 }
 
+//---------------------------------------------------------------
+// Functions needed for the external interface
 
-/*-----------------------------------------------------------------
-M3SD_ClearStatus
-Tries to make the CF card go back to idle mode
-bool return OUT:  true if a CF card is idle
------------------------------------------------------------------*/
-bool M3SD_ClearStatus (void) 
-{
+bool _M3SD_startUp (void) {
+	_M3SD_unlock();
+	return _M3SD_initCard();
+}
 
-//	int i=SDDIR;
-	int i;
-	u16 sta;
-
-	i = 0;
-	M3_REG_STS = CF_STS_INSERTED1;
-	while (i < CARD_TIMEOUT)
-	{
-		sta=M3_REG_STS;
-		if(  (sta == CF_STS_INSERTED1)||(sta == CF_STS_INSERTED2)  )break;
-		i++;
+bool _M3SD_isInserted (void) {
+	u8 responseBuffer [6];
+	// Make sure the card receives the command
+	if (!_M3SD_sendCommand (SEND_STATUS, 0)) {
+		return false;
 	}
-	if (i >= CARD_TIMEOUT)
+	// Make sure the card responds
+	if (!_M3SD_getResponse_R1 (responseBuffer)) {
 		return false;
-
+	}
+	// Make sure the card responded correctly
+	if (responseBuffer[0] != SEND_STATUS) {
+		return false;
+	}
 	return true;
 }
 
+bool _M3SD_readSectors (u32 sector, u32 numSectors, void* buffer) {
+	u32 i;
+	u8* dest = (u8*) buffer;
+	u8 responseBuffer[6];
+	
+	if (numSectors == 1) {
+		// If it's only reading one sector, use the (slightly faster) READ_SINGLE_BLOCK
+		if (!_M3SD_sendCommand (READ_SINGLE_BLOCK, sector * BYTES_PER_READ)) {
+			return false;
+		}
 
-/*-----------------------------------------------------------------
-M3SD_ReadSectors
-Read 512 byte sector numbered "sector" into "buffer"
-u32 sector IN: address of first 512 byte sector on CF card to read
-u8 numSecs IN: number of 512 byte sectors to read,
- 1 to 256 sectors can be read, 0 = 256
-void* buffer OUT: pointer to 512 byte buffer to store data in
-bool return OUT: true if successful
------------------------------------------------------------------*/
-bool M3SD_ReadSectors (u32 sector, u8 numSecs, void* buffer)
-{
+		if (!_M3SD_readData (buffer)) {
+			return false;
+		}
 
-
-	//void M3SD_read1sector(u32 sectorn,u32 TAddr)
-	bool r=true;
-	int i;
-	for(i=0;i<numSecs;i++)
-	{
-		if(M3SD_read1sector(i + sector , 512*i + (u32) buffer )==false)
-		{
-			r=false;
-			break;
+	} else {
+		// Stream the required number of sectors from the card
+		if (!_M3SD_sendCommand (READ_MULTIPLE_BLOCK, sector * BYTES_PER_READ)) {
+			return false;
 		}
+	
+		for(i=0; i < numSectors; i++, dest+=BYTES_PER_READ) {
+			if (!_M3SD_readData(dest)) {
+				return false;
+			}
+			REG_M3SD_STS = 0x8;
+		}
+	
+		// Stop the streaming
+		_M3SD_sendCommand (STOP_TRANSMISSION, 0);
+		_M3SD_getResponse_R1b (responseBuffer);
 	}
-	return r;
 
+	return true;
 }
 
-
-
-/*-----------------------------------------------------------------
-M3SD_WriteSectors
-Write 512 byte sector numbered "sector" from "buffer"
-u32 sector IN: address of 512 byte sector on CF card to read
-u8 numSecs IN: number of 512 byte sectors to read,
- 1 to 256 sectors can be read, 0 = 256
-void* buffer IN: pointer to 512 byte buffer to read data from
-bool return OUT: true if successful
------------------------------------------------------------------*/
-bool M3SD_WriteSectors (u32 sector, u8 numSecs, void* buffer)
-{
-
-	bool r=true;
+bool _M3SD_writeSectors (u32 sector, u32 numSectors, const void* buffer) {
+	u8 crc[8];
+	u8 responseBuffer[6];
+	u32 offset = sector * BYTES_PER_READ;
+	u8* data = (u8*) buffer;
 	int i;
-	for(i=0;i<numSecs;i++)
-	{
-		if(M3SD_write1sector(i + sector , 512*i + (u32) buffer )==false)
-		{
-			r=false;
-			break;
+	// Precalculate the data CRC
+	_SD_CRC16 ( data, BYTES_PER_READ, crc);
+	
+	while (numSectors--) {
+		// Send a single sector write command
+		_M3SD_sendCommand (WRITE_BLOCK, offset);
+		if (!_M3SD_getResponse_R1 (responseBuffer)) {
+			return false;
 		}
+	
+		REG_M3SD_DIR = 0x4;
+		REG_M3SD_STS = 0x0;
+	
+		// Send the data
+		if (! _M3SD_writeData( data, crc)) {
+			return false;
+		}
+		
+		if (numSectors > 0) {
+			offset += BYTES_PER_READ;
+			data += BYTES_PER_READ;
+			// Calculate the next CRC while waiting for the card to finish writing
+			_SD_CRC16 ( data, BYTES_PER_READ, crc);
+		}
+		
+		// Wait for the card to be ready for the next transfer
+		i = WRITE_TIMEOUT;
+		responseBuffer[3] = 0;
+		do {
+			_M3SD_sendCommand (SEND_STATUS, _M3SD_relativeCardAddress);
+			_M3SD_getResponse_R1 (responseBuffer);
+			i--;
+			if (i <= 0) {
+				return false;
+			}
+		} while (((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA)));
 	}
-	return r;
+	
+	return true;
 
-//	return false;
+}
 
-
+bool _M3SD_clearStatus (void) {
+	return _M3SD_initCard ();
 }
 
-
-/*-----------------------------------------------------------------
-M3_Unlock
-Returns true if M3 was unlocked, false if failed
-Added by MightyMax
------------------------------------------------------------------*/
-bool M3SD_Unlock(void) 
-{
-
-	// run unlock sequence
-	volatile unsigned short tmp ;
-	tmp = *(volatile unsigned short *)0x08000000 ;
-	tmp = *(volatile unsigned short *)0x08E00002 ;
-	tmp = *(volatile unsigned short *)0x0800000E ;
-	tmp = *(volatile unsigned short *)0x08801FFC ;
-	tmp = *(volatile unsigned short *)0x0800104A ;
-	tmp = *(volatile unsigned short *)0x08800612 ;
-	tmp = *(volatile unsigned short *)0x08000000 ;
-	tmp = *(volatile unsigned short *)0x08801B66 ;
-	tmp = *(volatile unsigned short *)0x08800006 ;
-	tmp = *(volatile unsigned short *)0x08000000 ;
-	// test that we have register access
-	vu16 sta;
-	sta=M3_REG_STS;
-	sta=M3_REG_STS;
-	if(  (sta == CF_STS_INSERTED1)||(sta == CF_STS_INSERTED2)  )return true;
-
-	return false;
+bool _M3SD_shutdown (void) {
+	_M3_changeMode (M3_MODE_ROM);
+	return true;
 }
 
-bool M3SD_Shutdown(void) {
-	return M3SD_ClearStatus() ;
-} ;
-
-bool M3SD_StartUp(void) {
-	return M3SD_Unlock() ;
-} ;
-
-
-IO_INTERFACE io_m3sd = {
+IO_INTERFACE _io_m3sd = {
 	DEVICE_TYPE_M3SD,
-	FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE,
-	(FN_MEDIUM_STARTUP)&M3SD_StartUp,
-	(FN_MEDIUM_ISINSERTED)&M3SD_IsInserted,
-	(FN_MEDIUM_READSECTORS)&M3SD_ReadSectors,
-	(FN_MEDIUM_WRITESECTORS)&M3SD_WriteSectors,
-	(FN_MEDIUM_CLEARSTATUS)&M3SD_ClearStatus,
-	(FN_MEDIUM_SHUTDOWN)&M3SD_Shutdown
+	FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
+	(FN_MEDIUM_STARTUP)&_M3SD_startUp,
+	(FN_MEDIUM_ISINSERTED)&_M3SD_isInserted,
+	(FN_MEDIUM_READSECTORS)&_M3SD_readSectors,
+	(FN_MEDIUM_WRITESECTORS)&_M3SD_writeSectors,
+	(FN_MEDIUM_CLEARSTATUS)&_M3SD_clearStatus,
+	(FN_MEDIUM_SHUTDOWN)&_M3SD_shutdown
 } ;
 
-
 LPIO_INTERFACE M3SD_GetInterface(void) {
-	return &io_m3sd ;
+	return &_io_m3sd ;
 } ;
 
-#endif // SUPPORT_M3CF

Modified: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.h
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.h	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd.h	2006-11-03 23:16:29 UTC (rev 24596)
@@ -1,39 +1,37 @@
 /*
-	io_m3sd.h  by SaTa.
+ io_m3sd.h 
 
-	Hardware Routines for reading an SD card
-	using the M3 SD
+ Hardware Routines for reading a Secure Digital card
+ using the M3 SD
 
-	This software is completely free. No warranty is provided.
-	If you use it, please give me credit and email me about your
-	project at chishm at hotmail.com
+ Some code based on M3 SD drivers supplied by M3Adapter.
+ Some code written by SaTa may have been unknowingly used.
 
-	See gba_nds_fat.txt for help and license details.
-*/
+ Copyright (c) 2006 Michael "Chishm" Chisholm
+	
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
 
-#ifndef IO_M3SD_H
-#define IO_M3SD_H
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation and/or
+     other materials provided with the distribution.
+  3. The name of the author may not be used to endorse or promote products derived
+     from this software without specific prior written permission.
 
-// 'M3SD'
-#define DEVICE_TYPE_M3SD 0x4453334D
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "disc_io.h"
-
-// export interface
-extern LPIO_INTERFACE M3SD_GetInterface(void) ;
-
-#endif	// define IO_M3SD_H
-/*
-	io_m3sd.h  by SaTa.
-
-	Hardware Routines for reading an SD card
-	using the M3 SD
-
-	This software is completely free. No warranty is provided.
-	If you use it, please give me credit and email me about your
-	project at chishm at hotmail.com
-
-	See gba_nds_fat.txt for help and license details.
+	2006-07-11 - Chishm
+		* Original release
 */
 
 #ifndef IO_M3SD_H
@@ -45,6 +43,7 @@
 #include "disc_io.h"
 
 // export interface
-extern LPIO_INTERFACE M3SD_GetInterface(void) ;
+//extern const IO_INTERFACE _io_m3sd ;
+LPIO_INTERFACE M3SD_GetInterface(void);
 
 #endif	// define IO_M3SD_H

Modified: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd_asm.s
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd_asm.s	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_m3sd_asm.s	2006-11-03 23:16:29 UTC (rev 24596)
@@ -193,3 +193,4 @@
 
 	ldmfd   r13!,{r4-r5,r15}
 @-----------------end-------------------
+

Added: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.c
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.c	                        (rev 0)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.c	2006-11-03 23:16:29 UTC (rev 24596)
@@ -0,0 +1,363 @@
+/*
+  io_mmcf.c based on
+
+	io_mpcf.c based on
+
+	compact_flash.c
+	By chishm (Michael Chisholm)
+
+	Hardware Routines for reading a compact flash card
+	using the GBA Movie Player
+
+	CF routines modified with help from Darkfader
+
+	This software is completely free. No warranty is provided.
+	If you use it, please give me credit and email me about your
+	project at chishm at hotmail.com
+
+	See gba_nds_fat.txt for help and license details.
+*/
+
+
+#include "io_mmcf.h"
+
+#ifdef SUPPORT_MMCF
+
+//---------------------------------------------------------------
+// DMA
+#ifdef _CF_USE_DMA
+ #ifndef NDS
+  #include "gba_dma.h"
+ #else
+  #include <nds/dma.h>
+  #ifdef ARM9
+   #include <nds/arm9/cache.h>
+  #endif
+ #endif
+#endif
+
+//---------------------------------------------------------------
+// CF Addresses & Commands
+
+#define CF_RD_DATA          (*(volatile u16*)(0x08000000 + 0x00000))
+#define CF_RD_ERROR         (*(volatile u16*)(0x08000000 + 0x20000))
+#define CF_RD_SECTOR_COUNT  (*(volatile u16*)(0x08000000 + 0x40000))
+#define CF_RD_SECTOR_NO     (*(volatile u16*)(0x08000000 + 0x60000))
+#define CF_RD_CYLINDER_LOW  (*(volatile u16*)(0x08000000 + 0x80000))
+#define CF_RD_CYLINDER_HIGH (*(volatile u16*)(0x08000000 + 0xA0000))
+#define CF_RD_SEL_HEAD      (*(volatile u16*)(0x08000000 + 0xC0000))
+#define CF_RD_STATUS        (*(volatile u16*)(0x08000000 + 0xE0000))
+
+#define CF_WR_DATA          (*(volatile u16*)(0x08000000 + 0x00000))
+#define CF_WR_FEATURES      (*(volatile u16*)(0x08000000 + 0x20000))
+#define CF_WR_SECTOR_COUNT  (*(volatile u16*)(0x08000000 + 0x40000))
+#define CF_WR_SECTOR_NO     (*(volatile u16*)(0x08000000 + 0x60000))
+#define CF_WR_CYLINDER_LOW  (*(volatile u16*)(0x08000000 + 0x80000))
+#define CF_WR_CYLINDER_HIGH (*(volatile u16*)(0x08000000 + 0xA0000))
+#define CF_WR_SEL_HEAD      (*(volatile u16*)(0x08000000 + 0xC0000))
+#define CF_WR_COMMAND       (*(volatile u16*)(0x08000000 + 0xE0000))
+
+
+#define GAME_PAK		0x08000000			// Game pack start address
+#define MP_DATA			(vu16*)(GAME_PAK + 0x01000000)		// Pointer to buffer of CF data transered from card
+#define MP_REG_LBA1		*(vu16*)(GAME_PAK + 0x01060000)	// 1st byte of sector address
+#define CARD_TIMEOUT	10000000		// Updated due to suggestion from SaTa, otherwise card will timeout sometimes on a write
+
+
+static bool cf_block_ready(void)
+{
+  int i;
+
+  i = 0;
+
+  /*
+  do
+  {
+    while (!(CF_RD_STATUS & 0x40));
+  } while (CF_RD_STATUS & 0x80); 
+  */
+
+  do
+  {
+    i++;
+    while ( (!(CF_RD_STATUS & 0x40)) && (i < CARD_TIMEOUT) ) i++;    
+  } while ( (CF_RD_STATUS & 0x80) && (i < CARD_TIMEOUT) ); 
+
+  if (i >= CARD_TIMEOUT) {
+	return false;
+  }
+
+  return true;
+}
+
+
+static bool cf_set_features(u32 feature)
+{
+  if ( !cf_block_ready() ) return false;
+
+  CF_WR_FEATURES = feature;
+  CF_WR_SECTOR_COUNT = 0x00;  // config???
+  CF_WR_SEL_HEAD = 0x00;
+  CF_WR_COMMAND = 0xEF;
+
+  return true;
+}
+
+
+
+/*-----------------------------------------------------------------
+MMCF_IsInserted
+Is a compact flash card inserted?
+bool return OUT:  true if a CF card is inserted
+-----------------------------------------------------------------*/
+bool MMCF_IsInserted (void) 
+{
+  if ( !cf_set_features(0xAA) ) return false;
+
+  return true;
+}
+
+
+/*-----------------------------------------------------------------
+MMCF_ClearStatus
+Tries to make the CF card go back to idle mode
+bool return OUT:  true if a CF card is idle
+-----------------------------------------------------------------*/
+bool MMCF_ClearStatus (void) 
+{
+	return true;
+}
+
+
+/*-----------------------------------------------------------------
+MMCF_ReadSectors
+Read 512 byte sector numbered "sector" into "buffer"
+u32 sector IN: address of first 512 byte sector on CF card to read
+u8 numSecs IN: number of 512 byte sectors to read,
+ 1 to 256 sectors can be read, 0 = 256
+void* buffer OUT: pointer to 512 byte buffer to store data in
+bool return OUT: true if successful
+-----------------------------------------------------------------*/
+bool MMCF_ReadSectors (u32 sector, u8 numSecs, void* buffer)
+{
+	int i;
+	int j = (numSecs > 0 ? numSecs : 256);
+	u16 *buff = (u16*)buffer;
+#ifdef _CF_ALLOW_UNALIGNED
+	u8 *buff_u8 = (u8*)buffer;
+	int temp;
+#endif
+
+#if (defined _CF_USE_DMA) && (defined NDS) && (defined ARM9)
+	DC_FlushRange( buffer, j * BYTE_PER_READ);
+#endif
+
+  if ( !cf_block_ready() ) return false;
+
+  CF_WR_SECTOR_COUNT = numSecs;
+  CF_WR_SECTOR_NO = sector;
+  CF_WR_CYLINDER_LOW = sector >> 8;
+  CF_WR_CYLINDER_HIGH = sector >> 16;
+  CF_WR_SEL_HEAD = ((sector >> 24) & 0x0F) | 0xE0;
+  CF_WR_COMMAND = 0x20; // read sectors
+
+  while (j--)
+  {
+    if ( !cf_block_ready() ) return false;
+
+#ifdef _CF_USE_DMA
+ #ifdef NDS
+		DMA3_SRC = (u32)MP_DATA;
+		DMA3_DEST = (u32)buff;
+		DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_SRC_FIX;
+ #else
+		DMA3COPY ( MP_DATA, buff, 256 | DMA16 | DMA_ENABLE | DMA_SRC_FIXED);
+ #endif
+		buff += BYTE_PER_READ / 2;
+#elif defined _CF_ALLOW_UNALIGNED
+		i=256;
+		if ((u32)buff_u8 & 0x01) {
+			while(i--)
+			{
+				temp = *MP_DATA;
+				*buff_u8++ = temp & 0xFF;
+				*buff_u8++ = temp >> 8;
+			}
+		} else {
+		while(i--)
+			*buff++ = *MP_DATA; 
+		}
+#else
+		i=256;
+		while(i--)
+			*buff++ = *MP_DATA;
+#endif
+  }
+
+#if (defined _CF_USE_DMA) && (defined NDS)
+	// Wait for end of transfer before returning
+	while(DMA3_CR & DMA_BUSY);
+#endif
+
+	return true;
+}
+
+
+
+/*-----------------------------------------------------------------
+MMCF_WriteSectors
+Write 512 byte sector numbered "sector" from "buffer"
+u32 sector IN: address of 512 byte sector on CF card to read
+u8 numSecs IN: number of 512 byte sectors to read,
+ 1 to 256 sectors can be read, 0 = 256
+void* buffer IN: pointer to 512 byte buffer to read data from
+bool return OUT: true if successful
+-----------------------------------------------------------------*/
+bool MMCF_WriteSectors (u32 sector, u8 numSecs, void* buffer)
+{
+	int i;
+	int j = (numSecs > 0 ? numSecs : 256);
+	u16 *buff = (u16*)buffer;
+#ifdef _CF_ALLOW_UNALIGNED
+	u8 *buff_u8 = (u8*)buffer;
+	int temp;
+#endif
+	
+#if defined _CF_USE_DMA && defined NDS && defined ARM9
+	DC_FlushRange( buffer, j * BYTE_PER_READ);
+#endif
+
+	if (numSecs > 1) 
+	{
+		int r = 0;
+		
+		for (r = 0; r < numSecs; r++)
+		{
+			MMCF_WriteSectors(sector + r, 1, ((unsigned char *) (buffer)) + 512);
+		}
+  }
+
+  if ( !cf_block_ready() ) return false;
+
+  CF_WR_SECTOR_COUNT = numSecs;
+  CF_WR_SECTOR_NO = sector;
+  CF_WR_CYLINDER_LOW = sector >> 8;
+  CF_WR_CYLINDER_HIGH = sector >> 16;
+  CF_WR_SEL_HEAD = ((sector >> 24) & 0x0F) | 0xE0;
+  CF_WR_COMMAND = 0x30; // write sectors
+
+  while (j--)
+  {
+    if ( !cf_block_ready() ) return false;
+
+#ifdef _CF_USE_DMA
+ #ifdef NDS
+		DMA3_SRC = (u32)buff;
+		DMA3_DEST = (u32)MP_DATA;
+		DMA3_CR = 256 | DMA_COPY_HALFWORDS | DMA_DST_FIX;
+ #else
+		DMA3COPY( buff, MP_DATA, 256 | DMA16 | DMA_ENABLE | DMA_DST_FIXED);
+ #endif
+		buff += BYTE_PER_READ / 2;
+#elif defined _CF_ALLOW_UNALIGNED
+		i=256;
+		if ((u32)buff_u8 & 0x01) {
+			while(i--)
+			{
+				temp = *buff_u8++;
+				temp |= *buff_u8++ << 8;
+				*MP_DATA = temp;
+			}
+		} else {
+		while(i--)
+			*MP_DATA = *buff++; 
+		}
+#else
+		i=256;
+		while(i--)
+			*MP_DATA = *buff++; 
+#endif
+
+  }
+
+#if defined _CF_USE_DMA && defined NDS
+	// Wait for end of transfer before returning
+	while(DMA3_CR & DMA_BUSY);
+#endif  
+
+//#define _CF_VERIFY
+
+#ifdef _CF_VERIFY
+	char* tmp = malloc(512);
+	int r;
+
+	for (r = 0; r < numSecs; r++)
+	{
+		MMCF_ReadSectors(sector + r, 1, tmp);
+		while (memcmp(temp, ((unsigned char *) (buffer)) + 512 * r, 512) != 0)
+		{
+			consolePrintf("Rewriting sector %d\n", r);
+			MMCF_WriteSectors(sector + r, 1, ((unsigned char *) (buffer)) + 512 * r);
+			MMCF_ReadSectors(sector + r, 1, tmp);
+		}
+	}
+
+	free(temp);
+#endif
+
+	return true;
+}
+
+/*-----------------------------------------------------------------
+MMCF_Shutdown
+unload the GBAMP CF interface
+-----------------------------------------------------------------*/
+bool MMCF_Shutdown(void) 
+{
+	return MMCF_ClearStatus() ;
+}
+
+/*-----------------------------------------------------------------
+MMCF_StartUp
+initializes the CF interface, returns true if successful,
+otherwise returns false
+-----------------------------------------------------------------*/
+bool MMCF_StartUp(void)
+{
+  /*
+	u8 temp = MP_REG_LBA1;
+	MP_REG_LBA1 = (~temp & 0xFF);
+	temp = (~temp & 0xFF);
+	return (MP_REG_LBA1 == temp);
+  */
+  if ( (CF_RD_STATUS != 0x0050) || ( *((u8 *) (0x080000B2)) == 0x96) )
+  {
+	return false;
+  }
+
+  return true;
+}
+
+/*-----------------------------------------------------------------
+the actual interface structure
+-----------------------------------------------------------------*/
+IO_INTERFACE io_mmcf = {
+	DEVICE_TYPE_MMCF,
+	FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
+	(FN_MEDIUM_STARTUP)&MMCF_StartUp,
+	(FN_MEDIUM_ISINSERTED)&MMCF_IsInserted,
+	(FN_MEDIUM_READSECTORS)&MMCF_ReadSectors,
+	(FN_MEDIUM_WRITESECTORS)&MMCF_WriteSectors,
+	(FN_MEDIUM_CLEARSTATUS)&MMCF_ClearStatus,
+	(FN_MEDIUM_SHUTDOWN)&MMCF_Shutdown
+} ;
+
+/*-----------------------------------------------------------------
+MPCF_GetInterface
+returns the interface structure to host
+-----------------------------------------------------------------*/
+LPIO_INTERFACE MMCF_GetInterface(void) {
+	return &io_mmcf ;
+} ;
+
+#endif // SUPPORT_MMCF


Property changes on: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.c
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + LF

Added: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.h
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.h	                        (rev 0)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.h	2006-11-03 23:16:29 UTC (rev 24596)
@@ -0,0 +1,25 @@
+/*
+	io_mmcf.h 
+
+	Hardware Routines for reading a compact flash card
+	using the GBA Movie Player
+
+	This software is completely free. No warranty is provided.
+	If you use it, please give me credit and email me about your
+	project at chishm at hotmail.com
+
+	See gba_nds_fat.txt for help and license details.
+*/
+
+#ifndef IO_MMCF_H
+#define IO_MMCF_H
+
+// 'MMCF'
+#define DEVICE_TYPE_MMCF 0x4646504D
+
+#include "disc_io.h"
+
+// export interface
+extern LPIO_INTERFACE MMCF_GetInterface(void) ;
+
+#endif	// define IO_MMCF_H


Property changes on: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mmcf.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + LF

Modified: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mpcf.c
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mpcf.c	2006-11-03 22:36:05 UTC (rev 24595)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_mpcf.c	2006-11-03 23:16:29 UTC (rev 24596)
@@ -329,7 +329,8 @@
 	u8 temp = MP_REG_LBA1;
 	MP_REG_LBA1 = (~temp & 0xFF);
 	temp = (~temp & 0xFF);
-	return (MP_REG_LBA1 == temp) ;
+	// NDM: Added GBA ROM header check so that this doesn't detect a Max Media Dock!
+	return (MP_REG_LBA1 == temp) && ( *((u8 *) (0x080000B2)) == 0x96);
 }
 
 /*-----------------------------------------------------------------

Added: scummvm/trunk/backends/platform/ds/arm9/source/fat/io_njsd.c
===================================================================
--- scummvm/trunk/backends/platform/ds/arm9/source/fat/io_njsd.c	                        (rev 0)
+++ scummvm/trunk/backends/platform/ds/arm9/source/fat/io_njsd.c	2006-11-03 23:16:29 UTC (rev 24596)
@@ -0,0 +1,679 @@
+/*
+	io_njsd.c
+
+	Hardware Routines for reading an SD card using
+	a NinjaDS SD adapter.
+	
+	Original code supplied by NinjaMod
+	
+ Copyright (c) 2006 Michael "Chishm" Chisholm
+	
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation and/or
+     other materials provided with the distribution.
+  3. The name of the author may not be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ 
+	2006-08-05 - Chishm
+		* First release
+*/
+
+#include "io_njsd.h"
+
+#ifdef NDS
+
+#include <nds.h>
+#include <string.h>
+#include "io_sd_common.h"
+
+#define BYTES_PER_READ 512
+//#define _NJSD_SYNC
+// #define _NJSD_DEBUG
+
+//---------------------------------------------------------------
+// Card communication speeds
+#define SD_CLK_200KHz		00
+#define SD_CLK_5MHz		01
+#define SD_CLK_8MHz			02
+#define SD_CLK_12MHz		03
+
+//---------------------------------------------------------------
+// Response types
+#define SD_RSP_48		0
+#define SD_RSP_136		1
+#define SD_RSP_DATA		2
+#define SD_RSP_STREAM	3
+
+//---------------------------------------------------------------
+// Send / receive timeouts, to stop infinite wait loops
+#define IRQ_TIMEOUT 1000000
+#define RESET_TIMEOUT 1000
+#define COMMAND_TIMEOUT 10000
+#define MAX_STARTUP_TRIES 2000	// Arbitrary value, check if the card is ready 20 times before giving up
+#define WRITE_TIMEOUT	300	// Time to wait for the card to finish writing
+
+
+static const u8 _NJSD_read_cmd[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40};
+static const u8 _NJSD_read_end_cmd[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x41};
+
+static int _NJSD_speed = SD_CLK_8MHz;		// Default speed;
+
+static u32 _NJSD_cardFlags;
+
+static u32 _NJSD_relativeCardAddress = 0;
+
+#define _NJSD_irqFlag		(*(volatile unsigned long*)(0x027FFEB0))
+
+
+static inline bool _NJSD_waitIRQ(void) {
+/*#ifdef _NJSD_SYNC
+	int i = IRQ_TIMEOUT;
+	while (!(REG_IF & 0x100000) && --i); 
+	REG_IF = 0x100000;
+	if (i <= 0) {
+		return false;
+	} else {
+		return true;
+	}
+#else*/
+	int i = IRQ_TIMEOUT;
+	//if (!(REG_IME & 1))
+	//{
+		// irq's disabled...
+		while (!(REG_IF & 0x100000) && (!(_NJSD_irqFlag)) && --i); 
+		_NJSD_irqFlag = 0;
+		REG_IF = 0x100000;
+		if (i <= 0) {
+			return false;
+		} else {
+			return true;
+		}
+	//} else {
+		// irq's enabled
+	//	while (!(_NJSD_irqFlag) && --i); 
+	//	_NJSD_irqFlag = 0;
+	//	REG_IF = 0x100000;
+	//	if (i <= 0) {
+	//		return false;
+	//	} else {
+	//		return true;
+	//	}
+	//}
+//#endif
+}
+
+static inline void _NJSD_writeCardCommand 
+	(u8 cmd0, u8 cmd1, u8 cmd2, u8 cmd3, u8 cmd4, u8 cmd5, u8 cmd6, u8 cmd7) 
+{
+	CARD_COMMAND[0] = cmd0;
+	CARD_COMMAND[1] = cmd1;
+	CARD_COMMAND[2] = cmd2;
+	CARD_COMMAND[3] = cmd3;
+	CARD_COMMAND[4] = cmd4;
+	CARD_COMMAND[5] = cmd5;
+	CARD_COMMAND[6] = cmd6;
+	CARD_COMMAND[7] = cmd7;
+}
+
+
+static bool _NJSD_reset (void) {
+	int i;
+	CARD_CR1H = CARD_CR1_ENABLE;
+	_NJSD_writeCardCommand (0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	CARD_CR2 = 0xA0406000;
+	i = RESET_TIMEOUT;
+	while ((CARD_CR2 & CARD_BUSY) && --i);
+	if (i <= 0) {
+		return false;
+	}
+	
+	return true;
+}
+
+static void _NJSD_irqHandler (void) {
+	_NJSD_irqFlag = 1;
+}
+
+static bool _NJSD_init (u32 flags) {
+	_NJSD_cardFlags = flags;
+
+	REG_IF = 0x100000; // Clear cart IRQ.
+
+	_NJSD_irqFlag = 0;
+#ifdef _NJSD_SYNC
+    irqDisable (IRQ_CARD_LINE);
+#else
+    irqSet(IRQ_CARD_LINE, _NJSD_irqHandler);
+    irqEnable (IRQ_CARD_LINE);
+#endif
+
+	if (! _NJSD_reset() ) {
+		return false;
+	}
+	return true;
+}
+
+static bool _NJSD_sendCMDR (int speed, u8 *rsp_buf, int type, u8 cmd, u32 param) {
+	int i;
+	u32 data;
+
+#ifdef _NJSD_SYNC
+	u32 old_REG_IME;
+	old_REG_IME = REG_IME;
+	REG_IME = 0;
+#endif
+
+	REG_IE &= ~0x100000; 
+	REG_IF =   0x100000;
+
+	CARD_CR1H = CARD_CR1_ENABLE;
+
+	if ((type & 3) < 2) {
+		CARD_COMMAND[0] = 0xF0 | (speed << 2) | 1 | (type << 1);
+	} else if ((type & 3) == 2) {
+		CARD_COMMAND[0] = 0xE0 | (speed << 2) | 0 | (1 << 1);
+	} else {
+		CARD_COMMAND[0] = 0xF0 | (speed << 2) | 0 | (1 << 1);
+	}
+	
+	CARD_COMMAND[1] = (type & 0x40) | ((( type >> 2) & 7) << 3);
+	CARD_COMMAND[2] = 0x40 | cmd;
+	CARD_COMMAND[3] = (param>>24) & 0xFF;
+	CARD_COMMAND[4] = (param>>16) & 0xFF;
+	CARD_COMMAND[5] = (param>>8) & 0xFF;
+	CARD_COMMAND[6] = (param>>0) & 0xFF;
+	CARD_COMMAND[7] = 0; // offset = 0
+
+	if ((type & 3) < 2) {
+		CARD_CR2 = _NJSD_cardFlags | 0x01000000;
+
+		// wait for ninja DS to be done!
+		if (!_NJSD_waitIRQ ()) {
+#ifdef _NJSD_SYNC
+			REG_IME = old_REG_IME;
+#endif
+			return false;
+		}
+
+		i = 0;
+		do {
+			// Read data if available
+			if (CARD_CR2 & CARD_DATA_READY) {
+				data=CARD_DATA_RD;
+				if (rsp_buf != NULL) {
+					if (i == 4) {
+						rsp_buf[0] = (data>>0)&0xFF;
+						rsp_buf[1] = (data>>8)&0xFF;
+						rsp_buf[2] = (data>>16)&0xFF;
+						rsp_buf[3] = (data>>24)&0xFF;
+					} else if (i == 5) {
+						rsp_buf[4] = (data>>0)&0xFF;
+						rsp_buf[5] = (data>>8)&0xFF;
+					}
+				}
+				i++;
+			}
+		} while (CARD_CR2 & CARD_BUSY);
+
+#ifdef _NJSD_DEBUG
+		iprintf ("r: ");
+		for (i = 0; i < 6; i++)
+			iprintf ("%02X ", rsp_buf[i]);
+		iprintf ("\n");
+#endif
+	} else {
+		CARD_CR2 = _NJSD_cardFlags;
+		while (CARD_CR2 & CARD_BUSY);
+
+		// wait for ninja DS to be done!
+		if (!_NJSD_waitIRQ ()) {
+#ifdef _NJSD_SYNC
+			REG_IME = old_REG_IME;
+#endif
+			return false;
+		}
+	}
+
+#ifdef _NJSD_SYNC
+	REG_IME = old_REG_IME;
+#endif
+	return true;
+}
+
+static bool _NJSD_writeSector (u8 *buffer, u8 *crc_buf, u32 offset) {
+	int i;
+	u8 responseBuffer[6];
+	u32 data;
+
+#ifdef _NJSD_SYNC
+	u32 old_REG_IME;
+	old_REG_IME = REG_IME;
+	REG_IME = 0;
+#endif
+
+	CARD_CR1H = CARD_CR1_ENABLE;
+	_NJSD_writeCardCommand (0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	CARD_CR2 = 0xA0406000;
+	i = COMMAND_TIMEOUT;
+	while ((CARD_CR2 & CARD_BUSY) && --i);
+	if (i <= 0) {
+#ifdef _NJSD_SYNC
+		REG_IME = old_REG_IME;
+#endif
+		return false;
+	}
+
+	for (i = 0; i < 65; i++)
+	{
+		CARD_CR1H = CARD_CR1_ENABLE; // | CARD_CR1_IRQ;
+		if (i < 64)
+		{
+			_NJSD_writeCardCommand (buffer[i*8+0], buffer[i*8+1], buffer[i*8+2], buffer[i*8+3],
+				buffer[i*8+4], buffer[i*8+5], buffer[i*8+6], buffer[i*8+7]);
+		} else {
+			_NJSD_writeCardCommand (crc_buf[0], crc_buf[1], crc_buf[2], crc_buf[3],
+				crc_buf[4], crc_buf[5], crc_buf[6], crc_buf[7]);
+		}
+		CARD_CR2 = 0xA7406000;
+
+		do {
+			// Read data if available
+			if (CARD_CR2 & CARD_DATA_READY) {
+				data=CARD_DATA_RD;
+			}
+		} while (CARD_CR2 & CARD_BUSY);
+	}
+
+
+	REG_IE &= ~0x100000; 
+	REG_IF =   0x100000;
+
+	CARD_CR1H = CARD_CR1_ENABLE;
+	_NJSD_writeCardCommand (0xF0 | (1 << 2) | 1, 0x80, 0x40 | WRITE_BLOCK, (u8)(offset>>24),
+		(u8)(offset>>16), (u8)(offset>>8), (u8)(offset>>0), 0x00);
+	CARD_CR2 = 0xA7406000;
+
+	// wait for ninja DS to be done!
+	if (!_NJSD_waitIRQ ()) {
+#ifdef _NJSD_SYNC
+		REG_IME = old_REG_IME;
+#endif
+		return false;
+	}
+
+	i = 0;
+	do {
+		// Read data if available
+		if (CARD_CR2 & CARD_DATA_READY) {
+			data = CARD_DATA_RD;
+			if (i == 2) {
+				responseBuffer[0] = (u8)(data>>0);
+				responseBuffer[1] = (u8)(data>>8);
+				responseBuffer[2] = (u8)(data>>16);
+				responseBuffer[3] = (u8)(data>>24);
+			} else if (i == 3) {
+				responseBuffer[4] = (u8)(data>>0);
+				responseBuffer[5] = (u8)(data>>8);
+			}
+			i++;
+		}
+	} while (CARD_CR2 & CARD_BUSY);
+	
+	i = WRITE_TIMEOUT;
+	responseBuffer[3] = 0;
+	do {
+		_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, SEND_STATUS, _NJSD_relativeCardAddress);
+		i--;
+		if (i <= 0) {
+#ifdef _NJSD_SYNC
+			REG_IME = old_REG_IME;
+#endif
+			return false;
+		}
+	} while (((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA)));
+
+
+#ifdef _NJSD_SYNC
+	REG_IME = old_REG_IME;
+#endif
+	
+	return true;
+}
+
+static bool _NJSD_sendCLK (int speed, int count) {
+	int i;
+
+#ifdef _NJSD_SYNC
+	u32 old_REG_IME;
+	old_REG_IME = REG_IME;
+	REG_IME = 0;
+
+#endif
+	REG_IE &= ~0x100000; 
+	REG_IF =   0x100000;
+
+	//CARD_CR1H = CARD_CR1_ENABLE; // | CARD_CR1_IRQ;
+	_NJSD_writeCardCommand (0xE0 | ((speed & 3) << 2), 0, (count - 1), 0, 0, 0, 0, 0);
+	
+	CARD_CR2 = _NJSD_cardFlags;
+	i = COMMAND_TIMEOUT;
+	while ((CARD_CR2 & CARD_BUSY) && --i);
+	if (i <= 0) {
+#ifdef _NJSD_SYNC
+		REG_IME = old_REG_IME;
+#endif
+		return false;
+	}
+
+	// wait for ninja DS to be done!
+	if (!_NJSD_waitIRQ ()) {
+#ifdef _NJSD_SYNC
+	REG_IME = old_REG_IME;
+#endif
+		return false;
+	}
+
+#ifdef _NJSD_SYNC
+	REG_IME = old_REG_IME;
+#endif
+	return true;
+}
+
+static bool _NJSD_sendCMDN (int speed, u8 cmd, u32 param) {
+	int i;
+
+#ifdef _NJSD_SYNC
+	u32 old_REG_IME;
+	old_REG_IME = REG_IME;
+	REG_IME = 0;
+#endif
+
+	REG_IE &= ~0x100000; 
+	REG_IF =   0x100000;
+
+	CARD_CR1H = CARD_CR1_ENABLE; // | CARD_CR1_IRQ;
+	_NJSD_writeCardCommand (0xF0 | ((speed & 3) << 2), 0x00, 0x40 | cmd, (param>>24) & 0xFF,
+		(param>>16) & 0xFF, (param>>8) & 0xFF, (param>>0) & 0xFF, 0x00);
+
+	CARD_CR2 = _NJSD_cardFlags;
+	i = COMMAND_TIMEOUT;
+	while ((CARD_CR2 & CARD_BUSY) && --i);
+	if (i <= 0) {
+#ifdef _NJSD_SYNC
+		REG_IME = old_REG_IME;
+#endif
+		return false;
+	}
+
+	// wait for ninja DS to be done!
+	if (!_NJSD_waitIRQ ()) {
+#ifdef _NJSD_SYNC
+	REG_IME = old_REG_IME;
+#endif
+		return false;
+	}
+
+#ifdef _NJSD_SYNC
+	REG_IME = old_REG_IME;
+#endif
+	return true;
+}
+
+static bool _NJSD_cardInit (void) {
+	u8 responseBuffer[17];
+	int i;
+ 
+	// If the commands succeed the first time, assume they'll always succeed
+	if (! _NJSD_sendCLK (SD_CLK_200KHz, 256) ) return false;
+	if (! _NJSD_sendCMDN (SD_CLK_200KHz, GO_IDLE_STATE, 0) ) return false;
+	_NJSD_sendCLK (SD_CLK_200KHz, 8);
+ 
+	_NJSD_sendCLK (SD_CLK_200KHz, 256);
+ 	_NJSD_sendCMDN (SD_CLK_200KHz, GO_IDLE_STATE, 0);
+	_NJSD_sendCLK (SD_CLK_200KHz, 8);
+ 
+	for (i = 0; i < MAX_STARTUP_TRIES ; i++) {
+		_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, APP_CMD, 0);
+		if ( 
+			_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, SD_APP_OP_COND, SD_OCR_VALUE) &&
+			((responseBuffer[1] & 0x80) != 0))
+		{	
+			// Card is ready to receive commands now
+			break;
+		}
+	}
+	if (i >= MAX_STARTUP_TRIES) {
+		return false;
+	}
+ 
+	// The card's name, as assigned by the manufacturer
+	_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_136, ALL_SEND_CID, 0);
+ 
+	// Get a new address
+	for (i = 0; i < MAX_STARTUP_TRIES ; i++) {
+		_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, SEND_RELATIVE_ADDR, 0);
+		_NJSD_relativeCardAddress = (responseBuffer[1] << 24) | (responseBuffer[2] << 16);
+		if ((responseBuffer[3] & 0x1e) != (SD_STATE_STBY << 1)) {
+			break;
+		}
+	}
+ 	if (i >= MAX_STARTUP_TRIES) {
+		return false;
+	}
+
+	// Some cards won't go to higher speeds unless they think you checked their capabilities
+	_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_136, SEND_CSD, _NJSD_relativeCardAddress);
+ 
+	// Only this card should respond to all future commands
+	_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, SELECT_CARD, _NJSD_relativeCardAddress);
+ 
+	// Set a 4 bit data bus
+	_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, APP_CMD, _NJSD_relativeCardAddress);
+	_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, SET_BUS_WIDTH, 2); // 4-bit mode.
+
+	// Use 512 byte blocks
+	_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, SET_BLOCKLEN, 512); // 512 byte blocks
+ 
+	return true;
+}
+
+
+bool _NJSD_isInserted(void) {
+	u8 responseBuffer [8];
+	_NJSD_sendCMDR (SD_CLK_200KHz, responseBuffer, SD_RSP_48, SEND_STATUS, 0);
+
+	// Make sure the card responded correctly
+	if (responseBuffer[0] != SEND_STATUS) {
+		return false;
+	}
+	return true;
+}
+
+bool _NJSD_clearStatus (void) {
+	return _NJSD_reset();
+}
+
+bool _NJSD_shutdown(void) {
+	return _NJSD_clearStatus();
+}
+
+bool _NJSD_startup(void) {
+	if (! _NJSD_init(0xA0406000) ) {
+		return false;
+	}
+	if (! _NJSD_cardInit() ) {
+		return false;
+	}
+	return true;
+} 
+
+
+bool _NJSD_writeSectors (u32 sector, u32 numSectors, const void* buffer) {
+ 	u8 crc[8];
+	u32 offset = sector * BYTES_PER_READ;
+	u8* data = (u8*) buffer;
+
+	while (numSectors--) {
+		_SD_CRC16 ( data, BYTES_PER_READ, crc);
+		
+		if (! _NJSD_writeSector (data, crc, offset)) {
+			return false;
+		}
+		offset += BYTES_PER_READ;
+		data += BYTES_PER_READ;
+	}
+	return true;
+}
+
+#ifdef _IO_ALLOW_UNALIGNED
+bool _NJSD_readSectors (u32 sector, u32 numSectors, void* buffer) {
+	u32 tmp[BYTES_PER_READ>>2];
+	int i;
+
+#ifdef _NJSD_SYNC
+	u32 old_REG_IME;
+#endif
+	
+	u8* tbuf = (u8*)buffer;
+
+	if (numSectors == 0) {
+		return false;
+	}
+
+#ifdef _NJSD_SYNC
+	old_REG_IME = REG_IME;
+	REG_IME = 0;
+#endif
+
+	if (numSectors > 1) {
+		_NJSD_sendCMDR (_NJSD_speed, NULL, SD_RSP_DATA, READ_MULTIPLE_BLOCK, sector * BYTES_PER_READ);
+		for (i = 0; i < numSectors - 2; i++) {
+			if (((int)buffer & 0x03) != 0){
+				cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, (u8*)_NJSD_read_cmd);
+				memcpy (tbuf + i * BYTES_PER_READ, tmp, BYTES_PER_READ);
+			} else {
+				cardPolledTransfer (0xA1406000, (u32*)(tbuf + i * BYTES_PER_READ), BYTES_PER_READ, (u8*)_NJSD_read_cmd);
+			}
+			if (!_NJSD_waitIRQ ()) {
+#ifdef _NJSD_SYNC
+				REG_IME = old_REG_IME;
+#endif		
+				return false;
+			}
+		}
+		if (((int)buffer & 0x03) != 0){
+			cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, (u8*)_NJSD_read_end_cmd);
+			memcpy (tbuf + (numSectors - 2) * BYTES_PER_READ, tmp, BYTES_PER_READ);
+		} else {
+			cardPolledTransfer (0xA1406000, (u32*)(tbuf + (numSectors - 2) * BYTES_PER_READ), BYTES_PER_READ, (u8*)_NJSD_read_end_cmd);
+		}
+		if (!_NJSD_waitIRQ ()) {
+#ifdef _NJSD_SYNC
+			REG_IME = old_REG_IME;
+#endif		
+			return false;
+		}
+		
+		if (((int)buffer & 0x03) != 0){
+			cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, (u8*)_NJSD_read_cmd);
+			memcpy (tbuf + (numSectors - 1) * BYTES_PER_READ, tmp, BYTES_PER_READ);
+		} else {
+			cardPolledTransfer (0xA1406000, (u32*)(tbuf + (numSectors - 1) * BYTES_PER_READ), BYTES_PER_READ, (u8*)_NJSD_read_cmd);
+		}
+	} else {
+		_NJSD_sendCMDR (_NJSD_speed, NULL, SD_RSP_STREAM, READ_SINGLE_BLOCK, sector * BYTES_PER_READ);
+		if (((int)buffer & 0x03) != 0){
+			cardPolledTransfer (0xA1406000, tmp, BYTES_PER_READ, (u8*)_NJSD_read_cmd);
+			memcpy (tbuf, tmp, BYTES_PER_READ);
+		} else {
+			cardPolledTransfer (0xA1406000, (u32*)tbuf, BYTES_PER_READ, (u8*)_NJSD_read_cmd);
+		}
+	}
+
+#ifdef _NJSD_SYNC
+	REG_IME = old_REG_IME;
+#endif
+	return true;
+}
+#else // not defined _IO_ALLOW_UNALIGNED
+bool _NJSD_readSectors (u32 sector, u32 numSectors, void* buffer) {
+	int i;
+
+#ifdef _NJSD_SYNC
+	u32 old_REG_IME;
+#endif
+	
+	u8* tbuf = (u8*)buffer;
+
+	if (numSectors == 0) {
+		return false;
+	}
+
+#ifdef _NJSD_SYNC
+	old_REG_IME = REG_IME;
+	REG_IME = 0;
+#endif
+
+	if (numSectors > 1) {
+		_NJSD_sendCMDR (_NJSD_speed, NULL, SD_RSP_DATA, READ_MULTIPLE_BLOCK, sector * BYTES_PER_READ);
+		for (i = 0; i < numSectors - 2; i++) {

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list