|
|
|
#include <gba_console.h> |
|
#include <gba_video.h> |
|
#include <gba_interrupt.h> |
|
#include <gba_systemcalls.h> |
|
#include <gba.h> |
|
|
|
#include <stdio.h> |
|
|
|
enum NorS71InfoOffset |
|
{ |
|
NOR_S71_INFO_OFFSET_SAVE = 0x790000, |
|
NOR_S71_INFO_OFFSET_NOR = 0x7A0000, |
|
NOR_S71_INFO_OFFSET_SET = 0x7B0000, |
|
}; |
|
|
|
enum NorS71SetInfo |
|
{ |
|
NOR_S71_SET_INFO_LANG = NOR_S71_INFO_OFFSET_SET + (0 * 2), |
|
NOR_S71_SET_INFO_RESET = NOR_S71_INFO_OFFSET_SET + (1 * 2), |
|
NOR_S71_SET_INFO_RTS = NOR_S71_INFO_OFFSET_SET + (2 * 2), |
|
NOR_S71_SET_INFO_SLEEP = NOR_S71_INFO_OFFSET_SET + (3 * 2), |
|
NOR_S71_SET_INFO_CHEAT = NOR_S71_INFO_OFFSET_SET + (4 * 2), |
|
NOR_S71_SET_INFO_SLEEP_KEY0 = NOR_S71_INFO_OFFSET_SET + (5 * 2), |
|
NOR_S71_SET_INFO_SLEEP_KEY1 = NOR_S71_INFO_OFFSET_SET + (6 * 2), |
|
NOR_S71_SET_INFO_SLEEP_KEY2 = NOR_S71_INFO_OFFSET_SET + (7 * 2), |
|
NOR_S71_SET_INFO_MENU_KEY0 = NOR_S71_INFO_OFFSET_SET + (8 * 2), |
|
NOR_S71_SET_INFO_MENU_KEY1 = NOR_S71_INFO_OFFSET_SET + (9 * 2), |
|
NOR_S71_SET_INFO_MENU_KEY2 = NOR_S71_INFO_OFFSET_SET + (10 * 2), |
|
NOR_S71_SET_INFO_ENGINE = NOR_S71_INFO_OFFSET_SET + (11 * 2), |
|
NOR_S71_SET_INFO_SHOW_THUMBNAIL = NOR_S71_INFO_OFFSET_SET + (12 * 2), |
|
NOR_S71_SET_INFO_RTC_OPEN_STATUS = NOR_S71_INFO_OFFSET_SET + (13 * 2), |
|
|
|
// DE setting |
|
NOR_S71_SET_INFO_AUTO_SAVE_SEL = NOR_S71_INFO_OFFSET_SET + (14 * 2), |
|
NOR_S71_SET_INFO_MODE_B_INIT = NOR_S71_INFO_OFFSET_SET + (15 * 2), |
|
NOR_S71_SET_INFO_LED_OPEN_SEL = NOR_S71_INFO_OFFSET_SET + (16 * 2), |
|
NOR_S71_SET_INFO_BREATHING_R = NOR_S71_INFO_OFFSET_SET + (17 * 2), |
|
NOR_S71_SET_INFO_BREATHING_G = NOR_S71_INFO_OFFSET_SET + (18 * 2), |
|
NOR_S71_SET_INFO_BREATHING_B = NOR_S71_INFO_OFFSET_SET + (19 * 2), |
|
NOR_S71_SET_INFO_SD_R = NOR_S71_INFO_OFFSET_SET + (20 * 2), |
|
NOR_S71_SET_INFO_SD_G = NOR_S71_INFO_OFFSET_SET + (21 * 2), |
|
NOR_S71_SET_INFO_SD_B = NOR_S71_INFO_OFFSET_SET + (22 * 2), |
|
}; |
|
|
|
// some of these addr are labled as unknown but that's not entierly true |
|
// i just don't know of an appropriate name to give them. |
|
// most of the unk are part of a sequence to r/w to a device |
|
// such as the sd card, fpga or spi. |
|
enum RegAddr |
|
{ |
|
UNK0 = 0x9FE0000, // writes always 0xD200 |
|
UNK1 = 0x8000000, // writes always 0x1500 |
|
UNK2 = 0x8020000, // writes always 0xD200 |
|
UNK3 = 0x8040000, // writes always 0x1500 |
|
|
|
// i think this is used to flush pending data to sd card |
|
UNK5 = 0x9FC0000, // writes always 0x1500 |
|
|
|
SD_RESPONSE = 0x9E00000, |
|
|
|
SD_CONTROL = 0x9400000, |
|
BUFFER_CONTROL = 0x9420000, // (A1) |
|
ROMPAGE = 0x9880000, // (C4) |
|
PS_RAMPAGE = 0x9860000, // (C3) |
|
RAMPAGE = 0x9C00000, // (E0) |
|
SPI_CONTROL = 0x9660000, |
|
SPI_WRITE = 0x9680000, |
|
RTC_STATUS = 0x96A0000, |
|
AUTO_SAVE_MODE = 0x96C0000, |
|
|
|
// DE stuff |
|
LED_CONTROL = 0x96E0000, |
|
RUMBLE_CONTROL = 0x9E20000, |
|
ROM64_FLAG = 0x9700000, // ??? |
|
|
|
SD_ADDR_LOW = 0x9600000, // low 16 bits |
|
SD_ADDR_HIGH = 0x9620000, // upper 16 bits |
|
SD_BLOCKS = 0x9640000, // number of blocks to transfer |
|
|
|
// this is used for many things depending on spi control |
|
// is spi control is enabled then this is used for fpga version |
|
// otherwise, it is used for ??? |
|
FPGA_VER = 0x9E00000, |
|
|
|
FLASH_BASE_S71 = 0x08000000, // writes always 0xF0 |
|
FLASH_BASE_S71_END = 0x087FFFFF, |
|
|
|
FLASH_BASE_S98 = 0x09000000, // writes always 0xF0 |
|
FLASH_BASE_S98_END = 0x097FFFFF, |
|
|
|
SET_INFO_LANG = 0x08000000 + NOR_S71_SET_INFO_LANG, |
|
SET_INFO_RESET = 0x08000000 + NOR_S71_SET_INFO_RESET, |
|
SET_INFO_RTS = 0x08000000 + NOR_S71_SET_INFO_RTS, |
|
SET_INFO_SLEEP = 0x08000000 + NOR_S71_SET_INFO_SLEEP, |
|
SET_INFO_CHEAT = 0x08000000 + NOR_S71_SET_INFO_CHEAT, |
|
SET_INFO_SLEEP_KEY0 = 0x08000000 + NOR_S71_SET_INFO_SLEEP_KEY0, |
|
SET_INFO_SLEEP_KEY1 = 0x08000000 + NOR_S71_SET_INFO_SLEEP_KEY1, |
|
SET_INFO_SLEEP_KEY2 = 0x08000000 + NOR_S71_SET_INFO_SLEEP_KEY2, |
|
SET_INFO_MENU_KEY0 = 0x08000000 + NOR_S71_SET_INFO_MENU_KEY0, |
|
SET_INFO_MENU_KEY1 = 0x08000000 + NOR_S71_SET_INFO_MENU_KEY1, |
|
SET_INFO_MENU_KEY2 = 0x08000000 + NOR_S71_SET_INFO_MENU_KEY2, |
|
SET_INFO_ENGINE = 0x08000000 + NOR_S71_SET_INFO_ENGINE, |
|
SET_INFO_SHOW_THUMBNAIL = 0x08000000 + NOR_S71_SET_INFO_SHOW_THUMBNAIL, |
|
SET_INFO_RTC_OPEN_STATUS = 0x08000000 + NOR_S71_SET_INFO_RTC_OPEN_STATUS, |
|
|
|
// DE |
|
SET_INFO_AUTO_SAVE_SEL = 0x08000000 + NOR_S71_SET_INFO_AUTO_SAVE_SEL, |
|
SET_INFO_MODE_B_INIT = 0x08000000 + NOR_S71_SET_INFO_MODE_B_INIT, |
|
SET_INFO_LED_OPEN_SEL = 0x08000000 + NOR_S71_SET_INFO_LED_OPEN_SEL, |
|
SET_INFO_BREATHING_R = 0x08000000 + NOR_S71_SET_INFO_BREATHING_R, |
|
SET_INFO_BREATHING_G = 0x08000000 + NOR_S71_SET_INFO_BREATHING_G, |
|
SET_INFO_BREATHING_B = 0x08000000 + NOR_S71_SET_INFO_BREATHING_B, |
|
SET_INFO_SD_R = 0x08000000 + NOR_S71_SET_INFO_SD_R, |
|
SET_INFO_SD_G = 0x08000000 + NOR_S71_SET_INFO_SD_G, |
|
SET_INFO_SD_B = 0x08000000 + NOR_S71_SET_INFO_SD_B, |
|
|
|
RTC_DATA = 0x080000C4, |
|
RTC_RW = 0x080000C6, |
|
RTC_ENABLE = 0x080000C8, |
|
// this is unused in ezflash kernel |
|
// todo: debug on hw what the output of |
|
// polling this register is! |
|
RTC_CART_NAME = 0x080000A0, |
|
}; |
|
|
|
void IWRAM_CODE SetRompage(u16 page) |
|
{ |
|
*(vu16 *)0x9fe0000 = 0xd200; |
|
*(vu16 *)0x8000000 = 0x1500; |
|
*(vu16 *)0x8020000 = 0xd200; |
|
*(vu16 *)0x8040000 = 0x1500; |
|
*(vu16 *)0x9880000 = page;//C4 |
|
*(vu16 *)0x9fc0000 = 0x1500; |
|
} |
|
|
|
void IWRAM_CODE SetSPIControl(u16 control) |
|
{ |
|
*(u16 *)0x9fe0000 = 0xd200; |
|
*(u16 *)0x8000000 = 0x1500; |
|
*(u16 *)0x8020000 = 0xd200; |
|
*(u16 *)0x8040000 = 0x1500; |
|
*(u16 *)SPI_WRITE = control; |
|
*(u16 *)0x9fc0000 = 0x1500; |
|
} |
|
// -------------------------------------------------------------------- |
|
void IWRAM_CODE SPI_Enable(void) |
|
{ |
|
SetSPIControl(1); |
|
} |
|
// -------------------------------------------------------------------- |
|
void IWRAM_CODE SPI_Disable(void) |
|
{ |
|
SetSPIControl(0); |
|
} |
|
|
|
void IWRAM_CODE clrs() |
|
{ |
|
printf("\x1b[2J\n"); |
|
} |
|
|
|
char game_name[17] = {0}; |
|
|
|
vu16 v0x9fe0000 = 0; |
|
vu16 vSD_CONTROL = 0; |
|
vu16 vBUFFER_CONTROL = 0; |
|
vu16 vROMPAGE = 0; |
|
vu16 vPS_RAMPAGE = 0; |
|
vu16 vRAMPAGE = 0; |
|
vu16 vSPI_CONTROL = 0; |
|
vu16 vSPI_WRITE = 0; |
|
vu16 vRTC_STATUS = 0; |
|
vu16 vAUTO_SAVE_MODE = 0; |
|
vu16 vSD_ADDR_LOW = 0; |
|
vu16 vSD_ADDR_HIGH = 0; |
|
vu16 vSD_BLOCKS = 0; |
|
|
|
vu16 vFPGA_VER = 0; |
|
vu16 vSET_INFO_LANG = 0; |
|
vu16 vSET_INFO_RESET = 0; |
|
vu16 vSET_INFO_RTS = 0; |
|
vu16 vSET_INFO_SLEEP = 0; |
|
vu16 vSET_INFO_CHEAT = 0; |
|
vu16 vSET_INFO_SLEEP_KEY0 = 0; |
|
vu16 vSET_INFO_SLEEP_KEY1 = 0; |
|
vu16 vSET_INFO_SLEEP_KEY2 = 0; |
|
vu16 vSET_INFO_MENU_KEY0 = 0; |
|
vu16 vSET_INFO_MENU_KEY1 = 0; |
|
vu16 vSET_INFO_MENU_KEY2 = 0; |
|
vu16 vSET_INFO_ENGINE = 0; |
|
vu16 vSET_INFO_SHOW_THUMBNAIL = 0; |
|
vu16 vSET_INFO_RTC_OPEN_STATUS = 0; |
|
|
|
void IWRAM_CODE update_regs() |
|
{ |
|
for (int i = 0; i < 16; i++) |
|
{ |
|
game_name[i] = *(vu8*)(0x8000000+160+i); |
|
} |
|
|
|
game_name[16] = '\0'; |
|
|
|
SPI_Enable(); |
|
vFPGA_VER = *(vu16*)FPGA_VER; |
|
SPI_Disable(); |
|
|
|
vSET_INFO_LANG = *(vu16*)SET_INFO_LANG; |
|
vSET_INFO_RESET = *(vu16*)SET_INFO_RESET; |
|
vSET_INFO_RTS = *(vu16*)SET_INFO_RTS; |
|
vSET_INFO_SLEEP = *(vu16*)SET_INFO_SLEEP; |
|
vSET_INFO_CHEAT = *(vu16*)SET_INFO_CHEAT; |
|
vSET_INFO_SLEEP_KEY0 = *(vu16*)SET_INFO_SLEEP_KEY0; |
|
vSET_INFO_SLEEP_KEY1 = *(vu16*)SET_INFO_SLEEP_KEY1; |
|
vSET_INFO_SLEEP_KEY2 = *(vu16*)SET_INFO_SLEEP_KEY2; |
|
vSET_INFO_MENU_KEY0 = *(vu16*)SET_INFO_MENU_KEY0; |
|
vSET_INFO_MENU_KEY1 = *(vu16*)SET_INFO_MENU_KEY1; |
|
vSET_INFO_MENU_KEY2 = *(vu16*)SET_INFO_MENU_KEY2; |
|
vSET_INFO_ENGINE = *(vu16*)SET_INFO_ENGINE; |
|
vSET_INFO_SHOW_THUMBNAIL = *(vu16*)SET_INFO_SHOW_THUMBNAIL; |
|
vSET_INFO_RTC_OPEN_STATUS = *(vu16*)SET_INFO_RTC_OPEN_STATUS; |
|
|
|
v0x9fe0000 = *(vu16*)0x9fe0000; |
|
vSD_CONTROL = *(vu16*)SD_CONTROL; |
|
vBUFFER_CONTROL = *(vu16*)BUFFER_CONTROL; |
|
vROMPAGE = *(vu16*)ROMPAGE; |
|
vPS_RAMPAGE = *(vu16*)PS_RAMPAGE; |
|
vRAMPAGE = *(vu16*)RAMPAGE; |
|
vSPI_CONTROL = *(vu16*)SPI_CONTROL; |
|
vSPI_WRITE = *(vu16*)SPI_WRITE; |
|
vRTC_STATUS = *(vu16*)RTC_STATUS; |
|
vAUTO_SAVE_MODE = *(vu16*)AUTO_SAVE_MODE; |
|
|
|
vSD_ADDR_LOW = *(vu16*)SD_ADDR_LOW; |
|
vSD_ADDR_HIGH = *(vu16*)SD_ADDR_HIGH; |
|
vSD_BLOCKS = *(vu16*)SD_BLOCKS; |
|
} |
|
|
|
void IWRAM_CODE log_reg() |
|
{ |
|
printf("idk: 0x%04X\n", v0x9fe0000); |
|
printf("SD_CONTROL: 0x%04X\n", vSD_CONTROL); |
|
printf("BUFFER_CONTROL: 0x%04X\n", vBUFFER_CONTROL); |
|
printf("ROMPAGE: 0x%04X\n", vROMPAGE); |
|
printf("PS_RAMPAGE: 0x%04X\n", vPS_RAMPAGE); |
|
printf("RAMPAGE: 0x%04X\n", vRAMPAGE); |
|
printf("SPI_CONTROL: 0x%04X\n", vSPI_CONTROL); |
|
printf("SPI_WRITE: 0x%04X\n", vSPI_WRITE); |
|
printf("RTC_STATUS: 0x%04X\n", vRTC_STATUS); |
|
printf("AUTO_SAVE_MODE: 0x%04X\n", vAUTO_SAVE_MODE); |
|
printf("SD_ADDR_LOW: 0x%04X\n", vSD_ADDR_LOW); |
|
printf("SD_ADDR_HIGH: 0x%04X\n", vSD_ADDR_HIGH); |
|
printf("SD_BLOCKS: 0x%04X\n", vSD_BLOCKS); |
|
printf("game_name: %s\n", game_name); |
|
} |
|
|
|
void IWRAM_CODE log_set() |
|
{ |
|
printf("FPGA_VER: 0x%04X\n", vFPGA_VER); |
|
printf("SET_INFO_LANG: 0x%04X\n", vSET_INFO_LANG); |
|
printf("SET_INFO_RESET: 0x%04X\n", vSET_INFO_RESET); |
|
printf("SET_INFO_RTS: 0x%04X\n", vSET_INFO_RTS); |
|
printf("SET_INFO_SLEEP: 0x%04X\n", vSET_INFO_SLEEP); |
|
printf("SET_INFO_CHEAT: 0x%04X\n", vSET_INFO_CHEAT); |
|
printf("SET_INFO_SLEEP_KEY0: 0x%04X\n", vSET_INFO_SLEEP_KEY0); |
|
printf("SET_INFO_SLEEP_KEY1: 0x%04X\n", vSET_INFO_SLEEP_KEY1); |
|
printf("SET_INFO_SLEEP_KEY2: 0x%04X\n", vSET_INFO_SLEEP_KEY2); |
|
printf("SET_INFO_MENU_KEY0: 0x%04X\n", vSET_INFO_MENU_KEY0); |
|
printf("SET_INFO_MENU_KEY1: 0x%04X\n", vSET_INFO_MENU_KEY1); |
|
printf("SET_INFO_MENU_KEY2: 0x%04X\n", vSET_INFO_MENU_KEY2); |
|
printf("SET_INFO_ENGINE: 0x%04X\n", vSET_INFO_ENGINE); |
|
printf("SET_INFO_SHOW_THUMBNAIL: 0x%04X\n", vSET_INFO_SHOW_THUMBNAIL); |
|
printf("SET_INFO_RTC_OPEN_STATUS: 0x%04X\n", vSET_INFO_RTC_OPEN_STATUS); |
|
} |
|
|
|
void IWRAM_CODE wait_vblank() |
|
{ |
|
while (*(vu16*)0x04000006 != 160); |
|
} |
|
|
|
void IWRAM_CODE loop() |
|
{ |
|
#if 0 |
|
RESET_EWRAM = (1<<0), /*!< Clear 256K on-board WRAM */ |
|
RESET_IWRAM = (1<<1), /*!< Clear 32K in-chip WRAM */ |
|
RESET_PALETTE = (1<<2), /*!< Clear Palette */ |
|
RESET_VRAM = (1<<3), /*!< Clear VRAM */ |
|
RESET_OAM = (1<<4), /*!< Clear OAM */ |
|
RESET_SIO = (1<<5), /*!< Switches to general purpose mode */ |
|
RESET_SOUND = (1<<6), /*!< Reset Sound registers */ |
|
RESET_OTHER = (1<<7) /*!< all other registers */ |
|
#endif |
|
|
|
while (1) { |
|
scanKeys(); |
|
u16 keys = keysDown(); |
|
if (keys & KEY_SELECT) |
|
{ |
|
clrs(); |
|
printf("BOOTLOADER\n"); |
|
REG_IME = 0; |
|
SetRompage(0x8000); |
|
wait_vblank(); |
|
update_regs(); |
|
SetRompage(0x200); |
|
REG_IME = 1; |
|
printf("DID BOOTLOADER\n"); |
|
} |
|
if (keys & KEY_L) |
|
{ |
|
clrs(); |
|
REG_IME = 0; |
|
printf("KERNEL\n"); |
|
SetRompage(0x8002); |
|
wait_vblank(); |
|
update_regs(); |
|
SetRompage(0x200); |
|
REG_IME = 1; |
|
printf("DID KERNEL\n"); |
|
} |
|
if (keys & KEY_A) |
|
{ |
|
clrs(); |
|
printf("RELOGGING REG\n\n"); |
|
log_reg(); |
|
} |
|
if (keys & KEY_B) |
|
{ |
|
clrs(); |
|
printf("RELOGGING SET\n\n"); |
|
log_set(); |
|
} |
|
if (keys & KEY_R) |
|
{ |
|
clrs(); |
|
printf("OS MODE AND THEN GAMEMODE\n"); |
|
REG_IME = 0; |
|
SetRompage(0x8000); |
|
wait_vblank(); |
|
update_regs(); |
|
SetRompage(0x200); |
|
REG_IME = 1; |
|
printf("GAMEMODE\n"); |
|
} |
|
if (keys & KEY_UP) |
|
{ |
|
clrs(); |
|
printf("changing to nor\n"); |
|
REG_IME = 0; |
|
SetRompage(0x0); |
|
wait_vblank(); |
|
update_regs(); |
|
SetRompage(0x200); |
|
REG_IME = 1; |
|
printf("GAMEMODE\n"); |
|
} |
|
if (keys & KEY_DOWN) |
|
{ |
|
update_regs(); |
|
} |
|
VBlankIntrWait(); |
|
} |
|
} |
|
|
|
//--------------------------------------------------------------------------------- |
|
// Program entry point |
|
//--------------------------------------------------------------------------------- |
|
int main(void) { |
|
//--------------------------------------------------------------------------------- |
|
|
|
// the vblank interrupt must be enabled for VBlankIntrWait() to work |
|
// since the default dispatcher handles the bios flags no vblank handler |
|
// is required |
|
irqInit(); |
|
irqEnable(IRQ_VBLANK); |
|
consoleDemoInit(); |
|
|
|
/* |
|
reading via ezflash kernel: |
|
|
|
idk = 0xE832 |
|
SD_CONTROL = 0x682A |
|
BUFFER_CONTROL = 0x6A09 |
|
ROMPAGE = 0x0095 |
|
PS_RAMPAGE = 0x4005 |
|
RAMPAGE = 0x5209 |
|
SPI_CONTROL = 0x9C04 |
|
SPI_WRITE = 0x4ED4 |
|
RTC_STATUS = 0x42D5 |
|
AUTO_SAVE_MODE = 0x8245 |
|
*/ |
|
|
|
#if 0 |
|
// ansi escape sequence to clear screen and home cursor |
|
// /x1b[line;columnH |
|
printf("\x1b[2J\n"); |
|
|
|
printf("\n\n"); |
|
|
|
// ansi escape sequence to set print co-ordinates |
|
// /x1b[line;columnH |
|
printf("\x1b[10;10HHello World!\n"); |
|
|
|
// ansi escape sequence to move cursor up |
|
// /x1b[linesA |
|
printf("\x1b[10ALine 0\n"); |
|
|
|
// ansi escape sequence to move cursor left |
|
// /x1b[columnsD |
|
printf("\x1b[28DColumn 0\n"); |
|
|
|
// ansi escape sequence to move cursor down |
|
// /x1b[linesB |
|
printf("\x1b[19BLine 19\n"); |
|
|
|
// ansi escape sequence to move cursor right |
|
// /x1b[columnsC |
|
printf("\x1b[5CColumn 20\n"); |
|
#endif |
|
|
|
printf("Hello world :)\n\n"); |
|
|
|
loop(); |
|
return 0; |
|
} |