Beispiel #1
0
/*-------------------------------------------------------------------------

	Audio command callback.

	Input:	Timer		Pointer to the timer that triggered the callback.
			Data		Data associated with the timer.

---------------------------------------------------------------------------*/
void neogeo_audio_command_timer_callback ( TIMER *Timer, Uint32 Data )
{
	Uint32	Z80_Elapsed;

	/* Post the audio command to the Z80 */
	neogeo_audio_command = Data;
	z80_set_irq_line ( INPUT_LINE_NMI, ASSERT_LINE );
	z80_set_irq_line ( INPUT_LINE_NMI, CLEAR_LINE );

	/* Let the Z80 take the command into account */
	Z80_Elapsed = z80_execute ( REF_TO_Z80 ( 2000 ) );
	neogeo_z80_time_to_execute -= Z80_TO_REF ( Z80_Elapsed );
	neogeo_z80_time_this_vbl += Z80_TO_REF ( Z80_Elapsed );
}
Beispiel #2
0
// 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
}
Beispiel #3
0
/* Run the virtual console emulation for one frame */
void system_frame(int skip_render)
{
    static int iline_table[] = {0xC0, 0xE0, 0xF0};
    int lpf = (sms.display == DISPLAY_NTSC) ? 262 : 313;
    int iline;

    /* Debounce pause key */
    if(input.system & INPUT_PAUSE)
    {
        if(!sms.paused)
        {
            sms.paused = 1;

            z80_set_irq_line(IRQ_LINE_NMI, ASSERT_LINE);
            z80_set_irq_line(IRQ_LINE_NMI, CLEAR_LINE);
        }
    }
    else
    {
         sms.paused = 0;
    }

    text_counter = 0;

    /* End of frame, parse sprites for line 0 on line 261 (VCount=$FF) */
    if(vdp.mode <= 7)
        parse_line(0);

    for(vdp.line = 0; vdp.line < lpf;)
    {
        z80_execute(227);

        iline = iline_table[vdp.extended];

        if(!skip_render)
        {
            render_line(vdp.line);
        }

        if(vdp.line <= iline)
        {
            vdp.left -= 1;
            if(vdp.left == -1)
            {
                vdp.left = vdp.reg[0x0A];
                vdp.hint_pending = 1;

                z80_execute(16);

                if(vdp.reg[0x00] & 0x10)
                {
                    z80_set_irq_line(0, ASSERT_LINE);
                }
            }
        }
        else
        {
            vdp.left = vdp.reg[0x0A];
        }

        if(vdp.line == iline)
        {
            vdp.status |= 0x80;
            vdp.vint_pending = 1;

            z80_execute(16);

            if(vdp.reg[0x01] & 0x20)
            {
                z80_set_irq_line(0, ASSERT_LINE);
            }
        }

        sound_update(vdp.line);

        ++vdp.line;

        if(vdp.mode <= 7)
            parse_line(vdp.line);
    }
}
Beispiel #4
0
static TIMER_CALLBACK( qsound_interrupt )
{
	z80_set_irq_line(0, HOLD_LINE);
	timer_set(QSOUND_INTERRUPT, TIME_IN_HZ(251), 0, qsound_interrupt);
}
Beispiel #5
0
void cps1_sound_interrupt(int state)
{
	z80_set_irq_line(0, state ? ASSERT_LINE : CLEAR_LINE);
}
Beispiel #6
0
// Z80 scanline handler
word    Loop_SMS (void)
{
    int Interrupt = INT_NONE;

    tsms.VDP_Line = (tsms.VDP_Line + 1) % g_machine.TV_lines;
    // Debugger hook
    #ifdef MEKA_Z80_DEBUGGER
		if (Debugger.active)
			Debugger_RasterLine_Hook(tsms.VDP_Line);
	#endif

    // Update sound cycle counter0
    Sound.CycleCounter += opt.Cur_IPeriod;

    if (tsms.VDP_Line == 0)
    {
        Interrupt_Loop_Misc_Line_Zero();
        g_machine.VDP.scroll_x_latched = sms.VDP[8];
        g_machine.VDP.scroll_y_latched = sms.VDP[9];
        sms.Lines_Left = sms.VDP [10];
    }

    // Screen Refresh
    if (tsms.VDP_Line >= g_driver->y_show_start && tsms.VDP_Line <= g_driver->y_show_end)
    {
        g_machine.VDP.scroll_x_latched_table[tsms.VDP_Line] = g_machine.VDP.scroll_x_latched;
        if (tsms.VDP_VideoMode > 3)
            Refresh_Line_5();
        g_machine.VDP.scroll_x_latched = sms.VDP[8];
        if (g_driver->vdp == VDP_TMS9918)
            Check_Sprites_Collision_Modes_1_2_3_Line (tsms.VDP_Line);
        if (tsms.VDP_Line == g_driver->y_show_end)
        {
            //if (g_driver->vdp == VDP_TMS)
            //   Check_Sprites_Collision_Modes_1_2_3();
            // Msg(MSGT_DEBUG, "Loop_SMS: Video_RefreshScreen()");
            Video_RefreshScreen();
            if ((opt.Force_Quit) || (CPU_Loop_Stop))
                Macro_Stop_CPU;
        }
    }

    if (tsms.VDP_Line <= g_driver->y_int)
    {
        if (sms.Lines_Left -- <= 0)
        {
            sms.Lines_Left = sms.VDP [10];
            sms.Pending_HBlank = TRUE;
            #ifdef DEBUG_VDP
                Msg(MSGT_DEBUG, "%d @ Lines_Left == 0, HBlank == %d, Reloading VDP[10] = %d", tsms.VDP_Line, (HBlank_ON) ? 1 : 0, sms.VDP [10]);
            #endif
        }
        if ((sms.Pending_HBlank) && (HBlank_ON))
            Interrupt = INT_IRQ;
    }
    else
#if 1
    {
        // --------------------------------------------------------------------------
        // New interrupt code
        // --------------------------------------------------------------------------
        // FIXME: Needless to say, this is vastly incorrect but has given pretty
        // good result so far.
        // --------------------------------------------------------------------------
        if (tsms.VDP_Line == g_driver->y_int + 1)
            sms.VDP_Status |= VDP_STATUS_VBlank;
        else
            if (tsms.VDP_Line > g_driver->y_int && tsms.VDP_Line <= (g_driver->y_int + 32) && (sms.VDP_Status & VDP_STATUS_VBlank) && (VBlank_ON))
                Interrupt = INT_IRQ;
            else
                if (tsms.VDP_Line == g_driver->y_int + 33)   // Interruption duration. Isn't that scary-lame?
                    Interrupt_Loop_Misc;
    }
#else
        // --------------------------------------------------------------------------
        // Original interrupt code
        // --------------------------------------------------------------------------
    {
        if (tsms.VDP_Line == 193)
            sms.VDP_Status |= VDP_STATUS_VBlank;
        else
            if (tsms.VDP_Line <= 224 && (sms.VDP_Status & 0x80) && (VBlank_ON))
                Interrupt = INT_IRQ;
            else
                if (tsms.VDP_Line == 225)
                    Interrupt_Loop_Misc;
    }
#endif
    // ----------------------------------------------------------------------------
    if (Interrupt == INT_IRQ)
    {
        #ifdef MARAT_Z80
            sms.R.IRequest = INT_IRQ;
        #elif MAME_Z80
            z80_set_irq_line (0, ASSERT_LINE);
        #endif
    }

    return (Interrupt);
}
void sms_z80_clear_irq(void) {
    CrabZ80_clear_irq(cpuz80);
    z80_set_irq_line(1, 0);
}
void sms_z80_nmi(void) {
    CrabZ80_pulse_nmi(cpuz80);
    z80_set_irq_line(INPUT_LINE_NMI, 1);
}
void sms_z80_assert_irq(void) {
    CrabZ80_assert_irq(cpuz80, 0xFFFFFFFF);
    z80_set_irq_line(1, 1);
}
Beispiel #10
0
static void timer_tick(qsf_synth_t *s)
{
	z80_set_irq_line(s->z80, 0, ASSERT_LINE);
	z80_set_irq_line(s->z80, 0, CLEAR_LINE);
}
Beispiel #11
0
word    Loop_SG1000_SC3000 (void)
{
    int Interrupt = INT_NONE;

    // Update sound cycle counter
    Sound.CycleCounter += opt.Cur_IPeriod;

    tsms.VDP_Line = (tsms.VDP_Line + 1) % g_machine.TV_lines;

    // Debugger hook
    #ifdef MEKA_Z80_DEBUGGER
	if (Debugger.active)
		Debugger_RasterLine_Hook(tsms.VDP_Line);
	#endif

    if (tsms.VDP_Line == 0)
    {
        Interrupt_Loop_Misc;
        Interrupt_Loop_Misc_Line_Zero();
    }

    if (tsms.VDP_Line >= 0 && tsms.VDP_Line < 192)
    {
        // Skip collision check if the sprite collision flag is already set
        if (!(sms.VDP_Status & VDP_STATUS_SpriteCollision))
            Check_Sprites_Collision_Modes_1_2_3_Line (tsms.VDP_Line);
    }

    if (tsms.VDP_Line == 192)
    {
        if (fskipper.Show_Current_Frame)
        {
            // Msg(MSGT_DEBUG, "Loop_SG1000_SC3000: Refresh_Modes_0_1_2_3()");
            Refresh_Modes_0_1_2_3();
        }

        sms.VDP_Status |= VDP_STATUS_VBlank;
        //if (!(sms.VDP_Status & VDP_STATUS_SpriteCollision))
        //   Check_Sprites_Collision_Modes_1_2_3();

        // Note: refresh screen may reset the system, so you can NOT change
        // the status AFTER it, or else it would screw the newly emulated code
        // Msg(MSGT_DEBUG, "Loop_SG1000_SC3000: Video_RefreshScreen()");
        Video_RefreshScreen();

        if ((opt.Force_Quit) || (CPU_Loop_Stop))
            Macro_Stop_CPU;
    }

    if ((VBlank_ON) /* && (sms.VDP_Access_Mode == VDP_Access_Mode_1) */
        && (sms.VDP_Status & VDP_STATUS_VBlank))
    {
        Interrupt = INT_IRQ;
        // Msg(MSGT_DEBUG, "At PC=%04X: V-Blank", CPU_GetPC);
    }

    if (Interrupt == INT_IRQ)
    {
        #ifdef MARAT_Z80
            sms.R.IRequest = Interrupt;
        #elif MAME_Z80
            z80_set_irq_line (0, ASSERT_LINE);
        #endif
    }
    else
        // Note: NMI should have the priority over standard Interrupts (by definition)
        // but this behavior is weird to emulate, and should not to be needed in the
        // case we are using CPU_ForceNMI now.
        if (CPU_ForceNMI)
        {
            CPU_ForceNMI = FALSE;
            sms.R.IRequest = Interrupt;
            return (INT_NMI);
        }

        return (Interrupt);
}
Beispiel #12
0
static void timer_tick(void)
{
	z80_set_irq_line(0, ASSERT_LINE);
	z80_set_irq_line(0, CLEAR_LINE);
}
Beispiel #13
0
// 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
}