// // Test program for GBA devkitadv // // 型情報 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef signed char s8; typedef signed short s16; typedef signed long s32; // 制御レジスタ情報 #define VRAMTOP (u16*)0x6000000 // VRAM frame buffer top address #define MAPTOP0 (u16*)0x6004000 // MAP buffer top address #define PALETTE (u16*)0x5000000 // PALETTE buffer top address #define register(p) *((u16*) p) // I/O register handling macro // コントロールレジスタ #define LCD_CTRL 0x04000000 // LCD control #define BG0CNT 0x04000008 // BG0 control #define BG1CNT 0x0400000a // BG1 control #define COM_BUF32_L 0x04000120 #define COM_BUF32_H 0x04000122 #define COM_CTRL 0x04000128 // COM control #define COM_BUF8 0x0400012A #define KEY_INPUT 0x04000130 // 画面モード #define LCD_BGMODE0 0x0000 // BG mode 0 // 有効な背景 #define LCD_BG0EN 0x0100 // Enable BG0 // 背景表示優先度 #define BG_PRIORITY_HIGHEST 0x0000 #define BG_PRIORITY_HIGH 0x0001 #define BG_PRIORITY_NORMAL 0x0002 #define BG_PRIORITY_LOW 0x0003 // 背景用 VRAM アドレス #define BG_VRAM0 0x0000 // 0x06000000- // パレット選択 #define BG_PALETTE16 0x0000 // 16 colors * 16 palettes #define BG_PALETTE1 0x0080 // 256 colors * 1 palette // 背景用 MAP アドレス #define BG_MAP08 0x0800 // 0x06004000- #define BG_MAP09 0x0900 // 0x004800- // 背景サイズ #define BG_SIZE0 0x0000 // Tile 256*256 // Scale 128*128 #define RGB(r, g, b) (((b) << 10) + ((g) << 5) + (r)) #define KEY_A 0x0001 #define KEY_B 0x0002 #define KEY_SELECT 0x0004 #define KEY_START 0x0008 #define KEY_RIGHT 0x0010 #define KEY_LEFT 0x0020 #define KEY_UP 0x0040 #define KEY_DOWN 0x0080 #define KEY_R 0x0100 #define KEY_L 0x0200 #define KEY_INTEN 0x4000 #define KEY_INTAND 0x8000 // 通信用 #define COM_EXTERNAL 0x0000 #define COM_INTERNAL 0x0001 #define COM_256KHZ 0x0000 #define COM_2MHZ 0x0002 #define COM_SETSI 0x0004 #define COM_SETSO 0x0008 #define COM_SETSB 0x0080 #define COM_SEND8 0x0000 #define COM_SEND32 0x1000 #define COM_INTEN 0x4000 #define COM_MASTER 0x00 #define COM_SLAVE 0x01 // マルチブート指定 int __gba_multiboot = 0; // 押し続けによる連続入力を防止する u32 get_key(u32 key_value){ static u32 key_wok; if(!(*(volatile u32*)KEY_INPUT & key_value)){ if((key_wok & key_value) == 0){ key_wok |= key_value; return 1; } } else{ key_wok &= ~key_value; } return 0; } void WaitForVsync(void) { while(*(volatile u16*)0x4000006 >= 160){}; while(*(volatile u16*)0x4000006 < 160){}; } // メインプログラム int main(void) { int i; u8 com_flag; u16 own_state, opposite_state, key, com, com_buf; u16* vram = VRAMTOP; u16* map0 = MAPTOP0; u16* palette = PALETTE; // 画面モードの初期化 register(LCD_CTRL) = LCD_BG0EN | LCD_BGMODE0; // 背景 0 の初期化 register(BG0CNT) = BG_SIZE0 | BG_MAP08 | BG_VRAM0 | BG_PRIORITY_NORMAL; // パレットへの登録 palette[0] = RGB(31, 31, 31); palette[1] = RGB(31, 0, 0); palette[2] = RGB(0, 0, 31); // タイル 0 for(i = 0; i < 16; i++){vram[i] = 0x0000;} // タイル 1 for(i = 16; i < 32; i++){vram[i] = 0x1111;} // タイル2 for(i = 32; i < 48; i++){vram[i] = 0x2222;} // マップへタイルを配置 for(i = 0; i < 32 * 32; i++){map0[i] = 0x0000;} // 通信の初期化 register(0x04000134) &= 0x7FFF; register(COM_CTRL) &= ~COM_SETSB; // マスター、スレーブ決定 while(1){ key = register(KEY_INPUT); if((key & 0xC3FF) == 0xC3FF)continue; key = key ^ 0xC3FF; if(key & KEY_A){ // マスター register(COM_CTRL) |= (COM_SEND32 | COM_INTERNAL); com_buf = COM_MASTER; break; } else if(key & KEY_B){ // スレーブ register(COM_CTRL) |= (COM_SEND32 | COM_EXTERNAL); com_buf = COM_SLAVE; break; } } register(COM_CTRL) |= COM_SETSB; // 無限ループ while(1){ // キー入力 key = register(KEY_INPUT); key = key ^ 0xC3FF; if(get_key(KEY_A)){ own_state = 0; } else if(get_key(KEY_B)){ own_state = 1; } // 送信データをセット register(COM_BUF32_L) = own_state; if(com_flag == COM_MASTER){ // SI がクリアされるのを待機 while(1){ com = register(COM_CTRL); com ^= COM_SETSI; if(com & COM_SETSI)break; } // スタートビットをオン register(COM_CTRL) |= COM_SETSB; // スタートビットがクリアされるのを待機 while(1){ com = register(COM_CTRL); com ^= COM_SETSB; if(com & COM_SETSB)break; } } else if(com_flag == COM_SLAVE){ // スタートビットをオンにして SO をクリア register(COM_CTRL) |= COM_SETSB; register(COM_CTRL) &= ~COM_SETSO; // スタートビットがクリアされるのを待機 while(1){ com = register(COM_CTRL); com ^= COM_SETSB; if(com & COM_SETSB)break; } // SO をオン register(COM_CTRL) |= COM_SETSO; } // 受信データを受け取る opposite_state = register(COM_BUF32_L); // 表示 if(own_state == 0){ map0[0] = 0x0001; } else if(own_state == 1){ map0[0] = 0x0002; } if(opposite_state == 0){ map0[1] = 0x0001; } else if(opposite_state == 1){ map0[1] = 0x0002; } // Vブランクまで待機 WaitForVsync(); } }