void tests_wait_press() { per_init(); if (interrupt_get_level_mask() > 0x7) interrupt_set_level_mask(0x7); vdp_vsync(); // Wait until no buttons are pressed while (per[0].but_push_once || per[0].but_push) vdp_vsync(); for (;;) { vdp_vsync(); // return whenever a button pressed if (per[0].but_push_once & PAD_A || per[0].but_push_once & PAD_B || per[0].but_push_once & PAD_C || per[0].but_push_once & PAD_X || per[0].but_push_once & PAD_Y || per[0].but_push_once & PAD_Z || per[0].but_push_once & PAD_L || per[0].but_push_once & PAD_R || per[0].but_push_once & PAD_START) break; } vdp_vsync(); }
void vdp_fade_out(u16 screen, int num, int increment) { int i; vdp_set_color_offset(num, 0x1FF, 0x1FF, 0x1FF); vdp_enable_color_offset(screen, num); for (i = 0; i < 256; i+=increment) { s16 offset; vdp_vsync(); offset=0x1FF-i; vdp_set_color_offset(num, offset, offset, offset); } vdp_vsync(); }
void vdp_fade_in(u16 screen, int num, int increment) { int i; vdp_set_color_offset(num, 0x100, 0x100, 0x100); vdp_enable_color_offset(screen, num); for (i = 0; i < 256; i+=increment) { s16 offset; vdp_vsync(); offset=0x100+i; vdp_set_color_offset(num, offset, offset, offset); } vdp_vsync(); vdp_disable_color_offset(screen); }
BOOL ar_handle_detect_error(int err) { char text[128]; u16 press; u16 vendor_id, device_id; if (err == IAPETUS_ERR_HWNOTFOUND) sprintf(text, "HW not found."); else if(err == IAPETUS_ERR_UNSUPPORTED) sprintf(text, "HW not supported."); else sprintf(text, "Unknown error."); vdp_printf(&main_font, 8, 8, 0xF, "Error detecting cart. %s", text); ar_get_product_id(&vendor_id, &device_id); vdp_printf(&main_font, 8, 16, 0xF, "HW ID: %04X %04X", vendor_id, device_id); press=wait_for_press(-1); if (err != IAPETUS_ERR_UNSUPPORTED) return FALSE; if (press & PAD_A && press & PAD_B && press & PAD_C) { vdp_vsync(); vdp_clear_screen(&main_font); return TRUE; } return FALSE; }
u16 wait_for_press(u16 mask) { for (;;) { vdp_vsync(); if (per[0].but_push_once & mask) break; } return per[0].but_push_once & mask; }
void auto_test_take_screenshot(int frames_to_wait) { #ifdef BUILD_AUTOMATED_TESTING int i; for (i = 0; i < frames_to_wait; i++) { vdp_vsync(); } auto_test_send_message("SCREENSHOT", ""); #endif }
void vdp1_framebuffer_write_test() { volatile u16* framebuffer_ptr = (volatile u16*)0x25C80000; int i; vdp_vsync(); VDP1_REG_FBCR = 3; //we have to wait a little bit so we don't write to both framebuffers vdp_wait_hblankout(); for (i = 0; i < 128; i += 4) { framebuffer_ptr[i + 0] = 0xdead; framebuffer_ptr[i + 1] = 0xbeef; framebuffer_ptr[i + 2] = 0xfeed; framebuffer_ptr[i + 3] = 0xcafe; } #ifdef BUILD_AUTOMATED_TESTING auto_test_get_framebuffer(); #else for (;;) { while (!(VDP2_REG_TVSTAT & 8)) { ud_check(0); } while (VDP2_REG_TVSTAT & 8) {} if (per[0].but_push_once & PAD_START) break; if (per[0].but_push_once & PAD_X) { ar_menu(); } if (per[0].but_push_once & PAD_Y) { reset_system(); } } #endif }
void scsp_interactive_test() { u16 scieb=0; u16 mcieb=0; scsp_minimal_init(); test_disp_font.transparent = 0; scsp_counter=0; SCSPREG_SCIEB = mcieb; SCSPREG_MCIEB = scieb; // Mask SCSP interrupt temporarily bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40); // Set SCSP interrupt function bios_set_scu_interrupt(0x46, scsp_interrupt); // Unmask SCSP interrupt bios_change_scu_interrupt_mask(~0x40, 0); for (;;) { u16 scipd; u16 mcipd; vdp_vsync(); #define Refresh(line) \ scipd = SCSPREG_SCIPD; \ mcipd = SCSPREG_MCIPD; \ \ vdp_printf(&test_disp_font, 2 * 8, line * 8, 0xF, "SCIEB = %04X", scieb); \ vdp_printf(&test_disp_font, 2 * 8, (line+1) * 8, 0xF, "MCIEB = %04X", mcieb); \ vdp_printf(&test_disp_font, 2 * 8, (line+2) * 8, 0xF, "SCIPD = %04X", scipd); \ vdp_printf(&test_disp_font, 2 * 8, (line+3) * 8, 0xF, "MCIPD = %04X", mcipd); \ vdp_printf(&test_disp_font, 2 * 8, (line+4)* 8, 0xF, "int counter = %d", scsp_counter); Refresh(17); if (per[0].but_push_once & PAD_A) { SCSPREG_TIMERA = 0x700; Refresh(23); } else if (per[0].but_push_once & PAD_B) { SCSPREG_TIMERA = 0x07FF; Refresh(23); } else if (per[0].but_push_once & PAD_C) { SCSPREG_SCIRE = 0x40; Refresh(23); } else if (per[0].but_push_once & PAD_X) { mcieb ^= 0x40; SCSPREG_MCIEB = mcieb; Refresh(23); } else if (per[0].but_push_once & PAD_Y) { SCSPREG_MCIRE = 0x40; Refresh(23); } else if (per[0].but_push_once & PAD_L) { mcieb ^= 0x20; SCSPREG_MCIEB = mcieb; Refresh(23); } else if (per[0].but_push_once & PAD_R) { if (SCSPREG_MCIPD & 0x20) SCSPREG_MCIRE = 0x20; else SCSPREG_MCIPD = 0x20; Refresh(23); } } }
void vdp1_clip_test() { int gouraud_table_address = 0x40000; u32 clipping_mode = 3;//outside u16* p = (u16 *)(0x25C00000 + gouraud_table_address); for (;;) { vdp_start_draw_list(); sprite_struct quad; //system clipping quad.x = 319 - 8; quad.y = 223 - 8; vdp_system_clipping(&quad); //user clipping quad.x = 8; quad.y = 8; quad.x2 = 319 - 16; quad.y2 = 223 - 16; vdp_user_clipping(&quad); //fullscreen polygon quad.x = 319; quad.y = 0; quad.x2 = 319; quad.y2 = 223; quad.x3 = 0; quad.y3 = 223; quad.x4 = 0; quad.y4 = 0; quad.bank = RGB16(0x10, 0x10, 0x10);//gray quad.gouraud_addr = gouraud_table_address; quad.attr = (clipping_mode << 9) | 4;//use gouraud shading //red, green, blue, and white p[0] = RGB16(31, 0, 0); p[1] = RGB16(0, 31, 0); p[2] = RGB16(0, 0, 31); p[3] = RGB16(31, 31, 31); vdp_draw_polygon(&quad); vdp_end_draw_list(); vdp_vsync(); if (per[0].but_push_once & PAD_A) { clipping_mode = 0; //clipping disabled } if (per[0].but_push_once & PAD_B) { clipping_mode = 2; //inside drawing mode } if (per[0].but_push_once & PAD_C) { clipping_mode = 3; //outside drawing mode } if (per[0].but_push_once & PAD_START) break; } }
void vdp1_clip_test() { int gouraud_table_address = 0x40000; u32 clipping_mode = 3;//outside u16* p = (u16 *)(0x25C00000 + gouraud_table_address); auto_test_sub_test_start("Clipping test"); VDP1_REG_FBCR = 0; vdp_start_draw_list(); sprite_struct quad; quad.x = 0; quad.y = 0; vdp_local_coordinate(&quad); //system clipping quad.x = 319 - 8; quad.y = 223 - 8; vdp_system_clipping(&quad); //user clipping quad.x = 8; quad.y = 8; quad.x2 = 319 - 16; quad.y2 = 223 - 16; vdp_user_clipping(&quad); //fullscreen polygon quad.x = 319; quad.y = 0; quad.x2 = 319; quad.y2 = 223; quad.x3 = 0; quad.y3 = 223; quad.x4 = 0; quad.y4 = 0; quad.bank = RGB16(0x10, 0x10, 0x10);//gray quad.gouraud_addr = gouraud_table_address; quad.attr = (clipping_mode << 9) | 4;//use gouraud shading //red, green, blue, and white p[0] = RGB16(31, 0, 0); p[1] = RGB16(0, 31, 0); p[2] = RGB16(0, 0, 31); p[3] = RGB16(31, 31, 31); vdp_draw_polygon(&quad); vdp_end_draw_list(); vdp_vsync(); VDP1_REG_FBCR = 3; vdp_vsync(); vdp_vsync(); #ifdef BUILD_AUTOMATED_TESTING auto_test_get_framebuffer(); #else for (;;) { while (!(VDP2_REG_TVSTAT & 8)) { ud_check(0); } while (VDP2_REG_TVSTAT & 8) { } if (per[0].but_push_once & PAD_A) { clipping_mode = 0; //clipping disabled } if (per[0].but_push_once & PAD_B) { clipping_mode = 2; //inside drawing mode } if (per[0].but_push_once & PAD_C) { clipping_mode = 3; //outside drawing mode } if (per[0].but_push_once & PAD_START) break; if (per[0].but_push_once & PAD_X) { ar_menu(); } if (per[0].but_push_once & PAD_Y) { reset_system(); } } #endif }
void ar_delay_10ms() { // This should be good enough. Ideally though, you'd want something a little more accurate using WDT, FRT or something vdp_vsync(); vdp_vsync(); }
void do_tests(const char *testname, int x, int y) { int i; u8 stage=0; u8 line=0; // Clear out test log area memset((void *)TEST_LOG_ADDRESS, 0, TEST_LOG_SIZE); *((u32 *)TEST_LOG_ADDRESS) = TEST_LOG_ADDRESS+4; // Print messages and cursor vdp_printf(&test_disp_font, x * 8, y * 8, 0xF, (char *)testname); auto_test_section_start((char *)testname); for(;;) { vdp_vsync(); if (stage_status != STAGESTAT_BUSY && stage_status != STAGESTAT_WAITINGFORINT) { int textx = x * 8; int texty = (y + line + 2) * 8; int textstatx = (x + 38) * 8; if (stage_status == STAGESTAT_DONE) { vdp_printf(&test_disp_font, textstatx, texty, 0xA, "OK"); auto_test_send_result("PASS"); } else if (stage_status < 0) { // Handle error switch (stage_status) { case STAGESTAT_BADTIMING: vdp_printf(&test_disp_font, textstatx, texty, 0xE, "BT"); auto_test_send_result("FAIL (Bad Timing)"); break; case STAGESTAT_BADDATA: vdp_printf(&test_disp_font, textstatx, texty, 0xC, "BD"); auto_test_send_result("FAIL (Bad Data)"); break; case STAGESTAT_BADSIZE: vdp_printf(&test_disp_font, textstatx, texty, 0xC, "BS"); auto_test_send_result("FAIL (Bad Size)"); break; case STAGESTAT_BADINTERRUPT: vdp_printf(&test_disp_font, textstatx, texty, 0xC, "BI"); auto_test_send_result("FAIL (Bad Interrupt)"); break; case STAGESTAT_NOTEST: vdp_printf(&test_disp_font, textstatx, texty, 0xF, "NT"); auto_test_send_result("FAIL (No Test)"); break; default: vdp_printf(&test_disp_font, textstatx, texty, 0xC, "failed"); auto_test_send_result("FAIL"); break; } } if (stage >= numtests) { vdp_printf(&test_disp_font, textx, texty+8, 0xF, "All tests done."); break; } #ifndef BUILD_AUTOMATED_TESTING else if (line >= 23) { vdp_printf(&test_disp_font,textx, texty+8, 0xF, "Press any button to continue"); tests_wait_press(); // Clear window vdp_clear_screen(&test_disp_font); vdp_printf(&test_disp_font, x * 8, y * 8, 0xF, (char *)testname); line = 0; texty = (y + line + 2) * 8; } #endif stage_status = STAGESTAT_BUSY; if (tests[stage].name) { vdp_printf(&test_disp_font, textx, texty+8, 0xF, (char *)tests[stage].name); auto_test_sub_test_start((char *)tests[stage].name); } if (tests[stage].testfunc) tests[stage].testfunc(); waitcounter = 60 * 5; stage++; line++; } else { if (stage_status == STAGESTAT_WAITINGFORINT) { // decrement waitcounter waitcounter--; if (waitcounter <= 0) stage_status = STAGESTAT_BADINTERRUPT; #ifdef DEBUG vdp_printf(&test_disp_font, 0 * 8, 23 * 8, 0xF, "%08X", waitcounter); #endif } } } interrupt_set_level_mask(0xF); // Reset all interrupts for (i = 0; i < 0x80; i++) bios_set_sh2_interrupt(i, 0); for (i = 0x40; i < 0x60; i++) bios_set_scu_interrupt(i, 0); // Make sure all interrupts have been called bios_change_scu_interrupt_mask(0, 0); bios_change_scu_interrupt_mask(0xFFFFFFFF, 0xFFFFFFFF); auto_test_section_end(); // Enable commlink connection cl_set_service_func(ud_check); commlink_start_service(); tests_wait_press(); commlink_stop_service(); }
int reflash_ar(font_struct *font, u8 *rom_addr, int ask_upload) { int ret; volatile u16 *write_addr=(volatile u16 *)0x22000000; u16 *read_addr=(u16 *)((u32)rom_addr | 0x20000000); flash_info_struct flash_info; int i; vdp_start_draw_list(); vdp_end_draw_list(); for (;;) { start: if ((ret = ar_init_flash_io(&flash_info)) != IAPETUS_ERR_OK) { if (!ar_handle_detect_error(ret)) return 1; } vdp_printf(font, 8, 8, 0xF, "Detected cart succesfully"); if (ask_upload) { vdp_printf(font, 8, 3 * 8, 0xF, "Please upload flash to 0x00200000 and"); vdp_printf(font, 8, 4 * 8, 0xF, "then press 'A' to continue. "); vdp_printf(font, 8, 5 * 8, 0xF, "Press 'X' to exit."); commlink_start_service(); if (wait_for_press(PAD_A | PAD_X) & PAD_X) return 1; commlink_stop_service(); if (strncmp((char *)read_addr, "SEGA SEGASATURN ", 16) != 0) { vdp_printf(font, 8, 7 * 8, 0xF, "Invalid or no ROM uploaded. "); vdp_printf(font, 8, 8 * 8, 0xF, "Press 'A' to try again."); wait_for_press(PAD_A); vdp_clear_screen(font); goto start; } } vdp_printf(font, 8, 7 * 8, 0xF, "WARNING: Rewriting the flash may damage"); vdp_printf(font, 8, 8 * 8, 0xF, "your AR. Press A+B+C to continue."); vdp_printf(font, 8, 9 * 8, 0xF, "Press 'X' to exit."); for (;;) { vdp_vsync(); if (per[0].but_push & PAD_A && per[0].but_push & PAD_B && per[0].but_push & PAD_C) break; else if (per[0].but_push_once & PAD_X) return 1; } vdp_printf(font, 8, 11 * 8, 0xF, "DO NOT TURN OFF YOUR SYSTEM"); vdp_printf(font, 8, 12 * 8, 0xF, "Erasing flash..."); ar_erase_flash_all(&flash_info); vdp_printf(font, 17 * 8, 12 * 8, 0xF, "OK"); vdp_printf(font, 8, 13 * 8, 0xF, "Writing flash..."); font->transparent = FALSE; for (i = 0; i < flash_info.num_pages; i++) { vdp_printf(font, 17 * 8, 13 * 8, 0xF, "%d%% ", (i+1) * 100 / flash_info.num_pages); ar_write_flash(&flash_info, write_addr+(i*flash_info.page_size), read_addr+(i*flash_info.page_size), 1); } vdp_printf(font, 17 * 8, 13 * 8, 0xF, "OK "); font->transparent = TRUE; vdp_printf(font, 8, 14 * 8, 0xF, "Verifying flash..."); ret = ar_verify_write_flash(&flash_info, write_addr, read_addr, flash_info.num_pages); vdp_printf(font, 19 * 8, 14 * 8, 0xF, ret ? "OK" : "FAILED"); if (ret) { vdp_printf(font, 8, 15 * 8, 0xF, "SUCCESS! Press reset to finish."); goto done; } vdp_printf(font, 8, 15 * 8, 0xF, "Failed flashing AR. Press a 'A' to"); vdp_printf(font, 8, 16 * 8, 0xF, "retry or 'X' to exit"); if (wait_for_press(PAD_A | PAD_X) & PAD_X) return 0; vdp_clear_screen(font); } done: wait_for_press(PAD_A); return 1; }