#include #include #include #include #include #include #include #include #include #include #include static int switches = 0; static int menus = 0; static void switch_function(void) { switches++; } //--- // Saved system context visualizer //--- void *driver_ctx(char const *name) { extern gint_driver_t bdrv, edrv; for(gint_driver_t *drv = &bdrv; drv < &edrv; drv++) { if(!strcmp(drv->name, name)) return drv->sys_ctx; } return NULL; } #ifdef FX9860G static void ctx_tmu() { tmu_t *t = driver_ctx("TMU"); uint8_t *TSTR = (void *)t + 3 * sizeof(tmu_t) + 6 * sizeof(etmu_t); for(int i = 0; i < 3; i++, t++) { row_print(2*i+1, 1, "TMU%d=%d CNT:%08x", i, (*TSTR & (1 << i)) != 0, t->TCNT); row_print(2*i+2, 1, "TCR:%04x COR:%08x", t->TCR.word, t->TCOR); } } static void ctx_dd() { uint8_t *STRD = driver_ctx("T6K11"); row_print(1, 1, "STRD:%02x", *STRD); row_print(2, 2, "RESET:%d", (*STRD & 0x08) != 0); row_print(3, 2, "N/F:%d", (*STRD & 0x04) != 0); row_print(4, 2, "X/Y:%d", (*STRD & 0x02) != 0); row_print(5, 2, "U/D:%d", (*STRD & 0x01) != 0); } static void ctx_rtc() { uint8_t *ctx = driver_ctx("RTC"); if(!ctx) return; uint8_t RCR1=ctx[0], RCR2=ctx[1]; row_print(1, 1, "RCR1:%02x", RCR1); row_print(2, 1, "RCR2:%02x", RCR2); } static void show_etmu(int line, int id, etmu_t *t) { row_print(line, 1, "ETMU%d=%-3dCNT:%08x", id, t->TSTR, t->TCNT); row_print(line+1, 1, "TCR:%02x COR:%08x", t->TCR.byte, t->TCOR); } static void ctx_etmu(int start) { etmu_t *t = driver_ctx("TMU") + 3 * sizeof(tmu_t); int length = 3; if(isSH3()) length=1, start=0; t += start; for(int i = 0; i < length; i++, t++) { show_etmu(2*i+1, i+start, t); } } static void ctx_intc() { uint16_t *IPR = driver_ctx("INTC"); if(isSH3()) { row_print(1,1, "A:%04x B:%04x C:%04x", IPR[0], IPR[1], IPR[2]); row_print(2,1, "D:%04x E:%04x F:%04x", IPR[3], IPR[4], IPR[5]); row_print(3,1, "G:%04x H:%04x", IPR[6], IPR[7]); } else { row_print(1,1, "A:%04x B:%04x C:%04x", IPR[0], IPR[1], IPR[2]); row_print(2,1, "D:%04x E:%04x F:%04x", IPR[3], IPR[4], IPR[5]); row_print(3,1, "G:%04x H:%04x I:%04x", IPR[6], IPR[7], IPR[8]); row_print(4,1, "J:%04x K:%04x L:%04x", IPR[9],IPR[10],IPR[11]); } } #endif /* FX9860G */ #ifdef FXCG50 static void ctx_tmu() { tmu_t *t = driver_ctx("TMU"); etmu_t *e = (void *)(t + 3); uint8_t *TSTR = (void *)(e + 6); int const x[] = { 6, 138, 270, 6, 138, 270, 6, 138, 270 }; int const y[] = { 24, 24, 24, 84, 84, 84, 144, 144, 144 }; tmu_print(x[0], y[0], "TMU0", t+0, *TSTR & 0x1); tmu_print(x[1], y[1], "TMU1", t+1, *TSTR & 0x2); tmu_print(x[2], y[2], "TMU2", t+2, *TSTR & 0x4); etmu_print(x[3], y[3], "ETMU0", e+0); etmu_print(x[4], y[4], "ETMU1", e+1); etmu_print(x[5], y[5], "ETMU2", e+2); etmu_print(x[6], y[6], "ETMU3", e+3); etmu_print(x[7], y[7], "ETMU4", e+4); etmu_print(x[8], y[8], "ETMU5", e+5); } static void ctx_dd() { uint16_t *win = driver_ctx("R61524"); uint16_t HSA = win[0], HEA = win[1], VSA = win[2], VEA = win[3]; row_print(1, 1, "Horizontal range: %d..%d", HSA, HEA); row_print(2, 1, "Vertical range: %d..%d", VSA, VEA); } static void ctx_rtc() { uint8_t *ctx = driver_ctx("RTC"); if(!ctx) return; uint8_t RCR1=ctx[0], RCR2=ctx[1]; row_print(1, 1, "RCR1:%02x", RCR1); row_print(2, 1, "RCR2:%02x", RCR2); } static void ctx_dma() { sh7305_dma_channel_t *ch = driver_ctx("DMA0"); int *clock = (void *)(ch + 6); uint16_t *OR = (void *)(clock + 1); show_dma(6, 24, 0, ch+0); show_dma(138, 24, 1, ch+1); show_dma(270, 24, 2, ch+2); show_dma(6, 104, 3, ch+3); show_dma(138, 104, 4, ch+4); show_dma(270, 104, 5, ch+5); dprint(6, 184, C_BLACK, "DMAOR: %08X", *OR); dprint(198, 184, C_BLACK, "Clock enabled: %s",(*clock ? "No" : "Yes")); } #endif /* FXCG50 */ static void system_contexts(void) { int key=0, tab=0; while(key != KEY_EXIT) { dclear(C_WHITE); #ifdef FX9860G extern bopti_image_t img_opt_switch_ctx_sh3; extern bopti_image_t img_opt_switch_ctx; if(isSH3()) dimage(0, 56, &img_opt_switch_ctx_sh3); else dimage(0, 56, &img_opt_switch_ctx); #endif #ifdef FXCG50 row_title("System context visualizer"); fkey_button(1, "TMU"); fkey_button(2, "R61524"); fkey_button(3, "RTC"); fkey_button(4, "DMA"); #endif if(tab == 0) ctx_tmu(); if(tab == 1) ctx_dd(); if(tab == 2) ctx_rtc(); #ifdef FX9860G if(tab == 3) ctx_etmu(0); if(tab == 4) ctx_etmu(3); if(tab == 5) ctx_intc(); #endif #ifdef FXCG50 if(tab == 3) ctx_dma(); #endif dupdate(); key = getkey().key; if(key == KEY_F1) tab = 0; if(key == KEY_F2) tab = 1; if(key == KEY_F3) tab = 2; if(key == KEY_F4) tab = 3; if(key == KEY_F6) tab = 5; #ifdef FX9860G if(key == KEY_F5 && isSH3()) tab = 4; #endif } } //--- // Interactive in-out switching //--- /* Render VRAM for this screen, used when returning to menu */ void render(void) { dclear(C_WHITE); #ifdef FX9860G extern bopti_image_t img_opt_switch; row_print(1, 1, "Switch to OS"); row_print(3, 1, "Switches done: %d", switches); row_print(4, 1, "Menus done: %d", menus); dimage(0, 56, &img_opt_switch); #endif #ifdef FXCG50 row_title("Hot switching between gint and OS"); row_print(2, 1, "Switches done: %d", switches); row_print(3, 1, "Menus done: %d", menus); fkey_button(1, "SWITCH"); fkey_button(2, "MENU"); fkey_action(6, "SYSTEM"); #endif } /* gintctl_gint_switch(): Test the gint switch-in-out procedures */ void gintctl_gint_switch(void) { int key = 0; while(key != KEY_EXIT) { render(); dupdate(); key = getkey().key; if(key == KEY_F1) gint_switch(switch_function); /* Wait for F2 to be released before calling next getkey() */ if(key == KEY_F2) { /* Render next frame in advance. When we return from the main menu, our VRAM will be displayed but GetKeyWait() will not give control back until a key is pressed. This will make it look like we render a new frame right away. */ menus++; render(); dupdate(); gint_osmenu(); while(keydown(KEY_F2)) waitevent(NULL); } if(key == KEY_F6) system_contexts(); } }