void TVType_Set (int tv_type, bool verbose) { TV_Type_User = &TV_Type_Table[tv_type]; g_machine.TV = TV_Type_User; g_machine.TV_lines = TV_Type_User->screen_lines; // FIXME: CPU_Clock_Current is not taken into account for IPeriod in CPU emulation // 262 * 228 = 59736, * 60 = 3584160 // 313 * 228 = 71364, * 50 = 3568200 // SN76489_SetClock(opt.TV_Lines_Current * opt.Cur_IPeriod); // 59736 for NTSC // SN76489_SetClock(g_machine.TV->CPU_clock); Sound_UpdateClockSpeed(); if (Sound.LogVGM.Logging == VGM_LOGGING_ACCURACY_SAMPLE) VGM_Update_Timing (&Sound.LogVGM); if (verbose) { // Print message & and update GUI checks Msg(MSGT_USER, Msg_Get(MSG_TVType_Set), TV_Type_User->name); Msg(MSGT_USER_LOG, Msg_Get(MSG_TVType_Info_Speed), TV_Type_User->screen_frequency); gui_menu_uncheck_all (menus_ID.tvtype); gui_menu_check (menus_ID.tvtype, tv_type); // Note that GUI checks are NOT updated if verbose mode is not set. // The reason is the parameters in MEKA.NAM can force a TV type, but we don't // want the user to be notified by that (unless he manually reoverride it). } }
// RESET EMULATED MACHINE ----------------------------------------------------- void Machine_Reset (void) { int i; static byte VDPInit [16] = { /* Values set by BIOS */ 0x36, /*0xA0*/ 0x80 /* zero for Coleco */, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 /* Old (guessed ?) values */ // 0x06, 0x00, 0x0E, 0xFF, 0xFF, 0x7F, 0x00, 0x00, // 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }; #ifdef DEBUG_WHOLE Msg (MSGT_DEBUG, "Machine_Reset();"); #endif // Unpause machine if necessary if (machine & MACHINE_PAUSED) Machine_Pause (); // Set driver & machine stuff drv_set (cur_machine.driver_id); Machine_Set_Mapper (); if ((machine & MACHINE_RUN) != 0 /*== MACHINE_RUN */ && (cur_drv->id != DRV_NES)) Machine_Set_Mapping (); // ^^ FIXME: the test above isn't beautiful since MACHINE_RUN contains multiple flags, but I'm unsure which of them is actually needed to perform the correct test Machine_Set_Handler_IO (); Machine_Set_Handler_Read (); Machine_Set_Handler_Write (); Machine_Set_Handler_Loop (); Machine_Set_Country (); Machine_Set_IPeriod (); Machine_Set_TV_Lines (); // VDP MODEL -------------------------------------------------------------- if (DB_CurrentEntry && DB_CurrentEntry->emu_vdp_model != -1) cur_machine.VDP.model = DB_CurrentEntry->emu_vdp_model; else { if (cur_drv->id == DRV_GG) cur_machine.VDP.model = VDP_MODEL_315_5378; else cur_machine.VDP.model = VDP_MODEL_315_5226; } // 3-D GLASSES ------------------------------------------------------------ sms.Glasses_Register = ((Glasses.Mode == GLASSES_MODE_SHOW_ONLY_LEFT) ? 1 : 0); // CPU (MARAT FAIZULLIN'S CORE) ------------------------------------------- CPU_Loop_Stop = TRUE; CPU_ForceNMI = FALSE; #ifdef MARAT_Z80 sms.R.IPeriod = opt.Cur_IPeriod; sms.R.Trace = FALSE; ResetZ80 (&sms.R); sms.R.IFF |= IFF_IM1; sms.R.IAutoReset = FALSE; sms.R.TrapBadOps = FALSE; // CPU (MAME'S CORE) ------------------------------------------------------ #elif MAME_Z80 z80_reset (NULL); z80_set_irq_callback (Get_IRQ_Vector); z80_set_irq_line (0, ASSERT_LINE); z80_set_irq_line (0, CLEAR_LINE); // CPU (RICHARD MITTON'S CORE) -------------------------------------------- #elif RAZE_Z80 z80_init_memmap (); z80_add_write (0x0000, 0xFFFF, Z80_MAP_HANDLED, WrZ80); for (i = 0; i < 4; i ++) { z80_add_read ((i * 0x2000), (i * 0x2000) + 0x1FFF, Z80_MAP_DIRECT, Mem_Pages [i]); z80_map_fetch ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]); } for (i = 4; i < 8; i ++) { z80_map_fetch ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]); z80_map_read ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]); } z80_set_in (InZ80); z80_set_out (OutZ80); z80_end_memmap (); z80_reset (); #endif // MEMORY ----------------------------------------------------------------- memset (RAM, 0, 0x10000); // Clear all RAM memset (VRAM, 0, 0x04000); // Clear all VRAM PRAM = PRAM_Static; memset (PRAM, 0, 0x00040); // Clear all PRAM (palette) // Unload BIOS if... if ((cur_drv->id != DRV_SMS || sms.Country != COUNTRY_EXPORT) && (machine & MACHINE_ROM_LOADED)) { #ifdef DEBUG_WHOLE Msg (MSGT_DEBUG, "Machine_Reset(): BIOS_Unload()"); #endif BIOS_Unload (); } // GRAPHICS --------------------------------------------------------------- for (i = 0; i < 16; i++) Tms_VDP_Out (i, ((i == 1 && cur_drv->id == DRV_COLECO) ? 0x00 : VDPInit [i])); for (i = 0; i < MAX_TILES; i++) tgfx.Tile_Dirty [i] = TILE_DIRTY_DECODE | TILE_DIRTY_REDRAW; VDP_UpdateLineLimits(); clear_bitmap (screenbuffer_1); clear_bitmap (screenbuffer_2); screenbuffer = screenbuffer_1; screenbuffer_next = screenbuffer_2; cur_machine.VDP.sprite_shift_x = 0; cur_machine.VDP.scroll_x_latched = 0; cur_machine.VDP.scroll_y_latched = 0; memset(cur_machine.VDP.scroll_x_latched_table, 0, sizeof(cur_machine.VDP.scroll_x_latched_table)); tsms.VDP_Video_Change = VDP_VIDEO_CHANGE_ALL; // GRAPHICS: SPRITE FLICKERING -------------------------------------------- if (g_Configuration.sprite_flickering & SPRITE_FLICKERING_AUTO) { if (DB_CurrentEntry && (DB_CurrentEntry->flags & DB_FLAG_EMU_SPRITE_FLICKER)) g_Configuration.sprite_flickering |= SPRITE_FLICKERING_ENABLED; else g_Configuration.sprite_flickering &= ~SPRITE_FLICKERING_ENABLED; } // PALETTE ---------------------------------------------------------------- //if (machine & MACHINE_POWER_ON) Palette_Emulation_Reset(); // INPUT/OUTPUT/VDP ------------------------------------------------------- sms.VDP_Status = 0x00; sms.VDP_Address = 0x0000; sms.VDP_Access_Mode = VDP_Access_Mode_1; sms.VDP_Access_First = 0x00; sms.VDP_Pal = 0x00; sms.VDP_ReadLatch = 0x00; sms.Lines_Left = 255; sms.Pending_HBlank = FALSE; sms.Pending_NMI = FALSE; tsms.VDP_Line = 0; // CONTROLLERS ------------------------------------------------------------ for (i = 0; i < 8; i ++) tsms.Control [i] = 0xFFFF; /* 0x3FFF */ tsms.Control_GG = /*0x20 | 0x80*/ 0; tsms.Control_Start_Pause = 0; tsms.Periph_Nat = 0; sms.Input_Mode = 0x07; // SOUND ------------------------------------------------------------------ sms.FM_Register = 0; sms.FM_Magic = 0; // if (fm_use == TRUE) fm_init (FM_ALL_INIT); // resume_fm (); FM_Reset (); SN76489_Reset (cur_machine.TV->CPU_clock, audio_sample_rate); if (Sound.LogVGM.Logging == VGM_LOGGING_ACCURACY_SAMPLE) VGM_Update_Timing (&Sound.LogVGM); // Reset sound cycle counter Sound_Update_Count = 0; Sound_CycleCounter = 0; // FIXME: add a reset handler per driver, instead of the code below... // GAME GEAR COMMUNICATION PORT if (cur_machine.driver_id == DRV_GG) { Comm_Reset (); } // SF-7000 if (cur_machine.driver_id == DRV_SF7000) { SF7000_Reset (); } // NINTENDO CRAP if (cur_machine.driver_id == DRV_NES /* && cfg.NES_Enabled */) { ROM = Game_ROM; NES_Reset (); } // DEBUGGER --------------------------------------------------------------- #ifdef MEKA_Z80_DEBUGGER Debugger_MachineReset (); #endif }
// RESET EMULATED MACHINE ----------------------------------------------------- void Machine_Reset(void) { int i; static byte VDPInit [16] = { /* Values set by BIOS */ 0x36, /*0xA0*/ 0x80 /* zero for Coleco */, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 /* Old (guessed ?) values */ // 0x06, 0x00, 0x0E, 0xFF, 0xFF, 0x7F, 0x00, 0x00, // 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }; #ifdef DEBUG_WHOLE Msg(MSGT_DEBUG, "Machine_Reset();"); #endif // Unpause machine if necessary if (g_machine_flags & MACHINE_PAUSED) Machine_Pause(); // Set driver & machine stuff drv_set (g_machine.driver_id); Machine_Set_Mapper (); if ((g_machine_flags & MACHINE_RUN) != 0 /*== MACHINE_RUN */) Machine_Set_Mapping (); // ^^ FIXME: the test above isn't beautiful since MACHINE_RUN contains multiple flags, but I'm unsure which of them is actually needed to perform the correct test Machine_Set_Handler_IO (); Machine_Set_Handler_Read (); Machine_Set_Handler_Write (); Machine_Set_Handler_Loop (); Machine_Set_Country (); Machine_Set_IPeriod (); Machine_Set_TV_Lines (); // VDP MODEL -------------------------------------------------------------- if (DB.current_entry && DB.current_entry->emu_vdp_model != -1) { g_machine.VDP.model = DB.current_entry->emu_vdp_model; } else { if (g_driver->id == DRV_GG) g_machine.VDP.model = VDP_MODEL_315_5378; else g_machine.VDP.model = VDP_MODEL_315_5226; } // 3-D GLASSES ------------------------------------------------------------ sms.Glasses_Register = ((Glasses.Mode == GLASSES_MODE_SHOW_ONLY_LEFT) ? 1 : 0); if (Glasses.Mode == GLASSES_MODE_SHOW_ONLY_LEFT) { sms.Glasses_Register = 1; } // CPU (MARAT FAIZULLIN'S CORE) ------------------------------------------- CPU_Loop_Stop = TRUE; CPU_ForceNMI = FALSE; #ifdef MARAT_Z80 sms.R.IPeriod = opt.Cur_IPeriod; sms.R.Trace = FALSE; ResetZ80 (&sms.R); sms.R.IFF |= IFF_IM1; sms.R.IAutoReset = FALSE; sms.R.TrapBadOps = FALSE; // CPU (MAME'S CORE) ------------------------------------------------------ #elif MAME_Z80 z80_reset (NULL); z80_set_irq_callback (Get_IRQ_Vector); z80_set_irq_line (0, ASSERT_LINE); z80_set_irq_line (0, CLEAR_LINE); // CPU (RICHARD MITTON'S CORE) -------------------------------------------- #elif RAZE_Z80 z80_init_memmap(); z80_add_write (0x0000, 0xFFFF, Z80_MAP_HANDLED, WrZ80); for (i = 0; i < 4; i ++) { z80_add_read ((i * 0x2000), (i * 0x2000) + 0x1FFF, Z80_MAP_DIRECT, Mem_Pages [i]); z80_map_fetch ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]); } for (i = 4; i < 8; i ++) { z80_map_fetch ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]); z80_map_read ((i * 0x2000), (i * 0x2000) + 0x1FFF, Mem_Pages [i]); } z80_set_in (InZ80); z80_set_out (OutZ80); z80_end_memmap(); z80_reset(); #endif // MEMORY ----------------------------------------------------------------- // Clear RAM if (g_driver->id == DRV_SMS && sms.Country == COUNTRY_JAPAN) { // On Japanese SMS clear RAM with 0xF0 patterns // I am not sure how reliable is that pattern but this is what I'm seeing on my JSMS // In theory this should be applied to all drivers, all countries, etc. but the exact // behavior of other systems and bioses should be inspected more in details before // generalizing that. // The game "Ali Baba" require a non-00 and non-FF memory pattern to run to a bug // in the code which makes it execute uninitialized memory from 0xFF07 onward. // An F0 pattern correspond to RET P which happens to fix the game. memset (RAM, 0xF0, 0x10000); } else { memset (RAM, 0x00, 0x10000); } memset (VRAM, 0, 0x04000); // Clear all VRAM memset (PRAM, 0, 0x00040); // Clear all PRAM (palette) #ifdef DEBUG_UNINITIALIZED_RAM_ACCESSES memset (RAM_IsUninitialized, 1, 0x2000); #endif // Unload BIOS if... if ((g_driver->id != DRV_SMS || sms.Country != COUNTRY_EXPORT) && (g_machine_flags & MACHINE_ROM_LOADED)) { #ifdef DEBUG_WHOLE Msg(MSGT_DEBUG, "Machine_Reset(): BIOS_Unload()"); #endif BIOS_Unload(); } // GRAPHICS --------------------------------------------------------------- for (i = 0; i < 16; i++) Tms_VDP_Out (i, ((i == 1 && g_driver->id == DRV_COLECO) ? 0x00 : VDPInit [i])); for (i = 0; i < MAX_TILES; i++) tgfx.Tile_Dirty [i] = TILE_DIRTY_DECODE | TILE_DIRTY_REDRAW; VDP_UpdateLineLimits(); //assert(!Screenbuffer_IsLocked()); al_set_target_bitmap(screenbuffer_1); al_clear_to_color(COLOR_BLACK); al_set_target_bitmap(screenbuffer_2); al_clear_to_color(COLOR_BLACK); //screenbuffer = screenbuffer_1; //screenbuffer_next = screenbuffer_2; g_machine.VDP.sprite_shift_x = 0; g_machine.VDP.scroll_x_latched = 0; g_machine.VDP.scroll_y_latched = 0; memset(g_machine.VDP.scroll_x_latched_table, 0, sizeof(g_machine.VDP.scroll_x_latched_table)); tsms.VDP_Video_Change = VDP_VIDEO_CHANGE_ALL; // GRAPHICS: SPRITE FLICKERING -------------------------------------------- if (g_configuration.sprite_flickering & SPRITE_FLICKERING_AUTO) { if (DB.current_entry && (DB.current_entry->flags & DB_FLAG_EMU_SPRITE_FLICKER)) g_configuration.sprite_flickering |= SPRITE_FLICKERING_ENABLED; else g_configuration.sprite_flickering &= ~SPRITE_FLICKERING_ENABLED; } // PALETTE ---------------------------------------------------------------- //if (machine & MACHINE_POWER_ON) Palette_Emulation_Reset(); // INPUT/OUTPUT/VDP ------------------------------------------------------- sms.VDP_Status = 0x00; sms.VDP_Address = 0x0000; sms.VDP_Access_Mode = VDP_Access_Mode_1; sms.VDP_Access_First = 0x00; sms.VDP_Pal = 0x00; sms.VDP_ReadLatch = 0x00; sms.Lines_Left = 255; sms.Pending_HBlank = FALSE; sms.Pending_NMI = FALSE; tsms.VDP_Line = 0; // CONTROLLERS ------------------------------------------------------------ for (i = 0; i < 8; i ++) tsms.Control [i] = 0xFFFF; /* 0x3FFF */ tsms.Control_GG = /*0x20 | 0x80*/ 0; tsms.Control_Start_Pause = 0; tsms.Port3F = 0; sms.Input_Mode = 0x07; // SOUND ------------------------------------------------------------------ sms.FM_Register = 0; sms.FM_Magic = 0; // if (fm_use == TRUE) fm_init (FM_ALL_INIT); // resume_fm(); FM_Reset(); SN76489_Reset (g_machine.TV->CPU_clock, Sound.SampleRate); if (Sound.LogVGM.Logging == VGM_LOGGING_ACCURACY_SAMPLE) VGM_Update_Timing (&Sound.LogVGM); Sound_ResetCycleCounter(); // FIXME: add a reset handler per driver, instead of the code below... // GAME GEAR COMMUNICATION PORT if (g_machine.driver_id == DRV_GG) Comm_Reset(); // SF-7000 if (g_machine.driver_id == DRV_SF7000) SF7000_Reset(); // DEBUGGER --------------------------------------------------------------- #ifdef MEKA_Z80_DEBUGGER Debugger_MachineReset(); #endif }