1 // license:BSD-3-Clause
2 // copyright-holders:Nathan Woods
3 /***************************************************************************
4 
5     coco_orch90.cpp
6 
7     Code for emulating the CoCo Orch-90 (Orchestra 90) sound cartridge
8 
9     The Orch-90 was a simple sound cartridge; it had two 8-bit DACs
10     supporting stereo sound.  The left channel was at $FF7A, and the right
11     channel was at $FF7B
12 
13 
14     Hidden Code exists in the ORCH-90 to produce a higher quality output.
15     Once you start the PAK, hit "SHIFT+ENTER" at the title screen.  Once you
16     are at command, type the following (playing the William Tell default):
17     "S" + "ENTER"
18     "P" + "SHIFT+ENTER"
19 
20     The output will be cleaner due to code causing a change in CPU speed by
21     addressing CPU registers to run the 6809 at 2x speed.
22 
23     "P" + "ENTER" will play at regular CPU speed.  The difference should be
24     very noticeable.
25 
26 ***************************************************************************/
27 
28 #include "emu.h"
29 #include "coco_orch90.h"
30 #include "cococart.h"
31 
32 #include "sound/dac.h"
33 #include "speaker.h"
34 
35 
36 //**************************************************************************
37 //  ROM DECLARATIONS
38 //**************************************************************************
39 
40 ROM_START(coco_orch90)
41 	ROM_REGION(0x2000, "eprom", ROMREGION_ERASE00)
42 	ROM_LOAD("orchestra 90,1984,26 - 3143,tandy.rom", 0x0000, 0x2000, CRC(15fb39af) SHA1(6a20fee9c70b36a6435ac8378f31d5b626017df0))
43 ROM_END
44 
45 
46 //**************************************************************************
47 //  ORCH90 DEVICE CLASS
48 //**************************************************************************
49 
50 namespace
51 {
52 	// ======================> coco_orch90_device
53 
54 	class coco_orch90_device :
55 		public device_t,
56 		public device_cococart_interface
57 	{
58 	public:
59 		// construction/destruction
coco_orch90_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)60 		coco_orch90_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
61 			: device_t(mconfig, COCO_ORCH90, tag, owner, clock)
62 			, device_cococart_interface(mconfig, *this)
63 			, m_eprom(*this, "eprom")
64 			, m_ldac(*this, "ldac")
65 			, m_rdac(*this, "rdac")
66 		{
67 		}
68 
69 		// optional information overrides
70 		virtual void device_add_mconfig(machine_config &config) override;
71 
72 	protected:
73 		// device-level overrides
device_start()74 		virtual void device_start() override
75 		{
76 			// install handlers
77 			install_write_handler(0xFF7A, 0xFF7A, write8smo_delegate(*this, FUNC(coco_orch90_device::write_left)));
78 			install_write_handler(0xFF7B, 0xFF7B, write8smo_delegate(*this, FUNC(coco_orch90_device::write_right)));
79 
80 			// Orch-90 ties CART to Q
81 			set_line_value(line::CART, line_value::Q);
82 		}
83 
device_rom_region() const84 		virtual const tiny_rom_entry *device_rom_region() const override
85 		{
86 			return ROM_NAME(coco_orch90);
87 		}
88 
89 		// CoCo cartridge level overrides
get_cart_base()90 		virtual u8 *get_cart_base() override
91 		{
92 			return m_eprom->base();
93 		}
94 
get_cart_memregion()95 		virtual memory_region *get_cart_memregion() override
96 		{
97 			return m_eprom;
98 		}
99 
100 		virtual u8 cts_read(offs_t offset) override;
101 
102 	private:
write_left(u8 data)103 		void write_left(u8 data)   { m_ldac->write(data); }
write_right(u8 data)104 		void write_right(u8 data)  { m_rdac->write(data); }
105 
106 		// internal state
107 		required_memory_region m_eprom;
108 		required_device<dac_byte_interface> m_ldac;
109 		required_device<dac_byte_interface> m_rdac;
110 	};
111 };
112 
113 
114 //**************************************************************************
115 //  MACHINE AND ROM DECLARATIONS
116 //**************************************************************************
117 
device_add_mconfig(machine_config & config)118 void coco_orch90_device::device_add_mconfig(machine_config &config)
119 {
120 	SPEAKER(config, "lspeaker").front_left();
121 	SPEAKER(config, "rspeaker").front_right();
122 	DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // ls374.ic5 + r7 (8x20k) + r9 (8x10k)
123 	DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // ls374.ic4 + r6 (8x20k) + r8 (8x10k)
124 }
125 
126 //-------------------------------------------------
127 //  cts_read
128 //-------------------------------------------------
129 
cts_read(offs_t offset)130 u8 coco_orch90_device::cts_read(offs_t offset)
131 {
132 	return m_eprom->base()[offset & 0x1fff];
133 }
134 
135 
136 //**************************************************************************
137 //  DEVICE DECLARATION
138 //**************************************************************************
139 
140 DEFINE_DEVICE_TYPE_PRIVATE(COCO_ORCH90, device_cococart_interface, coco_orch90_device, "coco_orch90", "CoCo Orch-90 PAK")
141