forked from mamedev/mame
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sinclair/specnext_divmmc.cpp: Added Spectrum Next DivMMC device emula…
…tion. [holub]
- Loading branch information
Showing
2 changed files
with
229 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// license:BSD-3-Clause | ||
// copyright-holders:Andrei I. Holub | ||
/********************************************************************** | ||
Spectrum Next DivMMC | ||
**********************************************************************/ | ||
|
||
#include "emu.h" | ||
#include "specnext_divmmc.h" | ||
|
||
|
||
specnext_divmmc_device::specnext_divmmc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) | ||
: device_t(mconfig, SPECNEXT_DIVMMC, tag, owner, clock) | ||
{ | ||
} | ||
|
||
bool specnext_divmmc_device::conmem() const noexcept | ||
{ | ||
return BIT(m_divmmc_reg, 7); | ||
} | ||
|
||
bool specnext_divmmc_device::mapram() const noexcept | ||
{ | ||
return BIT(m_divmmc_reg, 6); | ||
} | ||
|
||
bool specnext_divmmc_device::page0() const noexcept | ||
{ | ||
return m_cpu_a_15_13 == 0; | ||
} | ||
|
||
bool specnext_divmmc_device::page1() const noexcept | ||
{ | ||
return m_cpu_a_15_13 == 1; | ||
} | ||
|
||
bool specnext_divmmc_device::rom_en() const noexcept | ||
{ | ||
return page0() && (conmem() || automap()) && !mapram(); | ||
} | ||
|
||
bool specnext_divmmc_device::ram_en() const noexcept | ||
{ | ||
return (page0() && (conmem() || automap()) && mapram()) || (page1() && (conmem() || automap())); | ||
} | ||
|
||
u8 specnext_divmmc_device::ram_bank() const noexcept | ||
{ | ||
return page0() ? 3 : (m_divmmc_reg & 0x0f); | ||
} | ||
|
||
bool specnext_divmmc_device::automap_nmi_instant_on() const noexcept | ||
{ | ||
return m_automap_nmi_instant_on && m_button_nmi; | ||
} | ||
|
||
bool specnext_divmmc_device::automap_nmi_delayed_on() const noexcept | ||
{ | ||
return m_automap_nmi_delayed_on && m_button_nmi; | ||
} | ||
|
||
bool specnext_divmmc_device::automap() const noexcept | ||
{ | ||
return !m_automap_reset && (m_automap_held | ||
|| (m_automap_active && (m_automap_instant_on || automap_nmi_instant_on())) | ||
|| (m_automap_rom3_active && m_automap_rom3_instant_on)); | ||
} | ||
|
||
void specnext_divmmc_device::clock_w() noexcept | ||
{ | ||
// Rising edge | ||
if (m_automap_reset || m_retn_seen) | ||
m_button_nmi = 0; | ||
else if (m_divmmc_button) | ||
m_button_nmi = 1; | ||
else if (m_automap_held) | ||
m_button_nmi = 0; | ||
|
||
if (m_automap_reset || m_retn_seen) | ||
{ | ||
m_automap_hold = 0; | ||
} | ||
else if (!m_cpu_mreq_n && !m_cpu_m1_n) | ||
{ | ||
m_automap_hold = (m_automap_active && (m_automap_instant_on || m_automap_delayed_on || automap_nmi_instant_on() || automap_nmi_delayed_on())) | ||
|| (m_automap_rom3_active && (m_automap_rom3_instant_on || m_automap_rom3_delayed_on)) | ||
|| (m_automap_held && !(m_automap_active && m_automap_delayed_off)); | ||
} | ||
|
||
if (m_automap_reset || m_retn_seen) | ||
m_automap_held = 0; | ||
else if (m_cpu_mreq_n) | ||
m_automap_held = m_automap_hold; | ||
} | ||
|
||
|
||
void specnext_divmmc_device::device_start() | ||
{ | ||
save_item(NAME(m_cpu_a_15_13)); | ||
save_item(NAME(m_cpu_mreq_n)); | ||
save_item(NAME(m_cpu_m1_n)); | ||
save_item(NAME(m_en)); | ||
save_item(NAME(m_automap_reset)); | ||
save_item(NAME(m_automap_active)); | ||
save_item(NAME(m_automap_rom3_active)); | ||
save_item(NAME(m_retn_seen)); | ||
save_item(NAME(m_divmmc_button)); | ||
save_item(NAME(m_divmmc_reg)); | ||
save_item(NAME(m_automap_instant_on)); | ||
save_item(NAME(m_automap_delayed_on)); | ||
save_item(NAME(m_automap_delayed_off)); | ||
save_item(NAME(m_automap_rom3_instant_on)); | ||
save_item(NAME(m_automap_rom3_delayed_on)); | ||
save_item(NAME(m_automap_nmi_instant_on)); | ||
save_item(NAME(m_automap_nmi_delayed_on)); | ||
save_item(NAME(m_button_nmi)); | ||
save_item(NAME(m_automap_hold)); | ||
save_item(NAME(m_automap_held)); | ||
} | ||
|
||
void specnext_divmmc_device::device_reset() | ||
{ | ||
m_cpu_mreq_n = 0; | ||
m_cpu_m1_n = 0; | ||
|
||
m_automap_instant_on = 0; | ||
m_automap_delayed_on = 0; | ||
m_automap_delayed_off = 0; | ||
m_automap_rom3_instant_on = 0; | ||
m_automap_rom3_delayed_on = 0; | ||
m_automap_nmi_instant_on = 0; | ||
m_automap_nmi_delayed_on = 0; | ||
|
||
m_automap_hold = 0; | ||
m_automap_held = 0; | ||
m_button_nmi = 0; | ||
} | ||
|
||
|
||
// device type definition | ||
DEFINE_DEVICE_TYPE(SPECNEXT_DIVMMC, specnext_divmmc_device, "specnext_divmmc", "Spectrum Next DivMMC") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// license:BSD-3-Clause | ||
// copyright-holders:Andrei I. Holub | ||
#ifndef MAME_SINCLAIR_SPECNEXT_DIVMMC_H | ||
#define MAME_SINCLAIR_SPECNEXT_DIVMMC_H | ||
|
||
#pragma once | ||
|
||
class specnext_divmmc_device : public device_t | ||
{ | ||
public: | ||
specnext_divmmc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); | ||
|
||
void cpu_a_15_13_w(u8 data) { m_cpu_a_15_13 = data & 0x07; }; | ||
void cpu_mreq_n_w(bool data) { m_cpu_mreq_n = data; } | ||
void cpu_m1_n_w(bool data) { m_cpu_m1_n = data; } | ||
void automap_active_w(bool data) { m_automap_active = data; } | ||
void automap_rom3_active_w(bool data) { m_automap_rom3_active = data; } | ||
|
||
void en_w(bool data) { m_en = data; } | ||
void automap_reset_w(bool data) { m_automap_reset = data; } | ||
void retn_seen_w(bool data) { m_retn_seen = data; } | ||
|
||
void divmmc_button_w(bool data) { m_divmmc_button = data; } | ||
void divmmc_reg_w(u8 data) { m_divmmc_reg = data; } | ||
|
||
void automap_instant_on_w(bool data) { m_automap_instant_on = data; } | ||
void automap_delayed_on_w(bool data) { m_automap_delayed_on = data; } | ||
void automap_delayed_off_w(bool data) { m_automap_delayed_off = data; } | ||
void automap_rom3_instant_on_w(bool data) { m_automap_rom3_instant_on = data; } | ||
void automap_rom3_delayed_on_w(bool data) { m_automap_rom3_delayed_on = data; } | ||
void automap_nmi_instant_on_w(bool data) { m_automap_nmi_instant_on = data; } | ||
void automap_nmi_delayed_on_w(bool data) { m_automap_nmi_delayed_on = data; } | ||
|
||
bool divmmc_rom_en_r() const { return rom_en() && m_en; } | ||
bool divmmc_ram_en_r() const { return ram_en() && m_en; } | ||
bool divmmc_rdonly_r() const { return page0() || (mapram() && ram_bank() == 3); } | ||
u8 divmmc_ram_bank_r() const { return ram_bank() & 0x0f; } | ||
|
||
void clock_w() noexcept; // called on active clock edge | ||
|
||
protected: | ||
virtual void device_start() override ATTR_COLD; | ||
virtual void device_reset() override ATTR_COLD; | ||
|
||
private: | ||
// in | ||
u8 m_cpu_a_15_13; | ||
bool m_cpu_mreq_n; | ||
bool m_cpu_m1_n; | ||
|
||
bool m_en; | ||
bool m_automap_reset; | ||
bool m_automap_active; | ||
bool m_automap_rom3_active; | ||
bool m_retn_seen; | ||
|
||
bool m_divmmc_button; | ||
u8 m_divmmc_reg; | ||
|
||
bool m_automap_instant_on; | ||
bool m_automap_delayed_on; | ||
bool m_automap_delayed_off; | ||
bool m_automap_rom3_instant_on; | ||
bool m_automap_rom3_delayed_on; | ||
bool m_automap_nmi_instant_on; | ||
bool m_automap_nmi_delayed_on; | ||
|
||
// internal | ||
bool m_button_nmi; | ||
bool m_automap_hold; | ||
bool m_automap_held; | ||
|
||
// signal | ||
bool conmem() const noexcept; | ||
bool mapram() const noexcept; | ||
bool page0() const noexcept; | ||
bool page1() const noexcept; | ||
bool rom_en() const noexcept; | ||
bool ram_en() const noexcept; | ||
u8 ram_bank() const noexcept; | ||
bool automap_nmi_instant_on() const noexcept; | ||
bool automap_nmi_delayed_on() const noexcept; | ||
bool automap() const noexcept; | ||
|
||
}; | ||
|
||
DECLARE_DEVICE_TYPE(SPECNEXT_DIVMMC, specnext_divmmc_device) | ||
|
||
#endif // MAME_SINCLAIR_SPECNEXT_DIVMMC_H |