Skip to content

Commit

Permalink
heathkit/h89.cpp: Add a software list for H88 cassettes. (mamedev#12019)
Browse files Browse the repository at this point in the history
New working software list items (h88_cass.xml)
------------------------
BUG-8 02.05.00 [Society of Eight-Bit Heathkit Computerists]
BUG-8 02.06.00 [Society of Eight-Bit Heathkit Computerists]
Extended Benton Harbor Basic 10.05.00 [Society of Eight-Bit Heathkit Computerists]
Extended Benton Harbor Basic 10.05.01 [Society of Eight-Bit Heathkit Computerists]
Extended Benton Harbor Basic 10.06.00 [Society of Eight-Bit Heathkit Computerists]
Heath H8 Assembler 04.05.00 [Society of Eight-Bit Heathkit Computerists]
Heath H8 Assembler 04.06.00 [Society of Eight-Bit Heathkit Computerists]
Heath/Wintek H8 Editor 03.05.00 [Society of Eight-Bit Heathkit Computerists]
Heath/Wintek H8 Editor 03.06.00 [Society of Eight-Bit Heathkit Computerists]
  • Loading branch information
mgarlanger authored and stonedDiscord committed Apr 8, 2024
1 parent 68b325c commit e121d44
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 35 deletions.
161 changes: 161 additions & 0 deletions hash/h88_cass.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?xml version="1.0"?>
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
<!--
license:CC0-1.0
-->
<softwarelist name="h88_cass" description="Heath H88 cassettes">

<software name="bug8_02_05_00" cloneof="bug8">
<description>BUG-8 02.05.00</description>
<year>1978</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="Heath/Wintek Terminal Debugger"/>
<info name="developer" value="Heath Corp./Wintek Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197806xx"/>
<info name="version" value="02.05.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="5027">
<rom name="bug8_02_05_00.h8t" size="5027" crc="6013dd00" sha1="805f89fee7ade4cf9d2401b111006634d9239d92"/>
</dataarea>
</part>
</software>

<software name="bug8">
<description>BUG-8 02.06.00</description>
<year>1978</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="Heath/Wintek Terminal Debugger"/>
<info name="developer" value="Heath Corp./Wintek Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197806xx"/>
<info name="version" value="02.06.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="5143">
<rom name="bug8_02_06_00.h8t" size="5143" crc="63ab0c02" sha1="29c0b0242dca535eebc911288df40f34813cf08b"/>
</dataarea>
</part>
</software>

<software name="exbasic_10_05_00" cloneof="exbasic">
<description>Extended Benton Harbor Basic 10.05.00</description>
<year>1978</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="Extended Benton Harbor Basic"/>
<info name="developer" value="Heath Corp./Wintek Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197806xx"/>
<info name="version" value="10.05.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="12028">
<rom name="exbasic_10_05_00.h8t" size="12028" crc="f7ff8fcc" sha1="d1010ed4d3cb68a0fb4a3380bf3d5c31b72bf370"/>
</dataarea>
</part>
</software>

<software name="exbasic_10_05_01" cloneof="exbasic">
<description>Extended Benton Harbor Basic 10.05.01</description>
<year>1978</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="Extended Benton Harbor Basic"/>
<info name="developer" value="Heath Corp./Wintek Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197806xx"/>
<info name="version" value="10.05.01"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="12029">
<rom name="exbasic_10_05_01.h8t" size="12029" crc="ac6f60f2" sha1="59cf1d2077548ba14cc5b600f065f3147b87a9e3"/>
</dataarea>
</part>
</software>

<software name="exbasic">
<description>Extended Benton Harbor Basic 10.06.00</description>
<year>1979</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="Extended Benton Harbor Basic"/>
<info name="developer" value="Heath Corp./Wintek Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197905xx"/>
<info name="version" value="10.06.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="12188">
<rom name="exbasic_10_06_00.h8t" size="12188" crc="9fafdac1" sha1="f55bfab541640ac92e615e83eb2d705347d17510"/>
</dataarea>
</part>
</software>

<software name="hasl8_04_05_00" cloneof="hasl8">
<description>Heath H8 Assembler 04.05.00</description>
<year>1978</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="Heath HASL"/>
<info name="developer" value="Heath Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197806xx"/>
<info name="version" value="04.05.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="7514">
<rom name="hasl8_04_05_00.h8t" size="7514" crc="2a67cc74" sha1="aa109a5cfc4e84d002c1f237e072524d7eb00cf9"/>
</dataarea>
</part>
</software>

<software name="hasl8">
<description>Heath H8 Assembler 04.06.00</description>
<year>1979</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="Heath HASL"/>
<info name="developer" value="Heath Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197905xx"/>
<info name="version" value="04.05.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="7656">
<rom name="hasl8_04_06_00.h8t" size="7656" crc="803261b4" sha1="475d2c9edd7d3b1e4e91e18265055747909882ff"/>
</dataarea>
</part>
</software>

<software name="ted8_03_05_00" cloneof="ted8">
<description>Heath/Wintek H8 Editor 03.05.00</description>
<year>1979</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="TED-8"/>
<info name="developer" value="Heath Corp./Wintek Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197803xx"/>
<info name="version" value="03.05.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="6975">
<rom name="ted8_03_05_00.h8t" size="6975" crc="b2f174ef" sha1="719305f2a431d77c8f77e49cf4d0f40765b59f0d"/>
</dataarea>
</part>
</software>

<software name="ted8">
<description>Heath/Wintek H8 Editor 03.06.00</description>
<year>1979</year>
<publisher>Heath Corp.</publisher>
<info name="alt_title" value="TED-8"/>
<info name="developer" value="Heath Corp./Wintek Corp."/>
<info name="distributor" value="Heath Corp."/>
<info name="release" value="197803xx"/>
<info name="version" value="03.05.00"/>

<part name="cass" interface="h88_cass_player">
<dataarea name="cass" size="7099">
<rom name="ted8_03_06_00.h8t" size="7099" crc="0e2d2186" sha1="a3df79d1629fc11864060e5858d554aa9b5963d1"/>
</dataarea>
</part>
</software>

</softwarelist>
71 changes: 38 additions & 33 deletions src/lib/formats/h8_cas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,31 @@ Support for Heathkit H8 H8T cassette images
Standard Kansas City format (300 baud)
TODO - investigate 1200 buad support, H8 should support it, but H88 does not.
We output a leader, followed by the contents of the H8T file.
********************************************************************/

#include "h8_cas.h"

#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767
#include <algorithm>


static constexpr uint16_t WAVEENTRY_LOW = -32768;
static constexpr uint16_t WAVEENTRY_HIGH = 32767;
static constexpr uint16_t SILENCE = 0;

// using a multiple of 4800 will ensure an integer multiple of samples for each wave.
static constexpr uint16_t H8_WAV_FREQUENCY = 9600;
static constexpr uint16_t TAPE_BAUD_RATE = 300;
static constexpr uint16_t SAMPLES_PER_BIT = H8_WAV_FREQUENCY / TAPE_BAUD_RATE;
static constexpr uint16_t SAMPLES_PER_HALF_WAVE = SAMPLES_PER_BIT / 2;

#define H8_WAV_FREQUENCY 9600
static constexpr uint16_t ONE_FREQ = 1200;
static constexpr uint16_t ZERO_FREQ = 2400;
static constexpr uint16_t ONE_CYCLES = H8_WAV_FREQUENCY / ONE_FREQ;
static constexpr uint16_t ZERO_CYCLES = H8_WAV_FREQUENCY / ZERO_FREQ;

// image size
static int h8_image_size; // FIXME: global variable prevents multiple instances
Expand All @@ -25,8 +40,7 @@ static int h8_put_samples(int16_t *buffer, int sample_pos, int count, int level)
{
if (buffer)
{
for (int i=0; i<count; i++)
buffer[sample_pos + i] = level;
std::fill_n(&buffer[sample_pos], count, level);
}

return count;
Expand All @@ -36,57 +50,48 @@ static int h8_output_bit(int16_t *buffer, int sample_pos, bool bit)
{
int samples = 0;

for (uint8_t i = 0; i < 4; i++)
const int loops = bit ? ONE_CYCLES : ZERO_CYCLES;
const int samplePerValue = SAMPLES_PER_HALF_WAVE / loops;

for (int i = 0; i < loops; i++)
{
if (bit)
{
samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_LOW);
samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_HIGH);
samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_LOW);
samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_HIGH);
}
else
{
samples += h8_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_LOW);
samples += h8_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_HIGH);
}
samples += h8_put_samples(buffer, sample_pos + samples, samplePerValue, WAVEENTRY_LOW);
samples += h8_put_samples(buffer, sample_pos + samples, samplePerValue, WAVEENTRY_HIGH);
}

return samples;
}

static int h8_output_byte(int16_t *buffer, int sample_pos, uint8_t byte)
static int h8_output_byte(int16_t *buffer, int sample_pos, uint8_t data)
{
int samples = 0;
uint8_t i;

// start bit
samples += h8_output_bit (buffer, sample_pos + samples, 0);
samples += h8_output_bit(buffer, sample_pos + samples, 0);

// data bits
for (i = 0; i<8; i++)
samples += h8_output_bit (buffer, sample_pos + samples, (byte >> i) & 1);
for (int i = 0; i < 8; i++)
{
samples += h8_output_bit(buffer, sample_pos + samples, data & 1);
data >>= 1;
}

// stop bits
for (i = 0; i<2; i++)
samples += h8_output_bit (buffer, sample_pos + samples, 1);
// stop bit
samples += h8_output_bit(buffer, sample_pos + samples, 1);

return samples;
}

static int h8_handle_cassette(int16_t *buffer, const uint8_t *bytes)
{
uint32_t sample_count = 0;
uint32_t byte_count = 0;
uint32_t i;

int sample_count = 0;

// leader
for (i=0; i<2000; i++)
// leader - 1 second
for (int i = 0; i < TAPE_BAUD_RATE; i++)
sample_count += h8_output_bit(buffer, sample_count, 1);

// data
for (i=byte_count; i<h8_image_size; i++)
for (int i = 0; i < h8_image_size; i++)
sample_count += h8_output_byte(buffer, sample_count, bytes[i]);

return sample_count;
Expand Down
3 changes: 3 additions & 0 deletions src/mame/heathkit/h89.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "machine/ram.h"
#include "machine/timer.h"

#include "softlist_dev.h"

// Single Step
#define LOG_SS (1U << 1)
Expand Down Expand Up @@ -837,6 +838,8 @@ void h88_state::h88(machine_config &config)
m_intr_socket->set_default_option("original");
m_intr_socket->set_fixed(true);

SOFTWARE_LIST(config, "cass_list").set_original("h88_cass");

// H-88-5 Cassette interface board
HEATH_H88_CASS(config, m_cassette, H89_CLOCK);
}
Expand Down
4 changes: 2 additions & 2 deletions src/mame/heathkit/h_88_cass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ void heath_h_88_cass_device::device_add_mconfig(machine_config &config)
m_cass_player->set_formats(h8_cassette_formats);
m_cass_player->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
m_cass_player->add_route(ALL_OUTPUTS, "mono", 0.15);
m_cass_player->set_interface("h89_cass_player");
m_cass_player->set_interface("h88_cass_player");

CASSETTE(config, m_cass_recorder);
m_cass_recorder->set_formats(h8_cassette_formats);
m_cass_recorder->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
m_cass_recorder->add_route(ALL_OUTPUTS, "mono", 0.15);
m_cass_recorder->set_interface("h89_cass_recorder");
m_cass_recorder->set_interface("h88_cass_recorder");

TIMER(config, "kansas_w").configure_periodic(FUNC(heath_h_88_cass_device::kansas_w), attotime::from_hz(4800));
TIMER(config, "kansas_r").configure_periodic(FUNC(heath_h_88_cass_device::kansas_r), attotime::from_hz(40000));
Expand Down

0 comments on commit e121d44

Please sign in to comment.