Pārlūkot izejas kodu

* ARM9 detection routine does not generate errors anymore
* Updated libmikmod
* libnds related changes:
* Fixed sound core
* Improved interrupt handling
- Removed unused code

git-svn-id: trunk@10542 -

Legolas 17 gadi atpakaļ
vecāks
revīzija
f262aff7ef

+ 173 - 2
packages/libndsfpc/src/libmikmod/inc/mikmod.inc

@@ -23,8 +23,8 @@
 (**** CONST *******************************************************************)
 const
   LIBMIKMOD_VERSION_MAJOR = 3;
-  LIBMIKMOD_VERSION_MINOR = 1;
-  LIBMIKMOD_REVISION      = 10;
+  LIBMIKMOD_VERSION_MINOR = 2;
+  LIBMIKMOD_REVISION      = 0;
 
   LIBMIKMOD_VERSION = (
                         (LIBMIKMOD_VERSION_MAJOR shl 16) or
@@ -88,6 +88,7 @@ const
   DMODE_SOFT_SNDFX = $0004; 
   DMODE_SOFT_MUSIC = $0008; 
   DMODE_HQMIXER    = $0010; 
+  DMODE_FLOAT      = $0020;
   DMODE_SURROUND   = $0100; 
   DMODE_INTERP     = $0200;
   DMODE_REVERSE    = $0400;
@@ -146,6 +147,7 @@ const
 
   MAXSAMPLEHANDLES  = 384;
 
+  STM_NTRACKERS = 3;
 
 (****** Types *****************************************************************)
 type
@@ -243,6 +245,18 @@ type
     MMERR_MAC_SPEED,
     MMERR_MAC_START,
 
+    MMERR_OSX_UNKNOWN_DEVICE,
+    MMERR_OSX_BAD_PROPERTY,
+    MMERR_OSX_UNSUPPORTED_FORMAT,
+    MMERR_OSX_SET_STEREO,
+    MMERR_OSX_BUFFER_ALLOC,
+    MMERR_OSX_ADD_IO_PROC,
+    MMERR_OSX_DEVICE_START,
+    MMERR_OSX_PTHREAD,
+    
+    MMERR_DOSWSS_STARTDMA,
+    MMERR_DOSSB_STARTDMA,
+    
     MMERR_MAX
   );
     
@@ -329,6 +343,7 @@ type
     fadevol: cushort;
     panning: csshort;
     kick: cuchar;
+    kick_flag: cuchar;
     period: cushort;
     nna: cuchar;
     volflg: cuchar;
@@ -362,7 +377,9 @@ type
 
   MP_CONTROL = packed record
     main: MP_CHANNEL;
+    
     slave: PMP_VOICE;
+    
     slavechn: cuchar;
     muted: cuchar;
     ultoffset: cushort;
@@ -394,27 +411,34 @@ type
     vibpos: cschar;
     vibspd: cuchar;
     vibdepth: cuchar;
+    
     trmpos: cschar;
     trmspd: cuchar;
     trmdepth: cuchar;
+    
     fslideupspd: cuchar;
     fslidednspd: cuchar;
     fportupspd: cuchar;
     fportdnspd: cuchar;
     ffportupspd: cuchar;
     ffportdnspd: cuchar;
+    
     hioffset: cuint;
     soffset: cushort;
+    
     sseffect: cuchar;
     ssdata: cuchar;
     chanvolslide: cuchar;
+    
     panbwave: cuchar;
     panbpos: cuchar;
     panbspd: cschar;
     panbdepth: cuchar;
+    
     newsamp: cushort;
     voleffect: cuchar;
     voldata: cuchar;
+    
     pat_reppos: csshort;
     pat_repcnt: cushort;
   end;
@@ -494,6 +518,20 @@ type
   TModule = MODULE;
   PModule = ^MODULE;
 
+
+  VOICEINFO = packed record
+    i: PInstrument;
+    s: PSample;
+    panning: csshort;
+    volume: cschar;
+    period: cushort;
+    kick: cuchar;
+  end;
+  TVoiceInfo = VOICEINFO;
+  PVoiceInfo = ^VOICEINFO;
+  
+
+
   drvenum1 = (
     MD_MUSIC = 0,
     MD_SNDFX
@@ -615,6 +653,7 @@ type
     HardVoiceLimit: cuchar;
     SoftVoiceLimit: cuchar;
     Alias: pcchar;
+    CmdLineHelp: pcchar;
     CommandLine: TMDCommandLine;
     IsPresent: TMDIsPresent;
     SampleLoad: TMDSampleLoad;
@@ -788,6 +827,7 @@ var
 
   load_669: MLOADER; cvar; external; (* 669 and Extended-669 (by Tran/Renaissance) *)
   load_amf: MLOADER; cvar; external; (* DMP Advanced Module Format (by Otto Chrons) *)
+  load_asy: MLOADER; cvar; external; (* ASYLUM Music Format 1.0 *)
   load_dsm: MLOADER; cvar; external; (* DSIK internal module format *)
   load_far: MLOADER; cvar; external; (* Farandole Composer (by Daniel Potter) *)
   load_gdm: MLOADER; cvar; external; (* General DigiMusic (by Edward Schlunder) *)
@@ -825,6 +865,7 @@ var
 {$ifdef ARM9}
 var
   md_bpm: cushort; cvar;
+  
 procedure MikMod9_SendCommand(command: cuint); cdecl; {forward;}external; 
 function Player_LoadMemory(const buffer: pointer; size: cint; maxchan: cint; curious: cint): PModule; cdecl; external;
 {$endif ARM9}
@@ -904,6 +945,42 @@ procedure _mm_write_M_ULONGS(value1: pcuint; value2: cint; value3: PMWriter); cd
 procedure _mm_write_I_ULONGS(value1: pcuint; value2: cint; value3: PMWriter); cdecl; external;
 
 
+procedure SL_HalveSample(value1: PSAMPLOAD; value2: cint); cdecl; external;
+procedure SL_Sample8to16(value: PSAMPLOAD); cdecl; external;
+procedure SL_Sample16to8(value: PSAMPLOAD); cdecl; external;
+procedure SL_SampleSigned(value: PSAMPLOAD); cdecl; external;
+procedure SL_SampleUnsigned(value: PSAMPLOAD); cdecl; external;
+function SL_LoadSamples(): cint; cdecl; external;
+function SL_RegisterSample(value1: PSAMPLE; value2: cint; value3: PMREADER): PSAMPLOAD; cdecl; external;
+function SL_Load(value1: pointer; value2: PSAMPLOAD; value3: cuint): cint; cdecl; external;
+function SL_Init(value: PSAMPLOAD): cint; cdecl; external;
+procedure SL_Exit(value: PSAMPLOAD); cdecl; external;
+
+
+
+
+procedure UniSetRow(value: pcuchar); cdecl; external;
+function UniGetByte(): cuchar; cdecl; external;
+function UniGetWord(): cushort; cdecl; external;
+function UniFindRow(value1: pcuchar; value2: cushort): pcuchar; cdecl; external;
+procedure UniSkipOpcode(); cdecl; external;
+procedure UniReset(); cdecl; external;
+procedure UniWriteByte(value: cuchar); cdecl; external;
+procedure UniWriteWord(value: cushort); cdecl; external;
+procedure UniNewline(); cdecl; external;
+function UniDup(): pcuchar; cdecl; external;
+function UniInit(): cint; cdecl; external;
+procedure UniCleanup(); cdecl; external;
+procedure UniEffect(value1: cushort; value2: cushort); cdecl; external;
+procedure UniInstrument(x: cushort); inline;
+procedure UniNote(x: cushort); inline;
+procedure UniPTEffect(value1: cuchar; value2: cuchar); cdecl; external;
+procedure UniVolEffect(value1: cushort; value2: cuchar); cdecl; external;
+
+
+
+
+
 function MikMod_strerror(value: cint): pcchar; cdecl; external;
 function MikMod_RegisterErrorHandler(value: MikMod_handler_t): MikMod_handler_t; cdecl; external;
 
@@ -912,6 +989,7 @@ procedure MikMod_RegisterAllDrivers(); cdecl; external;
 function MikMod_InfoDriver(): pcchar; cdecl; external;
 procedure MikMod_RegisterDriver(value: PMDriver); cdecl; external;
 function MikMod_DriverFromAlias(value: pcint): cint; cdecl; external;
+function MikMod_DriverByOrdinal(value: cint): PMDriver; cdecl; external;
 
 function MikMod_Init(value: string): cint; cdecl; external;
 procedure MikMod_Exit(); cdecl; external;
@@ -972,6 +1050,7 @@ procedure Player_Mute(value: csint; args: array of const); cdecl; external;
 procedure Player_ToggleMute(value: csint; args: array of const); cdecl; external;
 function Player_GetChannelVoice(value: cuchar): cint; cdecl; external;
 function Player_GetChannelPeriod(value: cuchar): cushort; cdecl; external;
+function Player_QueryVoices(numvoices: cushort; vinfo: PVOICEINFO): cint; cdecl; external; 
 
 function MikMod_RegisterPlayer(value: MikMod_player_t): MikMod_player_t; cdecl; external;
 
@@ -1060,6 +1139,87 @@ type
     NDS_HW_CMD_VOICE_UPDATE
   );
   
+
+var
+  modreader: PMREADER; cvar; external; 
+  finetune: array [0..15] of cushort; cvar; external;
+  _of: MODULE; external name 'of';
+  npertab: array [0..(7 * OCTAVE) - 1] of cushort; cvar; external;
+
+  remap: array [0..UF_MAXCHAN - 1] of cschar; cvar; external;
+  poslookup: pcuchar; cvar; external;
+
+  poslookupcnt: cuchar; cvar; external;
+  origpositions: pcushort; cvar; external;
+
+  filters: cint; cvar; external;
+  activemacro: cuchar; cvar; external;
+  filtermacros: array [0..UF_MAXMACRO - 1] of cuchar; cvar; external;
+  filtersettings: array [0..UF_MAXFILTER - 1] of FILTER; cvar; external;
+
+  noteindex: pcint; cvar; external;
+
+
+function ReadComment(value: cushort): cint; cdecl; external;
+function ReadLinedComment(value1: cushort; value2: cushort): cint; cdecl; external;
+function AllocPositions(value: cint): cint; cdecl; external;
+function AllocPatterns(): cint; cdecl; external;
+function AllocTracks(): cint; cdecl; external;
+function AllocInstruments(): cint; cdecl; external;
+function AllocSamples(): cint; cdecl; external;
+function DupStr(value1: pcchar; value2: cushort; value3: cint): pcchar; cdecl; external;
+
+function AllocLinear(): pcint; cdecl; external;
+procedure FreeLinear(); cdecl; external;
+function speed_to_finetune(value1: cuint; value2: cint): cint; cdecl; external;
+procedure S3MIT_ProcessCmd(value1: cuchar; value2: cuchar; value3: cuint); cdecl; external;
+procedure S3MIT_CreateOrders(value: cint); cdecl; external;
+
+function getlinearperiod(value1: cushort; value2: cuint): cushort; cdecl; external;
+function getfrequency(value1: cushort; value2: cuint): cuint; cdecl; external;
+
+var
+  STM_Signatures: array [0..STM_NTRACKERS - 1] of pcchar; cvar; external;
+  md_numchn: cushort; cvar; external;
+  md_sngchn: cushort; cvar; external;
+  md_sfxchn: cushort; cvar; external;
+  md_hardchn: cushort; cvar; external;
+  md_softchn: cushort; cvar; external;
+  
+  
+function MD_SampleLoad(value1: PSAMPLOAD; value2: cint): csshort; cdecl; external;
+procedure MD_SampleUnload(value: csshort); cdecl; external;
+function MD_SampleSpace(value: cint): cuint; cdecl; external;
+function MD_SampleLength(value1: cint; value2: PSAMPLE): cuint; cdecl; external;
+
+procedure unsignedtoulaw(value1: pcchar; value2: cint); cdecl; external;
+
+function MD_GetAtom(value1, value2: pcchar; value3: cint): pcchar; cdecl; external;
+
+procedure VC_SetupPointers(); cdecl; external;
+function VC1_Init(): cint; cdecl; external;
+function VC2_Init(): cint; cdecl; external;
+
+
+procedure _mm_registerdriver(value: PMDRIVER); cdecl; external;
+procedure _mm_registerloader(value: PMLOADER); cdecl; external;
+function MikMod_Active_internal(): cint; cdecl; external;
+procedure MikMod_DisableOutput_internal(); cdecl; external;
+function MikMod_EnableOutput_internal(): cint; cdecl; external;
+procedure MikMod_Exit_internal(); cdecl; external;
+function MikMod_SetNumVoices_internal(value1, value2: cint): cint; cdecl; external;
+procedure Player_Exit_internal(value: PMODULE); cdecl; external;
+procedure Player_Stop_internal(); cdecl; external;
+function Player_Paused_internal(): cint; cdecl; external;
+procedure Sample_Free_internal(value: PSAMPLE); cdecl; external;
+procedure Voice_Play_internal(value1: cschar; value2: PSAMPLE; value3: cuint); cdecl; external;
+procedure Voice_SetFrequency_internal(value1: cschar; value2: cuint); cdecl; external;
+procedure Voice_SetPanning_internal(value1: cschar; value2: cuint); cdecl; external;
+procedure Voice_SetVolume_internal(value1: cschar; value2: cushort); cdecl; external;
+procedure Voice_Stop_internal(value: cschar); cdecl; external;
+function Voice_Stopped_internal(value: cschar): cint; cdecl; external;
+
+
 {$endif NDS_INTERFACE}
 
 {$ifdef NDS_IMPLEMENTATION}
@@ -1073,4 +1233,15 @@ begin
     FreeMem(p);
   p := nil;
 end;
+
+procedure UniInstrument(x: cushort); inline;
+begin
+  UniEffect(cushort(UNI_INSTRUMENT), x)
+end; 
+
+procedure UniNote(x: cushort); inline;
+begin
+  UniEffect(cushort(UNI_NOTE), x)
+end;
+
 {$endif NDS_IMPLEMENTATION}

+ 41 - 3
packages/libndsfpc/src/nds/arm9/sound.inc

@@ -39,7 +39,45 @@
 *)
 
 {$ifdef NDS_INTERFACE}
-procedure playSound(sound: pTransferSoundData); cdecl; external;
-procedure setGenericSound(rate: cuint32; vol: cuint8; pan: cuint8; format: cuint8); cdecl; external;
-procedure playGenericSound(const data: pointer; length: cuint32); cdecl; external;
+var
+  Snd: TTransferSound;
+  SndDat: TTransferSoundData; //  =		{ (void *)0 , 0, 11025, 64, 64, 1 };
+
+procedure playSound(ASound: pTransferSoundData);
+procedure setGenericSound(rate: cuint32; vol: cuint8; pan: cuint8; format: cuint8);
+procedure playGenericSound(data: pointer; length: cuint32);
 {$endif NDS_INTERFACE}
+
+{$ifdef NDS_IMPLEMENTATION}
+procedure playSoundBlock(ASnd: PTransferSound);
+begin
+	DC_FlushRange(ASnd, sizeof(TTransferSound));
+	IPC^.soundData := ASnd;
+end;
+
+procedure setGenericSound(rate: cuint32; vol: cuint8; pan: cuint8; format: cuint8);
+begin
+	SndDat.rate		:= rate;
+	SndDat.vol		:= vol;
+	SndDat.pan		:= pan;
+	SndDat.format	:= format;
+end;
+
+procedure playSound(ASound: pTransferSoundData);
+begin
+	Snd.count := 1;
+	Move(ASound^,  Snd.data[0], sizeof(TTransferSoundData) );
+	playSoundBlock(@Snd);
+end;
+
+procedure playGenericSound(data: pointer; length: cuint32);
+begin
+	Snd.count := 1;
+  move(SndDat, Snd.data, sizeof(TTransferSoundData) );
+	Snd.data[0].data := data;
+	Snd.data[0].len := length;
+	playSoundBlock(@Snd);
+end;
+
+
+{$endif NDS_IMPLEMENTATION}

+ 10 - 4
packages/libndsfpc/src/nds/interrupts.inc

@@ -86,14 +86,20 @@ const
   IME_ENABLE  : IME_VALUE = 1;  (* Enable all interrupts not masked out in REG_IE *)
 
 
+type
+  TVoidFunctionPointer = procedure of object;
+  
 var
 //  __irq_vector: array [0..0] of VoidFunctionPointer; cvar; external;
 //  __irq_vector: array [0..0] of Pointer; cvar; external;
 //  __irq_flags: array [0..0] of cuint32; cvar; external;
 //  __irq_flags: pcuint32; cvar; external;
 //  __irq_vector: ^VoidFunctionPointer; cvar; external;
-  __irq_vector: Pointer; cvar; external;
-  __irq_flags: pcuint32; cvar; external;
+
+///  __irq_vector: Pointer; cvar; external;
+///  __irq_flags: pcuint32; cvar; external;
+  __irq_vector: Pointer; external name '__irq_vector';
+  __irq_flags: pcuint32; external name '__irq_flags';
 
 
 
@@ -107,10 +113,10 @@ type
   end;
 
 procedure irqInit(); cdecl; external;
-//procedure irqSet(irq: IRQ_MASK; handler: VoidFunctionPointer); cdecl; external;
+procedure irqSet(irq: IRQ_MASK; handler: TVoidFunctionPointer); cdecl; external;
 procedure irqSet(irq: IRQ_MASK; handler: pointer); cdecl; external;
 procedure irqClear(irq: IRQ_MASK); cdecl; external;
-//procedure irqInitHandler(handler: VoidFunctionPointer); cdecl; external;
+procedure irqInitHandler(handler: TVoidFunctionPointer); cdecl; external;
 procedure irqInitHandler(handler: pointer); cdecl; external;
 procedure irqEnable(irq: cuint32); cdecl; external;
 procedure irqDisable(irq: cuint32); cdecl; external;

+ 10 - 8
packages/libndsfpc/src/nds/ipc.inc

@@ -87,20 +87,22 @@ type
             end;
            ); 
     end;
-    unixTime: cint32;
+//    unixTime: cint32; // Moved!
     
   	battery: cuint16;            // battery life ??  hopefully.  :)
   	aux: cuint16;                // i have no idea...
 
   
     // Don't rely on these below, will change or be removed in the future
-  	soundData: pTransferSound;
+  	soundData: PTransferSound;
     mailAddr: cuint32;
     mailData: cuint32;
     mailRead: cuint8;
     mailBusy: cuint8;
     mailSize: cuint32;
 
+    // unixTime here, because in the old position it breaked nds sound system O_o
+    unixTime: cint32;
   end;
   TransferRegion = sTransferRegion; 
   TTransferRegion = TransferRegion;
@@ -129,14 +131,14 @@ const
 
 
 {$ifdef NDS_IMPLEMENTATION}
-function getIPC(): pTransferRegion; inline;
+function getIPC(): PTransferRegion; inline;
 begin
-	getIPC := pTransferRegion(pointer($027FF000));
+	getIPC := PTransferRegion(pointer($027FF000));
 end;
 
-function IPC(): TransferRegion; 
+function IPC(): PTransferRegion; inline;
 begin
-	IPC := getIPC()^;
+	IPC := getIPC();
 end;
   
 procedure IPC_SendSync(sync: cuint); inline; 
@@ -173,8 +175,8 @@ const
 {$endif NDS_INTERFACE}
 
 {$ifdef NDS_INTERFACE}
-function getIPC(): pTransferRegion; inline;
-function IPC(): TransferRegion; 
+function getIPC(): PTransferRegion; inline;
+function IPC(): PTransferRegion; inline;
 procedure IPC_SendSync(sync: cuint); inline; 
 function IPC_GetSync(): cint; inline;
 {$endif NDS_INTERFACE}

+ 22 - 18
packages/libndsfpc/src/nds/registers_alt.inc

@@ -39,17 +39,20 @@
 *)
 
 {$ifdef NDS_INTERFACE}
+type 
+  f32 = integer;
+
 const
   REG_DISPCNT		: pcuint32 = pointer($4000000);
 
 {$ifdef ARM9}
-  WAIT_CR = REG_EXMEMCNT;
+  {$define   WAIT_CR := REG_EXMEMCNT}
 {$else}
-  WAIT_CR = REG_EXMEMSTAT;
+  {$define   WAIT_CR := REG_EXMEMSTAT}
 {$endif}
 
-  DISP_SR = REG_DISPSTAT;
-  DISP_Y = REG_VCOUNT;
+{$define   DISP_SR := REG_DISPSTAT}
+{$define   DISP_Y := REG_VCOUNT}
   
   REG_BGCTRL		: pcuint16 = pointer($4000008);
   REG_BG0CNT		: pcuint16 = pointer($4000008);
@@ -106,12 +109,13 @@ const
   REG_BLDMOD		: pcuint16 = pointer($4000050);
   REG_COLV		: pcuint16 = pointer($4000052);
   REG_COLY		: pcuint16 = pointer($4000054);
-  
-  SERIAL_CR = REG_SPICNT;
-  SERIAL_DATA = REG_SPIDATA;
-  SIO_CR = REG_SIOCNT;
-  R_CR = REG_RCNT;  
-  
+
+{$ifdef ARM7}
+  {$define SERIAL_CR := REG_SPICNT}
+  {$define SERIAL_DATA := REG_SPIDATA}
+  {$define SIO_CR := REG_SIOCNT}
+  {$define R_CR := REG_RCNT}  
+{$endif ARM7}
   (*	secondary screen *)
   REG_DISPCNT_SUB		: pcuint32 = pointer($4001000);
   REG_BGCTRL_SUB		: pcuint16 = pointer($4001008);
@@ -218,22 +222,22 @@ const
   REG_TM3CNT	: pcuint16 = pointer($400010E);
   
   
-  REG_SIOCNT		: pcuint16 = pointer($4000128);
+//  REG_SIOCNT		: pcuint16 = pointer($4000128);
   REG_SIOMLT_SEND	: pcuint16 = pointer($400012A);
   
-  KEYS		= REG_KEYINPUT;
-  KEYS_CR = REG_KEYCNT;
+{$define KEYS		:= REG_KEYINPUT}
+{$define KEYS_CR := REG_KEYCNT}
   //???
-  REG_RCNT		: pcuint16 = pointer($4000134);
+//  REG_RCNT		: pcuint16 = pointer($4000134);
   REG_HS_CTRL		: pcuint16 = pointer($4000140);
   
   (* Interupt	enable registers *)
-  IE  = REG_IE;
-  _IF	=	REG_IF;
-  IME	= REG_IME;
+{$define IE  := REG_IE}
+{$define _IF :=	REG_IF}
+{$define IME	:= REG_IME}
   
   (*controls power  0x30f	is all on *)
-  POWER_CR = REG_POWERCNT;
+{$define POWER_CR := REG_POWERCNT}
   
   (* ram	controllers	0x8	is enabled,	other bits have	to do with mapping *)
   REG_VRAM_A_CR	: pcuint8 = pointer($4000240);

+ 1 - 20
packages/libndsfpc/src/nds/system.inc

@@ -83,17 +83,6 @@ end;
 
 {$ifdef ARM9}
 {$ifdef NDS_INTERFACE}
-{$ifdef DOXYGEN}
-type
-  ARM9_power = cint;
-const  
-  POWER_LCD       : ARM9_power = 0;
-  POWER_2D_A      : ARM9_power = 1;
-  POWER_MATRIX    : ARM9_power = 2;
-  POWER_3D_CORE   : ARM9_power = 3;
-  POWER_2D_B      : ARM9_power = 4;
-  POWER_SWAP_LCDS : ARM9_power = 5;
-{$else DOXYGEN}
 const
   POWER_LCD			= (1 shl 0);
   POWER_2D_A		= (1 shl 1);
@@ -103,7 +92,6 @@ const
   POWER_SWAP_LCDS	= (1 shl 15);
   POWER_ALL_2D    = (POWER_LCD or POWER_2D_A or POWER_2D_B);
   POWER_ALL       = (POWER_ALL_2D or POWER_3D_CORE or POWER_MATRIX);
-{$endif DOXYGEN}
 {$endif NDS_INTERFACE}
 
 {$ifdef NDS_IMPLEMENTATION}
@@ -126,17 +114,10 @@ end;
 
 {$ifdef ARM7}
 {$ifdef NDS_INTERFACE}
-{$ifdef DOXYGEN}
-type
-  ARM7_power = cint;
-const
-    POWER_SOUND: ARM7_power = 0;	
-    POWER_UNKNOWN: ARM7_power = 1;	
-{$else DOXYGEN}
 const
   POWER_SOUND  = (1 shl 0);
   POWER_UNKNOWN  = (1 shl 1);
-{$endif DOXYGEN}
+
 procedure readUserSettings(); cdecl; external;
 {$endif NDS_INTERFACE}
 {$endif ARM7}

+ 25 - 2
rtl/nds/system.pp

@@ -58,6 +58,9 @@ var
   envp: PPChar;
   errno: integer;
   fake_heap_end: ^byte; cvar;
+  irq_vector: integer; external name '__irq_vector';
+  
+
 
 implementation
 
@@ -81,6 +84,23 @@ implementation
 {$i ndsbios.inc}
 
 
+{
+  NDS CPU detecting function
+  --------------------------
+   ARM946E-S processor can handle dsp extensions, but ARM7TDMI does not. FPC can 
+   detect dsp by catching a SIGILL that fires when ARM7 cpu tries to use a dsp 
+   command. Unfortunately, NDS' rtl does not have any error catching mechanism.
+   This function takes care to check if the code is running on an ARM9 or on an 
+   ARM7 CPU, by checking the IRQ vector address ($0B003FFC for ARM9, 0380fff8 
+   for ARM7), declared in the linker script. This function is cleaner than the
+   older one, because does not raise any memory writing error.  
+   It works on Nintendo DS only, I guess :)
+}
+function IsARM9(): boolean;
+begin
+  IsARM9 := integer(@irq_vector) = $0B003FFC;
+end;
+
 {
   NDS CPU detecting function (thanks to 21o6):
   --------------------------------------------
@@ -93,17 +113,20 @@ implementation
    function takes care to check if the code is running on an ARM9 or on an ARM7
    CPU. It works on Nintendo DS only, I guess :)
 }
-function IsARM9(): boolean;
+function IsARM92(): boolean;
 var
   Dummy : pword absolute $06800000;
   tmp: word;
 begin
   tmp := Dummy^;
   Dummy^ := $C0DE;
-  IsARM9 := Dummy^ = $C0DE;
+  IsARM92 := Dummy^ = $C0DE;
   Dummy^ := tmp;
 end;
 
+
+
+
 {$ifdef FPC_HAS_FEATURE_PROCESSES}
 function GetProcessID: SizeUInt;
 begin