#include <nds.h>
#include "../../ipc6.h"

#include <nds/arm9/console.h>

#include <stdio.h>
#include <nds/registers_alt.h>
#include <string.h>
#include <dev_var.h>

#include "iointerface.h"
#include "../../share/ipctool.h"
#include "console11.h"
#include "romloader.h"
#ifndef min
	#define min(x, y)	(((x)<(y))?(x):(y))
#endif

#ifndef max
	#define max(x, y)	(((x)>(y))?(x):(y))
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern void fix_video(u32 addr,int len);
extern void fix_video2(u32 addr,int len,u32 addrd);
extern u32 arm9_reset_code;
#ifdef __cplusplus
}
#endif

#include "strpcm.h"



#define false 0
#define true 1
//int wait_test;
//int wait_test1;
//int wait_test2;

//int wait_test11;
//int wait_test12;
//int wait_test21;
extern void Start(void);

//int video_up_buf_write_old;
//int video_up_buf_read_old;
//int video_down_buf_write_old;
//int video_down_buf_read_old;
int audio_buf_write_old;
int audio_buf_read_old;
u8 seconds_old;
extern void test(void);
extern u32 get(void);

int fpga_mm1;
int fpga_mm2;

u32 testbuf[2048/4];
int Trg,Cont;
extern void read_audio (s16 *bufl,s16 *bufr);
typedef struct DSHeader_tag
{   
	char title[0xC];
	char gamecode[0x4];
	unsigned char makercode[2];
	unsigned char unitcode;
	unsigned char devicetype;		// type of device in the game card
	unsigned char devicecap;		// capacity
	unsigned char reserved1[0x9];
	unsigned char romversion;
	unsigned char reserved2;
	unsigned int arm9_rom_offset;
	unsigned int arm9_entry_address;
	unsigned int arm9_ram_address;
	unsigned int arm9_size;
	unsigned int arm7_rom_offset;
	unsigned int arm7_entry_address;
	unsigned int arm7_ram_address;
	unsigned int arm7_size;
	unsigned int fnt_offset;
	unsigned int fnt_size;
	unsigned int fat_offset;
	unsigned int fat_size;
	unsigned int arm9_overlay_offset;
	unsigned int arm9_overlay_size;
	unsigned int arm7_overlay_offset;
	unsigned int arm7_overlay_size;
	unsigned char rom_control_info1[8];
	unsigned int icon_title_offset;
	unsigned short secure_area_crc;
	unsigned short rom_control_info2;
	unsigned int offset_0x70;
	unsigned int offset_0x74;
	unsigned int offset_0x78;
	unsigned int offset_0x7C;
	unsigned int application_end_offset;			// rom size
	unsigned int rom_header_size;
	unsigned int offset_0x88;
	unsigned int offset_0x8C;
	unsigned int offset_0x90;
	unsigned int offset_0x94;
	unsigned int offset_0x98;
	unsigned int offset_0x9C;
	unsigned int offset_0xA0;
	unsigned int offset_0xA4;
	unsigned int offset_0xA8;
	unsigned int offset_0xAC;
	unsigned int offset_0xB0;
	unsigned int offset_0xB4;
	unsigned int offset_0xB8;
	unsigned int offset_0xBC;
	unsigned char logo[156];
	unsigned short logo_crc;
	unsigned short header_crc;
	unsigned char zero[160];
}DSHeader;


struct video_set video_set_buf;
struct audio_set audio_set_buf;
int video_enable;
//int audio_enable;
int key_enable;
int rtc_enable;
touchPosition touchPostemp;
u32 keys;
typedef void(*call0)(void);
int c2type;
int mm_num1;
int mm_num2;
/*
0x04000180 - REG_IPCSYNC - IPC Synchronize Register (R/W) Cpu  Bit Name Expl. 
9/7  0-3    IPC Remote Status   Reflects the remote processor's LOCALSTAT.   
9/7  8-11    IPC Local Status   Userconfigurable status for local processor.   
9/7  13    IPC IRQ Request   0=Nothing, 1=Trigger an interrupt on the remote processor   
9/7  14    IPC IRQ Enable   0=Disabled, 1=Allow remote processor to trigger IRQ   

0x04100000 - REG_IPCFIFORECV - IPC Receive Fifo (R) Cpu  Bit Name Expl. 
9/7  0-31    Received Fifo Data   Fifo data received from the remote processor. 
max 64byie
0x04000188 - REG_IPCFIFOSEND - IPC Send Fifo (W) Cpu  Bit Name Expl. 
9/7  0-31    Sending Fifo Data   Fifo data ready for the remote processor to receive.   

Caution!
1. Do not read from the receive fifo when it is empty, or this will result in error.
2. Do not write to the send fifo when it is full, or this will result in error.

0x04000184 - REG_IPCFIFOCNT - IPC Fifo Control Register (R/W) Cpu  Bit Name Expl. 
9/7  0    Send Fifo Empty Status   0=Not Empty, 1=Empty   
9/7  1    Send Fifo Full Status   0=Not Full, 1=Full   
9/7  2    Send Fifo IRQ Enable   0=Disable, 1=IRQ on Send Fifo Empty   
9/7  3    Send Fifo Clear   0=Nothing, 1=Flush Send Fifo   
9/7  8    Receive Fifo Empty   0=Not Empty, 1=Empty   
9/7  9    Receive Fifo Full   0=Not Full, 1=Full   
9/7  10    Receive Fifo IRQ Enable   0=Disable, 1=IRQ on Receive Fifo Not Empty   
9/7  14    Error   0=No Error, 1=Error   
9/7  15    Enable Fifo   0=Disable, 1=Enable Receive & Send Fifo 
*/
//////////////////////////////////////////////////////////////////
/*
4000180h - NDS9/NDS7 - IPCSYNC - IPC Synchronize Register (R/W)
  Bit   Dir  Expl.
  0-3   R    Data input from IPCSYNC Bit8-11 of remote CPU (00h..0Fh)
  4-7   -    Not used
  8-11  R/W  Data output to IPCSYNC Bit0-3 of remote CPU   (00h..0Fh)
  12    -    Not used
  13    W    Send IRQ to remote CPU      (0=None, 1=Send IRQ)
  14    R/W  Enable IRQ from remote CPU  (0=Disable, 1=Enable)
  15-31 -    Not used

 

4000184h - NDS9/NDS7 - IPCFIFOCNT - IPC Fifo Control Register (R/W)
  Bit   Dir  Expl.
  0     R    Send Fifo Empty Status      (0=Not Empty, 1=Empty)
  1     R    Send Fifo Full Status       (0=Not Full, 1=Full)
  2     R/W  Send Fifo Empty IRQ         (0=Disable, 1=Enable)
  3     W    Send Fifo Clear             (0=Nothing, 1=Flush Send Fifo)
  4-7   -    Not used
  8     R    Receive Fifo Empty          (0=Not Empty, 1=Empty)
  9     R    Receive Fifo Full           (0=Not Full, 1=Full)
  10    R/W  Receive Fifo Not Empty IRQ  (0=Disable, 1=Enable)
  11-13 -    Not used
  14    R/W  Error, Read Empty/Send Full (0=No Error, 1=Error/Acknowledge)
  15    R/W  Enable Send/Receive Fifo    (0=Disable, 1=Enable)
  16-31 -    Not used

 

4000188h - NDS9/NDS7 - IPCFIFOSEND - IPC Send Fifo (W)
  Bit0-31  Send Fifo Data (max 16 words; 64bytes)

 

4100000h - NDS9/NDS7 - IPCFIFORECV - IPC Receive Fifo (R)
  Bit0-31  Receive Fifo Data (max 16 words; 64bytes)
*/
vs32 CARD_LINE_iqe_w;
vs32 CARD_LINE_iqe_r;
u32 keys_old;
u8 time_seconds_old;
touchPosition touchPos_old;
bool write_key;
bool debug_a;
bool debug_b;
bool arm7_debug;


//u32 video_up_buf[4]  ;
//u32 video_up_buf_write;
//u32 video_up_buf_read;
//u32 video_down_buf[4];
//u32 video_down_buf_write;
//u32 video_down_buf_read;


//extern u32 audio_buf[4];
//extern u32 audio_buf_write;
//extern u32 audio_buf_read;
//extern u32 audio_enable;


u32 audio_enable_num;


u32 vram_a_buf1;
u32 vram_a_buf2;
u32 vram_a_buf3;
u32 vram_b_buf1;
u32 main_buf[512];

int nds_iqe_cmd;
int nds_iqe_ndsaddr;
int nds_iqe_cpuaddr;
int nds_iqe_type;
int nds_iqe_ret;
//int nds_iqe_address;
int nds_iqe_len;
int nds_iqe_num;
int nds_iqe_num_now;
int waitflag;
u32 nds_callback;

u32 databuf[(/*(256*192*2 * 8)*/ + (strpcmbufmaxlen  * (strpcmRingBufCount )))/4 ] __attribute__ ((aligned (32)));
/*u32 video_up_buf[4];
int video_up_buf_write;
int video_up_buf_read;

u32 video_down_buf[4];
int video_down_buf_write;
int video_down_buf_read;

u32 audio_l_buf[4];
int audio_l_buf_write;
int audio_l_buf_read;

u32 audio_r_buf[4];
int audio_r_buf_write;
int audio_r_buf_read;
*/
enum {
	a_mode_debug                = 0,
	a_mode_buf1             = 1,
	a_mode_buf2          = 2
};
enum {
	b_mode_debug                = 0,
	b_mode_buf1             = 1
};

//bool CARD_LINE_iqe_complete;
void CARD_LINE_Handler(void)
{
    CARD_LINE_iqe_w++;
}
void enable_video(void)
{
}
//int video_timer_num_write;
//int video_timer_num_read;
//void Timer1Handler(void)//video
//{
//        video_timer_num_write++;
//}

//TransferSound SoundDataL_T;
//TransferSoundData SoundDataL;

//TransferSound SoundDataR_T;
//TransferSoundData SoundDataR;


void enable_audio(void)
{

    audio_Samples = audio_set_buf.sample_size;
    audio_Rate = audio_set_buf.sample;
    audio_Channels = audio_set_buf.stereo == 0? 1:2;
    audio_len = audio_Samples * (audio_set_buf.sample_bit/8) * audio_Channels;
    if(audio_Rate==(32768/4)){
        audio_Format=SPF_PCMx4;
    }else{
        if(audio_Rate==(32768/2)){
          audio_Format=SPF_PCMx2;
          }else{
          if(audio_Rate==(32768/1)){
            audio_Format=SPF_PCMx1;
            }else{
            if(audio_Rate<=48000){
              audio_Format=SPF_PCMx4;
              }else{
              if(audio_Rate<=96000){
                audio_Format=SPF_PCMx2;
                }else{
                audio_Format=SPF_PCMx1;
              }
            }
          }
        }
    }
  //audio_Format=SPF_PCMx1;
  if (audio_enable==1)
  {
      strpcmStart();
  }
  else
  {
      strpcmStop();
  }



}

/*
void Timer3Handler(void)
{
    if (audio_enable == 1)
    {
        int i= audio_l_buf_write - audio_l_buf_read;
        if (i !=0)
        {
            SoundDataL.data=(u8*)(audio_l_buf[audio_l_buf_read &3]);
            //DC_FlushRange( &SoundDataL.data, SoundDataL.len );
            memcpy( &SoundDataL_T.data[0], &SoundDataL, sizeof(TransferSoundData) );
            DC_FlushRange( &SoundDataL_T, sizeof(TransferSound) );
            while(IPC->soundData_L != 0);
            IPC->soundData_L=(pTransferSound) &SoundDataL_T;
            audio_l_buf_read++;
        }
        i= audio_r_buf_write - audio_r_buf_read;
        if (i !=0)
        {
            SoundDataR.data=(u8*)audio_r_buf[audio_r_buf_read &3];
            //DC_FlushRange( &SoundDataL.data, SoundDataL.len );
            memcpy( &SoundDataR_T.data[0], &SoundDataR, sizeof(TransferSoundData) );
            DC_FlushRange( &SoundDataR_T, sizeof(TransferSound) );
            while(IPC->soundData_R != 0);
            IPC->soundData_R= (pTransferSound) &SoundDataR_T;
            audio_r_buf_read++;
        }
    }


}
*/

void clrreg(void)
{
 	int i;
  	(*(vu16*)0x4000208) = 0;
	(*(vu32*)0x4000210) = 0;
	(*(vu32*)0x4000214) = ~0;

	//clear out ARM9 DMA channels
	for (i=0; i<4; i++) {
		DMA_CR(i) = 0;
		DMA_SRC(i) = 0;
		DMA_DEST(i) = 0;
		TIMER_CR(i) = 0;
		TIMER_DATA(i) = 0;
	}
    /*
	VRAM_CR = 0x80808080;
	(*(vu32*)0x027FFE04) = 0;   // temporary variable
	PALETTE[0] = 0;
	dmaFillWords((void*)0x027FFE04, PALETTE+1, (2*1024)-2);
	dmaFillWords((void*)0x027FFE04, OAM,     2*1024);
	dmaFillWords((void*)0x027FFE04, (void*)0x04000000, 0x56);  //clear main display registers
	dmaFillWords((void*)0x027FFE04, (void*)0x04001000, 0x56);  //clear sub  display registers
	dmaFillWords((void*)0x027FFE04, VRAM,  656*1024);
	
	DISP_SR = 0;
	videoSetMode(0);
	videoSetModeSub(0);
	VRAM_A_CR = 0;
	VRAM_B_CR = 0;
	VRAM_C_CR = 0;
	VRAM_D_CR = 0;
	VRAM_E_CR = 0;
	VRAM_F_CR = 0;
	VRAM_G_CR = 0;
	VRAM_H_CR = 0;
	VRAM_I_CR = 0;
	VRAM_CR   = 0x03000000;
	WRAM_CR = 0x03;
	for (i=0; i<4; i++) {
		DMA_CR(i) = 0;
		DMA_SRC(i) = 0;
		DMA_DEST(i) = 0;
		TIMER_CR(i) = 0;
		TIMER_DATA(i) = 0;
	}
    */

}
void initreg(void)
{

    //powerON(POWER_ALL);
    powerON(POWER_ALL_2D);
    WRAM_CR = 0x03;
    *(vu16*)0x4000204=0xe880 & (~(BIT(11) | BIT(7)));
    //*(vu16*)0x4000204=0x6000;

}
void KeyRead(void)
{
    int i;
    u16 ReadData = (*(vu16 *)0x4000130 ^ 0x03ff);
    Trg  = ReadData & (ReadData ^ Cont);            // trigger input
    Cont = ReadData; 
    i=0xc000;//   beta input
	while(i--);
}

void set_a_mode(u8 mode)
{
    switch (mode)
    {
    case a_mode_debug:
        videoSetMode( MODE_5_2D | DISPLAY_BG0_ACTIVE );
         debug_a = true;
       break;
    case a_mode_buf1:
        videoSetMode( MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_BG3_ACTIVE 
        | DISPLAY_BG1_ACTIVE

/*        | DISPLAY_SPR_ACTIVE
        | DISPLAY_SPR_1D_BMP_SIZE_128
        | DISPLAY_SPR_1D_BMP 
  
        | DISPLAY_SPR_ACTIVE 
        | DISPLAY_SPR_2D 
        | DISPLAY_SPR_2D_BMP_256  
*/ 
 /*   
        | DISPLAY_SPR_ACTIVE 
         | DISPLAY_SPR_1D
            |DISPLAY_SPR_1D_BMP_SIZE_256
*/

    );
        debug_a = false;
        break;
    case a_mode_buf2:
        videoSetMode( MODE_5_2D | DISPLAY_BG3_ACTIVE );
          debug_a = false;
      break;
    default :
        videoSetMode( MODE_5_2D | DISPLAY_BG2_ACTIVE );
        debug_a = false;
        break;

    
    }


}
void set_b_mode(u8 mode)
{
    switch (mode)
    {
    case b_mode_debug:
        videoSetModeSub( MODE_5_2D | DISPLAY_BG0_ACTIVE );
        debug_b = true;
        break;
    case b_mode_buf1:
        videoSetModeSub( MODE_5_2D | DISPLAY_BG2_ACTIVE );
        debug_b = false;
        break;
    default :
        videoSetModeSub( MODE_5_2D | DISPLAY_BG2_ACTIVE );
        debug_b = false;
        break;

    }
}
vu8 curtime[8];
void update_input(void)
{
    IPC8->ipc_arm9_r_busy=1;
    if (IPC8->ipc_arm7_w_busy == 1)
    {
        IPC8->ipc_arm9_r_busy=0;
        //scanKeys();
        //keys = keysHeld();

    }
    else
    {
        touchPostemp.x=IPC->touchX;
        touchPostemp.y=IPC->touchY;
        touchPostemp.px=IPC->touchXpx;
        touchPostemp.py=IPC->touchYpx;
        touchPostemp.z1=IPC->touchZ1;
        touchPostemp.z2=IPC->touchZ2;
        memcpy((u8*)&curtime[0],(u8*)&IPC->time.curtime[0],8);
        scanKeys();
        keys = keysHeld();
    }

    IPC8->ipc_arm9_r_busy=0;


}

vu8  txt_dot_buf[192/8][256/8][8][8/2] __attribute__ ((aligned (32)));
int old_txt_y_begin;
int old_txt_y_end;
int old_txt_BLEND;
int old_txt_col;
#define CONSOLE_WIDTH 32
#define CONSOLE_HEIGHT 24

void init_txt(void)
{

    testbuf[0]=0;
    swiCopy(testbuf,(char*)BG_TILE_RAM(1),COPY_MODE_WORD | COPY_MODE_FILL | (0x8000 /4));
    int addr = BG_TILE_RAM(1);
    int charaddr=BG_MAP_RAM(22);
    int i;
	BG_PALETTE[1*16+0] = RGB15(0,0,0);

	BG_PALETTE[1*16+1] = RGB15(0,0,31);
    BG_PALETTE[1*16+2] = RGB15(10,10,10);
    BG_PALETTE[1*16+3] = RGB15(0,31,0);

    old_txt_y_begin=0;
    old_txt_y_end=0;
    old_txt_BLEND=0;
    old_txt_col=0;
    memset((char*)txt_dot_buf,0,sizeof(txt_dot_buf));


    for(i = 0; i < CONSOLE_HEIGHT * CONSOLE_WIDTH; i++)
    {
        *(vu16*)(charaddr + (i*2)) = (1<< 12) | (i);
    }
/*

    for (i = 0; i < ( 256 *32 /4 ); i++)
    {
        *(vu16*)(addr + (256 * (192 -32 ) / 2) + (i*2)) = 0x2222;
    }
    */
}
/*
int daw(int x,int y,int len,int h,int col)
{

	u16 (*p)[256];
    p=(u16 (*)[256])vram_a_buf1;
    int j,i;
    for (j=y;j<(y+h) ; j++)
    {
        for (i=x;i<(x+len) ;i++ )
        {
            p[j][i]=col | (1<<15);
        }
    }
}
*/
void set_txt(int x,int y,int len,int h,int col,int DST,int SRC)
{

    vu32 i,j,k,l,m,n,o,p;
    vu32 x_end;
    vu32 y_end;
    vu32 x_begin;
    vu32 y_begin;
    x &= ~1;

    x_begin = x;
    y_begin = y;
    x_end   = (x+len +1) & ~1;
    y_end   = y+h;

    vu8 temp8;
    vu8 *temp8p;
    vu8 data;
    vu8 mask;
    i=(int)&txt_dot_buf[old_txt_y_begin/8][0][0][0];
    j=(int)&txt_dot_buf[old_txt_y_end/8][0][0][0];

    //memset((char*)i,0,j-i);
    testbuf[0]=0;
    swiCopy(testbuf,(char*)i ,COPY_MODE_WORD | COPY_MODE_FILL | ((j-i) /4));


    for (i=y_begin;i<y_end ; i++)
    {
        for (j=x_begin;j<x_end ;j+=2 )
        {
            txt_dot_buf[i/8][j/8][i%8][(j/2)%4]= 0x11;
            /*
            k=j&1;
            l=j/2;

            temp8p=&txt_dot_buf[i/8][j/8][i%8][l%4];
            temp8 =* temp8p;
            if (k==0)
            {
                data=1;
                mask=0xf0;
            }
            else
            {
                data=1<<4;
                mask=0x0f;
            }
            temp8 &= mask;
            temp8 |= data;
            * temp8p =temp8;
            */

        }
    }
    i=min(old_txt_y_begin,y);
    j=max(old_txt_y_end,y_end);

    i &= ~7;
    j += 7;
    j &= ~7;

    k=(int)&txt_dot_buf[i/8][0][0][0];
    l=(int)&txt_dot_buf[j/8][0][0][0];

    if (old_txt_col != col)
    {
	    BG_PALETTE[1*16+1] = col;
        old_txt_col=col;

    }

    swiCopy((char*)k,(char*)(BG_TILE_RAM(1) + (k-((int)txt_dot_buf))),COPY_MODE_WORD | COPY_MODE_COPY | ((l-k) /4));
    //swiCopy((char*)txt_dot_buf,(char*)(BG_TILE_RAM(1)),COPY_MODE_WORD | COPY_MODE_COPY | ((sizeof(txt_dot_buf)) /4));
    old_txt_y_begin=y & ~7;
    old_txt_y_end=(y_end + 7) & ~7;

    i=(DST << 8) | SRC;

    
    if (old_txt_BLEND != i)
    {
        BLEND_AB = i;
        old_txt_BLEND =i;
    }


}

void videoSetMode_Set(void)
{
    vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
    vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
    vramSetBankC(VRAM_C_SUB_BG_0x06200000);
    vramSetBankD(VRAM_D_ARM7_0x06000000);
    vramSetBankE(VRAM_E_MAIN_SPRITE);
    vramSetBankF(VRAM_F_MAIN_SPRITE_0x06010000);
    vramSetBankG(VRAM_G_MAIN_SPRITE_0x06014000);

    //vramSetBankE(VRAM_E_LCD);
    //vramSetBankF(VRAM_F_LCD);
    //vramSetBankG(VRAM_G_LCD);

    vramSetBankH(VRAM_H_LCD);
    vramSetBankI(VRAM_I_LCD);

    //videoSetMode( MODE_5_2D
    //    | DISPLAY_BG2_ACTIVE
    //    );
    set_a_mode(a_mode_buf1);
    BG2_CR = BG_BMP16_256x256 | BG_BMP_BASE(4) | BG_PRIORITY_3;
    BG2_XDX = 1 << 8; // 2 =放大倍数
    BG2_YDY = 1 << 8;  // 2 =放大倍数
    BG2_XDY = 0;
    BG2_YDX = 0;
    BG2_CY = 0;
    BG2_CX = 0;

    BG3_CR = BG_BMP16_256x256 | BG_BMP_BASE(0xa) | BG_PRIORITY_1;
    BG3_XDX = 1 << 8; // 2 =放大倍数
    BG3_YDY = 1 << 8;  // 2 =放大倍数
    BG3_XDY = 0;
    BG3_YDX = 0;
    BG3_CY = 0;
    BG3_CX = 0;

    BG0_CR = BG_TILE_BASE(0) | BG_MAP_BASE(6) | BG_PRIORITY_3;
	BG_PALETTE[0] = RGB15(31,31,31);
	BG_PALETTE[15*16+15] = RGB15(0,0,0);
    BG_PALETTE[14*16+15] = RGB15(31,0,0);
    BG_PALETTE[13*16+15] = RGB15(0,31,0);
    //consoleInitDefault((u16*)BG_MAP_RAM(30), (u16*)BG_TILE_RAM(0), 16);
    //consoleClear();
    //_consoleInitDefault((u16*)BG_MAP_RAM(30), (u16*)BG_TILE_RAM(0),8);
    //_consoleClear();
    //_consolePrintSet(0,0);

    debugconsoleInitDefault((u16*)BG_MAP_RAM(6), (u16*)BG_TILE_RAM(0), 16);
    debugconsoleClear();

    BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(22) | BG_PRIORITY_2;
    //init_obj();
    init_txt();

    //BLEND_CR = BLEND_ALPHA | BLEND_DST_BG2 | BLEND_DST_BG3;
    //BLEND_AB = (4 << 8) | 7;

    BLEND_CR = BLEND_ALPHA | BLEND_DST_BG2  | BLEND_SRC_BG1  ;// BLEND_ALPHA | BLEND_DST_BG2 | BLEND_DST_BG3;
    //BLEND_CR = BLEND_ALPHA | BLEND_SRC_BG2 | BLEND_SRC_BG3 | BLEND_DST_BG1  ;// BLEND_ALPHA | BLEND_DST_BG2 | BLEND_DST_BG3;
    BLEND_AB = (0x10 << 8) | 0;

////////////////////////////////////////////////////////////////////////////////////////////
    //videoSetModeSub( MODE_5_2D | DISPLAY_BG0_ACTIVE );// | DISPLAY_BG2_ACTIVE );
    set_b_mode(b_mode_buf1);

    SUB_BG2_CR = BG_BMP16_256x256 | BG_BMP_BASE(2) | BG_PRIORITY_1;
    SUB_BG2_XDX = 1<<8;
    SUB_BG2_YDY = 1<<8;
    SUB_BG2_XDY = 0;
    SUB_BG2_YDX = 0;
    SUB_BG2_CY = 0;
    SUB_BG2_CX = 0;

    SUB_BG0_CR = BG_TILE_BASE(0) | BG_MAP_BASE(14) | BG_PRIORITY_1;
	BG_PALETTE_SUB[0] = RGB15(31,31,31);
	BG_PALETTE_SUB[15*16+15] = RGB15(0,0,0);
    BG_PALETTE_SUB[14*16+15] = RGB15(31,0,0);
    BG_PALETTE_SUB[13*16+15] = RGB15(0,31,0);
    consoleInitDefault((u16*)BG_MAP_RAM_SUB(14), (u16*)BG_TILE_RAM_SUB(0), 16);
    consoleClear();

    vram_a_buf1 = BG_BMP_RAM(0x4);
    vram_a_buf2 = BG_BMP_RAM(0xa);
    vram_a_buf3 = 0x06400000;
    vram_b_buf1 = BG_BMP_RAM_SUB(2);
    *(vu16*)0x04000304 |= (1<<15);


}
/*
#define BG_MAP_RAM(base)  (((base)*0x800) + 0x06000000)
#define BG_MAP_RAM_SUB(base) (((base)*0x800) + 0x06200000)

#define BG_TILE_RAM(base) (((base)*0x4000) + 0x06000000)
#define BG_TILE_RAM_SUB(base) (((base)*0x4000) + 0x06200000)

#define BG_BMP_RAM(base)  (((base)*0x4000) + 0x06000000)
#define BG_BMP_RAM_SUB(base) (((base)*0x4000) + 0x06200000)
*/
/*
cmd 
type video audio
offset
len
*/
/*
c0 iqe
c1 read512
c2 read512*n
c3 write key
c4 set


c8 write 512




*/
vs32 delay_times_0;
vs32 delay_times_1;

DTCM_DATA int Vblanknum;
DTCM_DATA int arm7debug_wait;

void VblankHandler(void)
{
    int temp;
    Vblanknum++;
    temp = Vblanknum&1;
    arm7debug_wait=temp ^ 1;

    waitflag=temp;
    IPC8->arm9_Vblank=temp ^ 1;
    if(delay_times_0 >0)
    {
        delay_times_0--;
    }
    if(delay_times_1 >0)
    {
        delay_times_1--;
    }
    /*
    if ((arm7strwrite != arm7strread))
    {
        int i;
        i=arm7strwrite - arm7strread;
        for (int j=0;j<i ;j++ )
        {
            int jj=(((arm7strread & arm7strindexmask)*4) + arm7strindexaddr);
           _consolePrint( (char*)(*(vu32*)jj));
            arm7strread++;
        }
    }
    */
    
}
int old_v1,old_v2;
int old_a1,old_a2;

void clear_var(void)
{
   // video_up_buf_write=0;
    //video_up_buf_read=0;
    //video_up_buf_write=0;
    //video_up_buf_read=0;

    //video_down_buf_write=0;
    //video_down_buf_read=0;
    //video_down_buf_write=0;
    //video_down_buf_read=0;

    //audio_enable =0;
    //key_enable=0;
    //rtc_enable=0;




    audio_buf_write=0;
    audio_buf_read=0;
    audio_buf_write=0;
    audio_buf_read=0;

    //video_up_buf_write_old=-1;
    //video_up_buf_read_old=-1;
    //video_down_buf_write_old=-1;
    //video_down_buf_read_old=-1;
    audio_buf_write_old=-1;
    audio_buf_read_old=-1;

    seconds_old=-1;

    keys_old=-1;
    touchPos_old.x=0;
    touchPos_old.px=0;
    touchPos_old.y=0;
    touchPos_old.py=0;

    nds_iqe_num_now =0 ;
    fpga_mm1=0;
    fpga_mm2=0;
    mm_num1=0;
    mm_num2=0;

}
void jz_debug(void)
{
    int i;
    cardcommand_r4_num(0xc4,0,0,0xf0);
#ifdef ENABLE_DEBUG  
    printf("CARD_LINE_iqe,%x,%x \n",CARD_LINE_iqe_r,CARD_LINE_iqe_w);
#endif
    i=0x100000;
    while(i--);
}
int zj_list;
int zj_list_w;
int zj_list_r;
int zj_list_sub;
#define DATE ""__DATE__" "__TIME__" GMT+09:00"
inline void fillMemory( void * addr, u32 count, u32 value )
{
    swiFastCopy( (void*)(&value), addr, (count>>2) | COPY_MODE_WORD | COPY_MODE_FILL);
}

inline void zeroMemory( void * addr, u32 count )
{
    fillMemory( addr, count, 0 );
}

void resetARM9Memory()
{
  int i;
    // DMA
    for (i=0; i<4; i++) {
        DMA_CR(i) = 0;
        DMA_SRC(i) = 0;
        DMA_DEST(i) = 0;
        TIMER_CR(i) = 0;
        TIMER_DATA(i) = 0;
    }

    //swiWaitForVBlank(); // wait for VBLANK to avoid screen picture break
    //PALETTE[0] = 0xFFFF;

    // VIDEO
    // trun on vram banks for clear
    VRAM_CR = 0x80808080;
    // clear video palette
    zeroMemory( PALETTE, 2048 );//PALETTE[0] = RGB15(1,1,1);
    zeroMemory( PALETTE_SUB, 2048 );
    // clear video object attribution memory
    zeroMemory( OAM, 2048 );
    zeroMemory( OAM_SUB, 2048 );
    // clear video object data memory
    zeroMemory( SPRITE_GFX, 128 * 1024 );
    zeroMemory( SPRITE_GFX_SUB, 128 * 1024 );
    // clear main display registers
    zeroMemory( (void*)0x04000000, 0x56 );
    // clear sub display registers
    zeroMemory( (void*)0x04001000, 0x56 );
    // clear vram
    zeroMemory( VRAM, 656 * 1024 );

    // clear video registers
    REG_DISPCNT = 0;
    REG_DISPCNT_SUB = 0;
    VRAM_A_CR = 0;
    VRAM_B_CR = 0;
    VRAM_C_CR = 0;
    VRAM_D_CR = 0;
    VRAM_E_CR = 0;
    VRAM_F_CR = 0;
    VRAM_G_CR = 0;
    VRAM_H_CR = 0;
    VRAM_I_CR = 0;
    VRAM_CR   = 0x00000000;
    POWER_CR  = 0x820F; // turn on all engines

    // Interrupt
    REG_IME = 0;
    REG_IE = 0;
    REG_IF = ~0;

    for (i=0; i<4; i++) {
        DMA_CR(i) = 0;
        DMA_SRC(i) = 0;
        DMA_DEST(i) = 0;
        TIMER_CR(i) = 0;
        TIMER_DATA(i) = 0;
    }

}

int main(void)
{
	int i;
    IPC8->IPC_ARM9 = IPC_MSG_NONE;
    IPC8->IPC_ARM7 = IPC_MSG_NONE;

	  clrreg();
    initreg();
    irqInit();
    resetARM9Memory();

    videoSetMode_Set();
    /*
    swiDelay(0x1000);
    while( IPC8->IPC_ARM7 != IPC_MSG_BOOTWAIT ) {
        swiDelay(0x100);
    }
     IPC8->IPC_ARM7=IPC_MSG_NONE;
     */


    //set_b_mode(b_mode_debug);
    //enable_arm7_debug(1);

    r4_delay = 0x280;
    w4_delay = 0x280;
    r512_delay = 0x280;
    w512_delay = 0x280;

    write_key = false;
    arm7debug_wait=0;

    CARD_LINE_iqe_w=0;
    CARD_LINE_iqe_r=0;
    IPC8->ipc_arm9_r_busy=0;
    Vblanknum=0;


    //video_up_buf[0]= (vu32)&databuf[(256*192*2*0)/4];video_up_buf[0] |= 0x400000;
    //video_up_buf[1]= (vu32)&databuf[(256*192*2*1)/4];video_up_buf[1] |= 0x400000;
    //video_up_buf[2]= (vu32)&databuf[(256*192*2*2)/4];video_up_buf[2] |= 0x400000;
    //video_up_buf[3]= (vu32)&databuf[(256*192*2*3)/4];video_up_buf[3] |= 0x400000;
    //video_down_buf[0]= (vu32)&databuf[(256*192*2*4)/4];video_down_buf[0] |= 0x400000;
    //video_down_buf[1]= (vu32)&databuf[(256*192*2*5)/4];video_down_buf[1] |= 0x400000;
    //video_down_buf[2]= (vu32)&databuf[(256*192*2*6)/4];video_down_buf[2] |= 0x400000;
    //video_down_buf[3]= (vu32)&databuf[(256*192*2*7)/4];video_down_buf[3] |= 0x400000;
    for (i=0;i<(strpcmRingBufCount) ;i++ )
    {
        audio_buf[i] = (u32)&databuf[(/*(256*192*2*8)  + */(strpcmbufmaxlen *i) )/4];audio_buf[i] |= 0x400000;
    }

    clear_var();

    //irqSet(IRQ_IPC_SYNC,IPCSYNC_Handler);
    //REG_IPC_SYNC = REG_IPC_SYNC | (1<<14);
    //irqEnable(IRQ_IPC_SYNC);

    irqSet(IRQ_CARD_LINE,CARD_LINE_Handler);
    irqEnable(IRQ_CARD_LINE);

    keysSetRepeat( 30, 1 );
    InitAudio();

    irqSet(IRQ_VBLANK, VblankHandler);
    irqEnable(IRQ_VBLANK);

    TIMER1_CR =0;

     //video_set_buf.timer_l_data = 32768;
     //video_set_buf.timer_h_data = 32768 / 25;//25hz

    audio_set_buf.sample_size = 512;
    audio_set_buf.sample = 44100;
    audio_set_buf.stereo = 1;
    audio_set_buf.sample_bit = 16;

    key_enable=0;
    video_enable=0;
    audio_enable=0;
    rtc_enable=0;

    //enable_video();
    //enable_audio();


    //printf("begin %s,%x %x\n",DATE,*(vu16*)0x4000204,arm7strchange);
    //while (1)
    //{
    //    if (arm7strchange != 0)
    //    {
    //        printf("arm7strchange %d %d\n",arm7strchange,arm7_debug);
    //        arm7strchange =0;
    //                    swiDelay(2);
    //
    //
    //    }
    //}

//    set_b_mode(b_mode_debug);
#ifdef ENABLE_DEBUG  
    printf("databuf %x\n",(u32)databuf);
#endif
    int enable_test_v = 0;
    //test();
    //Start();
    int cmpdata;
    zj_list=0;

    //cardexitemode();

    //int bmptest =get();
    //swiFastCopy((void*)bmptest,(void*)(vram_a_buf2+(256*64*2)),COPY_MODE_WORD | COPY_MODE_COPY | (256*16*2/4));

    //swiFastCopy((void*)bmptest,(void*)(vram_a_buf3),COPY_MODE_WORD | COPY_MODE_COPY | (256*64*2/4));

    //set_txt(0,192 -64,32,2,RGB15(0,0,31),4,7);
    //daw(64,64,32,2,RGB15(0,0,31));



//    printf("begin %s,%x\n",DATE,*(vu16*)0x4000204);
    while(CARD_LINE_iqe_w == CARD_LINE_iqe_r);
#ifdef ENABLE_DEBUG  
    printf("begin2 %s,%x\n",DATE,*(vu16*)0x4000204);
#endif
    while (1)
    {
        if ((CARD_LINE_iqe_w != CARD_LINE_iqe_r) && (zj_list==0))
        {
            CARD_LINE_iqe_r=CARD_LINE_iqe_w;
            
            if (audio_enable == 1)
            {
                audio_buf_read_old = -1;
            }
            else
            {
                cardcommand_r4_num(0xc4,0,0,0x70);
            }
            
            //zj_list=1;
        }
        if (zj_list!=0)
        {
                zj_list--;
                cardcommand_r512(0xc0,nds_iqe_num_now,(u32)&main_buf[0]) ;
//                printf("0xc0=%x,%x,%x,%x,%x,%x\n",main_buf[0],main_buf[1],main_buf[2],main_buf[3],main_buf[4],main_buf[5]);
//                printf("list=%x\n",zj_list);
                nds_iqe_cmd = main_buf[0]&0xff;
                nds_iqe_type = (main_buf[0]>>8) & 0xff;
                nds_iqe_ret = (main_buf[0]>>16) & 0xffff;

                nds_iqe_ndsaddr = main_buf[1];
                nds_iqe_cpuaddr = main_buf[2];
                nds_callback    = main_buf[3];
                nds_iqe_len = main_buf[4];

                //printf("nds_iqe_cmd=%x,%x,%x,%x \n",nds_iqe_cmd,main_buf[3],video_up_buf_write,video_up_buf_read);
//                wait_press_b();
                if ((nds_iqe_cmd ==0xc1)||(nds_iqe_cmd ==0xc2))
                {
                    //printf("nds_iqe_len=%x \n",nds_iqe_len);
                    switch (nds_iqe_type)
                    {
                        case VIDEO_UP:
                                nds_iqe_ndsaddr += vram_a_buf1;// video_up_buf[video_up_buf_write&3];
                                if ((enable_test_v == 1) || (fpga_mm1 !=0) || (fpga_mm2 !=0))
                                {
                                    nds_iqe_len = 0;
                                }
                                mm_num1++;
                            break;

                        case VIDEO_UP_TXT:
                                nds_iqe_ndsaddr += vram_a_buf2;// video_up_buf[video_up_buf_write&3];
                                set_txt(main_buf[6],main_buf[7],main_buf[8],main_buf[9],main_buf[10],main_buf[11],main_buf[12]);
                                
                            break;

                        case VIDEO_DOWN:
                                nds_iqe_ndsaddr += vram_b_buf1;//video_down_buf[video_down_buf_write&3];
                                mm_num2++;
                            break;

                        case AUDIO_G:
                            cmpdata = audio_buf_write - audio_buf_read;
                            if ((cmpdata != 0) && ((cmpdata &strpcmRingBufBitMask ) ==0))
                            {
#ifdef ENABLE_DEBUG  
                                printf("audio_buf_write full %x,%x,%x,%x \n",audio_buf_write,audio_buf_read,nds_iqe_ret,nds_iqe_ndsaddr);
#endif                                
                                nds_iqe_ndsaddr = audio_buf[(audio_buf_write-1) & strpcmRingBufBitMask];
                            }
                            else
                            {
                                nds_iqe_ndsaddr = audio_buf[audio_buf_write & strpcmRingBufBitMask];
                            }
                            //audio_l_buf_write++;
                            break;
                        //case AUDIO_G:

                    }
                }

               int temp_data;

                switch( nds_iqe_cmd)
                {
                    case 0xc1:
                    case 0xc2:
                        cardcommand_r512n(nds_iqe_cmd,nds_iqe_cpuaddr,nds_iqe_ndsaddr,nds_iqe_len,nds_callback,nds_iqe_ret); 
//                        printf( "%x,%x\n" ,*(vu32*)nds_iqe_ndsaddr ,*(vu32*)(nds_iqe_ndsaddr+4));
                        break;
                    case 0xc0:
                        /*
                        1 audio sample sample_size bit stereo
                        2 video hz? 1/25 size main buf
                        3 cmd num ,cmd offset
                        */
                        for (i=0;i<20;i++ )
                        {
                            int set_cmd =main_buf[4/4  + (i*2)];
                            int set_offset = main_buf[4/4 + 1 + (i*2)];
                            int buf_begin=(int)main_buf;
                            if (set_cmd == 0)break;
                            switch (set_cmd)
                            {
                            case IS_SET_VIDEO:
                                memcpy((void*)&video_set_buf,(void*)(buf_begin + set_offset),sizeof(struct video_set));
                                if (video_set_buf.swap==0)//a up b down
                                {
                                    *(vu16*)0x04000304 |= (1<<15);
                                }
                                else
                                {
                                    *(vu16*)0x04000304 &= ~(1<<15);
                                }
                                enable_video();
#ifdef ENABLE_DEBUG  
                                printf("IS_SET_VIDEO\n");
                                printf("video_enable=%d \n",video_enable);

                                //printf("video_set timer_l_data=%d \n",video_set_buf.timer_l_data);
                                //printf("video_set timer_h_data=%d \n",video_set_buf.timer_h_data);
#endif

                                
                                break;
                            case IS_SET_AUDIO:
                                memcpy((void*)&audio_set_buf,(void*)(buf_begin + set_offset),sizeof(struct audio_set));

                                //SoundDataL.format=(audio_set_buf.sample_bit/8);
                                //SoundDataL.len=audio_set_buf.sample_size * SoundDataL.format;
                                //SoundDataL.rate=audio_set_buf.sample;
                                //SoundDataL.vol=0x7F;
                                //SoundDataL.pan=0;


                                //SoundDataR.format=(audio_set_buf.sample_bit/8);
                                //SoundDataR.len=audio_set_buf.sample_size * SoundDataR.format;
                                //SoundDataR.rate=audio_set_buf.sample;
                                //SoundDataR.vol=0x7F;
                                //SoundDataR.pan=127;

                                //if (audio_set_buf.stereo == 0)
                                //{
                                //    SoundDataL.pan=127/2;
                                //    SoundDataR.pan=127/2;
                                //}
                                //SoundDataL_T.count=1;
                                //memcpy( &SoundDataL_T.data[0], &SoundDataL, sizeof(TransferSoundData) );
                                //SoundDataR_T.count=1;
                                //memcpy( &SoundDataR_T.data[0], &SoundDataR, sizeof(TransferSoundData) );
                                enable_audio();
                                //printf("audio_set timer_l_data=%d \n",audio_set_buf.timer_l_data);
                                //printf("audio_set timer_h_data=%d \n",audio_set_buf.timer_h_data);
                                //printf("audio_set sample_size=%d \n",audio_set_buf.sample_size);
                                //printf("audio_set sample=%d \n",audio_set_buf.sample);
                                //printf("audio_set sample_bit=%d \n",audio_set_buf.sample_bit);
#ifdef ENABLE_DEBUG  
                                printf("IS_SET_AUDIO\n");
#endif
                                break;
                            case IS_SET_ENABLE_VIDEO:
                                video_enable= *(vu32*)(buf_begin+set_offset);
                                enable_video();
                                if (video_enable == 1)
                                {
                                    //fpga_mm1=check_fpga_1();
                                    //fpga_mm2=check_fpga_2();
#ifdef ENABLE_DEBUG  
//                                printf("fpga_mm1=%d\n",fpga_mm1);
//                                printf("fpga_mm2=%d\n",fpga_mm2);
#endif
                                }


                                //if (video_enable == 1)
                                //{
                                //    enable_video();
                                //}
#ifdef ENABLE_DEBUG  
                                printf("video_enable=%d \n",video_enable);
#endif
                                break;

                            case IS_SET_ENABLE_AUDIO:
                                audio_enable= *(vu32*)(buf_begin+set_offset);
                                enable_audio();
                                if (audio_enable == 1)
                                {
                                    //fpga_mm1=check_fpga_1();
                                    //fpga_mm2=check_fpga_2();
#ifdef ENABLE_DEBUG  
//                                printf("fpga_mm1=%d\n",fpga_mm1);
//                                printf("fpga_mm2=%d\n",fpga_mm2);
#endif
                                }
                                //if (audio_enable == 1)
                                //{
                                //    enable_audio();
                                //}
#ifdef ENABLE_DEBUG  
                                printf("audio_enable=%d \n",audio_enable);
#endif
                                break;
                            case IS_SET_ENABLE_KEY:
                                key_enable= *(vu32*)(buf_begin+set_offset);
#ifdef ENABLE_DEBUG  
                                printf("key %d\n",key_enable);
#endif
                                break;
                            case IS_SET_ENABLE_RTC:
                                rtc_enable= *(vu32*)(buf_begin+set_offset);
#ifdef ENABLE_DEBUG  
                                printf("set rtc %d\n",rtc_enable);
#endif
                                break;
                            case IS_SET_CLEAR_VAR:
                                clear_var();
#ifdef ENABLE_DEBUG  
                                printf("clear_var\n");
#endif
                                break;
                            case IS_SET_VOL:
                                temp_data =(((*(vu32*)(buf_begin+set_offset) & 0xff ) <<16) + 
                                            ((*(vu32*)(buf_begin+set_offset +4) & 0xff ) <<8) + 
                                            ((*(vu32*)(buf_begin+set_offset +8) & 0xff ) <<0));
                                IPC8->IPC_ARM9_P1=temp_data;
                                IPC8->IPC_ARM9=IPC_MSG_SETAUDIOVOL;
                                while (IPC8->IPC_ARM9 != IPC_MSG_NONE)
                                {
                                    swiDelay(1);
                                }
#ifdef ENABLE_DEBUG  
                                printf("vol %x\n",temp_data);
#endif
                                break;
                            case IS_SET_BR:
                                //int temp_data;
                                temp_data =*(vu32*)(buf_begin+set_offset);
                                if (temp_data == -1)
                                {
                                    IPC8->IPC_ARM9=IPC_MSG_GET_BRIGHTNESS;
                                    while (IPC8->IPC_ARM9 != IPC_MSG_NONE){swiDelay(1);};
                                    IPC8->IPC_ARM9_P1++;
                                }
                                else
                                {
                                    IPC8->IPC_ARM9_P1=temp_data;
                                }
                                IPC8->IPC_ARM9 = IPC_MSG_SET_BRIGHTNESS;
                                while (IPC8->IPC_ARM9 != IPC_MSG_NONE){swiDelay(1);};
#ifdef ENABLE_DEBUG  
                                printf("IPC8->brightness %d\n",temp_data);
#endif
                                break;
                            case IS_SET_SUSPEND:
#ifdef ENABLE_DEBUG  
                                printf("suspend\n");
#endif
                                IPC8->IPC_ARM9=IPC_MSG_SUSPEND;

                                break;
                            case IS_SET_WAKEUP:
#ifdef ENABLE_DEBUG  
                                printf("wakeup\n");
#endif
                                IPC8->IPC_ARM9=IPC_MSG_WAKEUP;
                                break;
                            case IS_SET_SHUTDOWN:
#ifdef ENABLE_DEBUG  
                                printf("shutdown\n");
#endif
                                IPC8->IPC_ARM9=IPC_MSG_SETSHUTDOWN;
                                while (1);

                                break;

                            case IS_SET_SWAP:
                               temp_data =*(vu32*)(buf_begin+set_offset);
                                video_set_buf.swap=temp_data;
                                if (video_set_buf.swap==0)
                                {
                                    *(vu16*)0x04000304 |= (1<<15);
                                }
                                else
                                {
                                    *(vu16*)0x04000304 &= ~(1<<15);
                                }
#ifdef ENABLE_DEBUG  
                                 printf("set swap=%d\n",temp_data);
#endif
                                break;
                            case IS_SET_BACKLIGHT:
                                IPC8->IPC_ARM9_P1 =*(vu32*)(buf_begin+set_offset);
                                IPC8->IPC_ARM9 = IPC_MSG_SETBACKLIGHT;
                                while (IPC8->IPC_ARM9 != IPC_MSG_NONE){swiDelay(1);}
#ifdef ENABLE_DEBUG  
                                printf("set backlight %d\n",IPC8->IPC_ARM9_P1);
#endif
                                break;


                            case IS_RUN_Homebrew:
#ifdef ENABLE_DEBUG  
                                printf("IS_RUN_Homebrew\n");
#endif


                                read_set_512(0x2000000);
                                loadRom();
                                break;


                            case IS_RUN_JZHomebrew:

#ifdef ENABLE_DEBUG  
                                printf("IS_RUN_JzHomebrew run\n");
#endif
                                
															   REG_IME = 0;
															   REG_IE = 0;
															   REG_IF = ~0;
																 DC_FlushAll();    
															  int iqqq;
															  iqqq= (int)&arm9_reset_code;
															  *(vu32*)0x27ffdf4 = *(vu32*)(iqqq + 0);
															  *(vu32*)0x27ffdf8 = *(vu32*)(iqqq + 4);
															  *(vu32*)0x27ffdfc = *(vu32*)(iqqq + 8);
															  *(vu32*)0x27FFE24 = 0x27ffdf8;
															
															    WAIT_CR = 0xe880;
															    IPC8->IPC_ARM9 = IPC_MSG_BOOT_PLUGIN;
															
															    while( IPC8->IPC_ARM9 != IPC_MSG_NONE ) {
															        swiDelay(1);
															    }
															
															    IC_InvalidateAll();
															    DC_FlushAll();
															    DC_InvalidateAll();
															    swiSoftReset();	
                                  break;

/*
                            case IS_SET_TXTB:
#ifdef ENABLE_DEBUG  
                                printf("IS_RUN_JzHomebrew\n");
#endif
                                set_txt(*(vu32*)(buf_begin+set_offset),
                                        *(vu32*)(buf_begin+set_offset +4),
                                        *(vu32*)(buf_begin+set_offset +8),
                                        *(vu32*)(buf_begin+set_offset +12),
                                        *(vu32*)(buf_begin+set_offset +16),
                                        *(vu32*)(buf_begin+set_offset +20),
                                        *(vu32*)(buf_begin+set_offset +24)
                                        );

                            break;
*/
                             case IS_WRITE_IO:
#ifdef ENABLE_DEBUG  
                                printf("write io\n");
#endif
                                int temp_addr;
                                int temp_var;
                                while (1)
                                {
                                    temp_addr=*(vu32*)(buf_begin+set_offset);
                                    if (temp_addr == 0)
                                    {
                                        break;
                                    }
                                    set_offset += 4;
                                    temp_var = *(vu32*)(buf_begin+set_offset);
                                    *(u16*)temp_addr = temp_var & 0xffff;
                                    set_offset += 4;
                                    if ((buf_begin + set_offset ) >= ((u32)&main_buf[512/4]))
                                    {
                                        break;
                                    }
                                }
                                break;
                            }

                        }
                        break;


                    default:
                        break;
                }
                if ((nds_iqe_cmd ==0xc1)||(nds_iqe_cmd ==0xc2))
                {
                    switch (nds_iqe_type)
                    {
                        case VIDEO_UP:
                            break;
                        case VIDEO_DOWN:
                            break;

                        case AUDIO_G:
                            if ((cmpdata == 0) || ((cmpdata &strpcmRingBufBitMask ) !=0))//not full
                            {
                                audio_buf_write++;
                            }
                            break;

                    }
                }

        }
        
        u32 tempw,tempr;
        if (audio_enable == 1)
        {
            tempw=audio_buf_write;
            tempr=audio_buf_read;
            if ((tempw != audio_buf_write_old) || (tempr != audio_buf_read_old))
            {
                cardcommand_r4_num(0xc4,tempw,tempr,2);
                audio_buf_write_old=tempw;
                audio_buf_read_old=tempr;
            }
        }

#ifdef ENABLE_DEBUG  
   
        scanKeys();
        if ((keysDown() & KEY_Y) !=0 && (keysHeld() & KEY_L) !=0)
        {
            if (debug_b == true)
            {
                set_b_mode(b_mode_buf1);
            }
            else
            {
                set_b_mode(b_mode_debug);

                printf("\n\nzj_list=%x ",zj_list);
                printf("LINE_iqe=%x,%x ",CARD_LINE_iqe_w,CARD_LINE_iqe_r);
                //printf("up_buf=%x,%x ",video_up_buf_write,video_up_buf_read);
                //printf("down_buf=%x,%x ",video_down_buf_write,video_down_buf_read);
                printf("audio_buf=%x,%x ",audio_buf_write,audio_buf_read);
                printf("v a key rtc=%x,%x,%x,%x\n",video_enable,audio_enable,key_enable,rtc_enable);
                printf("i=%x\n",*(vu16*)0x4000208);
                if (IPC->temperature > (60 * 0x1000))
                {
                    printf("is ndsi\n");
                }
                else
                {
                    printf("is nds\n");

                }
                printf("fpga_mm1=%d\n",fpga_mm1);
                printf("fpga_mm2=%d\n",fpga_mm2);

                
            }


        }
        if ((keysDown() & KEY_X) !=0 && (keysHeld() & KEY_L) !=0)
        {
            if (debug_a == true)
            {
                set_a_mode(a_mode_buf1);
            }
            else
            {
                set_a_mode(a_mode_debug);
            }
        }
     
        if ((keysDown() & KEY_R) !=0 && (keysHeld() & KEY_L) !=0)
        {
            jz_debug();
        }

#endif




#ifdef ENABLE_DEBUG  
        if ((arm7strwrite != arm7strread)&& (arm7debug_wait == 1))
        {
            arm7debug_wait=0;
            i=arm7strwrite - arm7strread;
            for (int j=0;j<i ;j++ )
            {
                int jj=(((arm7strread & arm7strindexmask)*4) + arm7strindexaddr);
               _consolePrint( (char*)(*(vu32*)jj));
                arm7strread++;
            }
        }

#endif

        if (( key_enable ==1) && (waitflag == 1))
        {
            waitflag=0;
            update_input();

            write_key = false;
            if (keys_old != keys)
            {
                    keys_old = keys;
                    write_key=true;
            }
            if ((touchPostemp.x != touchPos_old.x)||(touchPostemp.y != touchPos_old.y))
            {
                touchPos_old=touchPostemp;
                write_key=true;
            }
            if (write_key == true )
            {
                tempw=(IPC8->brightness & 3);//2
                tempw |= ((*(vu16*)0x4000304 >>15) <<2);//1
                tempw |= (((IPC8->Powermanagement >> 2) &3)<<3);//2
                if (IPC->temperature > (60 * 0x1000))
                {
                    tempw |= ((1)<<5);//1
                }
                if (fpga_mm1 == 0)
                {
                    tempw |= ((1)<<6);//1
                }
                if (fpga_mm2 == 0)
                {
                    tempw |= ((1)<<7);//1
                }


                cardcommand_r4_key(0xc3,touchPostemp.px,touchPostemp.py,keys,tempw &0xff);
            }
        }
        if (( rtc_enable ==1) && (time_seconds_old != curtime[7]))
        {
            time_seconds_old = curtime[7];
            cardcommand_r4_rtc(0xc5,(u32)&curtime[1]);
        }

//mm
/*
        if (mm_num1 > 0x20)
        {
            fpga_mm1=check_fpga_1();
            mm_num1=0;
        }
        if (mm_num2 > 0x20)
        {
            fpga_mm2=check_fpga_2();
            mm_num2=0;
        }
*/
    }


}
