mirror of
https://github.com/holub/mame
synced 2025-07-05 01:48:29 +03:00
mac.cpp: Moved maclc3 and maclc520 to a new, cleaner, independent driver. [R. Belmont]
This commit is contained in:
parent
9403db09ee
commit
8d28264487
@ -7,7 +7,7 @@
|
||||
|
||||
TODO:
|
||||
- V8 and friends (LC, LC2, Classic 2, Color Classic) to own driver
|
||||
- LC3 / LC520 / IIvx / IIvi to own driver
|
||||
- IIvx / IIvi to own driver
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
@ -146,23 +146,6 @@ void mac_state::ariel_ramdac_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mac_state::mac_sonora_vctl_r(offs_t offset)
|
||||
{
|
||||
if (offset == 2)
|
||||
{
|
||||
// printf("Sonora: read monitor ID at PC=%x\n", m_maincpu->pc());
|
||||
return (m_montype.read_safe(6)<<4);
|
||||
}
|
||||
|
||||
return m_sonora_vctl[offset];
|
||||
}
|
||||
|
||||
void mac_state::mac_sonora_vctl_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
// printf("Sonora: %02x to vctl %x\n", data, offset);
|
||||
m_sonora_vctl[offset] = data;
|
||||
}
|
||||
|
||||
void mac_state::rbv_recalc_irqs()
|
||||
{
|
||||
// check slot interrupts and bubble them down to IFR
|
||||
@ -491,7 +474,6 @@ void mac_state::maclc3_map(address_map &map)
|
||||
map(0x50016000, 0x50017fff).rw(FUNC(mac_state::mac_iwm_r), FUNC(mac_state::mac_iwm_w)).mirror(0x00f00000);
|
||||
map(0x50024000, 0x50025fff).w(FUNC(mac_state::ariel_ramdac_w)).mirror(0x00f00000);
|
||||
map(0x50026000, 0x50027fff).rw(FUNC(mac_state::mac_rbv_r), FUNC(mac_state::mac_rbv_w)).mirror(0x00f00000);
|
||||
map(0x50028000, 0x50028003).rw(FUNC(mac_state::mac_sonora_vctl_r), FUNC(mac_state::mac_sonora_vctl_w)).mirror(0x00f00000);
|
||||
|
||||
map(0x5ffffffc, 0x5fffffff).r(FUNC(mac_state::mac_read_id));
|
||||
|
||||
@ -923,35 +905,6 @@ void mac_state::maccclas(machine_config &config)
|
||||
m_via1->writepb_handler().set(FUNC(mac_state::mac_via_out_b_cdadb));
|
||||
}
|
||||
|
||||
void mac_state::maclc3(machine_config &config, bool egret)
|
||||
{
|
||||
maclc(config, false, false, asc_device::asc_type::SONORA, 2);
|
||||
|
||||
M68030(config, m_maincpu, 25000000);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::maclc3_map);
|
||||
m_maincpu->set_dasm_override(FUNC(mac_state::mac_dasm_override));
|
||||
|
||||
MCFG_VIDEO_START_OVERRIDE(mac_state,macsonora)
|
||||
MCFG_VIDEO_RESET_OVERRIDE(mac_state,macsonora)
|
||||
|
||||
m_screen->set_screen_update(FUNC(mac_state::screen_update_macsonora));
|
||||
|
||||
m_ram->set_default_size("4M");
|
||||
m_ram->set_extra_options("8M,16M,32M,48M,64M,80M");
|
||||
|
||||
if (egret)
|
||||
{
|
||||
add_egret(config, EGRET_341S0851);
|
||||
}
|
||||
}
|
||||
|
||||
void mac_state::maclc520(machine_config &config)
|
||||
{
|
||||
maclc3(config, false);
|
||||
add_cuda(config, CUDA_341S0060);
|
||||
m_via1->writepb_handler().set(FUNC(mac_state::mac_via_out_b_cdadb));
|
||||
}
|
||||
|
||||
void mac_state::maciivx(machine_config &config)
|
||||
{
|
||||
maclc(config, false, true, asc_device::asc_type::VASP);
|
||||
@ -1232,20 +1185,11 @@ ROM_START( maclc2 )
|
||||
ROM_LOAD32_BYTE( "341-0473_ub2-ll.bin", 0x000003, 0x020000, CRC(8843c37c) SHA1(bb5104110507ca543d106f11c6061245fd90c1a7) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( maclc3 )
|
||||
ROM_REGION32_BE(0x100000, "bootrom", 0)
|
||||
ROM_LOAD( "ecbbc41c.rom", 0x000000, 0x100000, CRC(e578f5f3) SHA1(c77df3220c861f37a2c553b6ee9241b202dfdffc) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( maccclas )
|
||||
ROM_REGION32_BE(0x100000, "bootrom", 0)
|
||||
ROM_LOAD( "ecd99dc0.rom", 0x000000, 0x100000, CRC(c84c3aa5) SHA1(fd9e852e2d77fe17287ba678709b9334d4d74f1e) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( maclc520 )
|
||||
ROM_REGION32_BE(0x100000, "bootrom", 0)
|
||||
ROM_LOAD( "ede66cbd.rom", 0x000000, 0x100000, CRC(a893cb0f) SHA1(c54ee2f45020a4adeb7451adce04cd6e5fb69790) )
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
|
||||
COMP( 1987, macii, 0, 0, macii, macadb, mac_state, init_macii, "Apple Computer", "Macintosh II", MACHINE_SUPPORTS_SAVE )
|
||||
@ -1261,7 +1205,5 @@ COMP( 1990, maciisi, 0, 0, maciisi, maciici, mac_state, init_maci
|
||||
COMP( 1991, macclas2, 0, 0, macclas2, macadb, mac_state, init_macclassic2, "Apple Computer", "Macintosh Classic II", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND )
|
||||
COMP( 1991, maclc2, 0, 0, maclc2, maciici, mac_state, init_maclc2, "Apple Computer", "Macintosh LC II", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND )
|
||||
COMP( 1993, maccclas, 0, 0, maccclas, macadb, mac_state, init_maclrcclassic, "Apple Computer", "Macintosh Color Classic", MACHINE_NOT_WORKING )
|
||||
COMP( 1993, maclc3, 0, 0, maclc3, maciici, mac_state, init_maclc3, "Apple Computer", "Macintosh LC III", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND )
|
||||
COMP( 1993, maciivx, 0, 0, maciivx, maciici, mac_state, init_maciivx, "Apple Computer", "Macintosh IIvx", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND )
|
||||
COMP( 1993, maciivi, maciivx, 0, maciivi, maciici, mac_state, init_maciivi, "Apple Computer", "Macintosh IIvi", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND )
|
||||
COMP( 1993, maclc520, 0, 0, maclc520, maciici, mac_state, init_maclc520, "Apple Computer", "Macintosh LC 520", MACHINE_NOT_WORKING )
|
||||
|
@ -216,7 +216,6 @@ private:
|
||||
{
|
||||
RBV_TYPE_RBV = 0,
|
||||
RBV_TYPE_V8,
|
||||
RBV_TYPE_SONORA,
|
||||
RBV_TYPE_DAFB
|
||||
};
|
||||
|
||||
@ -236,7 +235,7 @@ private:
|
||||
int m_screen_buffer = 0;
|
||||
int irq_count = 0, ca1_data = 0, ca2_data = 0;
|
||||
|
||||
// 60.15 Hz timer for RBV/V8/Sonora/Eagle/VASP/etc.
|
||||
// 60.15 Hz timer for RBV/V8/Eagle/VASP/etc.
|
||||
emu_timer *m_6015_timer = nullptr;
|
||||
|
||||
// ADB refresh timer, independent of anything else going on
|
||||
@ -248,7 +247,6 @@ private:
|
||||
uint8_t m_rbv_regs[256]{}, m_rbv_ier = 0, m_rbv_ifr = 0, m_rbv_type = 0, m_rbv_montype = 0, m_rbv_vbltime = 0;
|
||||
uint32_t m_rbv_colors[3]{}, m_rbv_count = 0, m_rbv_clutoffs = 0, m_rbv_immed10wr = 0;
|
||||
uint32_t m_rbv_palette[256]{};
|
||||
uint8_t m_sonora_vctl[8]{};
|
||||
emu_timer *m_vbl_timer = nullptr, *m_cursor_timer = nullptr;
|
||||
uint16_t m_cursor_line = 0;
|
||||
|
||||
@ -295,8 +293,6 @@ private:
|
||||
uint32_t rbv_ramdac_r();
|
||||
void rbv_ramdac_w(offs_t offset, uint32_t data);
|
||||
void ariel_ramdac_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
uint8_t mac_sonora_vctl_r(offs_t offset);
|
||||
void mac_sonora_vctl_w(offs_t offset, uint8_t data);
|
||||
uint8_t mac_rbv_r(offs_t offset);
|
||||
void mac_rbv_w(offs_t offset, uint8_t data);
|
||||
|
||||
@ -355,17 +351,14 @@ private:
|
||||
void hdsel_w(int hdsel);
|
||||
|
||||
DECLARE_VIDEO_START(mac);
|
||||
DECLARE_VIDEO_START(macsonora);
|
||||
DECLARE_VIDEO_RESET(macrbv);
|
||||
DECLARE_VIDEO_START(macv8);
|
||||
DECLARE_VIDEO_RESET(macsonora);
|
||||
DECLARE_VIDEO_RESET(maceagle);
|
||||
DECLARE_VIDEO_START(macrbv);
|
||||
uint32_t screen_update_macse30(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_macrbvvram(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_macv8(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_macsonora(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(mac_rbv_vbl);
|
||||
TIMER_CALLBACK_MEMBER(mac_6015_tick);
|
||||
|
@ -1005,7 +1005,7 @@ void mac_state::mac_via2_out_b(uint8_t data)
|
||||
}
|
||||
}
|
||||
|
||||
// This signal is generated internally on RBV, V8, Sonora, VASP, Eagle, etc.
|
||||
// This signal is generated internally on RBV, V8, VASP, Eagle, etc.
|
||||
TIMER_CALLBACK_MEMBER(mac_state::mac_6015_tick)
|
||||
{
|
||||
m_via1->write_ca1(0);
|
||||
@ -1048,7 +1048,6 @@ void mac_state::machine_start()
|
||||
save_item(NAME(m_rbv_count));
|
||||
save_item(NAME(m_rbv_clutoffs));
|
||||
save_item(NAME(m_rbv_palette));
|
||||
save_item(NAME(m_sonora_vctl));
|
||||
save_item(NAME(m_scc_interrupt));
|
||||
save_item(NAME(m_via_interrupt));
|
||||
save_item(NAME(m_via2_interrupt));
|
||||
|
@ -11,7 +11,7 @@
|
||||
Classic)
|
||||
|
||||
Also emulates on-board video for systems with the
|
||||
RBV, V8, Eagle, Sonora, and DAFB chips.
|
||||
RBV, V8, Eagle, and DAFB chips.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Monitor sense codes
|
||||
@ -84,7 +84,7 @@ uint32_t mac_state::screen_update_macse30(screen_device &screen, bitmap_ind16 &b
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IIci/IIsi RAM-Based Video (RBV) and children: V8, Eagle, Spice, VASP, Sonora
|
||||
// IIci/IIsi RAM-Based Video (RBV) and children: V8, Eagle, Spice, VASP
|
||||
|
||||
VIDEO_START_MEMBER(mac_state,macrbv)
|
||||
{
|
||||
@ -150,77 +150,6 @@ VIDEO_RESET_MEMBER(mac_state,macrbv)
|
||||
target->set_view(view);
|
||||
}
|
||||
|
||||
VIDEO_RESET_MEMBER(mac_state,macsonora)
|
||||
{
|
||||
int htotal, vtotal;
|
||||
double framerate;
|
||||
int view = 0;
|
||||
|
||||
memset(m_rbv_regs, 0, sizeof(m_rbv_regs));
|
||||
|
||||
m_rbv_count = 0;
|
||||
m_rbv_clutoffs = 0;
|
||||
m_rbv_immed10wr = 0;
|
||||
|
||||
m_rbv_regs[2] = 0x7f;
|
||||
m_rbv_regs[3] = 0;
|
||||
|
||||
m_rbv_type = RBV_TYPE_SONORA;
|
||||
|
||||
m_rbv_montype = m_montype.read_safe(2);
|
||||
rectangle visarea;
|
||||
switch (m_rbv_montype)
|
||||
{
|
||||
case 1: // 15" portrait display
|
||||
visarea.set(0, 640-1, 0, 870-1);
|
||||
htotal = 832;
|
||||
vtotal = 918;
|
||||
framerate = 75.0;
|
||||
view = 1;
|
||||
break;
|
||||
|
||||
case 2: // 12" RGB
|
||||
visarea.set(0, 512-1, 0, 384-1);
|
||||
htotal = 640;
|
||||
vtotal = 407;
|
||||
framerate = 60.15;
|
||||
break;
|
||||
|
||||
case 6: // 13" RGB
|
||||
default:
|
||||
visarea.set(0, 640-1, 0, 480-1);
|
||||
htotal = 800;
|
||||
vtotal = 525;
|
||||
framerate = 59.94;
|
||||
break;
|
||||
}
|
||||
|
||||
// logerror("Sonora reset: monitor is %dx%d @ %f Hz\n", visarea.width(), visarea.height(), framerate);
|
||||
m_screen->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(framerate));
|
||||
render_target *target = machine().render().first_target();
|
||||
target->set_view(view);
|
||||
}
|
||||
|
||||
VIDEO_START_MEMBER(mac_state,macsonora)
|
||||
{
|
||||
memset(m_rbv_regs, 0, sizeof(m_rbv_regs));
|
||||
|
||||
m_rbv_count = 0;
|
||||
m_rbv_clutoffs = 0;
|
||||
m_rbv_immed10wr = 0;
|
||||
|
||||
m_rbv_regs[2] = 0x7f;
|
||||
m_rbv_regs[3] = 0;
|
||||
m_rbv_regs[4] = 0x6;
|
||||
m_rbv_regs[5] = 0x3;
|
||||
|
||||
m_sonora_vctl[0] = 0x9f;
|
||||
m_sonora_vctl[1] = 0;
|
||||
m_sonora_vctl[2] = 0;
|
||||
|
||||
m_rbv_type = RBV_TYPE_SONORA;
|
||||
}
|
||||
|
||||
VIDEO_START_MEMBER(mac_state,macv8)
|
||||
{
|
||||
memset(m_rbv_regs, 0, sizeof(m_rbv_regs));
|
||||
@ -575,131 +504,3 @@ uint32_t mac_state::screen_update_macv8(screen_device &screen, bitmap_rgb32 &bit
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t mac_state::screen_update_macsonora(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int hres, vres, stride;
|
||||
switch (m_rbv_montype)
|
||||
{
|
||||
case 1: // 15" portrait display
|
||||
stride = hres = 640;
|
||||
vres = 870;
|
||||
break;
|
||||
|
||||
case 2: // 12" RGB
|
||||
stride = hres = 512;
|
||||
vres = 384;
|
||||
break;
|
||||
|
||||
case 6: // 13" RGB
|
||||
default:
|
||||
stride = hres = 640;
|
||||
vres = 480;
|
||||
break;
|
||||
}
|
||||
|
||||
// forced blank?
|
||||
if (m_sonora_vctl[0] & 0x80)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (m_sonora_vctl[1] & 7)
|
||||
{
|
||||
case 0: // 1bpp
|
||||
{
|
||||
uint8_t const *const vram8 = (uint8_t *)m_vram.target();
|
||||
|
||||
for (int y = 0; y < vres; y++)
|
||||
{
|
||||
uint32_t *scanline = &bitmap.pix(y);
|
||||
for (int x = 0; x < hres; x+=8)
|
||||
{
|
||||
uint8_t const pixels = vram8[(y * (stride/8)) + ((x/8)^3)];
|
||||
|
||||
*scanline++ = m_rbv_palette[0x7f|(pixels&0x80)];
|
||||
*scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)];
|
||||
*scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)];
|
||||
*scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)];
|
||||
*scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)];
|
||||
*scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)];
|
||||
*scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)];
|
||||
*scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 2bpp
|
||||
{
|
||||
uint8_t const *const vram8 = (uint8_t *)m_vram.target();
|
||||
|
||||
for (int y = 0; y < vres; y++)
|
||||
{
|
||||
uint32_t *scanline = &bitmap.pix(y);
|
||||
for (int x = 0; x < hres/4; x++)
|
||||
{
|
||||
uint8_t const pixels = vram8[(y * (stride/4)) + (BYTE4_XOR_BE(x))];
|
||||
|
||||
*scanline++ = m_rbv_palette[0x3f|(pixels&0xc0)];
|
||||
*scanline++ = m_rbv_palette[0x3f|((pixels<<2)&0xc0)];
|
||||
*scanline++ = m_rbv_palette[0x3f|((pixels<<4)&0xc0)];
|
||||
*scanline++ = m_rbv_palette[0x3f|((pixels<<6)&0xc0)];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // 4bpp
|
||||
{
|
||||
uint8_t const *const vram8 = (uint8_t *)m_vram.target();
|
||||
|
||||
for (int y = 0; y < vres; y++)
|
||||
{
|
||||
uint32_t *scanline = &bitmap.pix(y);
|
||||
for (int x = 0; x < hres/2; x++)
|
||||
{
|
||||
uint8_t const pixels = vram8[(y * (stride/2)) + (BYTE4_XOR_BE(x))];
|
||||
|
||||
*scanline++ = m_rbv_palette[(pixels&0xf0) | 0xf];
|
||||
*scanline++ = m_rbv_palette[((pixels&0x0f)<<4) | 0xf];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // 8bpp
|
||||
{
|
||||
uint8_t const *const vram8 = (uint8_t *)m_vram.target();
|
||||
|
||||
for (int y = 0; y < vres; y++)
|
||||
{
|
||||
uint32_t *scanline = &bitmap.pix(y);
|
||||
for (int x = 0; x < hres; x++)
|
||||
{
|
||||
uint8_t const pixels = vram8[(y * stride) + (BYTE4_XOR_BE(x))];
|
||||
*scanline++ = m_rbv_palette[pixels];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // 16bpp
|
||||
{
|
||||
uint16_t const *const vram16 = (uint16_t *)m_vram.target();
|
||||
|
||||
for (int y = 0; y < vres; y++)
|
||||
{
|
||||
uint32_t *scanline = &bitmap.pix(y);
|
||||
for (int x = 0; x < hres; x++)
|
||||
{
|
||||
uint16_t const pixels = vram16[(y * stride) + (x^1)];
|
||||
*scanline++ = rgb_t(((pixels>>10) & 0x1f)<<3, ((pixels>>5) & 0x1f)<<3, (pixels & 0x1f)<<3);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
323
src/mame/apple/maclc3.cpp
Normal file
323
src/mame/apple/maclc3.cpp
Normal file
@ -0,0 +1,323 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
/****************************************************************************
|
||||
|
||||
drivers/maclc3.cpp
|
||||
Mac LC III ("Vail")
|
||||
Mac LC 520 ("Hook")
|
||||
|
||||
By R. Belmont
|
||||
|
||||
These are basically identical '030 machines, except the LC III is a pizzabox
|
||||
while the LC 520 is an all-in-one with a 14" Sony Trinitron built-in.
|
||||
LC III uses the Egret ADB microcontroller while LC 520 uses the later Cuda.
|
||||
Everything else is the same.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "bus/nscsi/devices.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "machine/ram.h"
|
||||
#include "machine/timer.h"
|
||||
#include "machine/z80scc.h"
|
||||
#include "machine/nscsi_bus.h"
|
||||
#include "machine/ncr5380.h"
|
||||
#include "cuda.h"
|
||||
#include "egret.h"
|
||||
#include "macadb.h"
|
||||
#include "macscsi.h"
|
||||
#include "sonora.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
static constexpr u32 C7M = 7833600;
|
||||
static constexpr u32 C15M = (C7M * 2);
|
||||
|
||||
class macvail_state : public driver_device
|
||||
{
|
||||
public:
|
||||
macvail_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_macadb(*this, "macadb"),
|
||||
m_ram(*this, RAM_TAG),
|
||||
m_sonora(*this, "sonora"),
|
||||
m_scsibus1(*this, "scsi"),
|
||||
m_ncr5380(*this, "scsi:7:ncr5380"),
|
||||
m_scsihelp(*this, "scsihelp"),
|
||||
m_scc(*this, "scc"),
|
||||
m_egret(*this, "egret"),
|
||||
m_cuda(*this, "cuda")
|
||||
{
|
||||
}
|
||||
|
||||
void maclc3_base(machine_config &config);
|
||||
void maclc3(machine_config &config);
|
||||
void maclc520(machine_config &config);
|
||||
void base_map(address_map &map);
|
||||
void maclc3_map(address_map &map);
|
||||
void maclc520_map(address_map &map);
|
||||
|
||||
private:
|
||||
required_device<m68030_device> m_maincpu;
|
||||
optional_device<macadb_device> m_macadb;
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<sonora_device> m_sonora;
|
||||
required_device<nscsi_bus_device> m_scsibus1;
|
||||
required_device<ncr5380_device> m_ncr5380;
|
||||
required_device<mac_scsi_helper_device> m_scsihelp;
|
||||
required_device<z80scc_device> m_scc;
|
||||
optional_device<egret_device> m_egret;
|
||||
optional_device<cuda_device> m_cuda;
|
||||
|
||||
virtual void machine_start() override;
|
||||
|
||||
WRITE_LINE_MEMBER(adb_irq_w) { m_adb_irq_pending = state; }
|
||||
int m_adb_irq_pending = 0;
|
||||
|
||||
u16 scc_r(offs_t offset)
|
||||
{
|
||||
u16 result = m_scc->dc_ab_r(offset);
|
||||
return (result << 8) | result;
|
||||
}
|
||||
void scc_w(offs_t offset, u16 data)
|
||||
{
|
||||
m_scc->dc_ab_w(offset, data >> 8);
|
||||
}
|
||||
|
||||
u16 scsi_r(offs_t offset, u16 mem_mask = ~0);
|
||||
void scsi_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
u32 scsi_drq_r(offs_t offset, u32 mem_mask = ~0);
|
||||
void scsi_drq_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
|
||||
void scsi_berr_w(u8 data)
|
||||
{
|
||||
m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(cuda_reset_w)
|
||||
{
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, state);
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, state);
|
||||
}
|
||||
};
|
||||
|
||||
void macvail_state::machine_start()
|
||||
{
|
||||
m_sonora->set_ram_info((u32 *) m_ram->pointer(), m_ram->size());
|
||||
|
||||
save_item(NAME(m_adb_irq_pending));
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
ADDRESS MAPS
|
||||
***************************************************************************/
|
||||
void macvail_state::base_map(address_map &map)
|
||||
{
|
||||
// RAM, ROM, and base I/O mappings come from Sonora (LCIII) / Ardbeg (LC520)
|
||||
map(0x40000000, 0x600fffff).m(m_sonora, FUNC(sonora_device::map));
|
||||
|
||||
map(0x50004000, 0x50005fff).rw(FUNC(macvail_state::scc_r), FUNC(macvail_state::scc_w)).mirror(0x00f00000);
|
||||
map(0x50006000, 0x50007fff).rw(FUNC(macvail_state::scsi_drq_r), FUNC(macvail_state::scsi_drq_w)).mirror(0x00f00000);
|
||||
map(0x50010000, 0x50011fff).rw(FUNC(macvail_state::scsi_r), FUNC(macvail_state::scsi_w)).mirror(0x00f00000);
|
||||
map(0x50012000, 0x50013fff).rw(FUNC(macvail_state::scsi_drq_r), FUNC(macvail_state::scsi_drq_w)).mirror(0x00f00000);
|
||||
}
|
||||
|
||||
void macvail_state::maclc3_map(address_map &map)
|
||||
{
|
||||
base_map(map);
|
||||
map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a0001; }));
|
||||
}
|
||||
|
||||
void macvail_state::maclc520_map(address_map &map)
|
||||
{
|
||||
base_map(map);
|
||||
map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a0100; }));
|
||||
}
|
||||
|
||||
u16 macvail_state::scsi_r(offs_t offset, u16 mem_mask)
|
||||
{
|
||||
const int reg = (offset >> 3) & 0xf;
|
||||
const bool pseudo_dma = (reg == 6) && (offset == 0x130);
|
||||
|
||||
return m_scsihelp->read_wrapper(pseudo_dma, reg) << 8;
|
||||
}
|
||||
|
||||
void macvail_state::scsi_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
const int reg = (offset >> 3) & 0xf;
|
||||
const bool pseudo_dma = (reg == 0) && (offset == 0x100);
|
||||
|
||||
m_scsihelp->write_wrapper(pseudo_dma, reg, data >> 8);
|
||||
}
|
||||
|
||||
u32 macvail_state::scsi_drq_r(offs_t offset, u32 mem_mask)
|
||||
{
|
||||
switch (mem_mask)
|
||||
{
|
||||
case 0xff000000:
|
||||
return m_scsihelp->read_wrapper(true, 6) << 24;
|
||||
|
||||
case 0xffff0000:
|
||||
return (m_scsihelp->read_wrapper(true, 6) << 24) | (m_scsihelp->read_wrapper(true, 6) << 16);
|
||||
|
||||
case 0xffffffff:
|
||||
return (m_scsihelp->read_wrapper(true, 6) << 24) | (m_scsihelp->read_wrapper(true, 6) << 16) | (m_scsihelp->read_wrapper(true, 6) << 8) | m_scsihelp->read_wrapper(true, 6);
|
||||
|
||||
default:
|
||||
logerror("scsi_drq_r: unknown mem_mask %08x\n", mem_mask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void macvail_state::scsi_drq_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
switch (mem_mask)
|
||||
{
|
||||
case 0xff000000:
|
||||
m_scsihelp->write_wrapper(true, 0, data >> 24);
|
||||
break;
|
||||
|
||||
case 0xffff0000:
|
||||
m_scsihelp->write_wrapper(true, 0, data >> 24);
|
||||
m_scsihelp->write_wrapper(true, 0, data >> 16);
|
||||
break;
|
||||
|
||||
case 0xffffffff:
|
||||
m_scsihelp->write_wrapper(true, 0, data >> 24);
|
||||
m_scsihelp->write_wrapper(true, 0, data >> 16);
|
||||
m_scsihelp->write_wrapper(true, 0, data >> 8);
|
||||
m_scsihelp->write_wrapper(true, 0, data & 0xff);
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("scsi_drq_w: unknown mem_mask %08x\n", mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE CONFIG
|
||||
***************************************************************************/
|
||||
|
||||
static INPUT_PORTS_START( macadb )
|
||||
INPUT_PORTS_END
|
||||
|
||||
/***************************************************************************
|
||||
MACHINE DRIVERS
|
||||
***************************************************************************/
|
||||
|
||||
void macvail_state::maclc3_base(machine_config &config)
|
||||
{
|
||||
M68030(config, m_maincpu, 25000000);
|
||||
|
||||
RAM(config, m_ram);
|
||||
m_ram->set_default_size("4M");
|
||||
m_ram->set_extra_options("8M,16M,32M,48M,64M,80M");
|
||||
|
||||
NSCSI_BUS(config, "scsi");
|
||||
NSCSI_CONNECTOR(config, "scsi:0", mac_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:1", mac_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:2", mac_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:3", mac_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, "cdrom");
|
||||
NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:6", mac_scsi_devices, "harddisk");
|
||||
NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR53C80).machine_config([this](device_t *device)
|
||||
{
|
||||
ncr53c80_device &adapter = downcast<ncr53c80_device &>(*device);
|
||||
adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w));
|
||||
});
|
||||
|
||||
MAC_SCSI_HELPER(config, m_scsihelp);
|
||||
m_scsihelp->scsi_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::read));
|
||||
m_scsihelp->scsi_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::write));
|
||||
m_scsihelp->scsi_dma_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_r));
|
||||
m_scsihelp->scsi_dma_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_w));
|
||||
m_scsihelp->cpu_halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
|
||||
m_scsihelp->timeout_error_callback().set(FUNC(macvail_state::scsi_berr_w));
|
||||
|
||||
SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd");
|
||||
SOFTWARE_LIST(config, "flop35hd_list").set_original("mac_hdflop");
|
||||
|
||||
SCC85C30(config, m_scc, C7M);
|
||||
m_scc->configure_channels(3'686'400, 3'686'400, 3'686'400, 3'686'400);
|
||||
m_scc->out_int_callback().set(m_sonora, FUNC(sonora_device::scc_irq_w));
|
||||
m_scc->out_txda_callback().set("printer", FUNC(rs232_port_device::write_txd));
|
||||
m_scc->out_txdb_callback().set("modem", FUNC(rs232_port_device::write_txd));
|
||||
|
||||
rs232_port_device &rs232a(RS232_PORT(config, "printer", default_rs232_devices, nullptr));
|
||||
rs232a.rxd_handler().set(m_scc, FUNC(z80scc_device::rxa_w));
|
||||
rs232a.dcd_handler().set(m_scc, FUNC(z80scc_device::dcda_w));
|
||||
rs232a.cts_handler().set(m_scc, FUNC(z80scc_device::ctsa_w));
|
||||
|
||||
rs232_port_device &rs232b(RS232_PORT(config, "modem", default_rs232_devices, nullptr));
|
||||
rs232b.rxd_handler().set(m_scc, FUNC(z80scc_device::rxb_w));
|
||||
rs232b.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w));
|
||||
rs232b.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w));
|
||||
|
||||
SONORA(config, m_sonora, C15M);
|
||||
m_sonora->set_maincpu_tag("maincpu");
|
||||
m_sonora->set_rom_tag(":bootrom");
|
||||
|
||||
MACADB(config, m_macadb, C15M);
|
||||
m_macadb->adb_irq_callback().set(FUNC(macvail_state::adb_irq_w));
|
||||
m_macadb->set_mcu_mode(true);
|
||||
}
|
||||
|
||||
void macvail_state::maclc3(machine_config &config)
|
||||
{
|
||||
maclc3_base(config);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &macvail_state::maclc3_map);
|
||||
|
||||
EGRET(config, m_egret, EGRET_341S0851);
|
||||
m_egret->reset_callback().set(FUNC(macvail_state::cuda_reset_w));
|
||||
m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w));
|
||||
m_egret->via_clock_callback().set(m_sonora, FUNC(sonora_device::cb1_w));
|
||||
m_egret->via_data_callback().set(m_sonora, FUNC(sonora_device::cb2_w));
|
||||
m_macadb->adb_data_callback().set(m_egret, FUNC(egret_device::set_adb_line));
|
||||
config.set_perfect_quantum(m_maincpu);
|
||||
|
||||
m_sonora->pb3_callback().set(m_egret, FUNC(egret_device::get_xcvr_session));
|
||||
m_sonora->pb4_callback().set(m_egret, FUNC(egret_device::set_via_full));
|
||||
m_sonora->pb5_callback().set(m_egret, FUNC(egret_device::set_sys_session));
|
||||
m_sonora->cb2_callback().set(m_egret, FUNC(egret_device::set_via_data));
|
||||
}
|
||||
|
||||
void macvail_state::maclc520(machine_config &config)
|
||||
{
|
||||
maclc3_base(config);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &macvail_state::maclc520_map);
|
||||
|
||||
CUDA(config, m_cuda, CUDA_341S0060);
|
||||
m_cuda->reset_callback().set(FUNC(macvail_state::cuda_reset_w));
|
||||
m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w));
|
||||
m_cuda->via_clock_callback().set(m_sonora, FUNC(sonora_device::cb1_w));
|
||||
m_cuda->via_data_callback().set(m_sonora, FUNC(sonora_device::cb2_w));
|
||||
m_macadb->adb_data_callback().set(m_cuda, FUNC(cuda_device::set_adb_line));
|
||||
config.set_perfect_quantum(m_maincpu);
|
||||
|
||||
m_sonora->pb3_callback().set(m_cuda, FUNC(cuda_device::get_treq));
|
||||
m_sonora->pb4_callback().set(m_cuda, FUNC(cuda_device::set_byteack));
|
||||
m_sonora->pb5_callback().set(m_cuda, FUNC(cuda_device::set_tip));
|
||||
m_sonora->cb2_callback().set(m_cuda, FUNC(cuda_device::set_via_data));
|
||||
}
|
||||
|
||||
ROM_START( maclc3 )
|
||||
ROM_REGION32_BE(0x100000, "bootrom", 0)
|
||||
ROM_LOAD( "ecbbc41c.rom", 0x000000, 0x100000, CRC(e578f5f3) SHA1(c77df3220c861f37a2c553b6ee9241b202dfdffc) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( maclc520 )
|
||||
ROM_REGION32_BE(0x100000, "bootrom", 0)
|
||||
ROM_LOAD( "ede66cbd.rom", 0x000000, 0x100000, CRC(a893cb0f) SHA1(c54ee2f45020a4adeb7451adce04cd6e5fb69790) )
|
||||
ROM_END
|
||||
|
||||
COMP(1993, maclc3, 0, 0, maclc3, macadb, macvail_state, empty_init, "Apple Computer", "Macintosh LC III", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND)
|
||||
COMP(1993, maclc520, 0, 0, maclc520, macadb, macvail_state, empty_init, "Apple Computer", "Macintosh LC 520", MACHINE_NOT_WORKING)
|
569
src/mame/apple/sonora.cpp
Normal file
569
src/mame/apple/sonora.cpp
Normal file
@ -0,0 +1,569 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
/*
|
||||
Apple "Sonora" system ASIC
|
||||
Emulation by R. Belmont
|
||||
|
||||
Sonora contains the following:
|
||||
- A memory controller for up to 36MB (up to 4MB soldered and 32MB of SIMMs)
|
||||
- A VRAM controller and framebuffer controller
|
||||
- A full VIA (VIA1) and a "pseudo-VIA", which is basically a combination GPIO and
|
||||
interrupt controller that looks somewhat like a VIA with no timers and no shift register.
|
||||
- A SWIM2 floppy controller
|
||||
- An ASC-like 4-channel audio controller
|
||||
|
||||
The "Ardbeg" ASIC (LC 520) appears to be a renamed copy of Sonora, and "Prime Time"
|
||||
(LC 475/575 and some low-end Quadras) is Sonora adapted to the 68040 bus. "Prime Time II"
|
||||
is similar but adds an ATA controller.
|
||||
|
||||
Sonora's video controller is in some of the PowerMac chipsets as well.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sonora.h"
|
||||
#include "formats/ap_dsk35.h"
|
||||
|
||||
static constexpr u32 C7M = 7833600;
|
||||
static constexpr u32 C15M = (C7M * 2);
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(SONORA, sonora_device, "sonora", "Apple Sonora system ASIC")
|
||||
|
||||
//-------------------------------------------------
|
||||
// ADDRESS_MAP
|
||||
//-------------------------------------------------
|
||||
|
||||
void sonora_device::map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x000fffff).r(FUNC(sonora_device::rom_switch_r)).mirror(0x0ff00000);
|
||||
|
||||
map(0x10000000, 0x10001fff).rw(FUNC(sonora_device::mac_via_r), FUNC(sonora_device::mac_via_w)).mirror(0x00fc0000);
|
||||
map(0x10014000, 0x10015fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00f00000);
|
||||
map(0x10016000, 0x10017fff).rw(FUNC(sonora_device::swim_r), FUNC(sonora_device::swim_w)).mirror(0x00f00000);
|
||||
map(0x10026000, 0x10027fff).rw(FUNC(sonora_device::pseudovia_r), FUNC(sonora_device::pseudovia_w)).mirror(0x00f00000);
|
||||
map(0x10f24000, 0x10f24003).rw(m_video, FUNC(mac_video_sonora_device::dac_r), FUNC(mac_video_sonora_device::dac_w));
|
||||
map(0x10f28000, 0x10f28007).rw(m_video, FUNC(mac_video_sonora_device::vctrl_r), FUNC(mac_video_sonora_device::vctrl_w));
|
||||
|
||||
map(0x20000000, 0x200fffff).ram().mirror(0x0ff00000).rw(FUNC(sonora_device::vram_r), FUNC(sonora_device::vram_w));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
//-------------------------------------------------
|
||||
|
||||
void sonora_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
MAC_VIDEO_SONORA(config, m_video);
|
||||
m_video->screen_vblank().set(FUNC(sonora_device::vbl_w));
|
||||
|
||||
R65NC22(config, m_via1, C7M / 10);
|
||||
m_via1->readpa_handler().set(FUNC(sonora_device::via_in_a));
|
||||
m_via1->readpb_handler().set(FUNC(sonora_device::via_in_b));
|
||||
m_via1->writepa_handler().set(FUNC(sonora_device::via_out_a));
|
||||
m_via1->writepb_handler().set(FUNC(sonora_device::via_out_b));
|
||||
m_via1->cb2_handler().set(FUNC(sonora_device::via_out_cb2));
|
||||
m_via1->irq_handler().set(FUNC(sonora_device::via1_irq));
|
||||
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
ASC(config, m_asc, C15M, asc_device::asc_type::SONORA);
|
||||
m_asc->add_route(0, "lspeaker", 1.0);
|
||||
m_asc->add_route(1, "rspeaker", 1.0);
|
||||
|
||||
SWIM2(config, m_fdc, C15M);
|
||||
m_fdc->devsel_cb().set(FUNC(sonora_device::devsel_w));
|
||||
m_fdc->phases_cb().set(FUNC(sonora_device::phases_w));
|
||||
|
||||
applefdintf_device::add_35_hd(config, m_floppy[0]);
|
||||
applefdintf_device::add_35_nc(config, m_floppy[1]);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// sonora_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sonora_device::sonora_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SONORA, tag, owner, clock),
|
||||
write_pb4(*this),
|
||||
write_pb5(*this),
|
||||
write_cb2(*this),
|
||||
read_pb3(*this),
|
||||
m_maincpu(*this, finder_base::DUMMY_TAG),
|
||||
m_video(*this, "sonora_video"),
|
||||
m_via1(*this, "via1"),
|
||||
m_asc(*this, "asc"),
|
||||
m_fdc(*this, "fdc"),
|
||||
m_floppy(*this, "fdc:%d", 0U),
|
||||
m_rom(*this, finder_base::DUMMY_TAG),
|
||||
m_cur_floppy(nullptr),
|
||||
m_hdsel(0),
|
||||
m_overlay(false)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sonora_device::device_start()
|
||||
{
|
||||
m_vram = std::make_unique<u32[]>(0x100000 / sizeof(u32));
|
||||
|
||||
write_pb4.resolve_safe();
|
||||
write_pb5.resolve_safe();
|
||||
write_cb2.resolve_safe();
|
||||
read_pb3.resolve_safe(0);
|
||||
|
||||
m_6015_timer = timer_alloc(FUNC(sonora_device::mac_6015_tick), this);
|
||||
m_6015_timer->adjust(attotime::never);
|
||||
|
||||
save_pointer(NAME(m_vram), 0x100000/sizeof(u32));
|
||||
save_item(NAME(m_via_interrupt));
|
||||
save_item(NAME(m_via2_interrupt));
|
||||
save_item(NAME(m_scc_interrupt));
|
||||
save_item(NAME(m_last_taken_interrupt));
|
||||
save_item(NAME(m_pseudovia_regs));
|
||||
save_item(NAME(m_pseudovia_ier));
|
||||
save_item(NAME(m_pseudovia_ifr));
|
||||
save_item(NAME(m_hdsel));
|
||||
|
||||
m_rom_ptr = &m_rom[0];
|
||||
m_rom_size = m_rom.length() << 2;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void sonora_device::device_reset()
|
||||
{
|
||||
m_video->set_vram_base((const u64 *)&m_vram[0]);
|
||||
m_video->set_vram_offset(0);
|
||||
m_video->set_32bit();
|
||||
|
||||
// start 60.15 Hz timer
|
||||
m_6015_timer->adjust(attotime::from_hz(60.15), 0, attotime::from_hz(60.15));
|
||||
|
||||
std::fill_n(m_pseudovia_regs, 256, 0);
|
||||
m_pseudovia_regs[2] = 0x7f;
|
||||
m_via_interrupt = m_via2_interrupt = m_scc_interrupt = 0;
|
||||
m_last_taken_interrupt = -1;
|
||||
m_hdsel = 0;
|
||||
|
||||
// main cpu shouldn't start until Egret wakes it up
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
||||
|
||||
m_overlay = true;
|
||||
|
||||
// put ROM mirror at 0
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
const u32 memory_size = std::min((u32)0x3fffff, m_rom_size);
|
||||
const u32 memory_end = memory_size - 1;
|
||||
offs_t memory_mirror = memory_end & ~(memory_size - 1);
|
||||
|
||||
space.unmap_write(0x00000000, memory_end);
|
||||
space.install_rom(0x00000000, memory_end & ~memory_mirror, memory_mirror, m_rom_ptr);
|
||||
}
|
||||
|
||||
u32 sonora_device::rom_switch_r(offs_t offset)
|
||||
{
|
||||
// disable the overlay
|
||||
if (m_overlay)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
const u32 memory_end = m_ram_size - 1;
|
||||
void *memory_data = m_ram_ptr;
|
||||
offs_t memory_mirror = memory_end & ~memory_end;
|
||||
|
||||
space.install_ram(0x00000000, memory_end & ~memory_mirror, memory_mirror, memory_data);
|
||||
m_overlay = false;
|
||||
}
|
||||
|
||||
return m_rom_ptr[offset & ((m_rom_size - 1) >> 2)];
|
||||
}
|
||||
|
||||
void sonora_device::set_ram_info(u32 *ram, u32 size)
|
||||
{
|
||||
m_ram_ptr = ram;
|
||||
m_ram_size = size;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(sonora_device::mac_6015_tick)
|
||||
{
|
||||
m_via1->write_ca1(CLEAR_LINE);
|
||||
m_via1->write_ca1(ASSERT_LINE);
|
||||
}
|
||||
|
||||
uint8_t sonora_device::via_in_a()
|
||||
{
|
||||
return 0x80;
|
||||
}
|
||||
|
||||
uint8_t sonora_device::via_in_b()
|
||||
{
|
||||
return read_pb3() << 3;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sonora_device::via_out_cb2)
|
||||
{
|
||||
write_cb2(state & 1);
|
||||
}
|
||||
|
||||
void sonora_device::via_out_a(uint8_t data)
|
||||
{
|
||||
int hdsel = BIT(data, 5);
|
||||
if (hdsel != m_hdsel)
|
||||
{
|
||||
if (m_cur_floppy)
|
||||
{
|
||||
m_cur_floppy->ss_w(hdsel);
|
||||
}
|
||||
}
|
||||
m_hdsel = hdsel;
|
||||
}
|
||||
|
||||
void sonora_device::via_out_b(uint8_t data)
|
||||
{
|
||||
write_pb4(BIT(data, 4));
|
||||
write_pb5(BIT(data, 5));
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sonora_device::via1_irq)
|
||||
{
|
||||
m_via_interrupt = state;
|
||||
field_interrupts();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sonora_device::via2_irq)
|
||||
{
|
||||
m_via2_interrupt = state;
|
||||
field_interrupts();
|
||||
}
|
||||
|
||||
void sonora_device::field_interrupts()
|
||||
{
|
||||
int take_interrupt = -1;
|
||||
|
||||
if (m_scc_interrupt)
|
||||
{
|
||||
take_interrupt = 4;
|
||||
}
|
||||
else if (m_via2_interrupt)
|
||||
{
|
||||
take_interrupt = 2;
|
||||
}
|
||||
else if (m_via_interrupt)
|
||||
{
|
||||
take_interrupt = 1;
|
||||
}
|
||||
|
||||
if (m_last_taken_interrupt > -1)
|
||||
{
|
||||
m_maincpu->set_input_line(m_last_taken_interrupt, CLEAR_LINE);
|
||||
m_last_taken_interrupt = -1;
|
||||
}
|
||||
|
||||
if (take_interrupt > -1)
|
||||
{
|
||||
m_maincpu->set_input_line(take_interrupt, ASSERT_LINE);
|
||||
m_last_taken_interrupt = take_interrupt;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sonora_device::scc_irq_w)
|
||||
{
|
||||
m_scc_interrupt = (state == ASSERT_LINE);
|
||||
field_interrupts();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sonora_device::vbl_w)
|
||||
{
|
||||
if (!state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pseudovia_regs[2] &= ~0x40; // set vblank signal
|
||||
|
||||
if (m_pseudovia_regs[0x12] & 0x40)
|
||||
{
|
||||
pseudovia_recalc_irqs();
|
||||
}
|
||||
}
|
||||
|
||||
void sonora_device::pseudovia_recalc_irqs()
|
||||
{
|
||||
// check slot interrupts and bubble them down to IFR
|
||||
uint8_t slot_irqs = (~m_pseudovia_regs[2]) & 0x78;
|
||||
slot_irqs &= (m_pseudovia_regs[0x12] & 0x78);
|
||||
|
||||
if (slot_irqs)
|
||||
{
|
||||
m_pseudovia_regs[3] |= 2; // any slot
|
||||
}
|
||||
else // no slot irqs, clear the pending bit
|
||||
{
|
||||
m_pseudovia_regs[3] &= ~2; // any slot
|
||||
}
|
||||
|
||||
uint8_t ifr = (m_pseudovia_regs[3] & m_pseudovia_ier) & 0x1b;
|
||||
|
||||
if (ifr != 0)
|
||||
{
|
||||
m_pseudovia_regs[3] = ifr | 0x80;
|
||||
m_pseudovia_ifr = ifr | 0x80;
|
||||
|
||||
via2_irq(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
via2_irq(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sonora_device::pseudovia_r(offs_t offset)
|
||||
{
|
||||
int data = 0;
|
||||
|
||||
if (offset < 0x100)
|
||||
{
|
||||
data = m_pseudovia_regs[offset];
|
||||
|
||||
if (offset == 0x10)
|
||||
{
|
||||
data &= ~0x38;
|
||||
}
|
||||
|
||||
// bit 7 of these registers always reads as 0 on pseudo-VIAs
|
||||
if ((offset == 0x12) || (offset == 0x13))
|
||||
{
|
||||
data &= ~0x80;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset >>= 9;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 13: // IFR
|
||||
data = m_pseudovia_ifr;
|
||||
break;
|
||||
|
||||
case 14: // IER
|
||||
data = m_pseudovia_ier;
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("pseudovia_r: Unknown pseudo-VIA register %d access\n", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void sonora_device::pseudovia_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (offset < 0x100)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0x02:
|
||||
m_pseudovia_regs[offset] |= (data & 0x40);
|
||||
pseudovia_recalc_irqs();
|
||||
break;
|
||||
|
||||
case 0x03: // write here to ack
|
||||
if (data & 0x80) // 1 bits write 1s
|
||||
{
|
||||
m_pseudovia_regs[offset] |= data & 0x7f;
|
||||
m_pseudovia_ifr |= data & 0x7f;
|
||||
}
|
||||
else // 1 bits write 0s
|
||||
{
|
||||
m_pseudovia_regs[offset] &= ~(data & 0x7f);
|
||||
m_pseudovia_ifr &= ~(data & 0x7f);
|
||||
}
|
||||
pseudovia_recalc_irqs();
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
m_pseudovia_regs[offset] = data;
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
if (data & 0x80) // 1 bits write 1s
|
||||
{
|
||||
m_pseudovia_regs[offset] |= data & 0x7f;
|
||||
}
|
||||
else // 1 bits write 0s
|
||||
{
|
||||
m_pseudovia_regs[offset] &= ~(data & 0x7f);
|
||||
}
|
||||
pseudovia_recalc_irqs();
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
if (data & 0x80) // 1 bits write 1s
|
||||
{
|
||||
m_pseudovia_regs[offset] |= data & 0x7f;
|
||||
|
||||
if (data == 0xff)
|
||||
m_pseudovia_regs[offset] = 0x1f; // I don't know why this is special, but the IIci ROM's POST demands it
|
||||
}
|
||||
else // 1 bits write 0s
|
||||
{
|
||||
m_pseudovia_regs[offset] &= ~(data & 0x7f);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
m_pseudovia_regs[offset] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset >>= 9;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 13: // IFR
|
||||
if (data & 0x80)
|
||||
{
|
||||
data = 0x7f;
|
||||
}
|
||||
pseudovia_recalc_irqs();
|
||||
break;
|
||||
|
||||
case 14: // IER
|
||||
if (data & 0x80) // 1 bits write 1s
|
||||
{
|
||||
m_pseudovia_ier |= data & 0x7f;
|
||||
}
|
||||
else // 1 bits write 0s
|
||||
{
|
||||
m_pseudovia_ier &= ~(data & 0x7f);
|
||||
}
|
||||
pseudovia_recalc_irqs();
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("pseudovia_w: Unknown extended pseudo-VIA register %d access\n", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sonora_device::cb1_w)
|
||||
{
|
||||
m_via1->write_cb1(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(sonora_device::cb2_w)
|
||||
{
|
||||
m_via1->write_cb2(state);
|
||||
}
|
||||
|
||||
uint16_t sonora_device::mac_via_r(offs_t offset)
|
||||
{
|
||||
uint16_t data;
|
||||
|
||||
offset >>= 8;
|
||||
offset &= 0x0f;
|
||||
|
||||
if (!machine().side_effects_disabled())
|
||||
via_sync();
|
||||
|
||||
data = m_via1->read(offset);
|
||||
|
||||
return (data & 0xff) | (data << 8);
|
||||
}
|
||||
|
||||
void sonora_device::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
offset >>= 8;
|
||||
offset &= 0x0f;
|
||||
|
||||
via_sync();
|
||||
|
||||
if (ACCESSING_BITS_0_7)
|
||||
m_via1->write(offset, data & 0xff);
|
||||
if (ACCESSING_BITS_8_15)
|
||||
m_via1->write(offset, (data >> 8) & 0xff);
|
||||
}
|
||||
|
||||
void sonora_device::via_sync()
|
||||
{
|
||||
// The via runs at 783.36KHz while the main cpu runs at 15MHz or
|
||||
// more, so we need to sync the access with the via clock. Plus
|
||||
// the whole access takes half a (via) cycle and ends when synced
|
||||
// with the main cpu again.
|
||||
|
||||
// Get the main cpu time
|
||||
u64 cycle = m_maincpu->total_cycles();
|
||||
|
||||
// Get the number of the cycle the via is in at that time
|
||||
u64 via_cycle = cycle * m_via1->clock() / m_maincpu->clock();
|
||||
|
||||
// The access is going to start at via_cycle+1 and end at
|
||||
// via_cycle+1.5, compute what that means in maincpu cycles (the
|
||||
// +1 rounds up, since the clocks are too different to ever be
|
||||
// synced).
|
||||
u64 main_cycle = (via_cycle * 2 + 3) * m_maincpu->clock() / (2 * m_via1->clock()) + 1;
|
||||
|
||||
// Finally adjust the main cpu icount as needed.
|
||||
m_maincpu->adjust_icount(-int(main_cycle - cycle));
|
||||
}
|
||||
|
||||
uint16_t sonora_device::swim_r(offs_t offset, u16 mem_mask)
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_maincpu->adjust_icount(-5);
|
||||
}
|
||||
|
||||
u16 result = m_fdc->read((offset >> 8) & 0xf);
|
||||
return result << 8;
|
||||
}
|
||||
void sonora_device::swim_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
m_fdc->write((offset >> 8) & 0xf, data & 0xff);
|
||||
else
|
||||
m_fdc->write((offset >> 8) & 0xf, data >> 8);
|
||||
}
|
||||
|
||||
void sonora_device::phases_w(uint8_t phases)
|
||||
{
|
||||
if (m_cur_floppy)
|
||||
m_cur_floppy->seek_phase_w(phases);
|
||||
}
|
||||
|
||||
void sonora_device::devsel_w(uint8_t devsel)
|
||||
{
|
||||
if (devsel == 1)
|
||||
m_cur_floppy = m_floppy[0]->get_device();
|
||||
else if (devsel == 2)
|
||||
m_cur_floppy = m_floppy[1]->get_device();
|
||||
else
|
||||
m_cur_floppy = nullptr;
|
||||
|
||||
m_fdc->set_floppy(m_cur_floppy);
|
||||
if (m_cur_floppy)
|
||||
m_cur_floppy->ss_w(m_hdsel);
|
||||
}
|
||||
|
||||
u32 sonora_device::vram_r(offs_t offset)
|
||||
{
|
||||
return m_vram[offset];
|
||||
}
|
||||
|
||||
void sonora_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_vram[offset]);
|
||||
}
|
||||
|
107
src/mame/apple/sonora.h
Normal file
107
src/mame/apple/sonora.h
Normal file
@ -0,0 +1,107 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
|
||||
#ifndef MAME_MACHINE_SONORA_H
|
||||
#define MAME_MACHINE_SONORA_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/6522via.h"
|
||||
#include "machine/applefdintf.h"
|
||||
#include "machine/mv_sonora.h"
|
||||
#include "machine/swim2.h"
|
||||
#include "sound/asc.h"
|
||||
#include "speaker.h"
|
||||
|
||||
// ======================> sonora_device
|
||||
|
||||
class sonora_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sonora_device(const machine_config &mconfig, const char *tag, device_t *owner)
|
||||
: sonora_device(mconfig, tag, owner, (uint32_t)0)
|
||||
{
|
||||
}
|
||||
|
||||
sonora_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// interface routines
|
||||
auto pb4_callback() { return write_pb4.bind(); }
|
||||
auto pb5_callback() { return write_pb5.bind(); }
|
||||
auto cb2_callback() { return write_cb2.bind(); }
|
||||
auto pb3_callback() { return read_pb3.bind(); }
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
template <typename T> void set_maincpu_tag(T &&cpu_tag) { m_maincpu.set_tag(std::forward<T>(cpu_tag)); }
|
||||
template <typename... T> void set_rom_tag(T &&... args) { m_rom.set_tag(std::forward<T>(args)...); }
|
||||
void set_ram_info(u32 *ram, u32 size);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(cb1_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(cb2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(vbl_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(scc_irq_w);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
private:
|
||||
devcb_write_line write_pb4, write_pb5, write_cb2;
|
||||
devcb_read_line read_pb3;
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<mac_video_sonora_device> m_video;
|
||||
required_device<via6522_device> m_via1;
|
||||
required_device<asc_device> m_asc;
|
||||
required_device<applefdintf_device> m_fdc;
|
||||
required_device_array<floppy_connector, 2> m_floppy;
|
||||
required_region_ptr<u32> m_rom;
|
||||
|
||||
std::unique_ptr<u32[]> m_vram;
|
||||
emu_timer *m_6015_timer;
|
||||
int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt;
|
||||
uint8_t m_pseudovia_regs[256], m_pseudovia_ier, m_pseudovia_ifr;
|
||||
floppy_image_device *m_cur_floppy = nullptr;
|
||||
int m_hdsel;
|
||||
bool m_overlay;
|
||||
u32 *m_ram_ptr, *m_rom_ptr;
|
||||
u32 m_ram_size, m_rom_size;
|
||||
|
||||
u32 rom_switch_r(offs_t offset);
|
||||
|
||||
uint8_t pseudovia_r(offs_t offset);
|
||||
void pseudovia_w(offs_t offset, uint8_t data);
|
||||
void pseudovia_recalc_irqs();
|
||||
|
||||
uint16_t mac_via_r(offs_t offset);
|
||||
void mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask);
|
||||
|
||||
uint8_t via_in_a();
|
||||
uint8_t via_in_b();
|
||||
void via_out_a(uint8_t data);
|
||||
void via_out_b(uint8_t data);
|
||||
void via_sync();
|
||||
void field_interrupts();
|
||||
DECLARE_WRITE_LINE_MEMBER(via_out_cb2);
|
||||
DECLARE_WRITE_LINE_MEMBER(via1_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(via2_irq);
|
||||
TIMER_CALLBACK_MEMBER(mac_6015_tick);
|
||||
|
||||
void phases_w(uint8_t phases);
|
||||
void devsel_w(uint8_t devsel);
|
||||
uint16_t swim_r(offs_t offset, u16 mem_mask);
|
||||
void swim_w(offs_t offset, u16 data, u16 mem_mask);
|
||||
|
||||
u32 vram_r(offs_t offset);
|
||||
void vram_w(offs_t offset, u32 data, u32 mem_mask);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(SONORA, sonora_device)
|
||||
|
||||
#endif // MAME_MACHINE_SONORA_H
|
@ -20729,9 +20729,11 @@ maciivx // 1993 Apple Macintosh IIvx
|
||||
maciix // 1988 Apple Macintosh IIx
|
||||
maclc // 1990 Apple Macintosh LC
|
||||
maclc2 // 1991 Apple Macintosh LC II
|
||||
macse30 // 1989 Apple Macintosh SE/30
|
||||
|
||||
@source:apple/maclc3.cpp
|
||||
maclc3 // 1993 Apple Macintosh LC III
|
||||
maclc520 // 1993 Apple Macintosh LC 520
|
||||
macse30 // 1989 Apple Macintosh SE/30
|
||||
|
||||
@source:apple/macpdm.cpp
|
||||
pmac6100 // 1993 Apple Power Macintosh 6100
|
||||
@ -27528,7 +27530,7 @@ m4hotrod__v //
|
||||
m4holdtm // Hold Timer (Barcrest)
|
||||
m4hpyjok // Happy Joker (Barcrest)
|
||||
m4jok300 // Jokers Millenium 300
|
||||
m4jok300a //
|
||||
m4jok300a //
|
||||
m4jolgem // Jolly Gems (Barcrest)
|
||||
m4jolgem__0 //
|
||||
m4jolgem__1 //
|
||||
|
Loading…
Reference in New Issue
Block a user