(MESS) Apple 1: Added support for expansion slot, moved cassette interface to a card to match reality. [R. Belmont]

This commit is contained in:
R. Belmont 2014-04-19 18:51:51 +00:00
parent ee6e952772
commit ee918601db
10 changed files with 640 additions and 145 deletions

4
.gitattributes vendored
View File

@ -388,6 +388,10 @@ src/emu/attotime.c svneol=native#text/plain
src/emu/attotime.h svneol=native#text/plain
src/emu/audit.c svneol=native#text/plain
src/emu/audit.h svneol=native#text/plain
src/emu/bus/a1bus/a1bus.c svneol=native#text/plain
src/emu/bus/a1bus/a1bus.h svneol=native#text/plain
src/emu/bus/a1bus/a1cassette.c svneol=native#text/plain
src/emu/bus/a1bus/a1cassette.h svneol=native#text/plain
src/emu/bus/a2bus/a2alfam2.c svneol=native#text/plain
src/emu/bus/a2bus/a2alfam2.h svneol=native#text/plain
src/emu/bus/a2bus/a2applicard.c svneol=native#text/plain

206
src/emu/bus/a1bus/a1bus.c Normal file
View File

@ -0,0 +1,206 @@
/***************************************************************************
a1bus.c - Apple I slot bus and card emulation
license: BSD-3-Clause
copyright-holders: R. Belmont
***************************************************************************/
#include "emu.h"
#include "emuopts.h"
#include "a1bus.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type A1BUS_SLOT = &device_creator<a1bus_slot_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// a1bus_slot_device - constructor
//-------------------------------------------------
a1bus_slot_device::a1bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, A1BUS_SLOT, "Apple I Slot", tag, owner, clock, "a1bus_slot", __FILE__),
device_slot_interface(mconfig, *this)
{
}
a1bus_slot_device::a1bus_slot_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_slot_interface(mconfig, *this)
{
}
void a1bus_slot_device::static_set_a1bus_slot(device_t &device, const char *tag, const char *slottag)
{
a1bus_slot_device &a1bus_card = dynamic_cast<a1bus_slot_device &>(device);
a1bus_card.m_a1bus_tag = tag;
a1bus_card.m_a1bus_slottag = slottag;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void a1bus_slot_device::device_start()
{
device_a1bus_card_interface *dev = dynamic_cast<device_a1bus_card_interface *>(get_card_device());
if (dev) device_a1bus_card_interface::static_set_a1bus_tag(*dev, m_a1bus_tag, m_a1bus_slottag);
}
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type A1BUS = &device_creator<a1bus_device>;
void a1bus_device::static_set_cputag(device_t &device, const char *tag)
{
a1bus_device &a1bus = downcast<a1bus_device &>(device);
a1bus.m_cputag = tag;
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// a1bus_device - constructor
//-------------------------------------------------
a1bus_device::a1bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, A1BUS, "Apple I Bus", tag, owner, clock, "a1bus", __FILE__),
m_out_irq_cb(*this),
m_out_nmi_cb(*this)
{
}
a1bus_device::a1bus_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
m_out_irq_cb(*this),
m_out_nmi_cb(*this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void a1bus_device::device_start()
{
m_maincpu = machine().device<cpu_device>(m_cputag);
// resolve callbacks
m_out_irq_cb.resolve_safe();
m_out_nmi_cb.resolve_safe();
// clear slot
m_device = NULL;
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void a1bus_device::device_reset()
{
}
device_a1bus_card_interface *a1bus_device::get_a1bus_card()
{
return m_device;
}
void a1bus_device::add_a1bus_card(device_a1bus_card_interface *card)
{
m_device = card;
}
void a1bus_device::set_irq_line(int state)
{
m_out_irq_cb(state);
}
void a1bus_device::set_nmi_line(int state)
{
m_out_nmi_cb(state);
}
void a1bus_device::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler)
{
m_maincpu = machine().device<cpu_device>(m_cputag);
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler);
}
void a1bus_device::install_bank(offs_t start, offs_t end, offs_t mask, offs_t mirror, const char *tag, UINT8 *data)
{
// printf("install_bank: %s @ %x->%x mask %x mirror %x\n", tag, start, end, mask, mirror);
m_maincpu = machine().device<cpu_device>(m_cputag);
address_space &space = m_maincpu->space(AS_PROGRAM);
space.install_readwrite_bank(start, end, mask, mirror, tag );
machine().root_device().membank(tag)->set_base(data);
}
// interrupt request from a1bus card
WRITE_LINE_MEMBER( a1bus_device::irq_w ) { m_out_irq_cb(state); }
WRITE_LINE_MEMBER( a1bus_device::nmi_w ) { m_out_nmi_cb(state); }
//**************************************************************************
// DEVICE CONFIG A1BUS CARD INTERFACE
//**************************************************************************
//**************************************************************************
// DEVICE A1BUS CARD INTERFACE
//**************************************************************************
//-------------------------------------------------
// device_a1bus_card_interface - constructor
//-------------------------------------------------
device_a1bus_card_interface::device_a1bus_card_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device),
m_a1bus(NULL),
m_a1bus_tag(NULL)
{
}
//-------------------------------------------------
// ~device_a1bus_card_interface - destructor
//-------------------------------------------------
device_a1bus_card_interface::~device_a1bus_card_interface()
{
}
void device_a1bus_card_interface::static_set_a1bus_tag(device_t &device, const char *tag, const char *slottag)
{
device_a1bus_card_interface &a1bus_card = dynamic_cast<device_a1bus_card_interface &>(device);
a1bus_card.m_a1bus_tag = tag;
a1bus_card.m_a1bus_slottag = slottag;
}
void device_a1bus_card_interface::set_a1bus_device()
{
m_a1bus = dynamic_cast<a1bus_device *>(device().machine().device(m_a1bus_tag));
m_a1bus->add_a1bus_card(this);
}
void device_a1bus_card_interface::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler)
{
m_a1bus->install_device(start, end, rhandler, whandler);
}
void device_a1bus_card_interface::install_bank(offs_t start, offs_t end, offs_t mask, offs_t mirror, char *tag, UINT8 *data)
{
m_a1bus->install_bank(start, end, mask, mirror, tag, data);
}

146
src/emu/bus/a1bus/a1bus.h Normal file
View File

@ -0,0 +1,146 @@
/***************************************************************************
a1bus.h - Apple I expansion slot and card emulation
license: BSD-3-Clause
copyright-holders: R. Belmont
***************************************************************************/
#pragma once
#ifndef __A1BUS_H__
#define __A1BUS_H__
#include "emu.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_A1BUS_CPU(_cputag) \
a1bus_device::static_set_cputag(*device, _cputag);
#define MCFG_A1BUS_OUT_IRQ_CB(_devcb) \
devcb = &a1bus_device::set_out_irq_callback(*device, DEVCB2_##_devcb);
#define MCFG_A1BUS_OUT_NMI_CB(_devcb) \
devcb = &a1bus_device::set_out_nmi_callback(*device, DEVCB2_##_devcb);
#define MCFG_A1BUS_SLOT_ADD(_nbtag, _tag, _slot_intf, _def_slot) \
MCFG_DEVICE_ADD(_tag, A1BUS_SLOT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
a1bus_slot_device::static_set_a1bus_slot(*device, _nbtag, _tag);
#define MCFG_A1BUS_SLOT_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
#define MCFG_A1BUS_ONBOARD_ADD(_nbtag, _tag, _dev_type, _def_inp) \
MCFG_DEVICE_ADD(_tag, _dev_type, 0) \
MCFG_DEVICE_INPUT_DEFAULTS(_def_inp) \
device_a1bus_card_interface::static_set_a1bus_tag(*device, _nbtag, _tag);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class a1bus_device;
class a1bus_slot_device : public device_t,
public device_slot_interface
{
public:
// construction/destruction
a1bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
a1bus_slot_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// device-level overrides
virtual void device_start();
// inline configuration
static void static_set_a1bus_slot(device_t &device, const char *tag, const char *slottag);
protected:
// configuration
const char *m_a1bus_tag, *m_a1bus_slottag;
};
// device type definition
extern const device_type A1BUS_SLOT;
class device_a1bus_card_interface;
// ======================> a1bus_device
class a1bus_device : public device_t
{
public:
// construction/destruction
a1bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
a1bus_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// inline configuration
static void static_set_cputag(device_t &device, const char *tag);
template<class _Object> static devcb2_base &set_out_irq_callback(device_t &device, _Object object) { return downcast<a1bus_device &>(device).m_out_irq_cb.set_callback(object); }
template<class _Object> static devcb2_base &set_out_nmi_callback(device_t &device, _Object object) { return downcast<a1bus_device &>(device).m_out_nmi_cb.set_callback(object); }
void add_a1bus_card(device_a1bus_card_interface *card);
device_a1bus_card_interface *get_a1bus_card();
void set_irq_line(int state);
void set_nmi_line(int state);
void install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
void install_bank(offs_t start, offs_t end, offs_t mask, offs_t mirror, const char *tag, UINT8 *data);
DECLARE_WRITE_LINE_MEMBER( irq_w );
DECLARE_WRITE_LINE_MEMBER( nmi_w );
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
// internal state
cpu_device *m_maincpu;
devcb2_write_line m_out_irq_cb;
devcb2_write_line m_out_nmi_cb;
device_a1bus_card_interface *m_device;
const char *m_cputag;
};
// device type definition
extern const device_type A1BUS;
// ======================> device_a1bus_card_interface
// class representing interface-specific live a1bus card
class device_a1bus_card_interface : public device_slot_card_interface
{
friend class a1bus_device;
public:
// construction/destruction
device_a1bus_card_interface(const machine_config &mconfig, device_t &device);
virtual ~device_a1bus_card_interface();
device_a1bus_card_interface *next() const { return m_next; }
void set_a1bus_device();
void raise_slot_irq() { m_a1bus->set_irq_line(ASSERT_LINE); }
void lower_slot_irq() { m_a1bus->set_irq_line(CLEAR_LINE); }
void raise_slot_nmi() { m_a1bus->set_nmi_line(ASSERT_LINE); }
void lower_slot_nmi() { m_a1bus->set_nmi_line(CLEAR_LINE); }
void install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
void install_bank(offs_t start, offs_t end, offs_t mask, offs_t mirror, char *tag, UINT8 *data);
// inline configuration
static void static_set_a1bus_tag(device_t &device, const char *tag, const char *slottag);
public:
a1bus_device *m_a1bus;
const char *m_a1bus_tag, *m_a1bus_slottag;
device_a1bus_card_interface *m_next;
};
#endif /* __A1BUS_H__ */

View File

@ -0,0 +1,206 @@
/*********************************************************************
a1cassette.c
Apple I Cassette Interface
*********************************************************************/
#include "a1cassette.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
#define CASSETTE_ROM_REGION "casrom"
const device_type A1BUS_CASSETTE = &device_creator<a1bus_cassette_device>;
/* sound output */
static const cassette_interface apple1_cassette_interface =
{
cassette_default_formats,
NULL,
(cassette_state)(CASSETTE_STOPPED),
"apple1_cass",
NULL
};
MACHINE_CONFIG_FRAGMENT( cassette )
MCFG_CASSETTE_ADD("cassette", apple1_cassette_interface)
MACHINE_CONFIG_END
ROM_START( cassette )
/* 256-byte cassette interface ROM, in two 82s129 or mmi6301 256x4 proms at locations 3 and 4 on the cassette interface daughtercard (they are labeled "MMI 6301-IJ // 7623L // APPLE-A3" and "MMI 6301-IJ // 7623L // APPLE-A4") */
ROM_REGION(0x100, CASSETTE_ROM_REGION, 0)
ROM_LOAD_NIB_HIGH( "apple-a3.3", 0x0000, 0x0100, CRC(6eae8f52) SHA1(71906932727ef70952ef6afe6b08708df15cd67d) )
ROM_LOAD_NIB_LOW( "apple-a4.4", 0x0000, 0x0100, CRC(94efa977) SHA1(851f3bd6863859a1a6909179a5e5bf744b3d807e) )
ROM_END
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor a1bus_cassette_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( cassette );
}
const rom_entry *a1bus_cassette_device::device_rom_region() const
{
return ROM_NAME( cassette );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
a1bus_cassette_device::a1bus_cassette_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, A1BUS_CASSETTE, "Apple I cassette board", tag, owner, clock, "a1cass", __FILE__),
device_a1bus_card_interface(mconfig, *this),
m_cassette(*this, "cassette")
{
}
a1bus_cassette_device::a1bus_cassette_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_a1bus_card_interface(mconfig, *this),
m_cassette(*this, "cassette")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void a1bus_cassette_device::device_start()
{
set_a1bus_device();
astring tempstring;
m_rom = device().machine().root_device().memregion(this->subtag(tempstring, CASSETTE_ROM_REGION))->base();
install_device(0xc000, 0xc0ff, read8_delegate(FUNC(a1bus_cassette_device::cassette_r), this), write8_delegate(FUNC(a1bus_cassette_device::cassette_w), this));
install_bank(0xc100, 0xc1ff, 0, 0, (char *)"bank_a1cas", m_rom);
}
void a1bus_cassette_device::device_reset()
{
m_cassette_output_flipflop = 0;
}
/*****************************************************************************
** Cassette interface I/O
**
** The Apple I's cassette interface was a small card that plugged
** into the expansion connector on the motherboard. (This was a
** slot-type connector, separate from the motherboard's edge
** connector, but with the same signals.) The cassette interface
** provided separate cassette input and output jacks, some very
** simple interface hardware, and 256 bytes of ROM containing the
** cassette I/O code.
**
** The interface was mostly software-controlled. The only hardware
** was an output flip-flop for generating the cassette output signal,
** a National Semiconductor LM311 voltage comparator for generating a
** digital signal from the analog cassette input, an input
** signal-level LED, and some gates to control the interface logic
** and address decoding. The cassette ROM code did most of the work
** of generating and interpreting tape signals. It also contained
** its own mini-monitor for issuing tape read and write commands.
**
** The cassette interface was assigned to the $C000-$CFFF block of
** addresses, although it did not use most of the space in that
** block. Addresses were mapped as follows:
**
** $C000-$C0FF: Cassette I/O space.
** Any access here toggles the output signal.
** $C000-$C07F: Cassette output only; input disabled.
** Mirrors $C100-$C17F on reads.
** $C080-$C0FF: Cassette input and output.
** When input low, mirrors $C180-$C1FF on reads.
** When input high, both odd and even addresses
** mirror even ROM addresses $C180-$C1FE.
** $C100-$C1FF: Cassette ROM code.
**
** Note the peculiar addressing scheme. Data was written simply
** through repeated accesses, rather than by writing to an address.
** Data was read by reading an odd input address and comparing the
** ROM byte returned to detect signal changes.
**
** The standard tape signal was a simple square wave, although this
** was often greatly distorted by the cassette recorder. A single
** tape record consisted of a 10-second 800-Hz leader, followed by a
** single short square-wave cycle used as a sync bit, followed by the
** tape data. The data was encoded using a single square-wave cycle
** for each bit; "1" bits were at 1000 Hz, "0" bits at 2000 Hz. (All
** of these frequencies are approximate and could vary due to
** differences in recorder speed.) Each byte was written starting
** from the most significant bit; bytes were written from low to high
** addresses. No error detection was provided. Multiple records
** could be placed on a single tape.
*****************************************************************************/
/* The cassette output signal for writing tapes is generated by a
flip-flop which is toggled to produce the output waveform. Any
access to the cassette I/O range, whether a read or a write,
toggles this flip-flop. */
void a1bus_cassette_device::cassette_toggle_output()
{
m_cassette_output_flipflop = !m_cassette_output_flipflop;
m_cassette->output(m_cassette_output_flipflop ? 1.0 : -1.0);
}
READ8_MEMBER(a1bus_cassette_device::cassette_r)
{
cassette_toggle_output();
if (offset <= 0x7f)
{
/* If the access is to address range $C000-$C07F, the cassette
input signal is ignored . In this case the value read
always comes from the corresponding cassette ROM location
in $C100-$C17F. */
return m_rom[offset];
}
else
{
/* For accesses to address range $C080-$C0FF, the cassette
input signal is enabled. If the signal is low, the value
read comes from the corresponding cassette ROM location in
$C180-$C1FF. If the signal is high, the low bit of the
address is masked before the corresponding cassette ROM
location is accessed; e.g., a read from $C081 would return
the ROM byte at $C180. The cassette ROM routines detect
changes in the cassette input signal by repeatedly reading
from $C081 and comparing the values read. */
/* (Don't try putting a non-zero "noise threshhold" here,
because it can cause tape header bits on real cassette
images to be misread as data bits.) */
if (m_cassette->input() > 0.0)
return m_rom[0xc100 + (offset & ~1)];
else
return m_rom[0xc100 + offset];
}
}
WRITE8_MEMBER(a1bus_cassette_device::cassette_w)
{
/* Writes toggle the output flip-flop in the same way that reads
do; other than that they have no effect. Any repeated accesses
to the cassette I/O address range can be used to write data to
cassette, and the cassette ROM always uses reads to do this.
However, we still have to handle writes, since they may be done
by user code. */
cassette_toggle_output();
}

View File

@ -0,0 +1,51 @@
/*********************************************************************
a1cassette.h
Apple II 6850 MIDI card, as made by Passport, Yamaha, and others.
*********************************************************************/
#ifndef __A1BUS_CASSETTE__
#define __A1BUS_CASSETTE__
#include "a1bus.h"
#include "imagedev/cassette.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class a1bus_cassette_device:
public device_t,
public device_a1bus_card_interface
{
public:
// construction/destruction
a1bus_cassette_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
a1bus_cassette_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
virtual const rom_entry *device_rom_region() const;
optional_device<cassette_image_device> m_cassette;
DECLARE_READ8_MEMBER(cassette_r);
DECLARE_WRITE8_MEMBER(cassette_w);
protected:
virtual void device_start();
virtual void device_reset();
void cassette_toggle_output();
private:
UINT8 *m_rom;
int m_cassette_output_flipflop;
};
// device type definition
extern const device_type A1BUS_CASSETTE;
#endif /* __A1BUS_CASSETTE__ */

View File

@ -1066,3 +1066,15 @@ BUSOBJS += $(BUSOBJ)/oricext/oricext.o
BUSOBJS += $(BUSOBJ)/oricext/jasmin.o
BUSOBJS += $(BUSOBJ)/oricext/microdisc.o
endif
#-------------------------------------------------
#
#@src/emu/bus/a1bus/a1bus.h,BUSES += A1BUS
#-------------------------------------------------
ifneq ($(filter A1BUS,$(BUSES)),)
OBJDIRS += $(BUSOBJ)/a1bus
BUSOBJS += $(BUSOBJ)/a1bus/a1bus.o
BUSOBJS += $(BUSOBJ)/a1bus/a1cassette.o
endif

View File

@ -129,30 +129,21 @@ When the prompt returns, press Stop.
#include "machine/6821pia.h"
#include "includes/apple1.h"
#include "imagedev/snapquik.h"
#include "imagedev/cassette.h"
#include "machine/ram.h"
#include "bus/a1bus/a1bus.h"
#include "bus/a1bus/a1cassette.h"
/* port i/o functions */
/* memory w/r functions */
static ADDRESS_MAP_START( apple1_map, AS_PROGRAM, 8, apple1_state )
AM_RANGE(0x0000, 0xbfff) AM_NOP
/* Cassette interface I/O space: */
AM_RANGE(0xc000, 0xc0ff) AM_READWRITE(apple1_cassette_r, apple1_cassette_w)
/* Cassette interface ROM: */
AM_RANGE(0xc100, 0xc1ff) AM_ROM
AM_RANGE(0xc200, 0xcfff) AM_NOP
/* In $D000-$DFFF, PIA is selected by address bit 4 being high,
and PIA registers are addressed with address bits 0-1. All
other address bits are ignored. Thus $D010-$D013 is mirrored
at all $Dxxx addresses with bit 4 high. */
AM_RANGE(0xd010, 0xd013) AM_MIRROR(0x0fec) AM_DEVREADWRITE("pia",pia6821_device, read, write)
/* $Dxxx addresses with bit 4 low are NOPs. */
AM_RANGE(0xd000, 0xd00f) AM_NOP AM_MIRROR(0xfe0)
/* We always include the remapped RAM for cassette BASIC, both for
simplicity and to allow the running of BASIC programs. */
@ -161,7 +152,7 @@ static ADDRESS_MAP_START( apple1_map, AS_PROGRAM, 8, apple1_state )
AM_RANGE(0xf000, 0xfeff) AM_NOP
/* Monitor ROM: */
AM_RANGE(0xff00, 0xffff) AM_ROM
AM_RANGE(0xff00, 0xffff) AM_ROM AM_REGION("maincpu", 0)
ADDRESS_MAP_END
/* graphics output */
@ -264,16 +255,9 @@ static INPUT_PORTS_START( apple1 )
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Clear") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
INPUT_PORTS_END
/* sound output */
static const cassette_interface apple1_cassette_interface =
{
cassette_default_formats,
NULL,
(cassette_state)(CASSETTE_STOPPED),
"apple1_cass",
NULL
};
static SLOT_INTERFACE_START(apple1_cards)
SLOT_INTERFACE("cassette", A1BUS_CASSETTE)
SLOT_INTERFACE_END
/* machine definition */
static MACHINE_CONFIG_START( apple1, apple1_state )
@ -309,10 +293,13 @@ static MACHINE_CONFIG_START( apple1, apple1_state )
MCFG_PIA_WRITEPB_HANDLER(WRITE8(apple1_state,apple1_pia0_dspout))
MCFG_PIA_CB2_HANDLER(WRITELINE(apple1_state,apple1_pia0_dsp_write_signal))
MCFG_DEVICE_ADD("a1bus", A1BUS, 0)
MCFG_A1BUS_CPU("maincpu")
MCFG_A1BUS_SLOT_ADD("a1bus", "exp", apple1_cards, "cassette")
/* snapshot */
MCFG_SNAPSHOT_ADD("snapshot", apple1_state, apple1, "snp", 0)
MCFG_CASSETTE_ADD("cassette", apple1_cassette_interface)
MCFG_SOFTWARE_LIST_ADD("cass_list","apple1")
/* Note that because we always include 4K of RAM at $E000-$EFFF,
@ -326,13 +313,10 @@ static MACHINE_CONFIG_START( apple1, apple1_state )
MACHINE_CONFIG_END
ROM_START(apple1)
ROM_REGION(0x10000, "maincpu",0)
ROM_REGION(0x100, "maincpu",0)
/* 256-byte main monitor ROM, in two 82s129 or mmi6301 256x4 proms at A1 and A2 called APPLE-A1(bits D3-D0) and APPLE-A2(bits D7-D4) */
ROM_LOAD_NIB_HIGH( "apple-a2.a2", 0xFF00, 0x0100, CRC(254bfb95) SHA1(b6468b72295b7d8ac288d104d252f24de1f1d611) )
ROM_LOAD_NIB_LOW( "apple-a1.a1", 0xFF00, 0x0100, CRC(434f8ce6) SHA1(9deee2d39903209b20c3fc6b58e16372f8efece1) )
/* 256-byte cassette interface ROM, in two 82s129 or mmi6301 256x4 proms at locations 3 and 4 on the cassette interface daughtercard (they are labeled "MMI 6301-IJ // 7623L // APPLE-A3" and "MMI 6301-IJ // 7623L // APPLE-A4") */
ROM_LOAD_NIB_HIGH( "apple-a3.3", 0xc100, 0x0100, CRC(6eae8f52) SHA1(71906932727ef70952ef6afe6b08708df15cd67d) )
ROM_LOAD_NIB_LOW( "apple-a4.4", 0xc100, 0x0100, CRC(94efa977) SHA1(851f3bd6863859a1a6909179a5e5bf744b3d807e) )
ROM_LOAD_NIB_HIGH( "apple-a2.a2", 0x0000, 0x0100, CRC(254bfb95) SHA1(b6468b72295b7d8ac288d104d252f24de1f1d611) )
ROM_LOAD_NIB_LOW( "apple-a1.a1", 0x0000, 0x0100, CRC(434f8ce6) SHA1(9deee2d39903209b20c3fc6b58e16372f8efece1) )
/* 512-byte Signetics 2513 character generator ROM at location D2-D3 */
ROM_REGION(0x0200, "gfx1",0)
ROM_LOAD("s2513.d2", 0x0000, 0x0200, CRC(a7e567fc) SHA1(b18aae0a2d4f92f5a7e22640719bbc4652f3f4ee)) // apple1.vid

View File

@ -8,7 +8,6 @@
#define APPLE1_H_
#include "imagedev/snapquik.h"
#include "imagedev/cassette.h"
#include "machine/ram.h"
typedef short termchar_t;
@ -34,7 +33,6 @@ public:
apple1_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_cassette(*this, "cassette"),
m_ram(*this, RAM_TAG),
m_gfxdecode(*this, "gfxdecode"),
m_screen(*this, "screen") { }
@ -43,12 +41,9 @@ public:
int m_kbd_data;
UINT32 m_kbd_last_scan[4];
int m_reset_flag;
int m_cassette_output_flipflop;
terminal_t *m_current_terminal;
terminal_t *m_terminal;
int m_blink_on;
DECLARE_READ8_MEMBER(apple1_cassette_r);
DECLARE_WRITE8_MEMBER(apple1_cassette_w);
DECLARE_DRIVER_INIT(apple1);
TILE_GET_INFO_MEMBER(terminal_gettileinfo);
virtual void machine_reset();
@ -62,7 +57,6 @@ public:
DECLARE_WRITE8_MEMBER(apple1_pia0_dspout);
DECLARE_WRITE_LINE_MEMBER(apple1_pia0_dsp_write_signal);
required_device<cpu_device> m_maincpu;
required_device<cassette_image_device> m_cassette;
void terminal_draw(screen_device &screen, bitmap_ind16 &dest, const rectangle &cliprect, terminal_t *terminal);
void verify_coords(terminal_t *terminal, int x, int y);
void terminal_putchar(terminal_t *terminal, int x, int y, int ch);
@ -79,7 +73,6 @@ public:
void apple1_vh_dsp_clr ();
void apple1_vh_cursor_blink ();
int apple1_verify_header (UINT8 *data);
void cassette_toggle_output();
terminal_t *terminal_create(int gfx, int blank_char, int char_bits,int (*getcursorcode)(int original_code),int num_cols, int num_rows);
attotime apple1_vh_dsp_time_to_ready();
DECLARE_SNAPSHOT_LOAD_MEMBER( apple1 );

View File

@ -402,111 +402,3 @@ TIMER_CALLBACK_MEMBER(apple1_state::apple1_dsp_ready_end)
}
/*****************************************************************************
** Cassette interface I/O
**
** The Apple I's cassette interface was a small card that plugged
** into the expansion connector on the motherboard. (This was a
** slot-type connector, separate from the motherboard's edge
** connector, but with the same signals.) The cassette interface
** provided separate cassette input and output jacks, some very
** simple interface hardware, and 256 bytes of ROM containing the
** cassette I/O code.
**
** The interface was mostly software-controlled. The only hardware
** was an output flip-flop for generating the cassette output signal,
** a National Semiconductor LM311 voltage comparator for generating a
** digital signal from the analog cassette input, an input
** signal-level LED, and some gates to control the interface logic
** and address decoding. The cassette ROM code did most of the work
** of generating and interpreting tape signals. It also contained
** its own mini-monitor for issuing tape read and write commands.
**
** The cassette interface was assigned to the $C000-$CFFF block of
** addresses, although it did not use most of the space in that
** block. Addresses were mapped as follows:
**
** $C000-$C0FF: Cassette I/O space.
** Any access here toggles the output signal.
** $C000-$C07F: Cassette output only; input disabled.
** Mirrors $C100-$C17F on reads.
** $C080-$C0FF: Cassette input and output.
** When input low, mirrors $C180-$C1FF on reads.
** When input high, both odd and even addresses
** mirror even ROM addresses $C180-$C1FE.
** $C100-$C1FF: Cassette ROM code.
**
** Note the peculiar addressing scheme. Data was written simply
** through repeated accesses, rather than by writing to an address.
** Data was read by reading an odd input address and comparing the
** ROM byte returned to detect signal changes.
**
** The standard tape signal was a simple square wave, although this
** was often greatly distorted by the cassette recorder. A single
** tape record consisted of a 10-second 800-Hz leader, followed by a
** single short square-wave cycle used as a sync bit, followed by the
** tape data. The data was encoded using a single square-wave cycle
** for each bit; "1" bits were at 1000 Hz, "0" bits at 2000 Hz. (All
** of these frequencies are approximate and could vary due to
** differences in recorder speed.) Each byte was written starting
** from the most significant bit; bytes were written from low to high
** addresses. No error detection was provided. Multiple records
** could be placed on a single tape.
*****************************************************************************/
/* The cassette output signal for writing tapes is generated by a
flip-flop which is toggled to produce the output waveform. Any
access to the cassette I/O range, whether a read or a write,
toggles this flip-flop. */
void apple1_state::cassette_toggle_output()
{
m_cassette_output_flipflop = !m_cassette_output_flipflop;
m_cassette->output(m_cassette_output_flipflop ? 1.0 : -1.0);
}
READ8_MEMBER(apple1_state::apple1_cassette_r)
{
cassette_toggle_output();
if (offset <= 0x7f)
{
/* If the access is to address range $C000-$C07F, the cassette
input signal is ignored . In this case the value read
always comes from the corresponding cassette ROM location
in $C100-$C17F. */
return space.read_byte(0xc100 + offset);
}
else
{
/* For accesses to address range $C080-$C0FF, the cassette
input signal is enabled. If the signal is low, the value
read comes from the corresponding cassette ROM location in
$C180-$C1FF. If the signal is high, the low bit of the
address is masked before the corresponding cassette ROM
location is accessed; e.g., a read from $C081 would return
the ROM byte at $C180. The cassette ROM routines detect
changes in the cassette input signal by repeatedly reading
from $C081 and comparing the values read. */
/* (Don't try putting a non-zero "noise threshhold" here,
because it can cause tape header bits on real cassette
images to be misread as data bits.) */
if (m_cassette->input() > 0.0)
return space.read_byte(0xc100 + (offset & ~1));
else
return space.read_byte(0xc100 + offset);
}
}
WRITE8_MEMBER(apple1_state::apple1_cassette_w)
{
/* Writes toggle the output flip-flop in the same way that reads
do; other than that they have no effect. Any repeated accesses
to the cassette I/O address range can be used to write data to
cassette, and the cassette ROM always uses reads to do this.
However, we still have to handle writes, since they may be done
by user code. */
cassette_toggle_output();
}

View File

@ -520,6 +520,7 @@ MACHINES += WOZFDC
# specify available bus cores
#-------------------------------------------------
BUSES += A1BUS
BUSES += A2BUS
BUSES += ABCBUS
BUSES += ABCKB