/* * savegame_manager: a tool to backup and restore savegames from Nintendo * DS cartridges. Nintendo DS and all derivative names are trademarks * by Nintendo. EZFlash 3-in-1 is a trademark by EZFlash. * * dsCard.cpp: Functions for accessing an EZFlash 3-in-1. * * Copyright (C) EZFlash Group (2006) * Copyright (C) Pokedoc (2010) */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "dscard.h" #include "string.h" #include #ifdef __cplusplus extern "C" { #endif // This is set by "ReadNORFlashID", which *must* *always* be called before anything else! uint32 ID; //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //--------------------------------------------------- //DS ¿¨ »ù±¾²Ù×÷ void Enable_Arm9DS() { REG_EXMEMCNT &= ~0x0800; //WAIT_CR &= ~0x0800; } void Enable_Arm7DS() { REG_EXMEMCNT |= 0x0800; //WAIT_CR |= 0x0800; } void OpenNorWrite() { *(vuint16 *)0x9fe0000 = 0xd200; *(vuint16 *)0x8000000 = 0x1500; *(vuint16 *)0x8020000 = 0xd200; *(vuint16 *)0x8040000 = 0x1500; *(vuint16 *)0x9C40000 = 0x1500; *(vuint16 *)0x9fc0000 = 0x1500; } void CloseNorWrite() { *(vuint16 *)0x9fe0000 = 0xd200; *(vuint16 *)0x8000000 = 0x1500; *(vuint16 *)0x8020000 = 0xd200; *(vuint16 *)0x8040000 = 0x1500; *(vuint16 *)0x9C40000 = 0xd200; *(vuint16 *)0x9fc0000 = 0x1500; } void SetRompage(u16 page) { *(vuint16 *)0x9fe0000 = 0xd200; *(vuint16 *)0x8000000 = 0x1500; *(vuint16 *)0x8020000 = 0xd200; *(vuint16 *)0x8040000 = 0x1500; *(vuint16 *)0x9880000 = page; *(vuint16 *)0x9fc0000 = 0x1500; } void SetRampage(u16 page) { *(vu16 *)0x9fe0000 = 0xd200; *(vu16 *)0x8000000 = 0x1500; *(vu16 *)0x8020000 = 0xd200; *(vu16 *)0x8040000 = 0x1500; *(vu16 *)0x9c00000 = page; *(vu16 *)0x9fc0000 = 0x1500; } void SetSerialMode() { *(vu16 *)0x9fe0000 = 0xd200; *(vu16 *)0x8000000 = 0x1500; *(vu16 *)0x8020000 = 0xd200; *(vu16 *)0x8040000 = 0x1500; *(vu16 *)0x9A40000 = 0xe200; *(vu16 *)0x9fc0000 = 0x1500; } uint32 ReadNorFlashID() { // This function was damaged on the original sample, "ID mode" was never left. It is fixed now. vuint16 id1,id2,id3,id4; ID=0; //check intel 512M 3in1 card *((vuint16 *)(FlashBase+0)) = 0xFF ; *((vuint16 *)(FlashBase+0x1000*2)) = 0xFF ; *((vuint16 *)(FlashBase+0)) = 0x90 ; *((vuint16 *)(FlashBase+0x1000*2)) = 0x90 ; id1 = *((vuint16 *)(FlashBase+0)) ; id2 = *((vuint16 *)(FlashBase+0x1000*2)) ; id3 = *((vuint16 *)(FlashBase+1*2)) ; id4 = *((vuint16 *)(FlashBase+0x1001*2)) ; if(id3==0x8810) id3=0x8816; if(id4==0x8810) id4=0x8816; if( (id1==0x89)&& (id2==0x89) &&(id3==0x8816) && (id4==0x8816)) { ID = 0x89168916; return 0x89168916; } //¼ì²â256M¿¨ *((vuint16 *)(FlashBase+0x555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x555*2)) = 0x90 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0x90 ; id1 = *((vuint16 *)(FlashBase+0x2)) ; id2 = *((vuint16 *)(FlashBase+0x2002)) ; if( (id1!=0x227E)|| (id2!=0x227E)) { *((vuint16 *)(FlashBase+0x555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ; return 0; } id1 = *((vuint16 *)(FlashBase+0xE*2)) ; id2 = *((vuint16 *)(FlashBase+0x100e*2)) ; if(id1==0x2218 && id2==0x2218) //H6H6 { *((vuint16 *)(FlashBase+0x555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ; ID = 0x227E2218; return 0x227E2218; } if(id1==0x2202 && id2==0x2202) //VZ064 { *((vuint16 *)(FlashBase+0x555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ; ID = 0x227E2202; return 0x227E2202; } if(id1==0x2202 && id2==0x2220) //VZ064 { *((vuint16 *)(FlashBase+0x555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ; ID = 0x227E2202; return 0x227E2202; } if(id1==0x2202 && id2==0x2215) //VZ064 { *((vuint16 *)(FlashBase+0x555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ; *((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ; *((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ; ID = 0x227E2202; return 0x227E2202; } return 0; } void chip_reset() { if(ID==0x89168916) { *((vuint16 *)(FlashBase+0)) = 0x50 ; *((vuint16 *)(FlashBase+0x1000*2)) = 0x50 ; *((vuint16 *)(FlashBase+0)) = 0xFF ; *((vuint16 *)(FlashBase+0x1000*2)) = 0xFF ; return; } *((vu16 *)(FlashBase)) = 0xF0 ; *((vu16 *)(FlashBase+0x1000*2)) = 0xF0 ; if(ID==0x227E2202) { *((vu16 *)(FlashBase+0x1000000)) = 0xF0 ; *((vu16 *)(FlashBase+0x1000000+0x1000*2)) = 0xF0 ; } } void Block_EraseIntel(u32 blockAdd) { u32 loop; vu16 v1,v2; bool b512=false; if(blockAdd>=0x2000000) { blockAdd-=0x2000000; CloseNorWrite(); SetRompage(768); OpenNorWrite(); b512=true; } else { CloseNorWrite(); SetRompage(0); OpenNorWrite(); } if(blockAdd==0) { for(loop=0;loop<0x40000;loop+=0x10000) { *((vu16 *)(FlashBase+loop)) = 0x50 ; *((vu16 *)(FlashBase+loop+0x2000)) = 0x50 ; *((vu16 *)(FlashBase+loop)) = 0xFF ; *((vu16 *)(FlashBase+loop+0x2000)) = 0xFF ; *((vu16 *)(FlashBase+loop)) = 0x60 ; *((vu16 *)(FlashBase+loop+0x2000)) = 0x60; *((vu16 *)(FlashBase+loop)) = 0xD0 ; *((vu16 *)(FlashBase+loop+0x2000)) = 0xD0; *((vu16 *)(FlashBase+loop)) = 0x20 ; *((vu16 *)(FlashBase+loop+0x2000)) = 0x20; *((vu16 *)(FlashBase+loop)) = 0xD0 ; *((vu16 *)(FlashBase+loop+0x2000)) = 0xD0; do { v1 = *((vu16 *)(FlashBase+loop)); v2 = *((vu16 *)(FlashBase+loop+0x2000)); } while((v1!=0x80)||(v2!=0x80)); } } else { *((vu16 *)(FlashBase+blockAdd)) = 0xFF ; *((vu16 *)(FlashBase+blockAdd+0x2000)) = 0xFF ; *((vu16 *)(FlashBase+blockAdd)) = 0x60 ; *((vu16 *)(FlashBase+blockAdd+0x2000)) = 0x60 ; *((vu16 *)(FlashBase+blockAdd)) = 0xD0 ; *((vu16 *)(FlashBase+blockAdd+0x2000)) = 0xD0 ; *((vu16 *)(FlashBase+blockAdd)) = 0x20 ; *((vu16 *)(FlashBase+blockAdd+0x2000)) = 0x20 ; *((vu16 *)(FlashBase+blockAdd)) = 0xD0 ; *((vu16 *)(FlashBase+blockAdd+0x2000)) = 0xD0 ; do { v1 = *((vu16 *)(FlashBase+blockAdd)); v2 = *((vu16 *)(FlashBase+blockAdd+0x2000)); } while((v1!=0x80)||(v2!=0x80)); } if(b512) { CloseNorWrite(); SetRompage(0); OpenNorWrite(); b512=true; } } void Block_Erase(u32 blockAdd) { vu16 v1,v2; u32 Address; u32 loop; u32 off=0; if(ID==0x89168916) { //intel 512 card Block_EraseIntel(blockAdd); return ; } if( (blockAdd>=0x1000000) && (ID==0x227E2202)) { off=0x1000000; *((vu16 *)(FlashBase+off+0x555*2)) = 0xF0 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xF0 ; } else off=0; Address=blockAdd; *((vu16 *)(FlashBase+0x555*2)) = 0xF0 ; *((vu16 *)(FlashBase+0x1555*2)) = 0xF0 ; if( (blockAdd==0) || (blockAdd==0x1FC0000) || (blockAdd==0xFC0000) || (blockAdd==0x1000000)) { for(loop=0;loop<0x40000;loop+=0x8000) { *((vu16 *)(FlashBase+off+0x555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x2AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x2AA*2)) = 0x55 ; *((vu16 *)(FlashBase+Address+loop)) = 0x30 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x12AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x12AA*2)) = 0x55 ; *((vu16 *)(FlashBase+Address+loop+0x2000)) = 0x30 ; *((vu16 *)(FlashBase+off+0x2555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x22AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x2555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x2555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x22AA*2)) = 0x55 ; *((vu16 *)(FlashBase+Address+loop+0x4000)) = 0x30 ; *((vu16 *)(FlashBase+off+0x3555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x32AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x3555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x3555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x32AA*2)) = 0x55 ; *((vu16 *)(FlashBase+Address+loop+0x6000)) = 0x30 ; do { v1 = *((vu16 *)(FlashBase+Address+loop)) ; v2 = *((vu16 *)(FlashBase+Address+loop)) ; }while(v1!=v2); do { v1 = *((vu16 *)(FlashBase+Address+loop+0x2000)) ; v2 = *((vu16 *)(FlashBase+Address+loop+0x2000)) ; }while(v1!=v2); do { v1 = *((vu16 *)(FlashBase+Address+loop+0x4000)) ; v2 = *((vu16 *)(FlashBase+Address+loop+0x4000)) ; }while(v1!=v2); do { v1 = *((vu16 *)(FlashBase+Address+loop+0x6000)) ; v2 = *((vu16 *)(FlashBase+Address+loop+0x6000)) ; }while(v1!=v2); } } else { *((vu16 *)(FlashBase+off+0x555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x2AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x2AA*2)) = 0x55; *((vu16 *)(FlashBase+Address)) = 0x30 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x12AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x12AA*2)) = 0x55 ; *((vu16 *)(FlashBase+Address+0x2000)) = 0x30 ; do { v1 = *((vu16 *)(FlashBase+Address)) ; v2 = *((vu16 *)(FlashBase+Address)) ; }while(v1!=v2); do { v1 = *((vu16 *)(FlashBase+Address+0x2000)) ; v2 = *((vu16 *)(FlashBase+Address+0x2000)) ; }while(v1!=v2); *((vu16 *)(FlashBase+off+0x555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x2AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x2AA*2)) = 0x55; *((vu16 *)(FlashBase+Address+0x20000)) = 0x30 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x12AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0x80 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x12AA*2)) = 0x55 ; *((vu16 *)(FlashBase+Address+0x2000+0x20000)) = 0x30 ; do { v1 = *((vu16 *)(FlashBase+Address+0x20000)) ; v2 = *((vu16 *)(FlashBase+Address+0x20000)) ; }while(v1!=v2); do { v1 = *((vu16 *)(FlashBase+Address+0x2000+0x20000)) ; v2 = *((vu16 *)(FlashBase+Address+0x2000+0x20000)) ; }while(v1!=v2); } } void ReadNorFlash(u8* pBuf,u32 address,u16 len) { vu16 *p = (vu16 *)pBuf; u32 loop; bool b512=false; if(address>=0x2000000)//256M { CloseNorWrite(); SetRompage(768); address-=0x2000000; b512=true; } else { CloseNorWrite(); SetRompage(0); } Enable_Arm7DS(); OpenNorWrite(); if(ID==0x89168916) { *((vuint16 *)(FlashBase+address)) = 0x50 ; *((vuint16 *)(FlashBase+address+0x1000*2)) = 0x50 ; *((vuint16 *)(FlashBase+address)) = 0xFF ; *((vuint16 *)(FlashBase+address+0x1000*2)) = 0xFF ; } for(loop=0;loop=0x2000000) { address-=0x2000000; CloseNorWrite(); SetRompage(768); OpenNorWrite(); b512=true; } else { CloseNorWrite(); SetRompage(0); OpenNorWrite(); } if(size>0x4000) { size2 = size >>1 ; lop = 2; } else { size2 = size ; lop = 1; } mapaddress = address; // _consolePrintf("WriteNorFlashINTEL begin\n"); for(j=0;j>1))) = 0x50; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) = 0x50; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1))) = 0xFF; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) = 0xFF; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1))) = 0xE8; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) = 0xE8; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1))) = 0x70; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) = 0x70; v1=v2=0; while((v1!= 0x80) || (v2 != 0x80) ) { v1 = *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1))) ; v2 = *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) ; } *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1))) = 0x0F; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) = 0x0F; for(i=0;i<0x10;i++) { *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+i*2)) = buf[(loopwrite>>2)+i]; *((vu16 *)(FlashBase+mapaddress+0x2000+(loopwrite>>1)+i*2)) = buf[0x1000+(loopwrite>>2)+i]; } *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1))) = 0xD0; *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) = 0xD0; v1=v2=0; // _consolePrintf("WriteNorFlashINTEL begin 2\n"); while((v1!= 0x80) || (v2 != 0x80) ) { v1 = *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1))) ; v2 = *((vu16 *)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)) ; if( (v1==0x90) || (v2==0x90)) { WriteSram(0xA000000,(u8 *)buf,0x8000); // _consolePrintf("Err \n"); while(1); break; } } // _consolePrintf("WriteNorFlashINTEL begin 3\n"); } } if(b512==true) { CloseNorWrite(); SetRompage(0); OpenNorWrite(); } } void WriteNorFlash(u32 address,u8 *buffer,u32 size) { if(ID==0x89168916) { WriteNorFlashINTEL(address,buffer,size); return; } CloseNorWrite(); SetRompage(0); OpenNorWrite(); vu16 v1,v2; register u32 loopwrite ; vu16* buf = (vu16*)buffer ; u32 size2,lop; u32 mapaddress; u32 j; v1=0;v2=1; u32 off=0; if( (address>=0x1000000) && (ID==0x227E2202)) { off=0x1000000; } else off=0; if(size>0x4000) { size2 = size >>1 ; lop = 2; } else { size2 = size ; lop = 1; } mapaddress = address; for(j=0;j>2);loopwrite++) { *((vu16 *)(FlashBase+off+0x555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x2AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x555*2)) = 0xA0 ; *((vu16 *)(FlashBase+mapaddress+loopwrite*2)) = buf[loopwrite]; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xAA ; *((vu16 *)(FlashBase+off+0x12AA*2)) = 0x55 ; *((vu16 *)(FlashBase+off+0x1555*2)) = 0xA0 ; *((vu16 *)(FlashBase+mapaddress+0x2000+loopwrite*2)) = buf[0x1000+loopwrite]; do { v1 = *((vu16 *)(FlashBase+mapaddress+loopwrite*2)) ; v2 = *((vu16 *)(FlashBase+mapaddress+loopwrite*2)) ; }while(v1!=v2); do { v1 = *((vu16 *)(FlashBase+mapaddress+0x2000+loopwrite*2)) ; v2 = *((vu16 *)(FlashBase+mapaddress+0x2000+loopwrite*2)) ; }while(v1!=v2); } } } void WriteSram(uint32 address, u8* data , uint32 size ) { uint32 i ; for(i=0;i>1]=*(u8*)(address+i)+(*(u8*)(address+i+1)*0x100); } } void WritePSram(u8* address, u8* data , uint32 length ) { vuint16 *pPatch=NULL; pPatch=(vuint16*)address; Enable_Arm7DS(); CloseNorWrite(); SetRompage(192); OpenNorWrite(); for(u32 pi=0;pi>1]= data[pi] + (data[pi+1]<<8); } CloseNorWrite(); Enable_Arm9DS(); } void ReadPSram(u8* address, u8* data , uint32 length ) { vuint16 *pPatch=NULL; pPatch=(vuint16*)address; Enable_Arm7DS(); CloseNorWrite(); SetRompage(192); OpenNorWrite(); for(u32 pi=0;pi>1] & 0xff; data[pi+1]=(pPatch[pi>>1] &0xff00)>>8; } CloseNorWrite(); Enable_Arm9DS(); } void OpenRamWrite() { *(vu16 *)0x9fe0000 = 0xd200; *(vu16 *)0x8000000 = 0x1500; *(vu16 *)0x8020000 = 0xd200; *(vu16 *)0x8040000 = 0x1500; *(vu16 *)0x9C40000 = 0xA500; *(vu16 *)0x9fc0000 = 0x1500; } void CloseRamWrite() { *(vu16 *)0x9fe0000 = 0xd200; *(vu16 *)0x8000000 = 0x1500; *(vu16 *)0x8020000 = 0xd200; *(vu16 *)0x8040000 = 0x1500; *(vu16 *)0x9C40000 = 0xA200; *(vu16 *)0x9fc0000 = 0x1500; } void SetShake(u16 data) { *(vuint16 *)0x9fe0000 = 0xd200; *(vuint16 *)0x8000000 = 0x1500; *(vuint16 *)0x8020000 = 0xd200; *(vuint16 *)0x8040000 = 0x1500; *(vuint16 *)0x9E20000 = data; *(vuint16 *)0x9fc0000 = 0x1500; } #ifdef __cplusplus } #endif